LibreOffice-DELPHI-Lazarus-OpenOffice

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение pi1 » 19.02.2018 12:20:17

Ниже самый простой пример работы с Word (ms office 2007)

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
MSWord,wdDoc,range1,wdTable: Variant;
begin
try
MsWord := CreateOleObject('Word.Application');
MsWord.Visible := True;
except
Exception.Create('Error');
end;
wdDoc:=MSWord.Documents.Add;
{ Работаем через объект Selection = текущее выделение. Точнее текущая точка в строке, так как не выполняли
метод Select, которым задается участок
}
//слева на право
MSWord.Selection.ParagraphFormat.Alignment :=0;
// межстрочный 3 пт
MsWord.selection.ParagraphFormat.LineSpacing:=MsWord.LinesToPoints(3.0);
//шрифт не жирный
MSWord.Selection.Font.Bold := false;
//размер шрифта
MSWord.Selection.Font.Size := 12;
//выводим в данную точку текст
MSWord.Selection.TypeText('Text'+#13#10);
//#13#10- перешли на новую строку и меняем в новом текущем выделении (в точке) шрифт на жирный
MSWord.Selection.Font.Bold := true;
//и положение точки по средине страницы
MSWord.Selection.ParagraphFormat.Alignment :=1;
//задаем, что после нашего selection будет межстрочный интервал 1.0 пт
MsWord.selection.ParagraphFormat.LineSpacing:=MsWord.LinesToPoints(1.0);
//выводим следующую строчку в наш выбранный диапазон (в нашу точку)
MSWord.Selection.TypeText('BOLD'+#13#10);
//#13#10- перешли на новую строку и меняем в новом текущем выделении (в точке) шрифт на НЕ жирный
// и порядок вывода справа на лево
MSWord.Selection.ParagraphFormat.Alignment :=2;
//после текста пробел в 1.0 пт
MsWord.selection.ParagraphFormat.LineSpacing:=MsWord.LinesToPoints(1.0);
MSWord.Selection.Font.Bold := false;
MSWord.Selection.TypeText('NOT BOLD');
//добавим таблицу  в конец текста
range1:=MSWord.ActiveDocument.Characters.Last;
//шрифт
range1.Font.Bold:= False;
range1.Font.Size:= 12;
wdTable:=MSWord.ActiveDocument.Tables.Add(range1,2,3);
//ширина колонок
wdTable.columns.Item(1).PreferredWidth:=80;
wdTable.columns.item(2).PreferredWidth:=60;
wdTable.columns.item(3).PreferredWidth:=60;
//толщина линий
wdTable.Borders.InsideLineStyle := 1;
wdTable.Borders.OutsideLineStyle := 1;   
Аватара пользователя
pi1
новенький
 
Сообщения: 59
Зарегистрирован: 19.04.2012 18:11:24
Откуда: г.Зеленокумск

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение pupsik » 19.02.2018 19:33:29

Вот не пойму почему, но у меня через TfrHtmExport из Lazreport выводится ну очень безобразная страничка. Вот и пришлось изучать другие технологии :)
Если вас не устраивает вывод в html и вы не можете исправить. Почему бы не подготовить пример не верного формирования и выложить сюда? Или компонент всё не правильно формирует. И файл получается не валидным?
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение pi1 » 19.02.2018 21:13:23

Планирую создать отдельную тему с разборкой причин и следствий некорректного вывода в htm в Lazreporte . Но это потом. А пока замечание по выводу в Word. Текст сначала присваивается переменной widestring, с конвертацией в текущую кодировку из кодировки lazarusa- utf8, и только потом корректно отображается в Word. Вот пример присвоения ячейке таблицы-
Код: Выделить всё
str:=utf8decode('Наименование');
wdTable.Cell(1,2).Range.Text :=str;
. То же самое с выводом из полей StringGrid или из SQLQuery. Сначала в переменную, а потом только в Word. В Delphi попроще, там не utf8.

Добавлено спустя 23 часа 44 минуты 30 секунд:
При работе с закладками в LibreOffice выяснил, что народ может довести своим "копи-пясте" до истерики. Доступ к закладке предлагается такой
Код: Выделить всё
  Bookmark:=BookmarksSupplier.getByName(BookmarksName).getAnchor;
  Bookmark.setString(MyText);
Причем если не найдется, то получите exception. И это предлагается на полном серьезе. У меня в цикле этих исключений будет пол сотни, я бы предпочел иметь список закладок и его перебирать, а такого примера не мог найти в инете течение 3 часов. И только один ресурс оказался более толковым- https://www.winsoft.sk/libre.htm Рекомендую.

Добавлено спустя 57 минут 18 секунд:
А вот и код рожденный по подсказке этого ресурса
Код: Выделить всё
   BookmarksSupplier:=Document.getBookmarks
   ElementNames := BookmarksSupplier.getElementNames;
   for k:=0 to Document.Bookmarks.count-1 do
   begin
   str:='my_'+ElementNames[k];
   Bookmark:=BookmarksSupplier.getByName(ElementNames[k]).getAnchor;
  Bookmark.setString(str);
   end;     

То есть мы получаем массив имен закладок и уже работаем с элементом массива и никаких exception :) Код выводит в местах закладок имя закладки с префиксом my_ .

