уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
При разработке одной небольшой программки в Lazarus, которая выводит результаты работы в документ MS Word столкнулся с несколькими “особенностями” создания документов и работы с Word в принципе. Как в итоге оказалось, “особенность” оказалась багом, который, судя по багрекеру, до сих пор не исправлен и, видимо, исправится ещё не скоро.
Но, так как ждать времени не было, то пришлось искать обходные пути решения проблемы. Об этих путях и поговорим сегодня.
Во-первых, что касается открытия документа MS Word. Что может быть проще вот такого кода:
var FReportObject: olevariant; begin FReportObject := CreateOleObject(cWordApplication);//создали объект FReportObject.Documents.Open(FileName := TemplatePath);//открыли документ end;
Однако тут Вас может ожидать целых две неожиданности:
1. Ошибка при открытии документа, т.е. результата мы не достигнем
2. Ошибка будет выведена в виде большого количества символов «?», т.е. в непонятной кодировке.
Как решить эти проблемы:
1. Указываем параметр FileName так:
FReportObject.Documents.Open(FileName := WideString(TemplatePath));//открыли документ
2. Для трансляции всех ошибок при работе с объектом используем функцию преобразования кодировки:
Теперь документ откроется, а в случае возникновения ошибки она будет написана по-русски :).
Двигаемся дальше. Следующая “особенность” – FPC не отличает параметры при вызове функции. Например, вы хотите использовать в работе объект Range документа, который, скажем, содержит весь текст документа. Как бы мы поступили для получения этого объекта? Самый простой способ – это вызвать:
var Range: OLEVariant; begin Range:=FReportObject.ActiveDocument.Range(FReportObject.ActiveDocument.Range.Start,FReportObject.ActiveDocument.Range.End-1); end;
Попробовав скомпилировать такой код я получил сообщение от fpc: Fatal: Syntax error, «identifier» expected but «END» found то есть, компилятор заругался на свойство END объект Range. Как поступить в этом случае? Я решал эту проблемку применительно к своей задаче, т.е. мне требовалось переместиться в конец документа и вставить там таблицу, делал я это ак:
myRange := FReportObject.ActiveDocument.Content; myRange.Collapse(Direction := wdCollapseEnd);
Теперь myRange можно использовать в параметрах функции добавления новой таблицы в документ:
Table := FReportObject.ActiveDocument.Tables.Add(MyRange, NumRows:=10, NumColumns:=4);
И теперь, самое интересной. Если Вы вставите в документ какойлибо текст не на латинице, скажем «Привет», то получите в документе непонятные кракозябры. При этом приведение строки к WideString не поможет, а использование UnicodeString вызовет ошибку на этапе компиляции: Error: Type is not automatable: «UnicodeString» Эта «особенность» отмечена в багтрекере FPC. Одним из вариантов решения этой проблемы является использование DLL-ки в которой определены функции вставки/замены текста в документах MS Word. DLL содержит всего две функции:
procedure WriteText(Range: olevariant; Text: variant); stdcall; function FindAndReplace(WordApp: olevariant; const Find, Replace: WideString): boolean;stdcall;
WriteText принимает объект Range документа и текст, который необходимо вставить в документ. FindAndReplace принимает объект MSWord, а также две строки — для поиска и замены. Пример использования библиотеки:
procedure WriteText(Range: olevariant; Text: variant); stdcall; external 'wordreports.dll'; function FindAndReplace(WordApp: olevariant; const Find, Replace: WideString): boolean; stdcall; external 'wordreports.dll'; implementation ..... procedure AyProc; var myRange: OLEVariant; begin MyRange := FReportObject.ActiveDocument.Content; myRange.Collapse(Direction := wdCollapseEnd); WriteText(MyRange, #10#13+rsTable1Preamble+#10#13);//записали строку WriteText(MyRange, 123);//записали число WriteText(MyRange, true);//записали строку "true" FindAndReplace(FReportObject,'true','false');//заменили true на false end;
Скачать библиотеку можно здесь: [download id=»71″ format=»1″]
Вот с такими моментами мы можем пока столкнуться при работе с документами MS Word в FPC и Lazarus. Да не удобно использовать DLL ради того, чтобы записать строчку текста в документ, не радует глаз ошибки в кодировках и т.д., но, видимо, это и есть та плата за бесплатный Lazarus. За всё приходится платить либо деньгами, либо временем :).
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
|
31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
|
|
1 |
|
|
29.02.2016, 13:59. Показов 8893. Ответов 12
Преподаватель поставил задачу:создание отчета в MS Word из программы в Lazarus. Должен запускаться Word, в нем печататься текст, выводиться в таблицу инфа из StringGrid. И все это визуально должно наблюдаться! Если честно, такое задание поставило меня в шок. Это вообще реально? Если да, то как все это можно реализовать или где можно об этом почитать? Я пытался гуглить, но что-то ничего стоящего не нашел. Помогите пожалуйста.
0 |
|
382 / 181 / 47 Регистрация: 11.07.2013 Сообщений: 984 |
|
|
29.02.2016, 14:49 |
2 |
|
РешениеЕсли есть желание изучить глубоко и на долго, то поищите книгу Корняков В.Н. «Программирование документов приложений MS Office в Delphi», если «сделать и забыть», то воспользуйтесь этим компонентом: MS Word-XP и Lazarus.rar
1 |
|
31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
|
|
12.03.2016, 22:12 [ТС] |
3 |
|
shyub, в Lazarus если делать, то в ворде что-то с кодировкой. Вместо русских букв кракозябры. Скажите пожалуйста, как исправить?
0 |
|
Супер-модератор 32518 / 20999 / 8120 Регистрация: 22.10.2011 Сообщений: 36,265 Записей в блоге: 7 |
|
|
12.03.2016, 22:16 |
4 |
|
Вся работа с Word-ом/Excel-ем должна осуществляться через WideString, а не через простой String. Показывай код, который вызывает озвученную проблему.
0 |
|
danek130995 31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
||||
|
12.03.2016, 22:20 [ТС] |
5 |
|||
|
volvo, да особо показывать нечего)
0 |
|
volvo Супер-модератор 32518 / 20999 / 8120 Регистрация: 22.10.2011 Сообщений: 36,265 Записей в блоге: 7 |
||||
|
12.03.2016, 22:28 |
6 |
|||
|
Что такое «AddText»? Это что, из этого вышеприкрепленного компонента? Так при вот такой сигнатуре:
оно будет работать в зависимости от фазы Луны. Я ж говорю, если нужна надежная работа — только через WideString, именно для этого этот тип и придумывался.
0 |
|
31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
|
|
12.03.2016, 22:31 [ТС] |
7 |
|
Volvo, да.
0 |
|
danek130995 31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
||||
|
14.03.2016, 13:18 [ТС] |
8 |
|||
|
Скажите пожалуйста, а как вставить картинку? Я пробовал использовать это:
но ошибка SYSGV в Lazarus. Добавлено через 2 минуты
0 |
|
Супер-модератор 32518 / 20999 / 8120 Регистрация: 22.10.2011 Сообщений: 36,265 Записей в блоге: 7 |
|
|
14.03.2016, 13:29 |
9 |
|
1 |
|
Хитрая блондиночка $) 1470 / 985 / 399 Регистрация: 21.12.2015 Сообщений: 3,785 |
|
|
14.03.2016, 13:33 |
10 |
|
Вместо русских букв кракозябры. А какая версия FPC у тебя? Случайно не 3.0.0?
1 |
|
danek130995 31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
||||
|
14.03.2016, 14:02 [ТС] |
11 |
|||
|
Hikari, последняя.
Добавлено через 23 минуты
0 |
|
Хитрая блондиночка $) 1470 / 985 / 399 Регистрация: 21.12.2015 Сообщений: 3,785 |
|
|
14.03.2016, 15:10 |
12 |
|
Hikari, последняя. О! Я тоже заметила, что в трешке упор посильнее на юникод сделали. Сама попалась недавно на кодировке, пришлось добавлять обратную совместимость исходникам директивами.
s := UTF8Decode(‘ОТЧЕТ’); Кстати там уже есть TEncoding. Можно и его использовать. P.S. А еще, раз уж ты в исходнике пишешь кириллицей, то можешь попробовать просто перекодировать исходник в нужную кодировку. В настройках редактора можно выбрать.
1 |
|
danek130995 31 / 31 / 3 Регистрация: 25.05.2014 Сообщений: 1,117 |
||||
|
28.03.2016, 14:09 [ТС] |
13 |
|||
|
Вот код для вставки картинки в Lazarus, может кому пригодится:
Добавлено через 1 час 5 минут
0 |
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
italiano (it) │
русский (ru) │
中文(中国大陆) (zh_CN) │
The ability to interact with Office software and generate spreadsheets, text documents and presentations from code can be invaluable in the office, and save a lot of time otherwise spent on repetitive tasks.
One example of this is the creation of applications that can read files in an arbitrary format and output an Excel file, a task that can be done much more efficiently with code than manually.
Using the OpenOffice UNO Bridge
OpenOffice has language bindings for C++, Java, JavaScript and Python. On Windows, OpenOffice can also be manipulated in Pascal via COM Automation (see below), but there is currently no easy way of using OpenOffice’s UNO (Universal Network Objects) from Pascal on OS X and Linux. If you’re interested in developing an OO «bridge» for Pascal, please refer to these links for more information (caution: these links are quite techie in true Sun fashion):
api.openoffice.org
About Bridges
Using COM Automation to interact with OpenOffice and Microsoft Office
Automation is unique to Windows so the following two examples won’t work on OS X or Linux. For those platforms, please refer to Making do without Windows COM Automation. If you only need to create and/or view a word processing document from your program, take a look at the XDev Toolkit.
OpenOffice/LibreOffice on Windows
Here’s a simple example of how to open a document with your program using the OpenOffice Automation server. Note that this works only on Windows.
program TestOO; {$IFDEF FPC} {$MODE Delphi} {$ELSE} {$APPTYPE CONSOLE} {$ENDIF} uses SysUtils, Variants, ComObj; const ServerName = 'com.sun.star.ServiceManager'; var Server : Variant; Desktop : Variant; LoadParams : Variant; Document : Variant; TextCursor : Variant; begin if Assigned(InitProc) then TProcedure(InitProc); try Server := CreateOleObject(ServerName); except WriteLn('Unable to start OO.'); Exit; end; Desktop := Server.CreateInstance('com.sun.star.frame.Desktop'); LoadParams := VarArrayCreate([0, -1], varVariant); {Create new document} Document := Desktop.LoadComponentFromURL('private:factory/swriter', '_blank', 0, LoadParams); {or Open existing} //you must use forward slashes, not backward! //Document := Desktop.LoadComponentFromURL('file:///C:/my/path/mydoc.doc', '_blank', 0, LoadParams); TextCursor := Document.Text.CreateTextCursor; {Insert existing document} //Substitute your path and doc TextCursor.InsertDocumentFromURL('file:///C:/my/path/mydoc.doc', LoadParams); end.
More comprehensive examples can found here:
- OLECreateTextDoc: Create and populate a text document with paragraph, table and frame
- OLEEditTextDoc: Load an existing text document, search with regular expression, replace text and add rows to a table
Office on Windows
Here’s a simple example of how to open a document with your program using the Word Automation server. Note that this example works only on Windows. This will work with both delphi and fpc.
program TestMsOffice; {$IFDEF FPC} {$MODE Delphi} {$ELSE} {$APPTYPE CONSOLE} {$ENDIF} uses SysUtils, Variants, ComObj; const ServerName = 'Word.Application'; var Server : Variant; w:widestring; begin if Assigned(InitProc) then TProcedure(InitProc); try Server := CreateOleObject(ServerName); except WriteLn('Unable to start Word.'); Exit; end; {Open existing document} //Substitute your path and doc w:= UTF8Decode('c:mypathmydoc.doc'); Server.Documents.Open(w); //OLE uses BSTR (http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069(v=vs.85).aspx). Only widestring is compatible with BSTR in FPC, so conversion is needed for nonlatin chars. Server.Visible := True; {Make Word visible} end.
Here is a sample code how to work in an open Word document, using the Word Automation server.
var Server: Variant; begin try Server := GetActiveOleObject('Word.Application'); except try ShowMessage('Word not already open create a Word Object'); // If no instance of Word is running, try to Create a new Word Object Server := CreateOleObject('Word.Application'); except ShowMessage('Cannot start Word/Word not installed ?'); Exit; end; end; end;
Limitations:
Since End is a reserved word in FPC it shall be used as a parameter after the & sign.
Server.ActiveDocument.Application.Selection.start:=Server.ActiveDocument.Application.Selection.&end+1;
A lot of examples for Excel are available on the German wiki page ExcelAutomation/de.
Using the fpXMLXSDExport unit
FPC 2.6 and newer contain the fpXMLXSDExport unit, part of the FCL-DB export components. With that, you can export datasets to various XML formats, including a Microsoft Access-compatible format and a Microsoft Excel-compatible format.
The Access format can output XML with or without an embedded XSD data/table definition. Note that exporting binary/BLOB type data needs additional action at the Access import end, as Access does not support proper binary fields, only OLE fields.
In the Excel format, multiline text fields are not supported at the moment: the line ends are removed during the export.
Lazarus provides a visual component for this: after installing the lazdbexport package, you will see the TXMLXSDExporter component on the Data Export tab
See fpXMLXSDExport for details.
Using the FPSpreadsheet Library
Another way to automate repetitive work with spreadsheets is to use the FPSpreadsheet library. It can read and write spreadsheets in several formats and it doesn’t require having any external application installed on the machine.
The advantages are that fpspreadsheet is 100% Object Pascal code, and it requires no external libraries or programs.
Writing an Excel file using ADO
please write me.
Reading/Writing an Excel file using OLE
This method needs Excel to be installed on the user’s machine because it uses OLE to access it.
Keep in mind that this method starts Excel in the background, which opens the file and works with it like a real user.
- Create a new form with button, stringgrid and edit.
- Create a new Excel file and fill a few cells.

