Welcome to the SRP Forum! Please refer to the SRP Forum FAQ post if you have any questions regarding how the forum works.
SRP_COM 64 bit
Hi
Last year I had problems with SRP_COM and WORD automation in OI10.2.0. I saw a new release of SRP Utilities and thought this may fix it.
However, I still get an error 80020005 whenever I attempt the following:
oSaveAs = SRP_Com(oDocHandle2, "CALL", "SAVEAS2", pdfName, wdFormatPDF$)
where pdfName = "foo.pdf" and wdFormatPDF$ = 17
oPrintOut = SRP_Com(oDocHandle2, "CALL", "PRINTOUT",wdBackground$)
where wdBackground$ = 0
As a matter of interest, the corresponding OI10.2.1 OLE functions fail as well.
Thanks
Last year I had problems with SRP_COM and WORD automation in OI10.2.0. I saw a new release of SRP Utilities and thought this may fix it.
However, I still get an error 80020005 whenever I attempt the following:
oSaveAs = SRP_Com(oDocHandle2, "CALL", "SAVEAS2", pdfName, wdFormatPDF$)
where pdfName = "foo.pdf" and wdFormatPDF$ = 17
oPrintOut = SRP_Com(oDocHandle2, "CALL", "PRINTOUT",wdBackground$)
where wdBackground$ = 0
As a matter of interest, the corresponding OI10.2.1 OLE functions fail as well.
Thanks
Comments
Using your example, the SAVEAS2 call would like something like this (Note: I didn't test this in Word or anything):
SRP_Com('', 'BEGINCALL') SRP_Com('', 'ADDPARAM', 'Value', pdfName) SRP_Com('', 'ADDPARAM', 'Value', wdFormatPDF$) SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') SRP_Com('', 'ADDPARAM', 'Omitted') oSaveAs = SRP_Com(oDocHandle2, 'ENDCALL', 'SAVEAS2')
Tried that, got the same error 80020005. I checked the number of parameters and it is correct.
This problem only arose in OI10 - with OI9 it worked perfectly. So it must be a 64 bit issue.
Regards
Nick
In OI9, does it work if you only pass in the FileName and FileFormat arguments? Also, does it work in OI 9 with both SRP_COM and the native OLE functions?
I've not tried to work with OLE automation and Word yet. I've done extensive work with Excel. It has a SaveAs method (not SaveAs2). These methods are similar in that they both have several optional arguments. I found that I'm able to leave out those optional arguments if they appear at the end, but if I need to skip any then I need to use the method that Kevin posted.
SRP_Com(objWorkbook@, 'CALL', 'SaveAs', DocumentPath, xlWorkbookDefault$, DocumentPassword)
What does that mean? Not sure other than SaveAs works for Excel in 32-bit and 64-bit. Therefore, I am a bit surprised that it isn't working for Word. I'm eager to get your answer to my 32-bit questions.
P.S. I doubt that it matters, but SaveAs and SaveAs2 return nothing which is why my syntax is called as a routine rather than a function.
The reason I'm trying this now is because we want to move away from 3rd party software (like Broadgun).
Never had a problem passing parameters - the ones I needed were always first in line so never had a missing one to deal with.
First, replace "Omitted" with "Object" in the above ADDPARAM lines and see if that makes a difference. By using "Object" and not supplying a third parameter, it should pass a NULL reference to Word.
If that doesn't work, it would be helpful to have some code to replicate. I can slap something together, but it'll take me some time. If, however, you have a stand-alone routine I can run, I'll be able to isolate the issue sooner.
Here is some code cobbled together to illustrate the problem. Adjust the RUN VARIABLES to point to an existing WORD document, and choose whether to use native OI OLE or SRP_COM, and whether you want to just print the document or save as a PDF.
You'll find the native OI works in OI9+ for both printing and saving as PDF.
But SRP_COM fails on save as PDF in both OI9+ and OI10+ as well as fails to print if wdBackground$ is a parm.
compile subroutine OLE_Word_Automation_test(err)
/* Author NS
Date December 2017
Purpose To automate a mail merge using OLE
*/
Declare Function OleCreateInstance, OleGetProperty, OleStatus, Msg, srp_com
Declare Subroutine OlePutProperty
$insert msg_equates
* SET RUN VARIABLES ******************************************************************************************
**************************************************************************************************************
MergeDocument = 'I:\Development\IPS_DEV_94\Documents\mytestdocument.docx' ;* full path and filename of WORD document
FileToSaveAs = 'I:\Development\IPS_DEV_94\Documents\mytestdocument.pdf' ;* full path and filename of PDF file to create
printToPDF = 1 ;* set to 1 to SAVEAS PDF, set to 0 to just print to default printer
*oleMethod = 'SRP' ;* use SRP OLE wrapper SRP_COM
oleMethod = 'OI' ;* use OI OLE functions
**************************************************************************************************************
**************************************************************************************************************
* set process vars
oleError = ''
* make sure the FileToSaveAs file does not exist
if len(FileToSaveAs) and FileToSaveAs # MergeDocument then
osDelete FileToSaveAs
End
DEBUG
* create Word instance
if oleMethod = 'OI' then
oWordApp = OleCreateInstance("Word.Application")
end else
retVal = SRP_Com(oWordApp, 'CREATE', "Word.Application")
end
gosub CheckError
* get next document handle
if OleStatus else
if oleMethod = 'OI' then
oNextHandle = OleGetProperty(oWordApp, "DOCUMENTS")
end else
oNextHandle = SRP_Com(oWordApp, "GET", "DOCUMENTS")
end
gosub CheckError
end
* make Word visible but minimised
if OLEStatus else
wdVisible$ = 1
if oleMethod = 'OI' then
OlePutProperty(oWordApp, "VISIBLE", wdVisible$)
end else
Result = SRP_Com(oWordApp, "SET", "VISIBLE", wdVisible$)
end
gosub CheckError
if OleStatus else
wdMinimise$ = 2
if oleMethod = 'OI' then
OlePutProperty(oWordApp, "WINDOWSTATE", wdMinimise$)
end else
Result = SRP_Com(oWordApp, "SET", "WINDOWSTATE", wdMinimise$)
end
gosub CheckError
end
end
* open the Word document
if OleStatus else
if oleMethod = 'OI' then
oDocHandle = OleCallMethod(oNextHandle, "OPEN", MergeDocument)
end else
oDocHandle = SRP_Com(oNextHandle, "CALL", "OPEN", MergeDocument)
end
gosub CheckError
end
* print the document or save as PDF
if OLEStatus else
if PrintToPDF then
* uses Word to SAVEAS PDF
wdFormatPDF$ = 17
*https://learn.microsoft.com/en-us/office/vba/api/word.saveas2
if oleMethod = 'OI' then
oSaveAs = OleCallMethod(oDocHandle, "SAVEAS2", FileToSaveAs, wdFormatPDF$)
end Else
srpVal = SRP_Com('', 'BEGINCALL')
srpVal = SRP_Com('', 'ADDPARAM', 'Value', FileToSaveAs)
srpVal = SRP_Com('', 'ADDPARAM', 'Value', wdFormatPDF$)
For xx = 1 To 15
srpVal = SRP_Com('', 'ADDPARAM', 'Object')
Next xx
oSaveAs = SRP_Com(oDocHandle, 'ENDCALL', 'SAVEAS2')
*oSaveAs = SRP_Com(oDocHandle, "CALL", "SAVEAS2", pdfName, wdFormatPDF$)
end
end Else
* prints the document to the selected device
wdBackground$ = 0
*https://learn.microsoft.com/en-us/office/vba/api/word.application.printout
if oleMethod = 'OI' then
oPrintOut = OleCallMethod(oWordApp, "PRINTOUT",wdBackground$)
*oPrintOut = OleCallMethod(oDocHandle, "PRINTOUT",wdBackground$)
end else
oPrintOut = SRP_Com(oWordApp, "CALL", "PRINTOUT", wdBackground$)
* seems to be a problem with wdBackground$ parm, so dropped it
*oPrintOut = SRP_Com(oDocHandle, "CALL", "PRINTOUT")
end
* seems to be a problem with wdBackground$ parm, so dropped it
end
gosub CheckError
end
* close the Word document
if OLEStatus else
wdSaveChanges$ = 0
if oleMethod = 'OI' then
oCloseNew = OleCallMethod(oDocHandle, "CLOSE", wdSaveChanges$)
end else
oCloseNew = SRP_Com(oDocHandle, 'CALL', "CLOSE", wdSaveChanges$)
end
gosub CheckError
end
* always try to quit even with previous error so that Word isn't holding the document locked
wdSaveChanges$ = 0 ;* -2
* clear idispatch variables in the REVERSE order they were created
if oleMethod = 'SRP' then
retVal = SRP_Com(oCloseNew, 'RELEASE')
retVal = SRP_Com(oPrintOut, 'RELEASE')
retVal = SRP_Com(oSaveAs, 'RELEASE')
retVal = SRP_Com(oDocHandle, 'RELEASE')
retVal = SRP_Com(oNextHandle, 'RELEASE')
end
oCloseNew = ""
oPrintOut = ""
oSaveAs = ""
oDocHandle = ""
oNextHandle = ""
* quit word application
if oleMethod = 'OI' then
Quit = OleCallMethod(oWordApp, "QUIT", wdSaveChanges$)
end else
Quit = SRP_Com(oWordApp, 'CALL', "QUIT", wdSaveChanges$)
end
* clear final idispatch variable
if oleMethod = 'SRP' then
retVal = SRP_Com(Quit, 'RELEASE')
retVal = SRP_Com(oWordApp, 'RELEASE')
end
Quit = ""
oWordApp = ""
gosub CheckError
Return
*-------------------------------------------------------------------------------
CheckError:
* get the error
OleStatus = ''
if oleMethod = 'OI' then
OleStatus = OleStatus()
end else
if SRP_Com('', 'ERROR') then
OleStatus = SRP_Com('', 'ERROR')
end
end
* see if the error is in the errors file
if OleStatus then
oleErrorDesc = ''
wdVisible$ = -1
if oleMethod = 'OI' then
OlePutProperty(oWordApp, "VISIBLE", wdVisible$)
end else
Result = SRP_Com(oWordApp, "SET", "VISIBLE", wdVisible$)
end
msg_def = ""
msg_def<3> = 'S'
msg_def = "BO"
msg_def = -2
msg_def = 'OLE fatal error: ':OleStatus
msgRetVal = MSG(@WINDOW,msg_def)
oleError = OleStatus
end
Return
*-------------------------------------------------------------------------------
When using COM automation, all parameters are passed as VARIANTs. These huge structures cover all the known types and it's up to Word to correctly convert these variants into whatever it needs. Most COM servers will do a good job converting a huge variety of VARIANTs if possible. For example, I can give Excel a number as a string (variant type VT_BSTR) or any variety of number(VT_INT, VT_UI8, etc.) and Excel will be able to handle it. Word, however, picks a single variant type and sends our beloved Type Mismatch exception when it doesn't get precisely what it wants. As you can see here, there are lot of variant options.
So, what was happening was that I was sending a variant of type VT_INT when you passed the file format type, but Word insists that it must be VT_I4. The difference is that VT_INT will be 32-bit on 32-bit Windows and 64-bit on 64-bit Windows whereas VT_I4 is always 32-bit. It took a LOT of google searches before I found this to be the issue. Microsoft does not document anywhere what VARIANT types it expects. If Microsoft is going to be picky, it should let users know. I had to discover the solution on an obscure reddit post.
With that, I give you version 2.2.11.0 of the SRP Utilities. It will now convert to VT_I4 for numbers that are recognized to fit within a signed 32-bit integer, instead of using VT_INT. You may also go back to using the simpler CALL service rather than the more complication BEGINCALL...ENDCALL. In my test, the following worked fine:
oSaveAs = SRP_Com(oDocHandle, "CALL", "SAVEAS2", FileToSaveAs, wdFormatPDF$)
Really appreciate your help! The SAVEAS is working perfectly, however I still get the dreaded 80020005 when printing, using:
wdBackground$ = 0
oPrintOut = SRP_Com(oDocHandle, "CALL", "PRINTOUT", wdBackground$)
If I remove the wdBackground$ parameter, the error goes away, but then WORD releases control back to the calling proc and WORD gets closed before the printing is finished, leaving a corrupted or partial document on the printer. I think background printing is usually set on WORD installs so I need to override it.
I may have a workaround by using
oBusy = SRP_Com(oWordApp, "GET", "BACKGROUNDPRINTINGSTATUS")
But just thought I'd let you know anyway.
Many thanks,
Nick