Создание Excel-отчетов средствами Perl
4 декабря 2009
Эту статью пару дней назад я отправил на Хабр. Сегодня пришел ответ:
Увы, твой топик в «Песочнице» http://habrahabr.ru/sandbox/ не был одобрен НЛО и не попал в общую ленту. Попробуй опубликовать что-то другое.
С уважением, Хабрахабр
Не знаю, чем им не понравилась статья, может вы мне объясните? Кстати, если у кого-то имеется инвайт, я был бы очень благодарен. Итак, далее — моя статья.
1. Введение
Perl в моей работе — незаменимое средство. Как аналитику, мне приходится обрабатывать большие объемы данных и генерировать отчеты в различных форматах, в зависимости от того, для кого этот отчет предназначен.
С большинством форматов проблем не возникает. В случае с html пишем шаблон и подставляем данные в нужные места. В случае с pdf — все аналогично, только шаблон должен быть в LaTeX. Долгое время я искал оптимальное решение для генерации отчетов в виде электронных таблиц. Кажется, мне удалось его найти, и об этом мне хотелось бы рассказать.
2. Старое решение
Первое время я пользовался модулем SpreadSheet::WriteExcel. Хочу сказать, что если ваша задача — генерация простых таблиц (заданным размером N x M, безо всяких графиков), то этот модуль вполне может решить все ваши проблемы. Правда, он позволяет работать только с одиночными ячейками, потому для простой генерации таблиц вам придется написать несколько небольших функций типа ВывестиЗаголовок(), ВывестиДанные(), ВывестиПодвал() или другие, в зависимости от ваших задач. Модуль прекрасно документирован.
Недостатка у него два. Во-первых, как я уже отметил, он позволяет работать только с одиночными ячейками. Если вам требуется в большом объеме генерировать какие-нибудь бухгалтерские бланки или вроде того, этот модуль вам не подходит. Разве что у вас имеется непреодолимое желание придумать язык описания этих самых бланков.
Во-вторых, модуль не позволяет генерировать графики. Вместо этот приходится строить их в Excel или OpenOffice, экспортировать с помощью прилагающейся к модулю программы chartex, затем прописывать импорт графика в коде своего скрипта. В моем случае работать по такой схеме оказалось невозможно — отчеты меняются чуть ли не каждую неделю, а генерация занимает несколько часов. Зачастую графики в созданном отчете отобразятся совсем не так, как вы планировали (важен порядок, в котором вы их аттачите и многое другое), а тестировать скрипты было просто нереально.
3. Новое решение
Сейчас я полностью отказался от SpreadSheet::WriteExcel и пользуюсь шаблонами .XLSX (формат Microsoft Office 2007) и .ODS (формат OpenOffice). Оба формата представляют собой ни что иное, как zip-архив, в котором хранятся XML-файлы (таблицы и графики) + кэшированные изображения графиков. Генерация отчетов происходит по следующей схеме:
- Сделать unzip .xlsx или .ods файла
- «Объединить» все распакованные текстовые файлы в один, используя специальный формат, например, {[разделитель][полное-имя-файла][разделитель][данные]}
- В полученном файле произвести замену шаблонных строк на реальные данные. Сделать это можно скриптом из восьми строк кода. Смотри #3 в моей записи Интересные примеры на Perl
- Разъединяем файлы
- Упаковываем обратно
Тут важно не забыть удалить кэшированные изображения графиков, иначе они не перерисуются. Еще есть маленькое неудобство — либо приходится править XML-файлы руками (можно этот вариант сразу отбросить), либо использовать в качестве шаблонных строк цифры. Другими словами, мы не можем в шаблоне прописать строку, а на ее место подставить число, поскольку имеет место контроль типов. Если нам просто нужно вывести какие-то цифры, можно вывести их и в виде строк. Но если мы пользуемся формулами или строим графики, придется придумывать специальные коды. У меня, к примеру, код 0102003004 означает «лист № 01», «таблица № 02», «X: 003», «Y: 004».
4. Вердикт
Подведем итоги. Для генерации простых отчетов более чем подходит модуль SpreadSheet::WriteExcel. Если же мы имеем дело с чуть более сложными отчетами или есть шанс, что в будущем наши отчеты усложнятся, лучше не тратить свое время на SpreadSheet::WriteExcel и использовать XLSX/ODS-шаблоны, безо всяких модулей.
Дополнение: Помните, что ковыряние формата XLSX является обратной инженерией (то есть крякигом) и нарушает то ли авторские права, то ли патенты, то ли пользовательское соглашение (все время путаю эти три понятия…) с Microsoft. Не изучайте его самостоятельно, просто используйте описанную мною схему. Сам я тоже никакой обратной инженерией не занимался, рецепт был найден в Google. Понятное дело, что история и все персонажи в этом посте вымышлены.
Дополнение: Работа с Excel-файлами в Scala
Метки: Perl.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.