Добавлено спустя 5 минут 31 секунду:
К сведению, поиск в инете (ради интереса) по "BookmarksSupplier.getElementNames" не дал нормальной консультации (типа статьи какого нить гуру).
Аватара пользователя
pi1
новенький
 
Сообщения: 59
Зарегистрирован: 19.04.2012 18:11:24
Откуда: г.Зеленокумск

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение pupsik » 20.02.2018 23:05:25

pi1 и куды ссыль то? Ценники таки там махонькие.

И всё ради Кома? Ах да: пардон, ОЛЕ. :)

Или вы уже до "моста" дошли? "Мост" - не издевка, а способ работы с... хм... либре/опен офисом. Вроде как мульти платформено.

п.с.
Если уж решили выложить свой "поход в дебри" то не кусками.... Так полезнее будет другим.
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение Sharfik » 22.02.2018 01:29:53

Код: Выделить всё
MsWord := CreateOleObject('Word.Application');
MsWord.Visible := True;

OLE приятная вещь, в том плане что можно из под VBA накидать код, посмотреть как он работает, и перенести на Pascal. Но очень, очень ненадежная.
Особенно когда у пользователя лайтовая версия программы, где нет поддержки OLE, или вобще нет программы. Или как это у Word происходит, после заполнения первых 300х(к примеру) строк программа падает, потому что ворд вывел сообщение о том что заколебаля проверять орфографию и отключает ее, и делай вывод снова.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 759
Зарегистрирован: 20.07.2013 01:04:30

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение SSerge » 23.02.2018 07:07:17

Sharfik писал(а):OLE приятная вещь


Она в десятки раз работает медленнее других способов, и это сразу заметно, например уже при генерации таблиц excel строк по 50.

...мне любопытно, почему никто из коллег даже не пытается воспользоваться нативным интерфейсом LibreOffice (я имею в виду инструментарий (или методику), который предполагает LibreOffice SDK)?
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение pi1 » 28.02.2018 16:08:20

Ниже вывод калькуляции в Writer (LibreOffice)
Код: Выделить всё
var
  ServiceManager, Desktop : Variant;
  CoreReflection, PropertyValue, VA: Variant;
  Document: Variant;
  Table, TableCell : Variant;
  obj, objText, objCursor : Variant;
  w,n : integer;
  Cols,range : Variant;
  str,fname1,faddresse1,finn,ffullname:widestring;
  i,j:integer;
  sum,s,sql_str:string;
  sumzatr:currency;
