Results 1 to 12 of 12

Thread: Lazarus Word ole automation

  1. #1

    Lazarus Word ole automation

    Hallo,

    Ik ben een tijdje bezig om een oplossing te vinden om tekst te vervangen in een word document (Office 365).
    Volgende code lijkt bijna te werken.
    Alleen krijg ik een foutmelding.
    Code :
    Code:
    procedure Tfrm_main.Button1Click(Sender: TObject);
    var
         WordApp : Variant;
         w : widestring;
         S1, S2 : OLEVariant;
    const
      wdFindContinue = 1;
      wdReplaceOne = 1;
      wdReplaceAll = 2;
    begin
      try
        WordApp := CreateOLEObject('Word.Application');
      except
        WriteLn('Unable to start Word.');
        Exit;
      end;
    
      S1 := 'XXXX';
      S2 := 'YYYY';
    
      // oWord := Server.Documents.Add;
      w:= UTF8Decode('D:\template.docx');
      WordApp.Visible := True;
      WordApp.Documents.Open(w);
    
    
      WordApp.Selection.Find.ClearFormatting;
      WordApp.Selection.Find.Text := '<lastname>';
      WordApp.Selection.Find.Replacement.Text := S1;
      WordApp.Selection.Find.Text := '<firstname>';
      WordApp.Selection.Find.Replacement.Text := S2;
      WordApp.Selection.Find.Forward := True;
      WordApp.Selection.Find.MatchAllWordForms := False;
      WordApp.Selection.Find.MatchCase := False;
      WordApp.Selection.Find.MatchWildcards := False;
      WordApp.Selection.Find.MatchSoundsLike := False;
      WordApp.Selection.Find.MatchWholeWord := False;
      WordApp.Selection.Find.MatchFuzzy := False;
      WordApp.Selection.Find.Format := False;
    
    // HIER ZIT DE FOUT
      WordApp.Selection.Find.Execute(Replace := 1);
    
    
      WordApp.ActiveDocument.SaveAs('D:\test.docx');
    
      WordApp.Visible := True;  {Make WordApp visible}
    
      WordApp.ActiveDocument.Close;
      WordApp.Quit;
      WordApp := Unassigned;
    end;
    en dit is de foutmelding

    Click image for larger version. 

