Welcome! Log In Create A New Profile

Advanced

[WD12] MS Word automation

Posted by Al 
Al
[WD12] MS Word automation
August 13, 2008 10:25AM
Hello All

I have to do a find and replace in a word document and can't seem to get started with the automation process. Can anyone help with a code example please.

As an alternative, a friend of mine has written a small vb script for me which does the job but I am having trouble running it from within Windev because I have to pass three parameters to it as strings and I am stuck there also.

The parameters I need to pass to exerun() as strings are
The filepath and name
The word to be replaced
The new word

Something like:
exerun("vbscript.vbs "DocumentPathAndName" "WordToReplace" "ReplacementWord")



Regards
Al

This is the VB script

'Pramas: (1) Filename with full path (2) Find Text (3) Replace Text.
'
'Example of use C:\Project.Al\ReplaceStr "C:\Project.Al\Form 01 Daily Log.doc" "XXX" "ABC"
'
'Notes: In the above example any errors will be logged to "C:\Project.Al\ReplaceStr.log", if this dir does not exist they will be logged to
' c:\ReplaceStr.log
'


'Check there are 3 Parma's
'
If Wscript.Arguments.Count <> 3 Then
pWriteLogFile "[ERROR]: 3 params are required. (1) Filename with full path (2) Find what (3) Replace with"
Wscript.Echo "[ERROR]: 3 params are required. (1) Filename with full path (2) Find what (3) Replace with"
Wscript.Quit
End If


'Store Pramas
'
strFilePath = Wscript.Arguments(0) 'Filename with path
strFind = Wscript.Arguments(1) 'Find this
strReplaceWith = Wscript.Arguments(2) 'Replace with This.
'strProcessDir = Wscript.Arguments(3) 'Verions 2: Process all files in dir. If 1 replace all files in dir else just replace single file.



'Write Log File extry.
'
'pWriteLogFile "Start"


'Check Imput File exists.
'
Set objFSO = CreateObject("Scripting.FileSystemObject")
sLogFilePathName = objFSO.GetParentFolderName(strFilePath) 'Set LogFile path as current input path

'Check LogFile Path Exists if Not set to c:\
If objFSO.FolderExists(sLogFilePathName) = False Then
sLogFilePathName = "c:\"
End If

If right(sLogFilePathName,1) <> "\" Then
sLogFilePathName = sLogFilePathName & "\"
End If
sLogFilePathName = sLogFilePathName & "ReplaceStr.log" 'Path to Log file

'Wscript.Echo sLogFilePathName

If objFSO.FileExists(strFilePath) Then

'Call pReplaceText Proc.
'
pReplaceText strFind, strReplaceWith
Else
pWriteLogFile "[ERROR]: Input file does not exist - " & strFilePath
Wscript.Echo "[ERROR]: Input file does not exist - " & strFilePath
End If

'Close File objects
'
Set objFSO = Nothing



'Proc: pReplaceText
'
Sub pReplaceText(strFind, strReplaceWith)
Const wdFindContinue = 1
Const wdReplaceAll = 2
intStrFound =0

'Create Word Object
'
On Error Resume Next
' Create new instance of Word
Set objWord = CreateObject("Word.Application")

If Err = 429 Then 'ERR_APP_NOTFOUND
pWriteLogFile "[ERROR]:Word is not installed on this computer."
WScript.Echo "[ERROR]:Word is not installed on this computer. "
WScript.Quit
End If
objWord.Visible = True


'Open Word Doc.
'
Set objDoc = objWord.Documents.Open(strFilePath)
Set objSelection = objWord.Selection


'Replace Body
'
With objSelection.Find 'or With objRange.Find
.Text = strFind
.Replacement.Text = strReplaceWith
'.Forward = False
.Wrap = 1
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.Execute ,,,,,,,,,,wdReplaceAll

If objSelection.Find.Found Then
intStrFound =1
End If
End With


'Replace Header Text
'
With objDoc.Sections(1).Headers(1).Range.Find
.Replacement.ClearFormatting
.ClearFormatting
.Text = strFind
.MatchWholeWord = True
.Wrap = wdFindContinue
.Format = False
.Replacement.Text = strReplaceWith
.Execute ,,,,,,,,,,wdReplaceAll

If objSelection.Find.Found Then
intStrFound =1
End If
End With


'Replace Footer Text
'
With objDoc.Sections(1).Footers(1).Range.Find
.Replacement.ClearFormatting
.ClearFormatting
.Text = strFind
.MatchWholeWord = True
.Wrap = wdFindContinue
.Format = False
.Replacement.Text = strReplaceWith
.Execute ,,,,,,,,,,wdReplaceAll

If objSelection.Find.Found Then
intStrFound =1
End If
End With


'Save Status
'
If intStrFound = 0 Then
pWriteLogFile "[NOT FOUND]:" & strFind & " not found in " & strFilePath
'Wscript.Echo "[NOT FOUND]:" & strFind & " not found in " & strFilePath
End If


'Save Changes and Quit Word
'
objWord.Application.Quit -1 'wdSaveChanges
Set objWord = Nothing

End Sub



'Write string to file
'
Sub pWriteLogFile(sFileContents)
Const ForWriting = 8 '2 Overwrite

If sLogFilePathName = "" Then
sLogFilePathName = "c:\ReplaceStr.log"
End If

Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFSFile = oFS.OpenTextFile(sLogFilePathName,ForWriting,True)

oFSFile.WriteLine(date & " " & time & ": " & sFileContents)
oFSFile.Close

Set oFSFile = Nothing
Set oFS = Nothing
End Sub

Bosher
Re: [WD12] MS Word automation
August 13, 2008 07:53PM
Hi Al,

Try something like this...

oWord is an object Automation "Word.Application.11"
oDoc is object Automation dynamic


You can use all the COM methods for word like

oRange = oDoc>>Range

OF course you will need to open or create a doc using COM methods first!!

You might also find DSOFramer ocx useful (Try a google search)

Tip: I don't use the merge methods. I put text placeholders I.e. [[Name]] and use COM replace text methods. Works better..

Cheers

Bob
Al
Re: [WD12] MS Word automation
August 14, 2008 04:11PM
Hello Bob

Thanks for the ideas. I will give them a go.


Regards
Al
Bosher
Re: [WD12] MS Word automation
August 14, 2008 04:25PM
Hi Al,

I have some code samples if it turn out that you need them.

Cheers

Bob

Piet van Zanten
Re: [WD12] MS Word automation
August 14, 2008 05:49PM
Hi Al,

This is an example of search and replace:

WHEN EXCEPTION 
	Error("An error has occuurred ","",...
	"Erro number: "+ExceptionInfo(errCode),...
	"Message:"+ExceptionInfo(errSummary),... 
	"Info:"+ExceptionInfo(errInfo),... 
	"During:"+ExceptionInfo(errDuring),... 
	"Procedure:"+ExceptionInfo(errProcess),... 
	"Object:"+ExceptionInfo(errElement),... 
	"Line:"+ExceptionInfo(errLine))
	
	MyWord>>Documents>>Close(OLEFalse)
	MyWord>>Quit()
	delete MyWord	
	RESULT False
END

bVisible is boolean =False

//-------BEGIN Loading and initializing Word
MyWord=GetActiveObject("Word.Application")
IF MyWord=Null THEN
	// there was no Word already opened , we allocate one 
	MyWord = new object OLE "Word.Application"//"Word.Basic"
ELSE
	IF YesNo("All active documents in Word must be closed first.","Do you want to close them?") THEN
		MyWord>>ActiveDocument>>Close(OLEFalse)
	ELSE
		RESULT False		
	END
END

MyWord>>Visible=bVisible
MyWord>>Application>>Visible=bVisible
MyWord>>Documents>>Open(DocumentName,OLEFalse,OLEFalse)
MyWord>>Selection>>WholeStory()
MyWord>>Selection>>Find>>Execute(sSearchString,OLEFalse,OLETrue,OLEFalse,OLEFalse,OLEFalse,OLETrue,1,OLEFalse,sSubstString,2)
MyWord>>Visible = OLETrue
MyWord>>Quit()
delete MyWord

sSearchString and sSubstString are the string to search and replace. It's advisable to render Word invisible, so the user cannot interfere with any keystrokes.
To learn how to do something in Word (or Excel) I always record a Macro, (menu extra) then look at the Macro (extra, macros, edit) and "translate" it using the Windev syntax.

Documents.Open FileName:="""Mydoc.doc"""

Becomes in Windev:

MyWord>>Documents>>Open("Mydoc.doc")

HTH, Best regards,
Piet
Al
Re: [WD12] MS Word automation
August 15, 2008 02:21PM
Hello Piet

Thank you very much, your code works and gives me encouragement that automation can be mastered.

I have one remaining favour to ask. I also need to find and replace in the headers and footers and from the macro I understand that I need to activate them but the conversion of the macro defeats me. I have tried all sorts of permutations without success and the error messages from WIndev are no help at all.
I am unclear how to reference the "wdPanelNone" and other "wd..." named automation items.

<pcode>
Macro
If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveWindow.Panes(2).Close
End If
If ActiveWindow.ActivePane.View.Type = wdNormalView Or ActiveWindow. _
ActivePane.View.Type = wdOutlineView Then
ActiveWindow.ActivePane.View.Type = wdPrintView
End If
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "ReplacementText "
.Replacement.Text = "SearchText"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
</pcode>

The crazy thing to me is that the macro parameters are different from those you recommend and which work. The Macro indicates that the find and replace strings are the first two parameters but your code has them as the first and the last parameters, yet it works fine.

Anyway, can you help with a translation of the header macro into Windev code.
The footer will be the same with a name change to "CurrentPageFooter"
I presume the macro code activates the header pane and then does a find and replace.

Regards
Al
Piet van Zanten
Re: [WD12] MS Word automation
August 15, 2008 03:54PM
Hi Al,

I'm not in the office right now, but I can give you some hints already.
The code I gave you is a code that I used in WD5, I'm still using it in WD12. That's probably why the current version of Word would produce other macro's for the same task.
wdPanelNone is a constant. So are the other wdXXX's. You can to find out their value's if you open the Visual Basic editor in Word and create a userform with a textbox and a button. In the button click code type TextBox1=wdPanelNone
If you run the userform and click the button the textbox will display the numerical value of the constant. (btw: wdPanelNone is zero, so the textbox remains blank)
I should have a small list of the ones I use already. Perhaps there's a list on the web somewhere too.

I'll get back to you on this. Meantime keep me posted if you made any progress.

Best regards,
Piet
Al
Re: [WD12] MS Word automation
August 15, 2008 05:51PM
Hello Piet

Thanks, that was the missing piece of the puzzle.

It now works ok on the header, body and footer

I found the constant values on the web as you suggested

The code I am now using is as follows

<pcode>
//define these constants in the project init
CONSTANT
wdPaneNone = 0
wdOutlineView = 2
wdNormalView = 1
wdPrintView = 3
wdSeekCurrentPageHeader = 9
wdSeekCurrentPageFooter = 10
END

LFindString is string = ""
LReplaceString is string = ""
MyWord is object OLE dynamic
IF MyWord <> Null THEN
MyWord>>Visible = OLETrue
MyWord>>Quit()
END
bVisible is boolean =False
MyWord=GetActiveObject("Word.Application")
MyWord>>Visible=bVisible
MyWord>>Application>>Visible=bVisible

//find and replace in the body of the document
MyWord>>Documents>>Open(LJobDirDoc,OLEFalse,OLEFalse)
MyWord>>Selection>>WholeStory()
MyWord>>Selection>>Find>>ClearFormatting
MyWord>>Selection>>Find>>Replacement>>ClearFormatting
MyWord>>Selection>>Find>>Execute(LFindString,OLEFalse,OLETrue,OLEFalse,OLEFalse,OLEFalse,OLETrue,1,OLEFalse,LReplaceString,2)

//find and replace in the header of the document
MyWord>>ActiveWindow>>ActivePane>>View>>SeekView = wdSeekCurrentPageHeader
MyWord>>Selection>>Find>>ClearFormatting
MyWord>>Selection>>Find>>Replacement>>ClearFormatting
MyWord>>Selection>>Find>>Execute(LFindString,OLEFalse,OLETrue,OLEFalse,OLEFalse,OLEFalse,OLETrue,1,OLEFalse,LReplaceString,2)

//find and replace in the footer of the document
MyWord>>ActiveWindow>>ActivePane>>View>>SeekView = wdSeekCurrentPageFooter
MyWord>>Selection>>Find>>ClearFormatting
MyWord>>Selection>>Find>>Replacement>>ClearFormatting
MyWord>>Selection>>Find>>Execute(LFindString,OLEFalse,OLETrue,OLEFalse,OLEFalse,OLEFalse,OLETrue,1,OLEFalse,LReplaceString,2)

MyWord>>Quit(-1)
delete MyWord
</pcode>


At this point I was just concerned with getting it working so I have left out all the tests that were in the macro code. I will play with them later. I still don't have a real understanding of what I am doing with this, I have just followed your lead, but I have something to build on now.

It seems quite straightforward once you know the basics and I am astounded that PCSoft do not include examples of how to translate a office macros into Windev

Thanks again for your generous help.

Regards
Al










Author:

Your Email:


Subject:


Spam prevention:
Please, enter the code that you see below in the input field. This is for blocking bots that try to post this form automatically. If the code is hard to read, then just try to guess it right. If you enter the wrong code, a new image is created and you get another chance to enter it right.
Message: