OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

Delphi: Interact with text docs from OpenOffice or MS-Word

 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets
View previous topic :: View next topic  
Author Message
bitfarmer
General User
General User


Joined: 06 May 2004
Posts: 39
Location: Murcia, Spain

PostPosted: Tue Oct 20, 2009 1:33 am    Post subject: Delphi: Interact with text docs from OpenOffice or MS-Word Reply with quote

In the same way some time I posted a code to manage spread sheet in a dual way (you don't care if your user has excel or OpenOffice at all), I also build a similar unit to manage text docs from delphi usign OOo Writer or MS Word transparently.

This unit is not so complete as spread sheet is, many features are not implemented, just the ones I needed, like search&replace, load/save docs., print it and that's all.

One special note: If you throh 100 search&replace to Word and then ask it to save/print, it can take 30 seconds to make the changes and the it saves/print, BUT word is not yet finished, so the print will be done too early... discastig, eh?

The only work around I found is to wait until the winword.exe process was iddle, tricky but work. I added a WaitForIddle function that makes that, but uses a set of processes functions pasted at the end of this post.

Well, I hope it is of some use to someone!

Code:

// *********************************************
// ** Object for dual WordProcessing managing **
// ** using Word or OpenOffice automaticaly   **
// ** By: Sergio Hernandez                    **
// ** oficina(at)hcsoft.net, CopyLeft 2004    **
// ** Version 0.3 20-10-2009 (DDMMYYYY)       **
// ** Use it freely, change it, etc.          **
// *********************************************

{EXAMPLE OF USE
  //Create object: We have two flavours:
  //(A) from an existing file...
  TxtDoc:= TDocumentoTexto.create(OpenDialog.FileName, false);
  //(B) from a blank document...
  TxtDoc:= TDocumentoTexto.create(thcOpenOffice, true); //OpenOffice doc if possible, please
  TxtDoc.FileName:= 'C:\MyNewDoc'; //Needs a file name before you SaveDoc!
  //--end of creation.
  //Change a text (search&replace)
  TxtDoc.ChangeOneValue('<MyClient>', 'Cocoa company, ltd.');
  //Preview print...
  TxtDoc.ShowPrintPreview
  TxtDoc.PrintDoc;
  TxtDoc.SaveDoc;
  TxtDoc.SaveToPDF(C:\MyPDF.pdf);
  TxtDoc.Free;
}

{ABOUT CONVERTING DOC TO PDF:
  //Force opening the .doc file with OOo like this:
  TxtDoc:= TDocumentoTexto.create(thcOpenOffice, true);
  TxtDoc.LoadDoc('C:\MyWord.doc');
  //Now that OOo has imported the .doc, convert it:
  TxtDoc.SaveToPDF('C:\MyPDF.pdf');
  TxtDoc.Free;
}

{HISTORIY:
V0.3 - SaveToPDF for OpenOffice added from www.oooforum.org/forum/viewtopic.phtml?t=22344
V0.2 - WaitForIddle added to avoid Word behavior (saving before completing work)
V0.1 - Initial version, it works ok.
}

{TODO LIST:
  -Can I know the OOo writer printing status like in Word?
  -Can I know if Word/Writer is doing something in background?
}

unit UDocumentoTexto;

interface

uses Variants, SysUtils, ComObj, Classes, Launch;

//thcError: Tried to open but both failes
//thcNone:  Haven't tried still to open
type TTipoDoc = (thcError, thcNone, thcWord, thcOpenOffice);

type TDocumentoTexto = class(TObject)
private
  fVisible:  boolean;
  //Program loaded stuff...
  procedure  LoadProg;
  procedure  CloseProg;
  function   GetProgLoaded: boolean;
  procedure  NewDoc;
  procedure  LoadDoc;
  procedure  CloseDoc;
  function   GetDocLoaded: boolean;
  function   GetIsWord: boolean;
  function   GetIsOpenOffice: boolean;
  procedure  SetVisible(v: boolean);
  //OpenOffice only stuff...
  function   FileName2URL(FileName: string): string;
  procedure  ooDispatch(ooCommand: string; ooParams: variant);
  function   ooCreateValue(ooName: string; ooData: variant): variant;
  function   isNullEmpty(thisVariant: Variant): Boolean;
public
  Tipo: TTipoDoc;         //Witch program was used to manage the doc?
  FileName:    string;    //In windows FileName format C:\MyDoc.XXX
  Programa:    variant;   //Word or OpenOfice instance created.
  DeskTop:     variant;   //OpenOffice desktop reference (not used now).
  Document:    variant;   //Document opened.
  //Object internals...
  constructor  Create(Name: string; MakeVisible: boolean); overload;
  constructor  Create(MyTipo: TTipoDoc; MakeVisible: boolean); overload;
  destructor   Destroy; override;
  //Program loaded stuff...
  function     SaveDoc: boolean;
  function     SaveToPDF(FileName: string): boolean;
  function     PrintDoc: boolean;
  procedure    ShowPrintPreview;
  property     ProgLoaded: boolean     read GetProgLoaded;
  property     DocLoaded:  boolean     read GetDocLoaded;
  property     IsWord: boolean         read GetIsWord;
  property     IsOpenOffice: boolean   read GetIsOpenOffice;
  property     Visible: boolean        read fVisible           write SetVisible;
  //Special function (Search & Replace)
  procedure    ChangeOneValue(SearchTxt, ReplaceTxt: String; Headers: boolean = true);
  //Wait until word end doing its things
  function     WaitForIddle(MaxSec: double = 30): double;
end;

var
  CoInitFlags: Integer = -1;

const
  SearchAll: integer = 2; //Word search_for_all (0=None, 1=Once, 2=All)

implementation

// ************************
// ** Create and destroy **
// ************************

//Create with an empty doc of requested type (use thcWord, thcOpenOffice)
//Remember to define FileName before calling to SaveDoc
constructor TDocumentoTexto.Create(MyTipo: TTipoDoc; MakeVisible: boolean);
var
  i: integer;
  IsFirstTry: boolean;
begin
  //Close all opened things first...
  CloseDoc;
  CloseProg;
  //I will try to open twice, so if Word fails, OpenOffice is used instead
  IsFirstTry:= true;
  for i:= 1 to 2 do begin
    //Try to open OpenOffice...
    if (MyTipo = thcOpenOffice) or (MyTipo = thcNone)then begin
      try
        Programa:= CreateOleObject('com.sun.star.ServiceManager');
      except
      end;
      if ProgLoaded then begin
        Tipo:= thcOpenOffice;
        break;
      end else begin
        if IsFirstTry then begin
          //Try Excel as my second choice
          MyTipo:= thcWord;
          IsFirstTry:= false;
        end else begin
          //Both failed!
          break;
        end;
      end;
    end;
    //Try to open Word...
    if (MyTipo = thcWord) or (MyTipo = thcNone) then begin
      try
        Programa:= CreateOleObject('Word.Application');
      except
      end;
      if ProgLoaded then begin
        Tipo:= thcWord;
        break;
      end else begin
        if IsFirstTry then begin
          //Try OpenOffice as my second choice
          MyTipo:= thcOpenOffice;
          IsFirstTry:= false;
        end else begin
          //Both failed!
          break;
        end;
      end;
    end;
  end;
  //Was it able to open any of them?
  if Tipo = thcNone then begin
    Tipo:= thcError;
    raise Exception.Create('TDocumentoTexto.create failed, may be no Office is installed?');
  end;
  //Add a blank document...
  fVisible:= MakeVisible;
  NewDoc;
end;

constructor TDocumentoTexto.Create(Name: string; MakeVisible: boolean);
begin
  //Close all opened things first...
  CloseDoc;
  CloseProg;
  Tipo:= thcNone;
  //Store values...
  FileName:= Name;
  //Open program and document...
  LoadProg;
  LoadDoc;
  //Visible?
  Visible:= MakeVisible;
end;

destructor TDocumentoTexto.Destroy;
begin
  CloseProg;
  inherited;
end;

// *************************
// ** Loading the program **
// ** Word or OpenOffice  **
// *************************

procedure TDocumentoTexto.LoadProg;
begin
  if ProgLoaded then CloseProg;
  if (UpperCase(ExtractFileExt(FileName))='.DOC') then begin
    //Word is the primary choice...
    try
      Programa:= CreateOleObject('Word.Application');
    except end;
    if ProgLoaded then Tipo:= thcWord;
  end;
  //Not lucky with Word? Another filetype? Let's go with OpenOffice...
  if Tipo = thcNone then begin
    //Try with OpenOffice...
    try
      Programa:= CreateOleObject('com.sun.star.ServiceManager');
    except end;
    if ProgLoaded then Tipo:= thcOpenOffice;
  end;
  //Still no program loaded?
  if not ProgLoaded then begin
    Tipo:= thcError;
    raise Exception.Create('TDocumentoTexto.LoadProg failed, may be no Office is installed?');
  end;
end;

procedure TDocumentoTexto.CloseProg;
begin
  if not Visible then CloseDoc;
  if ProgLoaded then begin
    try
      if IsWord then begin
        Programa.Quit;
        Programa:= Null;
      end;
      if IsOpenOffice then begin
        Desktop.Dispose;
        Desktop:= unassigned;
        Programa.Dispose;
      end;
      Programa:= Unassigned;
    finally end;
  end;
  Tipo:= thcNone;
end;

//Is there any prog loaded? Witch one?
function TDocumentoTexto.GetProgLoaded: boolean;
begin
  result:= not isNullEmpty(Programa);
end;
function  TDocumentoTexto.GetIsWord: boolean;
begin
  result:= (Tipo=thcWord);
end;
function  TDocumentoTexto.GetIsOpenOffice: boolean;
begin
  result:= (Tipo=thcOpenOffice);
end;

// ************************
// ** Loading a document **
// ************************

procedure TDocumentoTexto.NewDoc;
var ooParams: variant;
begin
  //Is the program running? (Word or OpenOffice)
  if not ProgLoaded then raise Exception.Create('No program loaded for the new document.');
  //Is there a doc already loaded?
  CloseDoc;
  DeskTop:= Unassigned;
  //OK, now try to create the doc...
  if IsWord then begin
    Programa.WorkBooks.Add;
    Programa.Visible:= Visible;
    Document:= Programa.ActiveWorkBook;
  end;
  if IsOpenOffice then begin
    Desktop:=  Programa.CreateInstance('com.sun.star.frame.Desktop');
    //Optional parameters (visible)...
    ooParams:=    VarArrayCreate([0, 0], varVariant);
    ooParams[0]:= ooCreateValue('Hidden', false); // çç not Visible);
    //Create the document...
    Document:= Desktop.LoadComponentFromURL('private:factory/swriter', '_blank', 0, ooParams);
  end;
end;

procedure TDocumentoTexto.LoadDoc;
var ooParams: variant;
begin
  if FileName='' then exit;
  //Is the program running? (Word or OpenOffice)
  if not ProgLoaded then LoadProg;
  //Is there a doc already loaded?
  CloseDoc;
  DeskTop:= Unassigned;
  //OK, now try to open the doc...
  if IsWord then begin
    Document:= Programa.Documents.Open(string(FileName),,,,,,,,,,,true);
  end;
  if IsOpenOffice then begin
    Desktop:=  Programa.CreateInstance('com.sun.star.frame.Desktop');
    //Optional parameters (visible)...
    ooParams:=    VarArrayCreate([0, 0], varVariant);
    ooParams[0]:= ooCreateValue('Hidden', false); //Should be "not Visible" but didn't work ok
    //Open the document...
    Document:= Desktop.LoadComponentFromURL(FileName2URL(FileName), '_blank', 0, ooParams);
    if isNullEmpty(Document) then
      raise Exception.Create('Could load the  document "'+FileName+'".');
  end;
  if Tipo=thcNone then
    raise Exception.Create('Could load the document "'+FileName+'". No Word processor installed?.');
end;

function TDocumentoTexto.SaveDoc: boolean;
begin
  result:= false;
  if DocLoaded then begin
    if IsWord then begin
      Document.Save;
      result:= true;
    end;
    if IsOpenOffice then begin
      //There is another method, more powerfull, see SaveToPDF function.
      Document.Store;
      result:= true;
    end;
  end;
end;

//If you are using OOo, you can export to PDF directly.
//In word, the only choice is to use a PDF printer, out of our scope here!
//NOTE: If you open a HTML in OOo, the param 0 need to be diferent as commented
//Code refactored from an example by Ryan at:
//  http://www.oooforum.org/forum/viewtopic.phtml?t=22344
function TDocumentoTexto.SaveToPDF(FileName: string): boolean;
var ooParams: variant;
begin
  result:= false;
  if DocLoaded then begin
    if IsOpenOffice then begin //Word can't export to PDF!
      ooParams:= VarArrayCreate([0, 3], varVariant);
      //If the doc loaded is a HTML, you should use this param[0] instead:
      //ooParam[0]:= ooCreateValue('FilterName', 'writer_web_pdf_Export')
      ooParams[0]:= ooCreateValue('FilterName', 'writer_pdf_Export');
      ooParams[1]:= ooCreateValue('CompressionMode', '1');
      ooParams[2]:= ooCreateValue('Pages', 'All');
      ooParams[3]:= ooCreateValue('Overwrite', TRUE);
      Document.StoreToURL(FileName2URL(FileName), ooParams);
      result:= true;
    end;
  end;
end;

//Print the Doc...
function TDocumentoTexto.PrintDoc: boolean;
var ooParams: variant;
begin
  result:= false;
  if DocLoaded then begin
    if IsWord then begin
      Document.PrintOut;
      while Programa.BackgroundPrintingStatus > 0 do
        sleep(500);
      result:= true;
    end;
    if IsOpenOffice then begin
      ooParams:=   VarArrayCreate([0, 0], varVariant);
      ooParams[0]:= ooCreateValue('Wait', true);
      Document.Print(ooParams);
      //Can't know printing status (maybe it is possible)
      //So wait for process to iddle (under 0.5% CPU)
      WaitForIddle;
      result:= true;
    end;
  end;
end;

procedure TDocumentoTexto.ShowPrintPreview;
begin
  if DocLoaded then begin
    //Force visibility of the doc...
    Visible:= true;
    if IsWord then
      Document.PrintOut(,,,true);
    if IsOpenOffice then
      ooDispatch('.uno:PrintPreview', Unassigned);
  end;
end;

procedure TDocumentoTexto.SetVisible(v: boolean);
begin
  if DocLoaded and (v<>fVisible) then begin
    if IsWord then
      Programa.Visible:= v;
    if IsOpenOffice then begin
      Document.getCurrentController.getFrame.getContainerWindow.setVisible(v);
    end;
    fVisible:= v;
  end;
end;

procedure TDocumentoTexto.CloseDoc;
begin
  if DocLoaded then begin
    //Close it...
    try
      if IsOpenOffice then Document.Dispose;
      if IsWord       then Document.close;
    finally end;
    //Clean up "pointer"...
    Document:= Null;
  end;
end;

function TDocumentoTexto.GetDocLoaded: boolean;
begin
  result:= not isNullEmpty(Document);
end;

procedure TDocumentoTexto.ChangeOneValue(SearchTxt, ReplaceTxt: String; Headers: boolean = true);
var  j, Paso: integer;
     Txt, Busca, Reemp: string;
     ooBuscador: variant;
begin
  case Tipo of
  thcWord: begin
      //Word can't replace with a text longer than 250!
      if length(ReplaceTxt) < 250 then begin
        Programa.ActiveDocument.Content.Find.Execute(SearchTxt, true, false, false, false, false,,,, ReplaceTxt, SearchAll);
        if Headers then begin
          //Search in page header...
          Programa.ActiveWindow.ActivePane.View.SeekView:=  9; //9 = wdSeekCurrentPageHeader
          Programa.Selection.Find.Execute(SearchTxt, true, false, false, false, false,,,,ReplaceTxt,SearchAll);
          //Search on footer...
          Programa.ActiveWindow.ActivePane.View.SeekView:= 10; //10 = wdSeekCurrentPageFooter
          Programa.Selection.Find.Execute(SearchTxt, true, false, false, false, false,,,,ReplaceTxt,SearchAll);
        end;
        //You can wait for Word to finish 0.1 secs. uncomenting next line...
        //sleep(100);
        //...but calling WaitForIddle after all your replaces is a better choice!
      end else begin
        //I have to "chop" the text into pieces of max. 240 chars!
        //NOTE: Coping from array N[] to D[] can make a DLL run out of memory
        //and raise rare errors, so I make it char by char!
        Busca:= ''; for j:= 1 to Length(SearchTxt)  do Busca:= Busca+SearchTxt[j];
        Reemp:= ''; for j:= 1 to Length(ReplaceTxt) do Reemp:= Reemp+ReplaceTxt[j];
        Paso:= 1;
        repeat
          Txt:=   copy(Reemp,1,240);
          Reemp:= copy(Reemp,241,9999);
          if (Reemp<>'') then
            Txt:= Txt+'[@#@'+IntToStr(Paso)+']';
          Programa.ActiveDocument.Content.Find.Execute(Busca,true,false,false,false,false,,,,Txt,SearchAll);
          Busca:= '[@#@'+IntToStr(Paso)+']';
          inc(Paso);
          //Need to wait for Word to finish before processing the next txt piece
          sleep(100);
        until (Reemp='');
      end;
    end;
  thcOpenOffice: begin
      if isNullEmpty(Document) then
        raise Exception.Create('No text document loaded');
      ooBuscador:= Document.createReplaceDescriptor;
      ooBuscador.SearchString:=  SearchTxt;
      ooBuscador.ReplaceString:= ReplaceTxt;
      Document.ReplaceAll(ooBuscador);
    end;
  end;
end;

//Wait for Word to end up with all instruction we have through at it.
//As Word diggest them asincronous, you never know if you are finish
//and you can end up saving BEFORE all previous commands are done!
//It detects it by measuring the proc %CPU usage until it drops below 0.5%
function TDocumentoTexto.WaitForIddle(MaxSec: double = 30): double;
var ProcName: string;
begin
  //Process Name...
  if Tipo=thcWord then ProcName:= 'WINWORD.EXE'
  else                 ProcName:= 'swriter.exe';
  //Wait for the %CPU to drop below 0.5%
  result:= WaitExeIddle(ProcName, 1, MaxSec);
end;

// ***************************
// ** OpenOffice only stuff **
// ***************************

//Change 'C:\File.txt' into 'file:///c:/File.txt' (for OpenOffice OpenURL)
function TDocumentoTexto.FileName2URL(FileName: string): string;
begin
  result:= '';
  if LowerCase(copy(FileName,1,8))<>'file:///' then
    result:= 'file:///';
  result:= result + StringReplace(FileName, '\', '/', [rfReplaceAll, rfIgnoreCase]);
end;

function TDocumentoTexto.ooCreateValue(ooName: string; ooData: variant): variant;
var
  ooReflection: variant;
begin
  if IsOpenOffice then begin
    ooReflection:= Programa.createInstance('com.sun.star.reflection.CoreReflection');
    ooReflection.forName('com.sun.star.beans.PropertyValue').createObject(result);
    result.Name := ooName;
    result.Value:= ooData;
  end else begin
    raise Exception.Create('ooValue imposible to create, load OpenOffice first!');
  end;
end;

procedure TDocumentoTexto.ooDispatch(ooCommand: string; ooParams: variant);
var
  ooDispatcher, ooFrame: variant;
begin
  if DocLoaded and IsOpenOffice then begin
    if (VarIsEmpty(ooParams) or VarIsNull(ooParams)) then
      ooParams:= VarArrayCreate([0, -1], varVariant);
    ooFrame:= Document.getCurrentController.getFrame;
    ooDispatcher:= Programa.createInstance('com.sun.star.frame.DispatchHelper');
    ooDispatcher.executeDispatch(ooFrame, ooCommand, '', 0, ooParams);
  end else begin
    raise Exception.Create('Dispatch imposible, load a OpenOffice doc first!');
  end;
end;

function TDocumentoTexto.isNullEmpty(thisVariant: Variant): Boolean;
begin
  Result:= VarIsEmpty(thisVariant) or VarIsNull(thisVariant) or VarIsClear(thisVariant);
end;

end.


And here comes the snippet that wait for a process to iddle (THIS is the most tricky part of all), comments are in plain spanish, but function names are pretty self explanatory. You can copy-paste into prior unit or place in another unit file:

Code:

// **************************************************************************
// ** AÑADIDO SERGIO PARA MENEJAR PROCESOS POR SU HANDLE O SU EXE FILENAME **
// **************************************************************************

function FileTime2Milliseconds(FileTime: TFileTime): integer;
var ST: TSystemTime;
begin
  FileTimeToSystemTime(FileTime, ST);
  result:= ST.wMilliseconds + 1000 *
          (ST.wSecond + 60 * (ST.wMinute + 60 * ST.wHour)) ;
end;

//Sabemos 'WINWORD.EXE', dame un THandle del proceso para hacerle putadillas
function GetProcHandle(ExeFileName: string): THandle;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  result:= 0;
  FSnapshotHandle:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize:= Sizeof(FProcessEntry32);
  ContinueLoop:= Process32First(FSnapshotHandle, FProcessEntry32);
  while integer(ContinueLoop) <> 0 do begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpperCase(ExeFileName))
     or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName))) then begin
      result:= OpenProcess(PROCESS_ALL_ACCESS, FALSE, FProcessEntry32.th32ProcessID);
      break;
    end;
    ContinueLoop:= Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