Name:	2020-10-17 22_39_02-Debugger Exception Notification.png 
Views:	19 
Size:	5.4 KB 
ID:	8130

    Enig idee wat er verkeerd loopt?

    Alvast bedankt

    Lainkes

  2. #2
    Ja, volgens mij is het bekend dat dat redelijk buggy kan zijn.

    Probeer het volgende eens
    Delphi Code:
    1. var
    2.   WordSelection: OleVariant;
    3. //..
    4. WordSelection := WordApp.Selection;
    5. //..
    6. WordSelection.Find.Text := '<firstname>';
    7. WordSelection.Find.Replacement.Text := S2;
    8. WordSelection.Find.Execute(Replace := 1);

    (Dus werken met een tussen-OleVariant voor selection)

  3. #3
    Ik krijg dezelfde foutmelding.

    De vraag die ik me stel is of dit een correcte oplossing is.
    Aangezien de info die ik vond redelijk oud is.
    Als er een betere oplossing bestaat zou ik dit ook graag horen.

    Alvast bedankt

    Lainkes

  4. #4
    Volgens mij zou die code nog moeten werken.
    (Ik hen alleen geen Word dus kan niets testen)

    Werkt het met dit wel?
    WordApp.ActiveDocument.Content.Find ?

    (Haal anders ook eens al die regels erboven, behalve text en replacement.text, weg.)

  5. #5
    Ik heb ook al een poosje geen Word meer.
    Ik weet wel dat het werken met Selection an sich niet zo handig is. Het is namelijk relatief traag, en als het document zichtbaar is kan de gebruiker bovendien roet in het eten gooien door de cursor te verplaatsen, of zelfs door een ander document te activeren! Er is namelijk maar 1 selection in de hele applicatie.

    Je moet dan dus maar hopen dat de selection inderdaad in het net geopende document valt. Je kan beter specifiek de handle naar dat document opslaan en daarmee verder werken, bijvoorbeeld door 'Find' te gebruiken op de range van het document. Dat is een wat minder veranderlijke entiteit, en is in ieder geval niet gevoelig voor cursorpositie en actieve document.

    Ik denk overigens niet dat dat nu concreet je probleem is. Meer een algemene tip.

    Dat, gecombineerd met rvk's tip:

    Delphi Code:
    1. var
    2.   WordApp, Doc, Find: OleVariant;
    3. begin
    4.   Doc := WordApp.Documents.Open(w);
    5.   Find := Doc.Range.Find;
    6.   Find.ClearFormatting;
    7.   Find.Text := '<lastname>';
    8.   Find.Replacement.Text := S1;
    9.   Find. enz...
    10.   Find.Format := False;
    11.  
    12.   Find.Execute(Replace := 1);
    13. end;

    Alternatieven zijn mail merge velden, of bladwijzers (bookmarks). Destijds deden wij alles met bladwijzers. Dat was veel sneller, en door de nieuwe inhoud ook in een bladwijzer te plaatsen kan je die zelfs naderhand nog eens aanpassen. Het geheim van de smid, mag ik wel zeggen, want ik heb acht jaar lang gespecialiseerde software geschreven met bladwijzers als drijvende kracht.
    Last edited by GolezTrol; 19-Oct-20 at 10:30.
    1+1=b

  6. #6
    Ik heb het stukje uit de openingspost even op Delphi geprobeerd en daar werkt het direct perfect.
    Ik denk dat er dus iets mis gaat in Lazarus met het OLE-object.
    Misschien dat deze vraag dan beter op https://forum.lazarus.freepascal.org gesteld kan worden.

    PS. Ik probeer het net ZONDER de (Replace := 1) parameter. En dan krijg ik geen foutmelding.
    Ik denk dat wanneer er een onverwachte parameter (of parameter conventie) opgegeven wordt, dat Lazarus de "method is not supported" geeft, terwijl "Execute" zelf wel supported is maar de aanroep met "Replace :=" niet.

    Dit gaat dus goed.
    Delphi Code:
    1. WordApp.Selection.Find.Execute;

    Extra PS. Waarschijnlijk kan het wel in Trunk (niet uitgetest). De oudere versies accepteren waarschijnlijk geen benoemde parameters bij aanroep van OLE-methods.
    Zie bugreport https://bugs.freepascal.org/view.php?id=37355

    Je kunt dus wel de replace opgeven als je ALLE verwachtte parameters opgeeft (eventueel met 0 of nil).

  7. #7
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,196
    In eerste instantie zou ik hetzelfde zeggen als Rvk, breek de lange gechainde statements op en assign het aan olevariant.

  8. #8
    Quote Originally Posted by marcov View Post
    In eerste instantie zou ik hetzelfde zeggen als Rvk, breek de lange gechainde statements op en assign het aan olevariant.
    Zoals ik in mijn laatste post (in de PS en extra PS) al aangaf, werkte dat ook niet.

    Even ter volledigheid:

    Het probleem is dat FPC in 3.2.0 (Lazarus 2.0.10) benoemde parameters (named parameters) niet meer accepteerde in OLE calls. In FPC 3.0.4 (Lazarus 2.0.8) werkte dit nog wel. Zie ook bugreport https://bugs.freepascal.org/view.php?id=37355. Die staat als fixed dus het zal in trunk wel weer werken (wat ik niet getest heb).

    Dus dit werkte niet (geeft een foutmelding)
    Delphi Code:
    1. WordApp.Selection.Find.Execute(Replace := 1);
    maar dit gaf geen foutmelding
    Delphi Code:
    1. WordApp.Selection.Find.Execute;

    Echter bleek dit ook niet goed te werken (er werd niets vervangen).
    De uiteindelijke oplossing is om alle parameters gewoon 'unnamed' mee te geven.

    Uiteindelijke werkende code (gebruikmakend van ActiveDocument.Content i.p.v. Selection):
    Delphi Code:
    1. uses Variants, ComObj;
    2.  
    3. procedure TForm1.Button1Click(Sender: TObject);
    4. var
    5.   WordApp : OleVariant;
    6.   w : widestring;
    7.   S1, S2 : OLEVariant;
    8. const
    9.   wdFindContinue = 1;
    10.   wdReplaceOne = 1;
    11.   wdReplaceAll = 2;
    12. begin
    13.   try
    14.     WordApp := CreateOLEObject('Word.Application');
    15.   except
    16.     WriteLn('Unable to start Word.');
    17.     Exit;
    18.   end;
    19.  
    20.   S1 := 'XXXX';
    21.   S2 := 'YYYY';
    22.  
    23.   w:= UTF8Decode('C:\temp\test.docx');
    24.   WordApp.Visible := True;
    25.   WordApp.Documents.Open(w);
    26.  
    27.   // FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike, MatchAllWordForms, Forward, Wrap, Format,
    28.   //   ReplaceWith, Replace, MatchKashida, MatchDiacritics, MatchAlefHamza, MatchControl
    29.  
    30.   WordApp.ActiveDocument.Content.Find.Execute('<lastname>', false, false, false, false, false, true, false, false, S1, 1);
    31.   WordApp.ActiveDocument.Content.Find.Execute('<firstname>', false, false, false, false, false, true, false, false, S2, 1);
    32.  
    33.   w:= UTF8Decode('C:\temp\test2.docx');
    34.   WordApp.ActiveDocument.SaveAs(w);
    35.  
    36.   WordApp.ActiveDocument.Close;
    37.   WordApp.Quit;
    38.   WordApp := Unassigned;
    39.  
    40. end;

  9. #9
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,196
    Ok, die rev(r45974) staat bij mij genoteerd als merged, dus 3.2.1 en later zouden goed moeten zijn.

  10. #10
    De oplossing van RvK werkt perfect, waarvoor mijn uitgebreide dank.
    Ik stel me nu de vraag waarom zulke info niet te vinden is in handboeken of cursussen.
    Op dit ogenblik volg ik een Delphi Bootcamp van M. Cantu. Maar ik vrees dat dit niet vermeld zal worden.

  11. #11
    Quote Originally Posted by alain.janquart View Post
    Ik stel me nu de vraag waarom zulke info niet te vinden is in handboeken of cursussen.
    Op dit ogenblik volg ik een Delphi Bootcamp van M. Cantu. Maar ik vrees dat dit niet vermeld zal worden.
    Zulke informatie vindt je niet in boeken omdat dit een (tijdelijke) bug was in Lazarus 2.0.10. In de nieuwere versie (en trunk) is dit dus alweer opgelost en werkt het weer nét als in Delphi.

    Vaak zijn dit soort dingen wel te vinden op forums. Zo had ik ook de referentie naar dat bugrapport gevonden op het Lazarus forum.

  12. #12
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    121
    Wij maken onze bestellingen in Word maar gebruiken dan een sjabloon met bookmarks ipv te vervangen teksten.

    WordApp.ActiveDocument.Bookmarks("Adres").Select
    WordApp.Selection.TypeText Text:=adres_text

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •