Создание 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-файлы (таблицы и графики) + кэшированные изображения графиков. Генерация отчетов происходит по следующей схеме:

  1. Сделать unzip .xlsx или .ods файла
  2. «Объединить» все распакованные текстовые файлы в один, используя специальный формат, например, {[разделитель][полное-имя-файла][разделитель][данные]}
  3. В полученном файле произвести замену шаблонных строк на реальные данные. Сделать это можно скриптом из восьми строк кода. Смотри #3 в моей записи Интересные примеры на Perl
  4. Разъединяем файлы
  5. Упаковываем обратно

Тут важно не забыть удалить кэшированные изображения графиков, иначе они не перерисуются. Еще есть маленькое неудобство — либо приходится править XML-файлы руками (можно этот вариант сразу отбросить), либо использовать в качестве шаблонных строк цифры. Другими словами, мы не можем в шаблоне прописать строку, а на ее место подставить число, поскольку имеет место контроль типов. Если нам просто нужно вывести какие-то цифры, можно вывести их и в виде строк. Но если мы пользуемся формулами или строим графики, придется придумывать специальные коды. У меня, к примеру, код 0102003004 означает «лист № 01», «таблица № 02», «X: 003», «Y: 004».

4. Вердикт

Подведем итоги. Для генерации простых отчетов более чем подходит модуль SpreadSheet::WriteExcel. Если же мы имеем дело с чуть более сложными отчетами или есть шанс, что в будущем наши отчеты усложнятся, лучше не тратить свое время на SpreadSheet::WriteExcel и использовать XLSX/ODS-шаблоны, безо всяких модулей.

Дополнение: Помните, что ковыряние формата XLSX является обратной инженерией (то есть крякигом) и нарушает то ли авторские права, то ли патенты, то ли пользовательское соглашение (все время путаю эти три понятия…) с Microsoft. Не изучайте его самостоятельно, просто используйте описанную мною схему. Сам я тоже никакой обратной инженерией не занимался, рецепт был найден в Google. Понятное дело, что история и все персонажи в этом посте вымышлены.

Дополнение: Работа с Excel-файлами в Scala

Метки: .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.