//Mata este proceso!
function KillProc(H: THandle): boolean;
const PROCESS_TERMINATE=$0001;
begin
  result:= (Integer(TerminateProcess(H, 0))<>0);
end;

//Espera a que un Proceso use menos del 0.5% de la CPU.
//Si no encuentra el proceso, esperara MinSeg, y si lo encuentra pero no baja
//del 1%, se esperara un maximo de MaxSeg.
function WaitProcIddle(H: THandle; MinSeg: double = 1; MaxSeg: double = 30): double;
var
  LastProcTime, NewProcTime, UsedTime: integer; //Milisegundos todo
  CreaTime, ExitTime, UserTime, KernelTime: TFileTime;
const
  WAIT_FOR_MS: integer = 1000; //Cada 1 segundo (1000 ms) vuelves a mirar
  IDDLE_LOWER: integer =    5; //Usados < 5 ms = (%CPU<0.5) salimos
begin
  //Llevo esperando 0 segundos...
  result:= 0;
  //Igual no lo encuentro...
  if (H=0) then begin
    //Pues no esta, espero algo y me voy...
    sleep(round(MinSeg*1000));
  end else begin
    //Proceso encontrado, a esperar...
    if GetProcessTimes(H, CreaTime, ExitTime, KernelTime, UserTime)=BOOL(0) then exit;
    LastProcTime:= FileTime2Milliseconds(KernelTime) + FileTime2Milliseconds(UserTime);
    //Cada decima de segundo, recalculo...
    repeat
      sleep(WAIT_FOR_MS);
      result:= result + (WAIT_FOR_MS/1000);
      //Rescato tiempo dle proceso actualizado...
      if GetProcessTimes(H, CreaTime, ExitTime, KernelTime, UserTime)=BOOL(0) then exit;
      NewProcTime:= FileTime2Milliseconds(KernelTime) + FileTime2Milliseconds(UserTime);
      UsedTime:= (NewProcTime - LastProcTime);
      if (UsedTime) < IDDLE_LOWER then
        break;
      LastProcTime:= NewProcTime;
    until (result >= MaxSeg);
  end;
