Работа с word на lazarus

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

При разработке одной небольшой программки в 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

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

Решение

Если есть желание изучить глубоко и на долго, то поищите книгу Корняков В.Н. «Программирование документов приложений 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



Супер-модератор

Эксперт Pascal/DelphiАвтор FAQ

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, да особо показывать нечего)

Delphi
1
2
3
var w : Variant;  
  NewDocument(w,true);   
 AddText('Тест вывода в Ворд из Delphi',w);



0



volvo

Супер-модератор

Эксперт Pascal/DelphiАвтор FAQ

32518 / 20999 / 8120

Регистрация: 22.10.2011

Сообщений: 36,265

Записей в блоге: 7

12.03.2016, 22:28

6

Что такое «AddText»? Это что, из этого вышеприкрепленного компонента? Так при вот такой сигнатуре:

Pascal
1
procedure AddText(s : ShortString; var wrd : Variant);StdCall;

оно будет работать в зависимости от фазы Луны. Я ж говорю, если нужна надежная работа — только через WideString, именно для этого этот тип и придумывался.



0



31 / 31 / 3

Регистрация: 25.05.2014

Сообщений: 1,117

12.03.2016, 22:31

 [ТС]

7

Volvo, да.
P.S. что с киберфорумом? Форма быстрого ответа изчезла. Нажимаю на Ваш ник, а он не вставляется в форму.



0



danek130995

31 / 31 / 3

Регистрация: 25.05.2014

Сообщений: 1,117

14.03.2016, 13:18

 [ТС]

8

Скажите пожалуйста, а как вставить картинку? Я пробовал использовать это:

Delphi
1
 w.Selection.InlineShapes.AddPicture(FileName:=dir+'screen.bmp', LinkToFile:=False, SaveWithDocument:=True);

но ошибка SYSGV в Lazarus.
В функциях из прикрепленной библиотеки нет функций для вставки картинки.

Добавлено через 2 минуты
volvo, а как использовать этот WideString?



0



Супер-модератор

Эксперт Pascal/DelphiАвтор FAQ

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

Цитата
Сообщение от danek130995
Посмотреть сообщение

Вместо русских букв кракозябры.

А какая версия FPC у тебя? Случайно не 3.0.0?



1



danek130995

31 / 31 / 3

Регистрация: 25.05.2014

Сообщений: 1,117

14.03.2016, 14:02

 [ТС]

11

Hikari, последняя.
да уже заработало, использую:

Delphi
1
2
3
var s:UnicodeString
 s := UTF8Decode('ОТЧЕТ');
  AddText(wideString(s), w);

Добавлено через 23 минуты
shyub, можно ли вставить картинку с помощью этой библиотеки?



0



Хитрая блондиночка $)

1470 / 985 / 399

Регистрация: 21.12.2015

Сообщений: 3,785

14.03.2016, 15:10

12

Цитата
Сообщение от danek130995
Посмотреть сообщение

Hikari, последняя.

О! Я тоже заметила, что в трешке упор посильнее на юникод сделали. Сама попалась недавно на кодировке, пришлось добавлять обратную совместимость исходникам директивами.

Цитата
Сообщение от danek130995
Посмотреть сообщение

s := UTF8Decode(‘ОТЧЕТ’);

Кстати там уже есть TEncoding. Можно и его использовать.

P.S. А еще, раз уж ты в исходнике пишешь кириллицей, то можешь попробовать просто перекодировать исходник в нужную кодировку. В настройках редактора можно выбрать.



1



danek130995

31 / 31 / 3

Регистрация: 25.05.2014

Сообщений: 1,117

28.03.2016, 14:09

 [ТС]

13

Вот код для вставки картинки в Lazarus, может кому пригодится:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
procedure pasteimage(var w:Variant);
var
Bit : TBitmap;
dir:string;
begin
   Bit := TBitmap.Create;
    Bit.Width := Form1.ClientWidth;
    Bit.Height := Form1.ClientHeight;
    Bit.Canvas.CopyRect(Rect(0, 0, Form1.ClientWidth, Form1.ClientHeight), Form1.Canvas, Rect(0, 0, Form1.ClientWidth, Form1.ClientHeight));
    dir:=GetCurrentDir;
    Clipboard.Assign(Bit);
    w.selection.paste;
end;

Добавлено через 1 час 5 минут
не забудьте в uses прописать ClipBrd



0



Windows logo - 2012.svg







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.

excel123.png

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. Напишем простое приложение которое покажет сообщение о том что все работает и завершит свою работу. Для этого нам потребуется:

Для начало нужно запустить нашего Леопарда

8

В пункте Caption, меняем заголовок нашей формы на: «Hello Word»

1

Добавляем на форму кнопку. Для этого жмем на кнопку во вкладке Standart, далее на форму(в том месте где хотим чтобы она появилась). Размеры формы, а так же всех компонентов мы можем менять мышкой.

2

Выбираем нашу кнопку в Инспекторе объектов, и так же меняем ее заголовок в Caption на «Старт»

3

Дважды на форме жмем на кнопку, и нас перекидываем в редактор кода.

4

Вводим следующий код:

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('Наше приложение работает!');  //Показываем сообщение
Application.Terminate;                     //Выходим из приложения
end;

5

Жмем F9 или на кнопку компиляции кода

6

Код нашего приложения проверяется на ошибки, далее запускается. Если все прошло удачно, то мы увидим окно:

7

Нажимает на Старт.

8

При нажатии на ОК, наше приложение должно закрыться.

Ну вот и все, вы написали свое первое приложение. Далее я расскажу вам как это сделать для WinCE.

Понравилась статья? Поделить с друзьями:

А вот еще интересные статьи:

  • Работа с word заполнение заявления
  • Работа с word выравнивание
  • Работа с word в linux
  • Работа с word pascal
  • Работа с word ios

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии