Recent

Author Topic: [SOLVED] Word: search and replace  (Read 7844 times)

w click

  • Full Member
  • ***
  • Posts: 180
[SOLVED] Word: search and replace
« on: May 04, 2016, 05:28:02 pm »
I'm trying to do a bunch of search-and-replacements in a Word document, via Word (or not), and then import that text into a memo.  I found some code in the forum, but couldn't locate what a 'wordapp' was supposed to be declared as.

Does anyone know how to do this?
« Last Edit: May 06, 2016, 09:46:36 am by w click »

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #1 on: May 05, 2016, 10:53:57 am »
I've got further.  I added 'uses comobj' and added this procedure.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.BitBtnWordClick(Sender: TObject);
  2. var wordapp : olevariant;
  3. begin
  4.   try
  5. //    if Assigned(InitProc) then TProcedure(InitProc);
  6.     try
  7.       WordApp := CreateOleObject('Word.Application');
  8.       memoword.lines.add('Created OleObject');
  9.     except
  10.       memoword.lines.add('Unable to start Word.');
  11.     end;
  12.       {Open existing document}
  13.       WordApp.Documents.Open('c:\users\david\desktop\firewood\testing.docx');
  14.  
  15.       memoword.lines.add('Opened word');
  16.  
  17.       WordApp.Visible := True;  {Make WordApp visible}
  18.  
  19.       memoword.lines.add('Word visible');
  20.  
  21.       WordApp.Selection.Find.ClearFormatting;
  22.       WordApp.Selection.Find.Text := 'the';
  23.       WordApp.selection.find.replacement.clearformatting;
  24.       WordApp.Selection.Find.Replacement.Text := '#######';
  25.       WordApp.Selection.Find.Forward := True;
  26.       WordApp.Selection.Find.MatchAllWordForms := False;
  27.       WordApp.Selection.Find.MatchCase := False;
  28.       WordApp.Selection.Find.MatchWildcards := False;
  29.       WordApp.Selection.Find.MatchSoundsLike := False;
  30.       WordApp.Selection.Find.MatchWholeWord := False;
  31.       WordApp.Selection.Find.MatchFuzzy := False;
  32.       WordApp.Selection.Find.Format := False;
  33.  
  34.       memoword.lines.add('Ready to replace');
  35.  
  36. //      WordApp.Selection.Find.Execute(Replace := 2);
  37.       wordapp.selection.find.execute(replace := 1);
  38.  
  39.       memoword.lines.add('Replaced');
  40.  
  41.     except
  42.       memoword.lines.add('All went wrong');
  43.     end;
  44. end;      
  45.  

It opens Word with the right document, but seems to fail in the setting up for the replace.

Anyone any ideas?

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Word: search and replace
« Reply #2 on: May 05, 2016, 12:20:34 pm »
OLE requires widestrings, Lazarus however uses utf8-strings. Therefore, you must convert all strings passed to wordapp to widestrings. (In fpc versions before 3.0 you must also call UTF8Decode if the strings contain non-ASCII characters)
Code: Pascal  [Select][+][-]
  1. WordApp.Documents.Open(WideString(UTF8Decode('c:\users\david\desktop\firewood\testing.docx')));

The assignments seem to be handles automatically, but the function calls, such as the "Open" above, must be adapted.

In addition, please note that your code does not destroy the WordApp instances. You'll notice a lot of dangling WINWORD.EXEs in the TaskManager after a while... At the end of your procedure, call
Code: Pascal  [Select][+][-]
  1.   WordApp.Quit;
  2.   WordApp := Unassigned;
and do this in a try - finally block to make sure that it is called.

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #3 on: May 05, 2016, 01:27:29 pm »
Thanks for the reply.

I tried this, opens as before fine.  I also tried it around the string passed to WordApp.Selection.Find.Text and WordApp.Selection.Find.Replacement.Text.

No joy, I'm afraid.

It has an exception: EOleException, value out of range at the WordApp.Selection.Fine.MatchWildcards line.  I've tried commenting this out, but it just fails at the next one or previous one if I've removed those.

Oh, I'd not been using the final close, quit and unassigned as I've been wanting to see the Word document in case it did change the text.  It didn't.
« Last Edit: May 05, 2016, 01:29:30 pm by w click »

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #4 on: May 05, 2016, 04:28:37 pm »
A step closer (particularly when I spell 'Find' correctly), but it's not finding anything.

It doesn't like 'WordApp.Selection.Find.Wrap:=true;' either.

Commenting this out, it gets down to the actual 'execute' for the replacement.  That seems to run, but it's reporting that it's not found anything.  I've tried various combinations of widestring and utf8decode to no avail.

It's on a .docx.

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #5 on: May 05, 2016, 04:44:12 pm »
This:-

Code: Pascal  [Select][+][-]
  1.         WordApp.Selection.Find.Execute(Replace := 2);
  2.  

Changes 'wordapp.selection.find.text' from 'the' (the text I set it to as there are lots of examples in the test .docx) to become '2'.

It feels very close, but I really don't know what other random permutations to try now. 

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Word: search and replace
« Reply #6 on: May 05, 2016, 05:17:45 pm »
Your code from reply #1 and my modification runs fine here: Word opens my file, finds the text and replaces it. I'm on Office 2007, Lazarus trunk/fpc 3.0, Win 7.

A good example why to avoid OLE as much as possible... Why don't you do the replacement within Word itself?

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #7 on: May 05, 2016, 05:36:07 pm »
Thanks for trying it for me.  I'm on Office Professional Plus 2010 here.

This is where I've got now.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.BitBtnWordClick(Sender: TObject);
  2. var wordapp : olevariant;
  3.     s,t : widestring;
  4. begin
  5.   try
  6.     try
  7.       WordApp:=CreateOleObject('Word.Application');
  8.       memoword.lines.add('Created OleObject');
  9.     except
  10.       memoword.lines.add('Unable to start Word.');
  11.     end;
  12.     s:='the';
  13.     t:='#####';
  14.  
  15.     WordApp.Documents.Open(WideString(utf8decode('c:\users\david\desktop\firewood\testing.docx')));
  16.     memoword.lines.add('Opened word');
  17.  
  18.     WordApp.Visible:=True;  {Make WordApp visible}
  19.     memoword.lines.add('Word visible');
  20.  
  21.     WordApp.Selection.Find.ClearFormatting;
  22.     WordApp.Selection.Find.Text := s;
  23. // wordapp.selection.find.font.italic:=true;
  24.     WordApp.selection.find.replacement.clearformatting;
  25.     WordApp.Selection.Find.Replacement.Text := t;
  26.     WordApp.Selection.Find.Forward := True;
  27.     WordApp.Selection.Find.MatchAllWordForms := False;
  28.     WordApp.Selection.Find.MatchCase := False;
  29.     WordApp.Selection.Find.MatchWildcards := False;
  30.     WordApp.Selection.Find.MatchSoundsLike := False;
  31.     WordApp.Selection.Find.MatchWholeWord := False;
  32.     WordApp.Selection.Find.MatchFuzzy := False;
  33.  
  34. //      try WordApp.Selection.Find.Wrap:=true; memoword.lines.add('Find Wrap'); except memoword.lines.add('No find wrap'); end;
  35.  
  36.     try WordApp.Selection.Find.Format:=False; memoword.lines.add('Find Format'); except memoword.lines.add('No find format'); end;
  37.  
  38.     memoword.lines.add('Ready to replace');
  39.     try
  40.       memoword.lines.add('   Find: <'+wordapp.selection.find.text+'>');
  41.       memoword.lines.add('Replace: <'+wordapp.selection.find.replacement.text+'>');
  42.       WordApp.Selection.Find.Execute(Replace := 2);
  43.       memoword.lines.add('Replaced');
  44.       memoword.lines.add('   Find: <'+wordapp.selection.find.text+'>');
  45.       memoword.lines.add('Replace: <'+wordapp.selection.find.replacement.text+'>');
  46.       if WordApp.Selection.Find.found then memoword.lines.add('Found') else memoword.lines.add('Nothing found');
  47.     except
  48.       memoword.lines.add('Did not replace')
  49.     end;
  50.  
  51.   except
  52.     memoword.lines.add('All went wrong');
  53.   end;
  54. {
  55.     try
  56. // Shut down and clean up.
  57.       WordApp.activedocument.close;
  58.       wordapp.quit;
  59.       wordapp:=unassigned;
  60.       memoword.lines.add('Shut down Word');
  61.     except
  62.       memoword.lines.add('Failed to clean up');
  63.     end;
  64. }
  65. end;                    
  66.  

My output in the memo is:-

Quote
Created OleObject
Opened word
Word visible
Find Format
Ready to replace
   Find: <the>
Replace: <#####>
Replaced
   Find: <2>
Replace: <#####>
Nothing found

It goes into the execute fine, comes out with that strange '2'.

Why don't I do it in Word - sigh.  It's part of a long chain of programs and I want to replace the unwieldy Word macro to take Word out of the loop.

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Word: search and replace
« Reply #8 on: May 05, 2016, 05:41:07 pm »
Do you know the official documentation? This is for (my) Word 2007: https://msdn.microsoft.com/en-us/library/bb244515%28v=office.12%29.aspx, maybe it's valid for your 2010, but you'll find your's easily.
« Last Edit: May 05, 2016, 05:58:38 pm by wp »

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #9 on: May 05, 2016, 06:32:53 pm »
I can't follow that, but it does have 'myrange' in it and that rings a bell from an online search I've done recently, but can't find again.

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #10 on: May 05, 2016, 06:47:41 pm »
I fixed one issue: WordApp.Selection.Find.Wrap:=1;  (Rather than ':=true;')

Still changes the find to '2'.

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #11 on: May 06, 2016, 09:05:06 am »
Tried it on a different machine with Word Home and Student 2016.  Exactly the same results.

My Lazarus is 0.9.30.

w click

  • Full Member
  • ***
  • Posts: 180
Re: Word: search and replace
« Reply #12 on: May 06, 2016, 09:46:14 am »
Bingo!!!

Thank you wp for all your help and patience.  It was the old version of Lazarus that must have been the issue.  I upgraded, ran it under 1.6 and after a little stumble, it worked first time.

Now the hard work begins, but I know that it'll work.

 

TinyPortal © 2005-2018