begin
  if VarIsEmpty(ServiceManager) then
    try
      ServiceManager := CreateOleObject('com.sun.star.ServiceManager');
    except
      Raise Exception.Create('Couldn''t get ServiceManager');
      Exit;
    end;
  sql_firm.Close;
  sql_firm.sql.Text:='select * from tfirm where fshortname='''+ed_firm.Text+'''';
  sql_firm.open;
  fname1:=ed_firm.Text;
  faddresse1:=trim(sql_firmfaddress.Value);
  finn:='ИНН '+trim(sql_firmfinn.Value);
  ffullname:= trim(sql_firmffullname.Value);
  sql_firm.Close;
  CoreReflection := ServiceManager.createInstance('com.sun.star.reflection.CoreReflection');
  CoreReflection.forName('com.sun.star.beans.PropertyValue').createObject(PropertyValue);
  VA := VarArrayCreate([0, 0], varVariant);
  VA[0] := PropertyValue;

  Desktop := ServiceManager.createInstance('com.sun.star.frame.Desktop');
  Document := Desktop.LoadComponentFromURL( 'private:factory/swriter','_blank', 0,  VA);
  if (VarIsNull(Document) or VarIsEmpty(Document)) then
     begin
       Raise Exception.Create('Couldn''t create document');
       Exit;
     end;
    //доступ к тексту документа
  objText := Document.getText;
// доступ к курсору документа
objCursor := objText.createTextCursor;
//для курсора задаем шрифт
  objCursor.setPropertyValue('CharHeight',12); //size
  objCursor.setPropertyValue('CharWeight',150);//bold
  //для курсора задаем положение текста на странице
  objCursor.setPropertyValue('ParaAdjust',2);  //left
  //переводим кодировку utf8 в текущую на ПК
  str:=utf8decode(fname1+', '+ffullname);
  //выводим текст
    objText.insertString(objCursor, str, false);
    //вносим разделитель - перенос строки не привязанный к размеру шрифта
   objText.insertControlCharacter(objCursor, 0, false );
  str:=utf8decode(faddresse1);
objText.insertString(objCursor, str, false);
objText.insertControlCharacter(objCursor, 0, false );

str:=utf8decode(finn);
objText.insertString(objCursor, str, false);
objText.insertControlCharacter(objCursor, 0, false );//разделитель

    //Заголовок документа
  objCursor.setPropertyValue('CharHeight',22); //size
  objCursor.setPropertyValue('CharWeight',150);//bold
  objCursor.setPropertyValue('ParaAdjust',3);  //center
  str:=utf8decode('Калькуляция на изделие : ');
  objText.insertString(objCursor, str, false);
  objText.insertControlCharacter(objCursor, 0, false );//разделитель
  objCursor.setPropertyValue('CharHeight',16); //size
  str:=utf8decode(trim(sql_nomFDESCR.Value));
  objText.insertString(objCursor, str, false);
  objText.insertControlCharacter(objCursor, 0, false );//разделитель
  objText.insertControlCharacter(objCursor, 0, false );//разделитель
  str:=utf8decode('Комплектация (изделия и материалы)');
  objText.insertString(objCursor, str, false);
  objText.insertControlCharacter(objCursor, 0, false ); //PARA_BREAK

  //создаем таблицу

  Table := Document.createInstance( 'com.sun.star.text.TextTable' );
  sql_str:='select * from tcalc where fdescr='''+'material'+''' and fud<>1 and ftovar='+sql_nomfid.asstring;
  sql_calc1.close;
  sql_calc1.SQL.Text:=sql_str;
  sql_calc1.open;
  sql_calc1.last;
    n:=sql_calc1.RecordCount;
    //задаем количество ячеек
  Table.initialize(n+1, 3);  //row, column
  //горизонтальная ореинтация
  Table.HoriOrient := 0;
//  поле слева
  Table.LeftMargin := 20; // 2* 1/100 mm;
  //  поле справа
  Table.RightMargin := 20;
  //доступ к тексту таблицы
  Document.getText.insertTextContent( objCursor, Table, false );
  //доступ к массиву вертикальных линий внутри таблицы
  obj := Table.TableColumnSeparators;
   //ширина первой колонки (поз. от начала таблы верт. разд. линии)
    obj[0].Position :=8000;//zatr
   // ширина второй колонки
  obj[1].Position := obj[0].Position+900;//kol
//передаем данные массива вертикальных линий в таблицу
  Table.TableColumnSeparators := obj;
  //заголовоки колонок таблицы (доступ возможен по имени или по индексу, по имени с 1, по индексу с 0)
   str:=utf8decode('Наименование затрат');
  TableCell := Table.getCellByName('A1');
  TableCell.setString(str);
   str:=utf8decode('Кол-во');
  TableCell := Table.getCellByname('B1');
   TableCell.setString(str);
    str:=utf8decode('Сумма');
  TableCell := Table.getCellByname('C1');
   TableCell.setString(str);
  //конец шапки
     //выделяем участок таблицы центруем текст в ячейках по горизонтали
  str:='B1:C'+inttostr(n+1);
   range := table.getCellRangeByname(str);
  range.setPropertyValue('ParaAdjust',3);  //center
     sumzatr:=0;
       sql_calc1.First;
       //заполняем материалы
  for i:=1 to sql_calc1.RecordCount do begin
    for j:=0 to 2 do begin
    //доступ к ячейке по индексу (i=0 - шапка)
  TableCell := Table.getCellByPosition(j, i);
if j=0 then begin
str:=utf8decode(trim(sql_calc1Fzatr.Value));  TableCell.setString(str);
end;
if j=1 then begin
str:=utf8decode(trim(sql_calc1Fkolvo.AsString)); TableCell.setString(str);
end;
if j=2 then begin
str:=utf8decode(sql_calc1Fsumzatr.AsString); TableCell.setString(str);
end;
      end;
    sumzatr:=sumzatr+ sql_calc1Fsumzatr.value;
  sql_calc1.Next;
end;
   //конец таблицы  1
   //отделяем заголовок второй таблицы(ниже) от первой таблицы
  objText.insertControlCharacter(objCursor, 0, false );//разделитель
  objCursor.setPropertyValue('CharHeight',16); //size
  objCursor.setPropertyValue('CharWeight',150);//bold
  objCursor.setPropertyValue('ParaAdjust',3);  //center
  //заголовок второй таблицы
  str:=utf8decode('Прочие затраты (зарплата и т.п.)');
  objText.insertString(objCursor, str, false);
  objText.insertControlCharacter(objCursor, 0, false ); //PARA_BREAK
   objCursor.setPropertyValue('CharHeight',12); //size
  objCursor.setPropertyValue('CharWeight',150);//bold
  objCursor.setPropertyValue('ParaAdjust',2);  //center
  Table := Document.createInstance( 'com.sun.star.text.TextTable' );
  sql_str:='select * from tcalc where fdescr='''+'rabota'+''' and fud<>1 and ftovar='+sql_nomfid.asstring;
  sql_calc1.close;
  sql_calc1.SQL.Text:=sql_str;
  sql_calc1.open;
  sql_calc1.last;
    n:=sql_calc1.RecordCount;
  Table.initialize(n+1, 2);  //row, column
  Table.HoriOrient := 0;
  Table.LeftMargin := 20; // 2* 1/100 mm;
  Table.RightMargin := 20;
   Document.getText.insertTextContent( objCursor, Table, false );
   obj := Table.TableColumnSeparators;
   obj[0].Position :=8000;//zatr
   Table.TableColumnSeparators := obj;
   str:=utf8decode('Наименование затрат');
  TableCell := Table.getCellByName('A1');
  TableCell.setString(str);
   str:=utf8decode('Сумма');
  TableCell := Table.getCellByname('B1');
   TableCell.setString(str);
   //конец шапки
  //центрируем текст в ячейках второго столбца
     str:='B1:B'+inttostr(n+1);
   range := table.getCellRangeByname(str);
  range.setPropertyValue('ParaAdjust',3);  //center
       sql_calc1.First;
       //заполняем
  for i:=1 to sql_calc1.RecordCount do begin
    for j:=0 to 1 do begin
  TableCell := Table.getCellByPosition(j, i);
if j=0 then begin  str:=utf8decode(trim(sql_calc1Fzatr.Value));TableCell.setString(str);end;
if j=1 then begin  str:=utf8decode(sql_calc1Fsumzatr.AsString);; TableCell.setString(str);end;
      end;
    sumzatr:=sumzatr+ sql_calc1Fsumzatr.value;
  sql_calc1.Next;
end;
   //конец таблицы
  //отделяем текст (ниже) от таблиц
   objText.insertControlCharacter(objCursor, 0, false ); //PARA_BREAK
  objText.insertControlCharacter(objCursor, 1, false ); //LINE_BREAK
  objText.insertControlCharacter(objCursor, 0, false ); //PARA_BREAK
  //Параметры текста
   objCursor.setPropertyValue('CharHeight',12); //size
   objCursor.setPropertyValue('CharWeight',150);//bold
   objCursor.setPropertyValue('ParaAdjust',2);  //left
    s:= currtostr(sql_nomfcenar.value);
    f_sborka.Sum_Propisyu(s,Sum) ;
  sum:=trim(sum);
  str:= utf8decode('Итого затрат : '+ currtostr(sumzatr)+' руб.'+#13#10);
   objText.insertString(objCursor, str, false);
   str:= utf8decode('С учетом накладных расходов: '+ sql_nomfcenar.AsString+' руб. /'+sum+'/'+#13#10+'Менеджер  ');
    objText.insertString(objCursor, str, false);
  end;
Аватара пользователя
pi1
новенький
 
Сообщения: 59
Зарегистрирован: 19.04.2012 18:11:24
Откуда: г.Зеленокумск

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение LearnMagic » 28.02.2018 23:58:32

Возможно поможет uOpenOffice и обсуждение
Как правильно писали выше, OLE хорош для небольших отчётов. При формировании отчёта листов на 400-500 (например расчётные листки) будут серьёзные проблемы
LearnMagic
новенький
 
Сообщения: 66
Зарегистрирован: 10.11.2016 23:13:38

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение sign » 01.03.2018 07:38:12

Попросили версию OpenOffice, адаптированную под Лазарус.
Прикладываю то, что сам адаптировал и пользую.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Re: LibreOffice-DELPHI-Lazarus-OpenOffice

Сообщение ZuluSpirit » 17.07.2019 22:14:51

sign писал(а):Попросили версию OpenOffice, адаптированную под Лазарус.
Прикладываю то, что сам адаптировал и пользую.

Спасибо за адаптацию, но не никак не могу заставить выполнять нужную задачу.

Задача состоит в том, что бы создать документ на основании подготовленного шаблона, заменить подготовленные в нем метки и сохранить в формате doc или pdf.
Вот код, который работал в Делфи с оригинальным uOpenOffice, но не хочет работать в Лазарусе.
Код: Выделить всё
uses
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, uOpenOffice;
// ...
procedure TfOOTest.btnStartClick(Sender : TObject);
var
  OOWriter : TOOWriter;
  fPath : String;
begin
  OOWriter := TOOWriter.Create;

  OOWriter.Connect := True;

  if not OOWriter.Connect then
  begin
    ShowMessage('Error connect');
    Exit;
  end;

  fPath := ExtractFilePath(Application.ExeName);

  OOWriter.OpenDocument(fPath + 'Test.ott',
                       [oomHidden, oomAsTemplate, oomReadOnly],
                        ommNever);
  // Старт
  //OOWriter.Visible := True;

  OOWriter.ReplaceAll('[@Contract]', 'фывапролджэ', [orpWholeWords]);

  //OOWriter.SaveDocument(fPath + 'Result.doc', 'Word97');
  OOWriter.ExportToPDF(fPath + 'Result.pdf');

  // Финиш
  OOWriter.Connect := False;

  OOWriter.Free;
end; 

Когда программа доходит до строки OOWriter.ReplaceAll() или даже OOWriter.ExportToPDF(даже без ReplaceAll) - получаю ошибку Project * raised exception class 'External: ?'.
Если между //Старт и //Финиш оставить только OOWriter.Visible := True; тогда откроется Writer с новым документом на основании шаблона.
Помогите, пожалуйста, исправить! Где копать? В какую сторону смотреть?
ZuluSpirit
незнакомец
 
Сообщения: 1
Зарегистрирован: 05.11.2018 19:55:16

Пред.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 28

Рейтинг@Mail.ru