Не так давно появилась задача создать простой сервис по созданию PDF отчетов на основе офисных документов для интранета. И вроде бы все просто, но вот с сохранением Excel в PDF возникли проблемы. Интересно? Прошу под кат.
Как я и сказал, поначалу все казалось легко, у меня были собственные наработки, на хабре была статья. Но обо всем по порядку.
Мои наработки использовали сom объекты excel.application и метод saveAs, это прекрасно работало, пока требовалось взять обычный, красивый документ и сделать из него pdf, но в данном случае файлы были нет так просты.
Во-первых, документы предполагаются трех форматов — xls, xlsx и xml. Во вторых все документы содержат макросы, а некоторые ссылки на другие документы. В третьих они содержат кучу листов, и перекрестные ссылки между листами. Не нужные для отчета листы делаются скрытыми, а на самих листах в каше вспомогательных цифр отчетная информация выделялась областью печати. Нужно ли говорить, что saveAs игнорирует все это богатство и на выходе после танца с бубнами получаем абсолютно не читаемую картину.
Здесь я думаю необходимо сделать лирическое отступление и пояснить, почему с файлами творится такая неразбериха. Я работаю в очень крупной организации, бок обок с кучей бабушке пенсионного возраста. Они не могут даже сделать текст в ячейке жирным, но прекрасно могут говорить начальству о том, что они не «программисты» и не должны это уметь. Начальства у нас тоже много, и в силу жалости к бабушкам или своей компьютерной безграмотности, а быть может, по велению звезд жалобы бабушек поощряются, и все попытки разгрести бардак в документах пресекается.
Вернемся к нашим баранам. В выше упомянутой статье был предложен вариант конвертации «Как вижу» с использованием open office, этот вариант меня не устроил в силу ветреного отношения OO к MS. Некоторые документы действительно открывались в нем корректно, но чаще всего содержимое ехало еще до конвертации.
Был еще третий вариант. Печатать документы на виртуальный принтер, но я решил, что этот вариант я приберегу на самый крайний случай, так это костыль.
И тогда я обратился к гуглу и он дал мне эту замечательную ссылку. Описанный в ней метод ExportAsFixedFormat был тем, что нужно! Но меня опять постигла не удача.
Он начисто игнорировал области печати, а без них получалась каша. Я гуглил, оставлял вопросы на множестве форумах, в том числе и на англоязычных. Ответа не было. Я даже перенес код статьи в C#, но результат не изменился.
После недели изысканий, я решил плюнуть на все и использовать тот самый крайний вариант с виртуальным принтером, но каково же было мое изумление, когда и он проигнорировал область печати, притом, что если отправить документ из самого Excel все было нормально.
Путем проб и ошибок, танцев с бубнами и увлекательным чтением гугла я выяснил, области печати игнорируется при вызове этого метода и печати в php, C#, но почему то при использовании VBScript все работает как надо. Чем это вызвано я, к сожалению, так и не выяснил.
И так, было решено из PHP открывать VBS скрип и уже из него преобразовывать excel в pdf. Да, это тоже костыль, но не такой неуклюжий как виртуальный принтер.
Вот получившийся скрипт:
Он довольно прост, принимает на входе два аргумента, первый путь к файлу, Excel второй путь и имя создаваемой PDF.
Вызывается из любого ЯП, например PHP:
В сухом остатке мы имеем не совсем красивый, но 100% рабочий метод по преобразованию Excel в PDF, который гарантирует результат «Как на печати» без подводных камней.
P.S.: Хабр, то место где из комментариев к статье ты узнаешь больше чем из статьи, так что буду рад если мне укажут более простой путь.
P.P.S.: Ошибки при письме мой крест, я проверил данный текст спелчекером огнелиса и ворда, но сомневаюсь, что помогло. Не ругайте сильно, лучше пишите в личку, все поправлю.
Как я и сказал, поначалу все казалось легко, у меня были собственные наработки, на хабре была статья. Но обо всем по порядку.
Мои наработки использовали сom объекты excel.application и метод saveAs, это прекрасно работало, пока требовалось взять обычный, красивый документ и сделать из него pdf, но в данном случае файлы были нет так просты.
Во-первых, документы предполагаются трех форматов — xls, xlsx и xml. Во вторых все документы содержат макросы, а некоторые ссылки на другие документы. В третьих они содержат кучу листов, и перекрестные ссылки между листами. Не нужные для отчета листы делаются скрытыми, а на самих листах в каше вспомогательных цифр отчетная информация выделялась областью печати. Нужно ли говорить, что saveAs игнорирует все это богатство и на выходе после танца с бубнами получаем абсолютно не читаемую картину.
Здесь я думаю необходимо сделать лирическое отступление и пояснить, почему с файлами творится такая неразбериха. Я работаю в очень крупной организации, бок обок с кучей бабушке пенсионного возраста. Они не могут даже сделать текст в ячейке жирным, но прекрасно могут говорить начальству о том, что они не «программисты» и не должны это уметь. Начальства у нас тоже много, и в силу жалости к бабушкам или своей компьютерной безграмотности, а быть может, по велению звезд жалобы бабушек поощряются, и все попытки разгрести бардак в документах пресекается.
Вернемся к нашим баранам. В выше упомянутой статье был предложен вариант конвертации «Как вижу» с использованием open office, этот вариант меня не устроил в силу ветреного отношения OO к MS. Некоторые документы действительно открывались в нем корректно, но чаще всего содержимое ехало еще до конвертации.
Был еще третий вариант. Печатать документы на виртуальный принтер, но я решил, что этот вариант я приберегу на самый крайний случай, так это костыль.
И тогда я обратился к гуглу и он дал мне эту замечательную ссылку. Описанный в ней метод ExportAsFixedFormat был тем, что нужно! Но меня опять постигла не удача.
Он начисто игнорировал области печати, а без них получалась каша. Я гуглил, оставлял вопросы на множестве форумах, в том числе и на англоязычных. Ответа не было. Я даже перенес код статьи в C#, но результат не изменился.
После недели изысканий, я решил плюнуть на все и использовать тот самый крайний вариант с виртуальным принтером, но каково же было мое изумление, когда и он проигнорировал область печати, притом, что если отправить документ из самого Excel все было нормально.
Путем проб и ошибок, танцев с бубнами и увлекательным чтением гугла я выяснил, области печати игнорируется при вызове этого метода и печати в php, C#, но почему то при использовании VBScript все работает как надо. Чем это вызвано я, к сожалению, так и не выяснил.
И так, было решено из PHP открывать VBS скрип и уже из него преобразовывать excel в pdf. Да, это тоже костыль, но не такой неуклюжий как виртуальный принтер.
Вот получившийся скрипт:
Dim XL
Dim XLWkbk
Dim ObjArgs
Dim paramSourceBookPath
Dim paramExportFilePath
set objargs = wscript.arguments
if objArgs.count <= 1 then
wscript.echo «invalid passed arguments»
wscript.quit
end if
Set XL = CreateObject(«excel.application»)
XL.Visible = false
paramSourceBookPath=objargs(0)
paramExportFilePath=objargs(1)
Set XLWkbk = XL.Workbooks.Open(paramSourceBookPath,False)
XLWkbk.ExportAsFixedFormat 0,paramExportFilePath,1,false,false
XLWkbk.Close False
XL.Quit
Set XLWkbk = Nothing
Set XL = Nothing
set ObjArgs = nothing
Он довольно прост, принимает на входе два аргумента, первый путь к файлу, Excel второй путь и имя создаваемой PDF.
Вызывается из любого ЯП, например PHP:
exec(APPLICATION_SCRIPT_FOLDER.'\\excel.vbs C:\\tmp\\test.xlsx C:\\tmp\\test.pdf");
В сухом остатке мы имеем не совсем красивый, но 100% рабочий метод по преобразованию Excel в PDF, который гарантирует результат «Как на печати» без подводных камней.
P.S.: Хабр, то место где из комментариев к статье ты узнаешь больше чем из статьи, так что буду рад если мне укажут более простой путь.
P.P.S.: Ошибки при письме мой крест, я проверил данный текст спелчекером огнелиса и ворда, но сомневаюсь, что помогло. Не ругайте сильно, лучше пишите в личку, все поправлю.