how to make vba-word work in vba-excel? - vba

the following two lines
Dim curTasks As Tasks
Set curTasks = Application.Tasks
get the list of all current tasks and work like charm in vba-word but not in vba-excel.
is there a way to port it into vba-excel?

As I said in comments, the Excel object in VBA doesn't have the concept of tasks. You can do the below though in an Excel Module (although I'm still not sure why you would do it):
Dim curTasks As Tasks
Dim wrd As Word.Application
Set wrd = CreateObject("Word.Application")
Set curTasks = wrd.Tasks
NOTE: you have to add a reference to Microsoft Word Object Library to get this to work

Related

MS Access Compile Error opening excel application [duplicate]

This question already has answers here:
How to fix Compile Error: User-defined type not defined when using Excel VBA from Outlook?
(2 answers)
Closed 5 days ago.
I am trying to write a simple onclick button to open an excel file that already exists on my desktop
what i dont understand is I am using the same Dim as many other examples I have seen. but I am getting a Compile Error "User defined type not defined" and it pulls up the code showing blue highlights Dim excelapp As Excel.Application but Yellow highlight on Private Sub line. Where am i going wrong. is the failure actually further down the code? I ma running Access 365 and Should i be using a different syntax to reference Excel?
Private Sub cmdcopyfieldsonly_Click()
Dim excelapp As Excel.Application
Dim wbTarget As Excel.Workbooks
Dim qdfquerytest As QueryDef
Dim rsquerytest As Recordset
Set qdfquerytest = CurrentDb.QueryDefs("OpenComplaintsQuery")
Set rsquerytest = qdfquerytest.OpenRecordset()
Set excelapp = CreateObject("Excel.Application")
excelapp.Visible = True
Set wbTarget = Excel.Workbooks.Open("C:\Desktop\copytest.xlsx")
wbTarget.worksheets("Sheet1").Range("B8").Value = rsquerytest(2).Value
End Sub
It's a matter of early vs late binding, which are mixed in your code.
Early Binding.
Early binding requires a hard reference of the type e.g. Excel, so VBA has information about the type during compilation. You can then declare the variable by its type and also have intellisense while typing.
Dim app As Excel.Application
Set app = New Excel.Application
The drawback is when changing office versions as the code still references the old version - the reference will need to be updated.
Late Binding
Late binding does not require a hard reference since the variable is declared using the base type of Object and gets resolved at runtime. No issues when changing office version but you lose intellisense.
Dim app As Object
Set app = CreateObject("Excel.Application")
In you case, this is absolutely valid when using late binding:
With CreateObject("Excel.Application")
With .Workbooks.Open("C:\Desktop\copytest.xlsx")
.Worksheets("Sheet1").Range("B8").Value = rsquerytest(2).Value
End With
End With

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

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

VBA - releasing Word.Application and Word.Document objects

I use the following macro to iterate through file paths stored in collection. On some test directory, total run time was 2,3 sec without setting openedApp and openedDoc to nothing and 2,75 with it. Is releasing both of these objects necessary in this case? I intend to use macro on a directory with thousands of files, so I would like to avoid any problems with memory which could cause errors or slow down macro execution.
Dim openedApp As Word.Application
Dim openedDoc As Word.Document
For Each filePath In filesCollection
Set openedApp = New Word.Application
Set openedDoc = openedApp.Documents.Open(filePath)
'openedApp.Visible = True
openedDoc.Close
openedApp.Quit
Set openedApp = Nothing: Set openedDoc = Nothing
Next filePath
There is no need to explicitly set you variables to Nothing. As descibred by this answer VB6 used a reference-counting GC. The GC is triggered deterministically when the last reference to a given object is set to Nothing. Setting local references to Nothing is unnecessary, this happens as they go out of scope.
In fact, if performance matters you can move the creation of the Word application outside the loop body:
Dim openedApp As Word.Application
Dim openedDoc As Word.Document
Set openedApp = New Word.Application
For Each filePath In filesCollection
Set openedDoc = openedApp.Documents.Open(filePath)
openedDoc.Close
Next filePath
openedApp.Quit
There is no need to set VBA objects to nothing. The VBA garbage collector will clean up all the variables when the subroutine goes out of scope. This is legacy from the early days of the VBA when computers weren't as powerful and the garbage collector wasn't as good.
The exception to the rule is when you are using external objects that run outside of the VBA such as connections and recordsets. These should be closed and set to nothing.
Along the same lines, there is no need to erase array at the end of a subroutine. If you have a large array (millions of elements) that is no longer needed and you still have more code to run then you might get a performance boost from erasing the array.

How do I set the default save format in PowerPoint?

