Jump to content
emendelson

Microsoft Word: run macro if it exists? or skip error if it doesn't?

Recommended Posts

emendelson

In another thread, with the expert help of user "water", I was able to put together a script that imports a WordPerfect document into Word and then exports it in Word format. Here is the briefest possible version:

$infile = @ScriptDir & "\test.wp"
$outfile = @ScriptDir & \test.docx"

$oWord = _Word_Create(False, True)
$oDoc = _Word_DocOpen($oWord, $infile, False)
$oDoc = $oWord.ActiveDocument
$oWord.Run("WPtoWordMacro")
_Word_DocSaveAs($oDoc, $outfile)
_Word_DocClose($oDoc)
_Word_Quit($oWord)

If the Word macro "WPtoWordMacro" does NOT exist, then the script crashes at the point where the macro is supposed to run.

In a VBS script I can avoid the crash by adding "On Error Resume Next" before that line, and "On Error GoTo 0" after it. I've searched the forum, and I see that similar problems have been discussed often, but I can't find a solution. Is there a solution?

I thought it might be possible to test whether the macro exists, but that seems even more complicated.

 

Share this post


Link to post
Share on other sites
emendelson

To answer my own question. I didn't look deeply enough. The top line and function in the script snippet here seems to do the trick:

US/UK/CA/AUS, etc. users can easily translate the error message from French. This does seem to work.

Share this post


Link to post
Share on other sites
water

That's a COM error handler.
All _Word* functions internally call such a handler. When you use the Word object model on your own you need to define such a handler.
I suggest to set the handler at the top of your script. The handler just needs to set @error to the raised error number and then return.
Then you simply can check for an error by adding

If @error Then ...

after you have processed a Word object.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
emendelson

Thank you again - I'm not sure whether I'm making things more complicated than they need to be, but here goes: following your advice in another thread, I added this function:

Func MyErrFunc($oMyError)
    Local $HexNumber
    Local $strMsg
    $HexNumber = Hex($oMyError.Number, 8)
    $strMsg = "Error Number: " & $HexNumber & @CRLF
    $strMsg &= "WinDescription: " & $oMyError.WinDescription & @CRLF
    $strMsg &= "Script Line: " & $oMyError.ScriptLine & @CRLF
    If Not @Compiled Then
        MsgBox(0, "Error", $strMsg)
    EndIf
    SetError(1)
EndFunc   ;==>MyErrFunc

and this line near the top of the script:

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")

And this seems to do a nice job of trapping the error. If I'm doing something foolish, I hope you'll tell me! Thank you again and again for this.

PS One further question: there seems to be a long delay before Word figures out that the macro I call for isn't present, and that an error condition occurs. Is there a way to speed this up, or should I simply live with it?

Share this post


Link to post
Share on other sites
water

I would remove line

SetError(1)

because @error would always be set to 1 after an error. When the line has been removed @error is set by AutoIt to the COM error returned by Word.
Query @error by simply

If @error Then ...

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
emendelson

Thank you again. I know this is an absurdly ignorant question, but when you say Query @error with "If @ error Then..." am I right to think that the lines that should follow "Then" would be a MsgBox, or a ConsoleWrite, or some other way of communicating what the error is?

I think that's my last question on this subject - you've been more than generous already.

 

Share this post


Link to post
Share on other sites
water

That's correct. Most of the time you exit your program when an error occurres. Most of th time the result of a function in error is undefined.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
water
2 hours ago, emendelson said:

PS One further question: there seems to be a long delay before Word figures out that the macro I call for isn't present, and that an error condition occurs. Is there a way to speed this up, or should I simply live with it?

The error handling should be quite fast. Most of the time is used to start up Word and read/open the document.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
emendelson

Thank you again! I'm now trying to add a log option the error handler, and when I get it working will post some code here.

Share this post


Link to post
Share on other sites
water

You could have a look at my OutlookEX UDF. There you'll find function _OL_ErrorNotify. This allows to create a COM error handler and send the output to a log file, MsgBox, Console or just ignore it.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
emendelson

I'll definitely look at your OutlookEX UDF. Before I saw your message, I threw together this error handler for my script.

I inserted $errLoc = "101" (etc.) before each line of code that runs Word, except that I inserted $errLoc = "Macro" before the line where I want to continue after the error. The StringLen line in the error handler limits the log file and the attempt to quit Word to $errLoc variables with three characters only (so "101" but not "Macro"):

Func MyErrFunc($oMyError)
    Local $HexNumber
    Local $oMyRet[1]
    Local $strMsg
    $HexNumber = Hex($oMyError.number, 8)
    $oMyRet[0] = $HexNumber
    $oMyRet[1] = StringStripWS($oMyError.description, 3)
    $strMsg = "### Com Error:  Number: " & $HexNumber & "  ScriptLine: " & $oMyError.scriptline & "  Description:" & $oMyRet[1] & @CRLF
    ConsoleWrite($strMsg)
    ; If Not @Compiled Then
    If $VBSerror = 1 Then
        MsgBox(0, "Error", $strMsg)
    EndIf
    If StringLen($errLoc) = 3 Then
        $x = FileOpen(@ScriptDir & "\" & @ScriptName & ".log", 1)
        FileWriteLine($x, "Location: " & $errLoc & " " & $strMsg)
        FileClose($x)
        _Word_Quit($oWord)
    EndIf
    Return
EndFunc   ;==>MyErrFunc

At the top of the script I insert:

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")
Global $errLoc, $oWord
FileDelete(@ScriptDir & "\" & @ScriptName & ".log")

Instead of that second "Global" line, I thought I could simply use: Func MyErrFunc($oMyError, $errLoc, $oWord) at the start of the function, but it seemed to stop things from working, presumably because I don't understand how functions work.

I know this is held together with paperclips and rubber bands, but it seems to work. Any improvements would of course be very welcome.

Edited by emendelson

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×