Open Word Document Run-time error '424': Object required - vba

I have a set of functions in an Access database where I am generating Word documents based on a fixed template in a folder.
I am doing this with the function shown below. For easier maintenance, I would like to be able to define the Word-template paths as public constants in the begining of my module. And therefore, I have been trying to create the adjusted function below.
Original function:
Function MyFunc(rs as DAO.Recordset)
Dim objWord As Object
Dim objDoc As Object
...
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open("C:\test_template.docx")
...
End Function
Adjusted function:
Public Const ReminderOneTemplate As Variant = "C:\test_template.docx"
...
Function MyFunc(rs as DAO.Recordset)
Dim objWord As Object
Dim objDoc As Object
...
Set objWord = CreateObject("Word.Application")
for the Word.Documents.Open method in the next, subsequent line of code I have tried this:
Set objDoc = objWord.Documents.Open(ReminderOneTemplate)
...
End Function
and
Set objDoc = objWord.Documents.Open(Chr(34) & ReminderOneTemplate & Chr(34))
...
End Function
But the function keeps returning Run-time error '424' Object required when I use a constant as input to the Word.Documents.Open method.
Can anyone explain why this is the case and what I am doing wrong. Is it not possible to pass a Constant to the Word.Open method?
Thanks.

I refactored your function, using the following sub procedure to test the basic code of creating a Word instance, and then opening an existing document using a constant for the document name.
I used Office 2007 to test the code, and everything worked fine. I don't see anything wrong with your code, what version of Access and Word are you using? Notice that I added some code to test whether the objWord variable is actually assigned a value by the call to CreateObject. I would suggest 2 things to help try to resolve the problem you are having:
1. use a String for the filename. I know the documentation for the Open method of the Documents collection says that the filename argument is a Variant, but the code does seem to work better if it is a String.
2. Make sure you set the instance of Word to be visible, otherwise you clutter up your system with invisible instances of Word (which will not be listed in Task Manager) and the only way to get rid of them is to restart the computer. If the Word instance is visible, you can switch to it and see if Word is displaying any error messages.
You may notice that the Word document my code opens is a macro-enabled .docm file. I did this because I tested whether a document with an Open event-handler that caused a runtime error would show the error message in the code in Access, but it does not.
When I first ran the code with the constant declared as a Variant, I did get an error, but not the Object required error that is giving you a problem. I then noticed that when I re-opened the Word document in Word, that I got an error message from Word that "the last time this document was opened it caused a serious error, are you sure you want to continue to open the document?" I would suggest you make sure that you can open your Word document in Word without errors or problems. I also suggest you add code similar to what I have in the example below to ensure that the objWord variable is indeed being initialized by the CreateObject method -- if CreatObject is failing to create an instance of Word, then objWord will still be Nothing, and might then produce an object required runtime error. (problems in the Registry can make CreateObject fail.)
I'm really sorry, but I have no idea why you are getting the error you are getting. I think if you redeclare the constant as a String, and ensure that you make the Word instance visible, that your code will work! The only problem I had when testing was that the document failed to open until I added the code to make the Word instance visible. But I did not get the same error that you are trying to overcome.
I have develop a library of Access VBA code for exactly this type of task -- using code in Access to create instances of Word, Excel, and to open documents and worksheets. If you think looking at a code library designed to provide easily called procedures and functions for inter-operability among MS Office applications, you can download it from here: [http://www.didjiman.com/business/vbademo/libMSOffice.htm] The code in the library has been tested to work in all versions of MS Office from 2003 though 2016, and is released to the public under the Gnu public license. The code is in a zip archive that contains an Access .accdb file with all the code, and a PDF document discussing the functions and procedures, and how to use them, along with complete code listings.
Public Const ReminderOneTemplate As String = "C:\users\matthew\documents\temp\test document1.docm"
Sub testWord_DocOpen()
Dim objWord As Object
Dim objDoc As Object
Set objWord = CreateObject("Word.Application")
objWord.Visible = True 'make the Word application window visible
objWord.Application.WindowState = 1 'maximize the Word application window
If (objWord Is Nothing) Then
Debug.Print "Word object NOT initialized."
End If
Set objDoc = objWord.Documents.Open(ReminderOneTemplate)
End Sub

Related

VBA : Enexpected running VBA from cmd line

I wanted to open an existing ppt using Wscript and modify it. For that I am opening the file in visual studio editor and executing the script from cmd in windows using WScript hi.vbs
But when I ran the same code I am getting error.
Expected end of statement in line 4
Line 4 looks like Dim objNewPowerPoint As Object
However Same case works when I run code in excel VBA editor.
When I am removing the As object I am not getting any error nor any changes are happening in the PPT file.
Wondering what is the possible issue.
I am not using excel vba or word vba i am just running the file from cmd
Sub Open_an_existing_Presentations()
Dim objNewPowerPoint As Object
Dim MyPresentation As Object
Dim pSlides As Object
Set objNewPowerPoint = CreateObject(PowerPoint.Application)
'Make this Application Object Visible
objNewPowerPoint.Visible = True
Please help me how can i modify and more importantly how to see both errors compile and syntax.
FYI : I am completely new into VBA and I am trying to update a PPT and wanted to run vba script from another program so trying something like this. Best suggestions are always welcome
In VBScript you cannot dim something as something.
Dim objNewPowerPoint
Dim MyPresentation
Dim pSlides
And dim is optional and serves no technical purpose in VBS (it merely catches spelling mistakes if Option Explicit is specified, else it does nothing at all as in your case except take time to the process the line). In compiled languages it allocates storage and checks data types when using it.
When you use Set = VBS knows it an object and makes it one (4 x 32 bit integers - One a reference count and another a memory address of the function table for the object - two are unused). If you use x=5555 vbs knows it's a integer.

Getting UCase, Trim, Left libary errors in VBA

I have a application that opens excel files. When I run a macro function in my excel that was opened with the application. I'm getting Compile error "Can't find project or library" on the "UCase" "Trim" "Left" just to name a few. In my macro functions, I have multiply cases of using the above functions. I also have references to "Visual Basic For Application", "Microsoft Excel 12.0 Object Library", "OLE Automation", "Microsoft Office 12.0 Library", Microsoft Forms 2.0 Object Library."
If I run excel by itself without the application, there is no errors. Is there any explanation to why this is happening? Libraries mix match? Works fine for the developer and a few but as for the rest of users, they will get these errors.
It's because those methods belong to Excel Application so that you must call them by preceding their name with the Excel object name (and possibly with its relevant member, too) you must have instantiated before
for instance
example 1: late binding
Option Explicit
Sub LateBindingExcel()
Dim xlApp As Object 'declaring your application object as of "Object" type doesn't require any reference to Excel library
' open an Excel session
Set xlApp = CreateObject("Excel.Application")
' call Excel application WorksheetFunction.Trim()
MsgBox xlApp.WorksheetFunction.Trim(" see how spaces get trimmed by this function ")
End Sub
example 2: early binding
Option Explicit
Sub EarlyBindingExcel()
Dim xlApp As Excel.Application 'declaring your application object as of "Excel.Application" type requires adding Excel library reference to your project
' open an Excel session
Set xlApp = CreateObject("Excel.Application")
' call Excel application WorksheetFunction.Trim()
MsgBox xlApp.WorksheetFunction.Trim(" see how spaces get trimmed by this function ")
End Sub
one sensible difference between the two binding "styles" is that the latter allows you exploiting IntelliSense features while the former doesn't
It is likely due to the 'Visual Basic for Applications' in the Tool reference refers to non-presence library. This may happen if the developer use the library in their customized directory instead of default library.
There are 2 means to solve the issue.
Make global replacement of all string related functions (Format, Left, Right, Mid, Trim etc) with prefix VBA. e.g. VBA.Left. This will force the use of functions within standard library.
Move all your excel sheets to another new workbook and then, select the 'Visual Basic for Applications' from Tool reference.

How to access a Word public variable in Excel VBA

I'm trying to automate some report generation where Excel VBA is doing all the work. My employer has a standardized set of templates of which all documents are supposed to be generated from. I need to populate one of these templates from Excel VBA. The Word templates utilize VBA extensively.
This is (some of) my Excel VBA code:
Sub GenerateReport() ' (Tables, InputDataObj)
' code generating the WordApp object (works!)
WordApp.Documents.Add Template:="Brev.dot"
' Getting user information from Utilities.Userinfo macro in Document
Call WordApp.Run("Autoexec") ' generating a public variable
Call WordApp.Run("Utilities.UserInfo")
' more code
End sub
In the Word VBA Autoexec module, a public variable named user is defined and declared. The Userinfo sub from the Utilities module populates user. Both these routines are run without any complaints from VBA. I would then like to be able to access the user variable in my Excel VBA, but I get the following error
Compile Error: Variable not yet created in this context.
How can I access the Word VBA variable in Excel VBA? I thought it more or less was the same?
EDIT: the user variable is a user defined Type with only String attributes. Copying the Word VBA functions that populate the user variable is absolutely doable, just more work than I though was necessary...
In a Word module:
Public Function GetUserVariable() As String '// or whatever data type
GetUserVariable = user
End Function
In an Excel module:
myUser = WordApp.Run("GetUserVariable")
Alternatively, you could be able to replicate the variables value - as it's called user I suspect it is returning some information about a user, or author, of a document. In which case one of the following might be what you're after:
'// Username assigned to the application
MsgBox WordApp.UserName
'// Username defined by the system
MsgBox Environ$("USERNAME")
'// Name of the author of the file specified
MsgBox CreateObject("Shell.Application").Namespace("C:\Users\Documents").GetDetailsOf("MyDocument.doc", 9)
Another option - if you could only add a line of code to the Utilities.UserInfo sub (after setting your public variable):
ActiveDocument.Variables("var_user") = user
Then you could access it easily afterwards in Excel:
Sub GenerateReport() ' (Tables, InputDataObj)
' code generating the WordApp object (works!)
'I am assuming your WordApp object is public, as you don't declare it.
'Capture the new document object
Dim newdoc as Object
set newdoc = WordApp.Documents.Add(Template:="Brev.dot")
' Getting user information from Utilities.Userinfo macro in Document
Call WordApp.Run("Autoexec") ' generating a public variable
Call WordApp.Run("Utilities.UserInfo")
'Get and show the value of "user"
Dim user as String
user = newdoc.Variables("var_user")
msgbox, user
End Sub
This is assuming that useris a string.
EDIT: As it is a requirement to work only on the Excel VBA, I would definely try the approach suggested by Scott and MacroMan - replicating the same functionality of the Word macros in Excel - if possible.
I assume that you've already ruled out the possibility of using an edited copy of the original template, set in a public folder...
For the sake of completness, there is another possibility: actually it is possible to inject VBA code in a Word document without the VBProject Object Model, by "brute force". If you rename a Word document as a .zip file and open it, you will notice a \word\vbaProject.bin file in it. This file contains the VBA project for the document and, in principle, one could add or change VBA code by modifying or replacing it.
I did some tests transplanting code from one document to another by simply copying the vbaProject.bin file, and the concept works. If you are interested in learning more about this file, this topic could be of use.
Notice, however, that to do what you want with such a technique would be somewhat complex (it would involve, for starters, updating zip files from your Excel VBA), and would require a lot of experimentation to mitigate the risk of accidentally corrupting your files. Definetly not recommended if you are looking for an easy and simple solution - but it is possible.

Why doesn't code work in VB.net, but works in VBA; GetObject

VBA code works great:
Sub testVBA()
Dim wb As Object ' Lotus123.Document
Set wb = GetObject("S:\Temp\T\0375D.WK3", "Lotus123.Workbook")
End Sub
VB.net code fails:
Sub TestVBNet()
Dim wb As Object ' Lotus123.Document
wb = GetObject("S:\Temp\T\0375D.WK3", "Lotus123.Workbook")
End Sub
In VB.net I get a FileNotFoundException: "File name or class name not found during Automation operation."
As I can run it from VBA that means the file exists and that the class name exists. So why doesn't it work and how can I fix it in VB.net.
EDIT: I guess I'm not sure how to start diagnosing this: Obviously the class exists on my computer but somehow VB.net doesn't manage to find it. Maybe VB.net uses a different method to activate the class. Maybe a registry entry is missing. I am glad for any suggestions.
Edit 2: I also tried using CreateObject and got this error: "Cannot create ActiveX component." Not unexpected.
For some reason VB.net cannot find the class name "Lotus123.Workbook" so I tried getting the file without the class name and it works fine in XP.
Dim wb As Object ' Lotus123.Document
wb = GetObject("S:\Temp\T\0375D.WK3")
EDIT: In Win8 64bit the above doesn't work; just hangs.
The code below works in XP 32 bit as well as in Win8 64 bit. I checked with process monitor what is happening under the hood. CreateObject checks for the CLSID in the registry using the given object. Then it looks up the necessary info using the CLSID.
Public Shared Function GetLotusWB(ByVal sFile As String) As Object
'HKCU takes precedence if exists
'HKCU\Software\Classes\Lotus123.Workbook\CLSID
'HKCU\Software\Classes\CLSID\{29130007-2EED-1069-BF5D-00DD011186B7}
'normally this is used because Lotus123 doesn't create HKCU entries
'HKCR\Lotus123.Workbook\CLSID = {29130007-2EED-1069-BF5D-00DD011186B7}
'HKCR\CLSID\{29130007-2EED-1069-BF5D-00DD011186B7}\InprocHandler32 = ole32.dll
'HKCR\CLSID\{29130007-2EED-1069-BF5D-00DD011186B7}\LocalServer32 = C:\Lotus\123\123w.exe
'using object as that sometimes works better
Dim LotusObj As Object = CreateObject("Lotus123.Workbook")
'get application
'need a reference to Lotus 123 else declare as Object
Dim LotusApp As Lotus123.Application = LotusObj.Application
'FAILS: LotusApp.Visible = True
'open file; also works fine As Lotus123.Document
Dim ldoc As Object = LotusApp.OpenDocument(sFile)
'visible and activate (must declare as Object else gives exception)
Dim appObject As Object = ldoc.Application
appObject.Visible = True
ldoc.Activate()
Return ldoc
End Function
This works great because it creates the "Lotus123.Workbook" which is used to get the application object.
Load the file into an Excel workbook. It should be able to convert the lotus123 workbook on the fly.
First of all, check to make sure your inclusions (I think under Tools menu, includes or references or something like that) include the library that references Lotus123.Document. Chances are it's in the "Microsoft Excel 14.0 Object Library" or similar.
I've heard it said that VB is not VBA!

Calling an External VBA from VBScript

I am using a program called mathtype to pull some equation objects out of a word document. I've written code in VBA that works perfectly using their API, but I have to translate it to a VBScript file. I have looked all over google, but have not found any solution on how (If it is even possible) to call a VBA library from VBScript.
VBScript can't see the MathTypeSDK Objects/Functions.
If not possible, how would I encase the macro I need to run in a globally available word file and call it from the VBScript?
Edit: Got it! Unfortunately the approaches below, while helpful, did not work for my situation. I found something closer: Embedding the macro in a global file and calling it through the Word Objects Run command.
objWord.Run "Normal.NewMacros.RunMain"
Here is an approach which might work for you. I tested this simple example.
Class "clsTest" in file "Tester.docm":
Public Sub Hello()
MsgBox "Hello"
End Sub
Class "Instancing" is marked "PublicNotCreatable".
Module in "Tester.docm":
Public Function GetClass() As clsTest
Set GetClass = New clsTest
End Function
In your vbscript:
Dim fPath, fName
fPath = "C:\Documents and Settings\twilliams\Desktop\"
fName = "Tester.docm"
Dim wdApp, o
Set wdApp = CreateObject("word.application")
wdApp.visible=true
wdapp.documents.open fPath & fName
Set o = wdApp.Run("GetClass")
o.Hello
Set o=nothing
Again - I only tested this simple example: you'll have to adapt it to your situation and try it out.
Word-VBA was not made to create reusable libraries, I suppose (for usage in external programs).
One way to reuse existing Word-VBA code is, however, run Word via WScript.Shell.Run using the /m<macroname> command line switch (see http://support.microsoft.com/kb/210565/en-us for details). This, has the restriction that evertime you need to call a specific macro, a Word process is started again, running that macro, and ends afterwards. Means, if you need just one call to your Word.VBA for a specfific task, this may be ok, but if you need a lot of interprocess communication between your VBScript and your VBA macro, you should look for a different solution.