Results 1 to 15 of 15

Thread: word search replace tekst door mergefield

  1. #1
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,077

    word search replace tekst door mergefield

    Een klant moet meer dan 100 documenten aanpassen.
    Een gewone tekst moet dan vervangen worden door een mergefield (dat natuurlijk een paar eigenschappen heeft).
    Zou dat programmatisch mogelijk zijn met OLE of anderszins?

  2. #2
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,313
    Ja hoor, geen problem.

    Hou er rekening mee dat een pagina binnen Word (ook) een header en footer heeft, die
    je apart moet aanroepen: het heeft mij destijds een hele tijd gekost voor ik doorhad
    waarom een bepaald woord niet gevonden werd (hij stond in de header van de pagina).
    TMemoryLeak.Create(Nil);

  3. #3
    Bovenstaande oplossing vervangt alleen tekst door andere tekst. Het vervangt die tekst niet door een mergefield. Als je er een mergefield van wilt maken zul je volgens mij wat meer moeten doen.

    Je zou dit een in een macro kunnen doen en dan de source van de vbs bekijken. Dan zie je gelijk hoe je dat in Delphi zou kunnen doen.

  4. #4
    I7 7700K 32Gb Win10 Pro Wok's Avatar
    Join Date
    Dec 2002
    Location
    Alkmaar
    Posts
    1,863
    Delphi Code:
    1. Function Word_StringReplace(ADocument: TFileName; SearchString, ReplaceString: String; Flags: TWordReplaceFlags): Boolean;
    2. Const
    3.   WdFindContinue = 1;
    4.   WdReplaceOne = 1;
    5.   WdReplaceAll = 2;
    6.   WdDoNotSaveChanges = 0;
    7. Var
    8.   WordApp: OLEVariant;
    9. Begin
    10.   Result := False;
    11.  
    12. { Check if file exists }
    13.   If Not FileExists(ADocument) Then
    14.     Begin
    15.       ShowMessage('Specified Document not found.');
    16.       Exit;
    17.     End;
    18.  
    19. { Create the OLE Object }
    20.   Try
    21.     WordApp := CreateOLEObject('Word.Application');
    22.   Except
    23.     On E: Exception Do
    24.       Begin
    25.         E.Message := 'Word is not available.';
    26.         Raise ;
    27.       End;
    28.   End;
    29.  
    30.   Try
    31. { Hide Word }
    32.     WordApp.Visible := False;
    33. { Open the document }
    34.     WordApp.Documents.Open(ADocument);
    35. { Initialize parameters }
    36.     WordApp.Selection.Find.ClearFormatting;
    37.     WordApp.Selection.Find.Text := SearchString;
    38.     WordApp.Selection.Find.Replacement.Text := ReplaceString;
    39.     WordApp.Selection.Find.Forward := True;
    40.     WordApp.Selection.Find.Wrap := WdFindContinue;
    41.     WordApp.Selection.Find.Format := False;
    42.     WordApp.Selection.Find.MatchCase := WrfMatchCase In Flags;
    43.     WordApp.Selection.Find.MatchWholeWord := False;
    44.     WordApp.Selection.Find.MatchWildcards := WrfMatchWildcards In Flags;
    45.     WordApp.Selection.Find.MatchSoundsLike := False;
    46.     WordApp.Selection.Find.MatchAllWordForms := False;
    47. { Perform the search }
    48.     If WrfReplaceAll In Flags Then
    49.       WordApp.Selection.Find.Execute(Replace := WdReplaceAll)
    50.     Else
    51.       WordApp.Selection.Find.Execute(Replace := WdReplaceOne);
    52. { Save word }
    53.     WordApp.ActiveDocument.SaveAs(ADocument);
    54. { Assume that successful }
    55.     Result := True;
    56. { Close the document }
    57.     WordApp.ActiveDocument.Close(WdDoNotSaveChanges);
    58.   Finally
    59. { Quit Word }
    60.     WordApp.Quit;
    61.     WordApp := Unassigned;
    62.   End;
    63. End;

    Ik heb een stukje oude code opgezocht.

    Ooit werkte dat met Word2003 en WordXP
    Nu krijg ik vele foutmeldingen, maar je krijg wel een in druk hou je het zou kunnen aanpakken.

    gr. Peter
    10.1, Delphi2010, of Lazarus 1.8.4

  5. #5
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,077
    Dank.
    De search replace code is al iets.
    Misschien search en dan "insert mergefield at position".
    Ik wacht even tot de klant evt. opdracht geeft. Het moet te doen zijn :-)

  6. #6
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,313
    Quote Originally Posted by rvk View Post
    een mergefield.
    Ik had nog nooit van een MergeField gehoord (althans volgens deze definitie).

    Wij gebruikten altijd een "Normaal" Word-document, met daarin specifieke en unieke woorden
    (bijvoorbeeld %_NAAM_%) erin die verwezen naar een waarde waarmee het vervangen moest
    worden.

    Volgens mij is de code van Peter(Wok) dezelfde als die in mijn linkje (en zou dat niet werken
    met mergefields).
    TMemoryLeak.Create(Nil);

  7. #7
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,077
    What on earth is dit?

    WordApp.Selection.Find.Execute(Replace := WdReplaceAll)

    Het compileert... Welke mij onbekende parameter syntax ligt hier aan ten grondslag?

  8. #8
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,313
    Het zal wel een fancy naam hebben, maar de Execute-method heeft een zooi optionele parameters.

    Je kunt via zo'n OLE-koppeling method gewoon alle parameters invullen (wel in de juiste volgorde),
    maar je kunt ook opgeven wat voor waarde een bepaalde parameter moet hebben.

    Delphi (Pascal) kent geen optionele parameters (alleen default parameters), dus daarom staat het
    voor ons zo raar (persoonlijk zou ik liever dergelijke optionele parameters in Delphi hebben, dan
    inline variabelen waar MarcoV het in het andere draadje over heeft).
    TMemoryLeak.Create(Nil);

  9. #9
    Ter info wat betreft het zoeken en vervangen door een MergeField. Werkelijk de Find/Replace hiervoor gebruiken zal niet lukken. Wat je wel kunt doen is zoeken en verwijderen en dan op die positie een MergeField tussenplaatsen.

    In VBA (macro opnemen) wordt een MergeField op deze manier op Selection.Range geplaatst.
    VBA Code:
    1. ActiveDocument.Fields.Add Range:=Selection.Range, Type:=wdFieldMergeField, Text:="""Voornaam"""

    Ander voorbeeldje met wat VBA code
    https://stackoverflow.com/questions/...il-merge-field
    en
    https://answers.microsoft.com/en-us/...b-68b599b31bf5

    VBA Code:
    1. Dim oRng As Range
    2. Set oRng = ActiveDocument.Range
    3. With oRng.Find
    4.     Do While .Execute(FindText:="(Player 1)")
    5.         oRng.Fields.Add oRng, wdFieldMergeField, "Player_1", False
    6.         oRng.Collapse wdCollapseEnd
    7.     Loop
    8. End With

  10. #10
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,077
    Ok snap ongeveer... Maar werkt deze (rode) syntax ook standaard in Delphi? Het lijkt van niet. Wanneer kan dit en wanneer niet?

    (ik lees met grote interesse de Cantu-blog en de thread van MarcoV).

  11. #11
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,077
    Thanks rvk. Wanneer ik bezig ga zal ik hier nog wel terugkomen..

  12. #12
    Quote Originally Posted by EricLang View Post
    Ok snap ongeveer... Maar werkt deze (rode) syntax ook standaard in Delphi? Het lijkt van niet. Wanneer kan dit en wanneer niet?
    Nee, die werkt niet met andere variabele. Dit zal in Delphi alleen werken met Variant variabele. Daar wordt met het aanroepen van procedures e.d. pas gecontroleerd wanneer deze uitgevoerd wordt (late binding). En dan is deze syntax wel toegestaan.

    Ik heb even in mijn source gekeken en de enige instance waar ik dit bij mij tegenkom is dit:
    Delphi Code:
    1. ooDocument.PrintOut(Preview := false);
    ooDocument is een variant van ooApp.Workbooks[1] en ooApp is weer een CreateOleObject('Excel.Application');

  13. #13
    Senior Member
    Join Date
    Mar 2002
    Location
    Edam
    Posts
    359
    gaat het om .doc bestanden of om .docx? Docx is een (gezipt) xml bestand en is als zodanig redelijk makkelijk te verwerken. Het zou me niet verbazen als de mergefields hierin direct kunnen worden benaderd.

  14. #14
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,313
    Ik dacht dat docx een gewone gezipte doc was.

    [EDIT]
    Inderdaad... grappig: allemaal XML's.
    Maar, ik heb even een test-docje opgeslagen met drie woorden en er worden wel veel dingen weggeschreven.
    De tekst zelf staat in "document.xml", maar dat zou dan betekenen dat je je weer moet gaan verdiepen in hoe
    een docx-bestand in elkaar zit; ik weet niet of ik daar zin in zou hebben (maar wellicht heeft Eric er wel zin in).
    Last edited by VideoRipper; 01-Nov-18 at 15:53.
    TMemoryLeak.Create(Nil);

  15. #15
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,077
    Uiteraard had ik dit al geprobeerd tijdens een testje :-)
    Echter er kan zoveel Word-onzin instaan (op de meest onvoorstelbare plekken) dat een unzip - search replace in document.xml - zip back ondoenlijk is.
    Voor deze ene maal zou het wel kunnen met OLE, maar ik vermoed dat de klant het handmatig gaat doen. Dat gaat ze een paar dagen kosten.
    Word OLE is overigens stom, tricky en vooral belachelijk langzaam, zelfs bij early binding.

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
  •