Как я уже отмечал в блоге, есть планы прейти на программирование в Lazarus. Учитывая, что уже сейчас решается вопрос о том, чтобы перевести все машины на работе под управление Linux с нового года, можно начинать чесать репу и думать каким макаром перегнать большой программный комплекс для экологов поту же Ubuntu. Самая острая проблема — документы. Как ни крути, а отчёт созданный в том же Excel или Word, выглядит намного более привлекательно, чем простой текстовик. Посмотрим, что можно предпринять в случае работы под Linux не потерять презентабельность документов.
В принципе вариантов не так уж и много.
Первый вариант — генерировать простой html-файл. Достоинство этого подхода очевидно — простота при разработке программ. Если учесть, что Lazarus вполне хорошо справляется с DOM, то есть возможность не только выдавать документ на печать, но и, в случае необходимости, проводить его анализ.
Недостаток подобного подхода — достаточно трудно сформировать удобочитаемый документ, если в нем встречается большое количество формул, диаграмм и т.д.
Второй вариант — использовать возможности OpenOffice. На данный момент этот вариант мне больше всего нравится. Что сразу бросилось в глаза при изучении документации по OO — это то, что в документе математические формулы хранятся точно также как и простой текст. То есть сразу появляется куча возможностей по формированию сложных по составу и содержанию отчётов и документов.
Помниться, когда только начинал разрабатывать первую версию программы, не мог понять как работать из Delphi с MathType (надстройка в office для рисования формул). В итоге, так и не поняв как это делается писал все формулы в строку простым текстом — корявенько и топорно, но читаемо. С OpenOffice + Lazarus все по другому — можно расписывать хоть 10-ти этажные дроби.
Дополнительным стимулом к использованию форматов OpenOffice послужило также то, что в этом случае можно создать 100% кросплатформенный проект и уже не заморачиваться над тем, какую ОС задумают поставить админы на машинах в следующем году — OpenOffice без проблем работает везде.
Посмотрим, что из себя в принципе представляет документ OpenOffice, например, возьмем файл Writer’а *.odt (аналог Word).
1. Формат Open Document
Собственно, для тех, кто имеет хотя бы общие представления об устройстве XML-файла, не составит особого труда разобраться и с форматом Open Document.
Дело в том, что любой документ из OpenOffice (текстовый, таблица, презентация, формула) представляет собой простой zip-архив внутри которого содержаться XML-файлы, каждый из которых содержит какую-либо информацию о документе.
Более того, само содержание и расположение файлов в архиве чертовски напоминает мне сайты на narod.ru :). Вот, например, содержимое файа *.odt в котором содержится всего одна строка по центру страницы — «hello world»
Тут, наверное, разберется даже ребенок, что основное содержимое документа располагается в файле content.xml. Посмотрим, как выглядит наша строка Hello world». Открываем файл в браузере и видим:
Всё те же знакомые узлы XML и не менее знакомые атрибуты типа center и пр.
Получается следующее. Если необходимо создавать документы по какому-либо шаблону (что мне наиболее часто и приходится делать), то достаточно накидать шаблон документа и распакавать его в какую-либо папку, затем уже в своей программе открыть нужный xml-файл, изменить и запокавать обратно в zip-архив, но с расширением файла Open Document. И никаких тебе OLE и т.д. и т.п. Организуется всё элементарно и без каких-либо сторонних компонентов.
Если же Вам требуется разрабатывать документы какого-нибудь уникального содержания, то тут Вам, как ни крути, придётся с головой окунуться в документацию по Open Document Format.
Итак, первый шаг к разработке кроссплатформенного проекта сделан — определились с форматами документов и в общих чертах представляем себе алгоритм работы.
Остается решить вопрос с тем, как паковать документ? Использоать dll, какой-либо компонент или обойтись тем, что есть в Lazarus?
2. Работа с архивами в Lazarus
Лично я сторонник того подхода к разработке любых программ, при котором по возможности не используются какие-либо сторонние компоненты — только «родные» компоненты и модули.
Это обстоятельство избавляет как минимум от одного геморроя — не надо за собой везде тягать тучу сторонних компонентов, чтобы проект без проблем открывался на любом компьютере.
Так и в случае работы с архивами в Lazarus — никто нам не запрещает воспользоваться компонентами, например с этой страницы Wiki Lazarus. Но зачем накручивать лишние компоненты, когда для работы с zip-архивами в составе Lazarus есть вполне понятная и простая в использовании утилита ZIP?
Воспользуемся ей, а заодно посмотрим, как можно обойтись в работе со сторонними приложениями без всяких ShellExecute, ShellAPI и пр.
Итак, пишем свой первый кроссплатформенный архиватор, который потом будем использовать для сборки документов OpenOffice.
Открываем Lazarus, создаем новые проект и, для наглядности работы программы, укладываем на форму две кнопки и Memo.
Самый простой вариант работы с утилитами наподобие zip и unzip — это использовать в Win32 пакетные файлы DOS (*.bat), а в Linuх — bash-скрипты. Смысл работы прост как три копейки:
1. В зависимости от того в какой ОС запущена программа, создаем либо файл скрипта с расширением sh, либо bat-файл
2. Выполняем скрипт, который пакует необходимые файлы в документ.
Разрабатываем скрипт.
Думаю, что тем, кто знаком с Linux, написать скрипт для упаковки папки в архив потребуется на всё пара минут, а то и меньше. Текст скрипта выглядит следующим образом:
#!/bin/bash cd /путь/до/папки/с_файлами zip -r Документ.расширение *
Обращу Ваше внимание, что переход в папку с докуменами необходим, т.к. если просто указать утилите zip расположение файлов, то в итоге в архив будет записан весь путь до файлов и документ просто не распознается как Open Document.
В случае с bat-файлов всё также просто и понятно:
CD Полныйпутьдопапки Полныйпутьк_утилитеzip -r Document.расширение Полныйпутьдопапки
Оба файла работают абсолютно идентично — пакуют всю папку, содержащую xml-файлы документа в один архив.
Со вспомогательной частью покончено. Переходим в Lazarus.
Первое, что необходимо — это написать обработчик одной из кнопок для создания необходимого нам файла в зависимости от ОСи. У меня получился следующий код:
procedure TForm1.Button2Click(Sender: TObject);
var F: TextFile;
begin
AssignFile(F, ExtractFilePath(Application.ExeName)+'mybash.sh');
Rewrite(F);
{$IFDEF LINUX}
WriteLn(F, '#!/bin/bash');
WriteLn(F, 'cd '+ExtractFilePath(Application.ExeName)+'document');
WriteLn(F, 'zip -r doc.odt *');
CloseFile(F);
Memo1.Lines.LoadFromFile(ExtractFilePath(Application.ExeName)+'mybash.sh');
{$ENDIF}
{$IFDEF WIN32}
WriteLn(F, 'CD '+ExtractFilePath(Application.ExeName)+'document');
WriteLn(F, ExtractFilePath(Application.ExeName)+'zip -r doc.odt '+
ExtractFilePath(Application.ExeName)+'document');
CloseFile(F);
Memo1.Lines.LoadFromFile(ExtractFilePath(Application.ExeName)+'mybash.bat');
{$ENDIF}
end;
Обратите внимание, что для того, чтобы узнать под какой ОС мы запустили программу, нам не требуется изгаляться и писать лишние процедуры и функции — достаточно использовать простенькие директивы «{$IFDEF}» и «{$ENDIF}».
В представленном обработчике в зависимости от операционной системы в которой запущено приложение создается свой файл для упаковки папки с xml-файлами документа и содержимое файла выводится в Memo.
Теперь посмотрим, как под Lazarus’ом можно запускать сторонние приложения.
Запуск скриптов и bat-файлов из своей программы.
Для того, чтобы запустить любую программу или выполнить скрипт в своем приложении и при этом не нарушить кроссплатформенность, в Lazarus предусмотрено использование класса TProcess или, кому удобнее использовать компоненты, сразу три невизуальных компонента TProcess* cо вкладки System:
Укладываем на форму самы простой из трех компонентов — TProcess и в обработчике второй кнопки пишем:
procedure TForm1.Button1Click(Sender: TObject);
begin
{$IFDEF LINUX}
Process1.CommandLine:='/bin/bash '+ExtractFilePath(Application.ExeName)+'mybash.sh';
{$ENDIF}
{$IFDEF WIN32}
Process1.CommandLine:='cmd '+ExtractFilePath(Application.ExeName)+'mybash.bat';
{$ENDIF}
Process1.Options:=[poWaitOnExit];
Process1.Execute;
end;
Здесь опять же, как мне кажется, особых сложностей нету — в зависимости от операционной сисемы запускаем на выполнение нужный файлик и ожидаем окончания выполнения. Аналогичным образом можно запускать абсолютно любые программы и приложения, отслеживать вывод консольных программ и т.д. и т.п. Чтобы лишний раз не повторяться и копипастить чужой текст — я просто скажу, что более подробно с работай компонента TProcess Вы всегда можете ознакомиться в Wiki Lazarus.
Вот теперь у нас в руках есть всё необходимое для работы с документами в любой операционной системе. Главное, не забудтся перенести утилиту zip.exe, входящую в сосав Lazarus к себе в проект.
Какие выводы можно сделать? Во-первых, работа с документами в Lazarus и OpenOffice, лично для меня оказалась намного проще, чем я ожидал. Всё, что требуется — разработать грамотный шаблон и потом немного поработать с XML. Во-вторых, использование утилиты zip избавляет нас от использования сторонних компонентов (не дай бог езё и платных). В-третьих, разработка кроссплатформенного приложения для работы с документами оказалась опять же не сложнее, чем под чисто под Win32 — достаточно не забывать про элементарные директивы компилятора. Так что, если Вас вдруг постинет та же проблема, что и меня — переход под другую ОС, то можете сильно не переживать — организовать документоооборот будет не сложнее, а даже в некотором смысле проще, чем для Win32 с использованием Microsoft Office.



Спасибо, в целом интересно, но немного не точен следующий момент. Ваша цитата:
===========
Обратите внимание, что для того, чтобы узнать под какой ОС мы запустили программу, нам не требуется изгаляться и писать лишние процедуры и функции – достаточно использовать простенькие директивы “{$IFDEF}” и “{$ENDIF}”.
===========
Насколько я понимаю, лучше написать «чтобы узнать под какой ОС мы КОМПИЛИРУЕМ программу». Иначе возникнет ощущение, что скомпилированная программа будет работать в обеих операционках
Да, полностью согласен, именно, чтобы узнать по какой ОС компилируем программу.
Автору большое спасибо за статью! Очень интересная информация а главное полезная ! Интересно было узнать что *.odt обычный zip архив. Да и Lazarus с каждым выходом хорошеет
docx тоже зип
Если директория до скрипта содержит пробелы, то необходимо:
Process1.CommandLine:=’/bin/bash «/home/user/Lazarus projects/zumas backuper/zumas scripts/save»‘;
Как видно .sh к скрипту приписывать нет надобности.
Автору огромная благодарность за проделанную работу и статью.
После изучения все стало просто и понятно, что и как устроено.
Попробовал скрипт запустить в WIN32. Не пашет, потому как нужно вот так писать:
[code]
Process1.CommandLine := 'cmd /c "' + ExtractFilePath(Application.ExeName) + 'mybatORmycmd.cmd)' + '"';
[/code]
PS: Аффтар, пробуй код перед публикацией.
Вообще-то проверяю. И конкретно этот код работает в Linux
прим: скобка лишняя ‘mybatORmycmd.cmd:)’
Народ сделал как в примере ничего не понял, прошу не издеваться а более конкретно рассказать
У меня не прокатывает ни:
Process1.CommandLine := 'cmd /c "' +......., ниProcess1.CommandLine := 'cmd ".... ни
Process1.CommandLine := 'file.bat'
Lazarus пишет "ошибка 123" или что-то другое. Все, что начинается с CMD запускает пустое окно DOS.Решил написать на паскале для ДОС программку, которая тупо запускает батник. Теперь из Lazarus запускается эта программка иfile.bat корректно обрабатывается
=))))))
[…] о том, что и где располагается в документе OpenOffice в этом посте. Теперь разберемся с содержимым документа […]
[…] необходимо при запуске в определенной ОС, то тут, как я уже упоминал, следует использовать директивы компилятора {$IFDEF …} […]