Автоматическое создание серии файлов 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 скрипт на язык Питон и оформить его в виде расширения. Благо такая возможность есть и хорошо документирована. Нужны только добровольцы. Надеюсь эта статья вдохновит кого-нибудь! :-)