end;

// ***************************************************
// ** MANEJO PROCESOS SABIENDO SU NOMBRE DE FICHERO **
// ***************************************************

//Espera a que una tarea baje del 1%CPU usando su filename
function WaitExeIddle(ExeFileName: string; MinSeg: double = 0.1; MaxSeg: double = 10): double;
begin
  result:= WaitProcIddle(GetProcHandle(ExeFileName), MinSeg, MaxSeg);
end;

//Mata programa por su nombre...
function KillTask(ExeFileName: string): boolean;
begin
  result:= KillProc(GetProcHandle(ExeFileName));
end;
Back to top
View user's profile Send private message Visit poster's website
brace77
Newbie
Newbie


Joined: 23 Apr 2010
Posts: 1

PostPosted: Fri Apr 23, 2010 5:33 am    Post subject: Reply with quote

Thanks a lot for the great class.

Please keep us informed as new features are added.

Just a note, i pasted the second part of the code just after the implementation keyword in the class but I had to add (in Delphi 2009) the following to compile it:

Code:

uses Windows, TlHelp32;


Anyway after that it works perfectly
Back to top
View user's profile Send private message
mike30
Newbie
Newbie


Joined: 01 Jul 2010
Posts: 1

PostPosted: Thu Jul 01, 2010 8:00 pm    Post subject: Good work Reply with quote

thanks. I use Turbo Power components for MS Office integration in Delphi, but, I want to offer my customers ( I am a small ISV) OpenOffice integration.
------

Supplements


Last edited by mike30 on Wed Feb 09, 2011 6:58 pm; edited 2 times in total
Back to top
View user's profile Send private message
mkp
Newbie
Newbie


Joined: 14 Oct 2010
Posts: 2

PostPosted: Sat Oct 30, 2010 2:38 am    Post subject: Reply with quote

Oh my god. It is just the thing I was looking for. I don’t know how you guys do it. Being a newbie to open office it almost looks like magic to me. I hope I will master it one day. The code worked fabulously for me but with the little correction that Brace has suggested here. The only thing I found a little annoying was that it took sometime to get this code run. The snippet for wait is in Spanish couldn’t make out a thing. 

__________
forex trading strategies
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group