Автоматическое создание серии файлов SVG и PDF из SVG шаблона на примере Inkscape
Содержание
- 1 Описание задачи
- 2 Создаём SVG шаблон визитки в Inkscape
- 3 Создаём базу данных с контактными данными в формате CSV
- 4 Создаём скрипт-парсер для копирования, заполнения и экспорта в PDF
- 5 Создаём командный скрипт в операционной системе для запуска скрипта-парсера в нужном окружении ОС
- 6 Подстановка данных встроенными средствами Inkscape
Описание задачи
В этой статье мы рассмотрим пример создания персонизированных визиток из единого шаблона. Имея подготовленный SVG шаблон визитки мы используя скрипты на выходе получим набор визиток в отдельных файлах в форматах SVG и PDF.
SVG - это XML файл с описанием всех объектов и их свойств, а значит может быть открыт и изменён как обычный текстовый файл. Написав парсер текстового файла, мы сможем сделать любые изменения в нём, в том числе поменять один фрагмент текста на другой.
SVG поддерживается многими векторными редакторами. Для бесплатного редактора Inkscape SVG - это родной формат, и команда этого проекта стремится полностью соответствовать публичной его спецификации.
Алгоритм таков:
- Создаём SVG шаблон визитки (например в Inkscape)
- Создаём базу данных с контактными данными в формате CSV
- Создаём скрипт-парсер для копирования, заполнения и экспорта в PDF
- Создаём командный скрипт в операционной системе для запуска скрипта-парсера в нужном окружении ОС.
В зависимости от настроек операционной системы могут возникнуть сложности с кириллическими буквами, поэтому в этом примере будем избегать их в названиях файлов.
Создаём SVG шаблон визитки в Inkscape
При проектировании визитки нужно учесть, что вставляемые значения могут быть разной длины. Также выравнивание текста должно быть задано с учётом этого. Переменные вместо которых будем вставлять текст лучше сделать заметными в общем дизайне и унифицированными по виду. Например обозначить заглавными латинскими буквами и заключить в скобки. Также они не должны повторять текст в шаблоне. В целом стоит иметь в виду что подстановка реальных данных в эти переменные будет осуществляться простым поиском и заменой одной подстроки на другую.
Пример шаблона визитки приведён справа ( скачать SVG исходник).
QR-код (содержащий URL сайта или другую контактную информацию) можно сгенерировать с помощью встроенного расширения, специально для этого созданного:
- Расширение → Отрисовка → Штрих-код → код QR...
Создаём базу данных с контактными данными в формате CSV
В приведённом выше шаблоне используется 4 переменных, соответственно CSV файл должен содержать строки вида:
Иванов Иван Иванович;НАЧАЛЬНИК ТЕХНИЧЕСКОГО ОТДЕЛА;+7 961-111-2222;ivanov@domain.ru Петров Пётр Петрович;ГЛАВНЫЙ СПЕЦИАЛИСТ;+7 961-333-4444;petrov@domain.ru
Разделитель полей можно будет поменять с ";" на любой другой в скрипте осуществляющем подстановку данных (см. ниже). Файл CSV может быть экспортирован из имеющейся таблицы (например LibreOffice Calc или Microsoft Excel).
Создаём скрипт-парсер для копирования, заполнения и экспорта в PDF
Скрипт-парсер можно написать на любом удобном языке. Главное, чтобы в системе был установлен необходимый интерпретатор или компилятор. Вместе с Inkscape поставляется также интерпритатор Python. Синтаксис Python 2.x и 3.x отличаются. Для 2-й версии есть проблемы с кириллицей, поскольку по умолчанию используется ASCII кодировка. Начиная с версии Inkscape 1.0 beta используется 3-я версия Питона, полноценно поддерживающая UTF-8.
Ниже приведены скрипты для формирования SVG и PDF файлов из одного шаблонного. Разница между вариантами для Windows и для Linux только в формате записи путей.
Скрипт на Python 3 для Linux
# This is Python 3 script for Inkscape in Linux
# coding=utf-8
# Notes befor run.
# Linux:
# - use / as directory delimiter
#
# More information: https://sysadminwiki.ru/wiki/Inkscape
import csv
import os
import shutil
import subprocess
#=== Определение переменных пользователем ===
# Рабочий каталог
workDir = '/home/user/images/'
# SVG шаблон
fnSVG = "Бейджик.svg"
# CSV файл с данными
fnCSV = "Участники.csv"
# Разделитель полей
csvDelimiter = ";"
# Скобки переменных, по умолчанию: { }
varStart = '{'
varEnd = '}'
# Номер поля, которое будет использоваться для имени файла (начинается с 0)
fieldN = 2
#=== Вычисляемые переменные (изменять не надо) ===
# Каталоги для выгрузки сформированных файлов
dirSVG = workDir + "SVG/"
dirPDF = workDir + "PDF/"
# Полные имена файлов (абсолютные пути)
fullfnSVG = workDir + fnSVG
fullfnCSV = workDir + fnCSV
#=== ОСНОВНОЙ КОД ===
#-----------------------------------------------------------------------------
print("Start to work with CSV file: " + fullfnCSV)
if not os.path.isdir(dirSVG):
os.mkdir(dirSVG)
if not os.path.isdir(dirPDF):
os.mkdir(dirPDF)
with open(fullfnCSV, newline='', encoding='utf-8') as fCSV:
reader = csv.DictReader(fCSV, delimiter=csvDelimiter)
headers = reader.fieldnames
for row in reader:
print('Work on: ' + row[headers[fieldN]])
destSVG = dirSVG + row[headers[fieldN]] + '.svg'
shutil.copyfile(fullfnSVG, destSVG)
with open (destSVG, 'r', encoding='utf-8') as f:
data = f.read()
for var in headers:
data = data.replace(varStart + var + varEnd, row[var])
with open (destSVG, 'w', encoding='utf-8') as f:
f.write(data)
destPDF = dirPDF + row[headers[fieldN]] + '.pdf'
print('SVG:', destSVG)
print('PDF:', destPDF)
os.system('inkscape ' + '--export-filename=\"' + destPDF + '\" --export-type=pdf -T \"' + destSVG + '\"')
Скрипт на Python 3 для Windows
# This is Python 3 script for Inkscape in Windows
# coding=utf-8
# Notes befor run.
# - set command line to utf-8 encoding: chcp 65001
# - use \ as directory delimiter
#
# More information: https://sysadminwiki.ru/wiki/Inkscape
import csv
import os
import shutil
import subprocess
#=== Определение переменных пользователем ===
# Рабочий каталог
workDir = 'c:\\Temp\\Python\\'
# SVG шаблон
fnSVG = "Бейджик.svg"
# CSV файл с данными
fnCSV = "Участники.csv"
# Разделитель полей
csvDelimiter = ";"
# Скобки переменных, по умолчанию: { }
varStart = '{'
varEnd = '}'
# Номер поля, которое будет использоваться для имени файла (начинается с 0)
fieldN = 2
#=== Вычисляемые переменные (изменять не надо) ===
# Каталоги для выгрузки сформированных файлов
dirSVG = workDir + "SVG\\"
dirPDF = workDir + "PDF\\"
# Полные имена файлов (абсолютные пути)
fullfnSVG = workDir + fnSVG
fullfnCSV = workDir + fnCSV
#=== ОСНОВНОЙ КОД ===
#-----------------------------------------------------------------------------
print("Start to work with CSV file: " + fullfnCSV)
if not os.path.isdir(dirSVG):
os.mkdir(dirSVG)
if not os.path.isdir(dirPDF):
os.mkdir(dirPDF)
with open(fullfnCSV, newline='', encoding='utf-8') as fCSV:
reader = csv.DictReader(fCSV, delimiter=csvDelimiter)
headers = reader.fieldnames
for row in reader:
print('Work on: ' + row[headers[fieldN]])
destSVG = dirSVG + row[headers[fieldN]] + '.svg'
shutil.copyfile(fullfnSVG, destSVG)
with open (destSVG, 'r', encoding='utf-8') as f:
data = f.read()
for var in headers:
data = data.replace(varStart + var + varEnd, row[var])
with open (destSVG, 'w', encoding='utf-8') as f:
f.write(data)
destPDF = dirPDF + row[headers[fieldN]] + '.pdf'
print('SVG:', destSVG)
print('PDF:', destPDF)
os.system('inkscape ' + destSVG + ' --export-filename=' + destPDF + ' --export-type=pdf -T')
Скрипт на PHP
<?php
//=== Определение переменных ===
// Каталог для выгрузки сформированных файлов
$outDir = "out";
// Базовое название выгружаемого файла, к которому будет добавлено уникальное окончание
$outFile = "visitka-";
// CSV файл с данными
$csv_file = "names-rus.csv";
// SVG шаблон
$sourceSVG = "visitka-template.svg";
// Перечень переменных в SVG шаблоне
$csv_fields = array(
'{FIO}',
'{OCCUPATION}',
'{PHONE}',
'{E-MAIL}'
);
//=== Основной код ===
// Копирование шаблона в новый файл и замена переменных на данные из массива
function fillTemplate($temlateFile, $destinationFile, $fields, $data) {
// Создаём указатель на шаблонный файл
$fpTmpl = fopen($temlateFile, 'r');
// Создаём указатель на новый файл
$fpDest = fopen($destinationFile, 'w+');
// Считываем шаблонный файл
$fileData = fread($fpTmpl, filesize($temlateFile));
// Делаем замену переменных из массива $fields на реальные значения в массиве $data
$fileData = str_replace($fields, $data, $fileData);
// Изменённый текст сохраняем в новый файл
fwrite($fpDest, $fileData);
// Закрываем открытые файлы
fclose($fpDest);
fclose($fpTmpl);
} //function fillTemplate()
$row = 1;
// Открываем CSV файл и для каждой считанной строки запускаем
// функцию fillTemplate(), подготавливающую SVG c данными,
// затем создаём PDF файл.
if (($handle = fopen($csv_file, "r")) !== FALSE) {
// Считываем строки из CSV файла, записывая в массив $data,
// разбивая поля по символу ";"
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$destSVG = $outDir . "/" . $outFile . $data[3] . ".svg";
$destPDF = $outDir . "/" . $outFile . $data[3] . ".pdf";
// Для отладки: вывод CSV строки и др
$num = count($data);
$csv_str = "";
for ($c=0; $c < $num; $c++) {
$csv_str = $csv_str . $data[$c] . ' | ';
}
echo "
CSV запись : $num полей в строке $row
CSV строка : $csv_str
исходн файл = $sourceSVG
конечн файл = $destSVG
файл PDF = $destPDF
";
// Завершение вывода отладочной инфы. Формируем новый SVG из шаблонного
fillTemplate($sourceSVG, $destSVG, $csv_fields, $data);
// Делаем экспорт нового SVG в PDF, преобразуя все шрифты и объекты в линии
system("inkscape -T $destSVG -A $destPDF");
// Делаем экспорт в PNG, указывая разрешение 300 dpi
//system("inkscape $destSVG --export-png=$destPNG -d 300");
$row++;
}
fclose($handle);
}
?>
Создаём командный скрипт в операционной системе для запуска скрипта-парсера в нужном окружении ОС
Если настройки окружения ОС позволяют запускать подготовленный скрипт командой
php5 svg2pdf.php
...то дополнительный командный скрипт не нужен. Однако, например в случае с Windows, где в командной строке по умолчанию до сих пор (Windows 7) используется досовская кодовая страница 866 потребуется следующий скрипт.
echo Меняем кодировку командной строки Windows на UTF-8 chcp 65001 echo Добавляем путь к Inkscape set path=%path%;C:\Program Files\Inkscape php5.exe svg2pdf.php pause
Подстановка данных встроенными средствами Inkscape
В будущем, возможно, в Inkscape появится собственное средство для работы с базами данных и переменными. И даже уже сейчас можно значительно облегчить подобную задачу с подстановкой данных, если написать соответствующее расширение. По сути нужно будет просто переложить приведённый в этой статье PHP скрипт на язык Питон и оформить его в виде расширения. Благо такая возможность есть и хорошо документирована. Нужны только добровольцы. Надеюсь эта статья вдохновит кого-нибудь! :-)