Example — Open/Read Excel file:
uses ..... comobj; procedure TForm1.Button1Click(Sender: TObject); Var XLApp: OLEVariant; x,y: byte; path: variant; begin XLApp := CreateOleObject('Excel.Application'); // requires comobj in uses try XLApp.Visible := False; // Hide Excel XLApp.DisplayAlerts := False; path := edit1.Text; XLApp.Workbooks.Open(Path); // Open the Workbook for x := 1 to 4 do begin for y := 1 to 6 do begin SG.Cells[x,y] := XLApp.Cells[y,x].Value; // fill stringgrid with values end; end; finally XLApp.Quit; XLAPP := Unassigned; end;
If you want to make some changes and you want them to write back into the Excel, file you can use:
XLApp.Cells[x,y].Value := SG.Cells[y,x];
If you want to save:
XLApp.ActiveWorkBook.Save;
Read/Writing an Excel file using the SpreadSheet Interface Component
The component provides a library interface, abstracting the Excel COM and the Calc Open Office UNO interfaces.
The component is available here:
http://tcoq.free.fr/composants.html (Link verified in May 2016)
Since Automation is not yet available, but COM is available, the Excel interface component provides a set of Lazarus classes encapsulating calls to the Excel COM interface (the one below the Automation). It hides most of the drudgery of working with low-level code.
Be careful, this is a work-in-progress. Use it at your own risk.
Functionality:
- creating and loading excel workbooks,
- saving workbooks,
- creating and accessing sheets,
- getting values and setting values (and formulas) in cells,
- getting and changing color of cells,
- getting and changing column height and row width,
- creating comments,
- creating shapes,
- creating charts.
Inits first.
IMPLEMENTATION USES ExcelUtilities, SpreadSheetInterfaces ; VAR aCell : IRange ; aValue : OleVariant ; // Not sure about this, but it works. ie( Edit.Text := STRING(aValue); ) ExcelApp : TExcelApplication ; ExcelWbs : IWorkBooks ; ExcelBook : IWorkBook ; ExcelSheet : ISheet ; ExcelSheets : ISheets ;
Getting a sheet is simple:
// Initializing the common excel workbook: ExcelApp := TExcelApplication.Create(nil) ; ExcelApp.Active := True ; ExcelApp.Visible := True ; ExcelWbs := ExcelApp.WorkBooks ; ExcelBook := ExcelWbs.Add ; ExcelSheets := ExcelBook.Sheets ; ExcelSheet := ExcelSheets.Sheet(1) ;
Playing around with cells is simple too:
// adding a value aCell := ExcelSheet.Cells(1, 1) ; aCell.Value := 10; // adding a formula aCell := ExcelSheet.Cells(2,1) ; aCell.Formula := '=A1+10' ; // getting the value computed in Excel aValue := aCell.Value ;
The test case provided has many more examples.
Copy HTML to the clipboard
You can copy HTML to the clipboard which is understood by many applications. This way you can copy formatted text. For those applications that only understand text put plain text too.
Microsoft Office applications require HTML to be pasted onto the clipboard in a more complex format than described here. See here for an example that works with Microsoft Office.
uses ClipBrd; ... // register the mime type for text/html. You can do this once at program start: ClipbrdFmtHTML:=RegisterClipboardFormat('text/html'); ... // Clear any previous formats off the clipboard before starting Clipboard.Clear; // put text and html on the clipboard. Other applications will choose the best format automatically. ThePlainUTF8Text:='Simple text'; Clipboard.AsText:=ThePlainUTF8Text; AsHTML:='<b>Formatted</b> text'; // text with formattings Clipboard.AddFormat(ClipbrdFmtHTML,AsHTML[1],length(AsHTML));
See also
- Clipboard
- Powerpoint Automation
External links
- Excel file format — description on OpenOffice website
.LOG Динамическая библиотека для автоматизации создания отчётов в M$ Word XP/2003 в Delphi/Lazarus Для использования необходимо в проект подключить модуль uworddll.pas (в Lazarus также необходимо подключить модуль Variants). Документация по использованию функций см. исходники модуля uworddll.pas и тестовый проект "+" - добалено новую функцию "*" - внесено изменения "!" - исправлено ошибку "-" - удалено ненужную более функцию 09.07.2007 + Портировано модуль из Delphi в динамическую библиотеку, которую можно использовать с другими средствами разработки 14.03.2008 * Комментарии в исходниках переведены на русский язык + Создано отдельный файл справки по использованию функций 01.05.2008 + Добавлено 2 функции: SetWordVisible,CheckWordVersion * Описание функций теперь использует stdcall, что позволяет использовать библиотеку с другими языками программирования 27.05.2008 + Добавлено 4 функции: SaveDocAs,CloseDoc,CloseWord,PrintDialogWord 20.06.2008 + Добавлено функцию CreateTableEx (см. описание в документации) ! Исправлено ошибку компиляции с помощью Delphi новее 3 версии 20.10.2008 ! Исправлено вызовы CoInitialize и CoUninitialize 27.10.2008 + Добавлено несколько функций для автоматизации M$ Excell (см. документацию) 13:00 12.12.2011 * Переименовано библиотеку в msofficedll.dll в связи с расширением функциональности + Добавлено новые функции для работы с M$ Excell (см. документацию) 10:41 14.12.2011 * Исправлено документацию 12:56 14.12.2011 + Добавлено несколько функций для работы с M$ Outlook (пока не тестировались), за что отдельное спасибо EmeraldMan 11:15 16.12.2011 + Добавлено функцию установки формата ячейки (см. документацию) 13:56 19.12.2011 * Попробовал на основе ДЛЛ-ки создать модуль для FPC (в последней версии FCL более-менее реализовано работу с COM/OLE, большинство функций работает нормально.
В данной статье я расскажу вам как создать свое первое приложение в среде Lazarus. Напишем простое приложение которое покажет сообщение о том что все работает и завершит свою работу. Для этого нам потребуется:
Для начало нужно запустить нашего Леопарда
В пункте Caption, меняем заголовок нашей формы на: «Hello Word»
Добавляем на форму кнопку. Для этого жмем на кнопку во вкладке Standart, далее на форму(в том месте где хотим чтобы она появилась). Размеры формы, а так же всех компонентов мы можем менять мышкой.
Выбираем нашу кнопку в Инспекторе объектов, и так же меняем ее заголовок в Caption на «Старт»
Дважды на форме жмем на кнопку, и нас перекидываем в редактор кода.
Вводим следующий код:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('Наше приложение работает!'); //Показываем сообщение
Application.Terminate; //Выходим из приложения
end;
Жмем F9 или на кнопку компиляции кода
Код нашего приложения проверяется на ошибки, далее запускается. Если все прошло удачно, то мы увидим окно:
Нажимает на Старт.
При нажатии на ОК, наше приложение должно закрыться.
Ну вот и все, вы написали свое первое приложение. Далее я расскажу вам как это сделать для WinCE.

Сообщение было отмечено danek130995 как решение