Microsoft, in their infinite wisdom, decided that the default file format for Office 2010 applications should be the format that was 13 years old (Office 97-2002) at the time of release.
The newer formats (2007 and newer) save the data in compressed XML files which are much smaller, and also allow for many additional features. Our corporate IT department hasn't or can't set a group policy to force users to default to saving in the new format, so I'm writing a macro to adjust the settings for everyone in our department.
I can do this in Excel and Word very simply by executing the following VBA code (I'm running it from an Excel workbook):
Public Sub SetExcelSave()
Dim myExcel As Excel.Application
Set myExcel = New Excel.Application
Excel.DefaultSaveFormat = xlOpenXMLWorkbook
Excel.Quit
Set Excel = Nothing
End Sub
Public Sub SetWordSave()
Dim myWord As Word.Application
Set myWord = New Word.Application
Word.DefaultSaveFormat = wdFormatDocumentDefault
Word.Quit
Set Word = Nothing
End Sub
However, I haven't been able to find the appropriate setting to adjust in PowerPoint. Does anyone know where that property is or what it's called?
This code will not compile cleanly, giving an error on the PPT.DefaultSaveFormat line:
Public Sub SetPowerPointSave()
Dim PPT As PowerPoint.Application
Set PPT = New PowerPoint.Application
PPT.DefaultSaveFormat = ppSaveAsOpenXMLPresentation
PPT.Quit
Set PPT = Nothing
End Sub
I've rummaged around in the Office Application Object documentation for PowerPoint, but I'm just not finding what I'm after. It's highly likely that I just don't know what I'm looking for and have simply overlooked it.
Does anyone know what property I'm supposed to set to be able to programmatically change this?
The default save format for PPT 2007 and later is the new XML format (PPTX rather than PPT and so on). If the user (or IT staff via policies) have overridden this in the File | Save | Save files in this format: then the default becomes whatever they've selected, for whatever reason.
App-wide defaults like this typically aren't exposed via the object model; they're stored in the registry. In this case, in
HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\PowerPoint\Options
DefaultFormat DWORD=27 for PPTX
Substitute the correct version for 14.0 above; 12.0 for PPT 2007, 14.0 for 2010, and so on (no 13.0).
If you can write the value you want to the registry when PPT isn't running, you can reset the defaults. If you write to the reg while PPT's running, it won't affect the current instance of PPT, and your changes will be overwritten when PPT quits.

How do I programatically add a reference to a VBA project?

I'm deploying an early bound styled VBA module that needs Scripting.Dictionary and RegExp.
The script, predictably, fails when it runs on another computer.
The user has to go to Tools->Reference in the VBA IDE and add a reference to those two libraries manually to make it work.
Hence lies the problem. Asking the non-technical end user to go to the IDE and manually add references is asking way too much of them.
The other alternative is to rewrite the whole (very long script written by someone else) to use late binding. I rather not take this path if there are other methods.
As an altervative, some people suggest adding a reference programatically like so:
Application.VBE.ActiveVBProject.References.AddFromFile [Path to library]
Is this the correct solution and if so are there any downsides of this strategy?
If not, are there other methods that will to enable the code to remain early bound yet does not require references to be added manually by the user.
Suggestions involving direct calls to the Win32/64 API are also welcome.
Thanks.
In my own limited environment (small # of other people using spreadsheets I develop, relatively standard machine setups), if I create the file and add the references, and then give a copy to someone else, they can open it with no problems and not have to do anything, so keep that in mind with this answer. (I'm wondering why that doesn't work for you.) Also, this was with Excel.
Rather than adding a reference from a file path, you might consider using the GUID property instead.
Here is some code I once used to automatically create references in a newly created workbook. (It's part of a script that would export code, references, and unit tests on worksheets to text for use with Subversion and then later reconstitute the workbook from the text files.) You might find it useful to your situation. (EH and cleanup removed to keep it short...)
'Export refs in existing workbook to text file
Private Sub exportRefs_(srcWbk As Workbook)
Dim fs As FileSystemObject
Set fs = New FileSystemObject
Dim tsout As TextStream
Set tsout = fs.CreateTextFile(fs.BuildPath(getTargetPath_(srcWbk), "refs.refs"))
Dim ref As Reference
For Each ref In Application.ThisWorkbook.VBProject.References
Call tsout.WriteLine(ref.GUID)
Next ref
'<EH + cleanup...>
End Sub
'Add refs to newly created workbook based on previously exported text file
Private Sub importRefs_(wbk As Workbook, path As String)
Dim fs As FileSystemObject
Set fs = New FileSystemObject
Dim tsin As TextStream
Set tsin = fs.OpenTextFile(path)
Dim line As String
Dim ref As Reference
While Not tsin.AtEndOfStream
line = tsin.ReadLine()
Set ref = Nothing
On Error Resume Next
Set ref = wbk.VBProject.References.AddFromGuid(line, 0, 0)
On Error GoTo 0
If ref Is Nothing Then
Debug.Print "add failed: " & line
End If
Wend
'<EH + cleanup...>
End Sub
Like, I said, limited environment, but hopefully it helps.