My goal is to use my application (written in visual c++ 2010) to open some files in excel and run a macro written in VBA
Here is the code I have right now
try
{
System::Object^ oMissing = System::Reflection::Missing::Value;
Excel::Application^ pExcel = gcnew Excel::Application();
pExcel->Visible = true;
Excel::Workbooks^ pBooks = pExcel->Workbooks;
Excel::_Workbook^ pBook = pBooks->Open(_XLSFile, ... );
Excel::_Workbook^ pBook2 = pBooks->Open(_XMLFile, ... );
Excel::_Workbook^ pBook3 = pBooks->Open(_MacroFile, ... );
pExcel->Run(macroName, ... );
// ....
}
catch(Exception^ e)
{
System::Windows::Forms::MessageBox::Show(e->Message);
}
I've omitted the 20ish "System::Reflection::Missing::Value" parameters required for Open() and Run().
The Run command throws an exception, gets caught, and the message box shows the error:
Cannot run the macro '<macroName>'. The macro may not be available in this workbook or all macros may be disabled
My problem is that this message appears for one macro file but not another, even though they are very similar and both do indeed have the macro defined in them.
I think it has to do with macros being enabled, which excel makes the user do manually. My confusion is why it works with one file and not the other.
Any suggestions on how to fix this are greatly appreciated!
EDIT: The solution to my particular problem (though I'm not sure why it worked) was to put my macro file into 'design mode' in the VBA IDE
Related
I have an Excel file, say Plano.xlsx and I am trying to run a VBA macro script on it using Autohotkey following the instructions stated here.
I don't want the Excel to be visible during this process. The VBA code is supposed to enter the value 99 in the cell C1 at the first sheet.
After hours of trial and error, the Autohotkey script runs smoothly without errors i.e. it opens an Excel process in the background supposedly
editing the Excel file and then exits. The problem is that the Excel file does not change at all. The VBA code works fine if I paste it manually
in a new VBA module in Excel without using Autohotkey.
Here is the code:
#SingleInstance force
#Include Acc.ahk
VBcode=
(
Sub myFunction()
Worksheets(1).Select
Worksheets(1).Range("C1").Select
Selection.Value = 99
End Sub
)
Excel_Run("myFunction")
Excel_Run(sFunction){
FilePath = C:\Users\KostasK\Desktop\Plano.xlsx
oExcel := ComObjCreate("Excel.Application")
Excel_ImportCode(VBcode)
oWorkbook := oExcel.Workbooks.Open(FilePath)
Excel_Get().Run(sFunction)
oWorkbook.Save
oExcel.Quit
}
Excel_ImportCode(VBcode){
if fileexist(A_ScriptDir . "\tempvbcode.txt")
FileDelete, %A_ScriptDir%\tempvbcode.txt
FileAppend, %VBcode%, %A_ScriptDir%\tempvbcode.txt
Excel_Get().ActiveWorkbook.VBProject
.VBComponents.Import(A_ScriptDir . "\tempvbcode.txt")
}
Excel_Get(WinTitle="ahk_class XLMAIN") { ; by Sean and Jethrow, minor modification by Learning one
ControlGet, hwnd, hwnd, , Excel71, %WinTitle%
if !hwnd
return
Window := Acc_ObjectFromWindow(hwnd, -16)
Loop
try
Application := Window.Application
catch
ControlSend, Excel71, {esc}, %WinTitle%
Until !!Application
return Application
}
To get the Acc.ahk library that is included in the script please see here. My Autohotkey version is v.1.1.23.05 and I use Excel 2013. I did not
take a closer look on Excel_Get() function but I used it instead of ComObjActive("Excel.Application") because the latter produces errors. There
is some useful info about that here. Finally, please note that I have enabled the following options in Excel Trust Center:
Enable all macros (not recommended, potentially dangerous code can run) and Trust access to the VBA project object model. Also, in Add-ins section
in COM Add-ins nothing is checked (I don't know if that matters). Finally, I always run the script as administrator.
This can be accomplished simply without VBA macro, while file being closed.
FilePath = C:\Users\KostasK\Desktop\Plano.xlsx
oExcel := ComObjGet(FilePath)
oExcel.Worksheets("Sheet1").Range("C1").VALUE := "99" ; you can put actual sheet name instead "sheet1"
oExcel.Save
oExcel.Quit
oExcel :=
I have a Word .dot file which works in older versions of Word but fails with error 432 when run in Word 2013.
When I debug the code I have the line:
Load customerForm
And VBA shows the error:
Run-time error '432': File name or class name not found during Automation operation
The project "pennyscode" includes "Module1" which contains the function being debugged, "ThisDocument" and a form called "customerForm".
I have tried changing the name to "pennyscode.customerForm" but this doesn't make any difference.
This code is being called from a Sub function which is called from Document_New().
Updates
I can place a breakpoint on the Load customerForm line and demonstrate that it is the line that is causing the problem. If at this point I mouse over the word "customerForm" VBA comes up with
customerForm = <Object variable or With block variable not set>
If I delete/skip the Load line then the next line is customerForm.Show and that produces the same error.
If I just open the .dotm file and then use Alt-F11 to open VBA, I can look at the code for selectCustomer, list properties/methods and customerForm appears in the list.
Additional Note
I believe that within the Load function it must be calling GetObject and it is this that is failing. It is as if VBA can't find the customerForm object even though it appears in the project.
I've posted the full code of the function being called from Document_New below.
Sub selectCustomer()
Dim Doc As Document
Set Doc = Application.ActiveDocument
If Doc.CustomDocumentProperties.Item("Customer") = "Nothing" Then
Load customerForm
customerForm.Show
Unload customerForm
Doc.Fields.Update
a$ = Doc.CustomDocumentProperties.Item("InvoiceNumber")
a$ = customerForm.pathBox.Value + "\" + a$
Doc.SaveAs (a$)
End If
End Sub
I've also posted the full .dotm (Excel 2013) and .dot (previous excel) and some sample data (.xls) here:
Dropbox/Public/Invoice 2015-16.dotm
Dropbox/Public/Invoice 2015-16.dot
Dropbox/Public/data.xls
Update
I've not had much luck making progress on this question. Can anyone suggest an approach to investigating this? Or how I might improve the information on the question?
I finally managed to fix this, and I have a few learnings.
Firstly the debugger shows the error as occurring on the Load customerForm line, but this is actually not the case.
The customerForm has an _Initialize function which loads data into it before it is displayed. This function was failing with but the debugger stops on the wrong place.
I was able to debug this more effectively by putting a breakpoint on the start of the _Initialize sub and then stepping through the code.
Once I had discovered this I realized that the code was failing to find the XLSX file due to a wrong path, thus causing the run-time error.
Once I'd fixed up all the paths, I then hit a second error: runtime error '9' which is a subscript problem. This also reported on the Load customerForm line and was also due to a problem with the _Initialize function.
This was the true source of the problem, and demonstrated a functional change between Office 2013 and previous versions of Office.
My code was opening an XLSX file and attempting to read data from it:
Dim myXL As Object
Dim myWS As Object
Set myXL = GetObject("C:\Test\data.xlsx")
myXL.Application.Visible = True
myXL.Parent.Windows(1).Visible = True
Set myWS = myXL.Application.Worksheets("Customers")
The run-time error 9 was due to the index of the Windows property, as their were no windows. In previous versions of Office, there was a single window, with 2013 the array is empty.
After much messing about I tried adding this line:
myXL.Activate
before accessing the Windows() array. Once that was executed Windows(1) existed and the code worked as before.
Hope this can help someone else struggling with similar problems.
I have a PowerPoint VBA function that opens presentations, copies slides into the active presentation, then closes the source presentation. It worked fine in 2010, but fails in 2013 (all on Windows 7) if it tries to open the same presentation more than once. It appears to me that after the presentation.close command is issued, the window is closed, but the file remains locked open until the VBA code exits. So if the code attempts to open that file again it returns the error:
"Method 'Open' of object 'Presentations' failed"
Here's a simplified form of the function I'm running that behaves the same way. I've had a colleague test this again in PowerPoint 2010 and it runs fine. I've also had a colleague test it under his 2013 to make sure it's not something with my particular installation.
Sub testopen()
Dim ppFile As Presentation
Dim i As Integer
Const fpath = "C:\test.pptx"
For i = 1 To 2
Set ppFile = Application.Presentations.Open(fpath)
ppFile.Close
Set ppFile = Nothing
Next i
End Sub
The file test.pptx is just a blank presentation. In debug mode I can see the file opens and closes on the first loop, then on the second loop the open command fails and I can see in Windows explorer that the hidden temporary file still exists, indicating the file is still open, until I exit the VBA code. I also verified that the file is held open by adding in a function to check the file open status.
I've spent probably an hour googling this and cannot find any other descriptions of this problem. I'm sure I can implement a workaround but it's driving me crazy that I can't find any other reports of seemingly such a simple issue. Any suggestions are greatly appreciated! Thanks.
The Best way that I have achieved this is to simply create a VBS file and in the VBS file I call out the desired VBA code. It's little more hassle than to write the VBA code, but it's the solution that worked for me.
For example in the VBS file:
Dim args, objPP
Set args = WScript.Arguments
Set objPP = CreateObject("Powerpoint.Application")
objPP.Open "C:\path\to\file.ppx"
objPP.Visible = True
objPP.Run "The_Macro"
objPP.Save
objPP.Close(0)
objPP.Quit
Or better yet, have the entire code within the VBS file and have it copy the desired slides.
Hope this helps you achieve your result.
Setting the file as Read Only resolved the issue. The open command is now:
Set ppFile = Application.Presentations.Open(fpath, msoTrue)
Also, saving the file before closing it resolved the issue. For that, add:
ppFile.Save
Interestingly, I had already tried setting the Saved property to True (ppFile.Saved = msoTrue), which does NOT work. Thanks to Michael for his suggestion on the VBS script. That does work and I had never run an external VBS script so I learned something new. In this case, I'd prefer to stick with a VBA solution.
I have a project that takes several documents as inputs, does some processing on them, and creates several new documents at the end. I am currently running into problems with pasting content from one Word document into another. The following code snippet seemed relevant:
Set refOrigin = FindReference(OriginDoc)
Set refDest = PasteDoc.Range(PasteDoc.Content.Start, PasteDoc.Content.End)
refDest.Collapse wdCollapseEnd
refOrigin.Copy
refDest.Paste
When running this code, I will occasionally get Run-time error 4198, Command Failed at the paste line in the code. However, when I go into the debugger, I can see that both refDest and refOrigin are valid ranges. Furthermore, when I step through the code line-by-line, it works. However, I can tell that in the instance where it failed, it inserted an embedded Word document already.
I've done some research on the issues and I believe that there is some type of problem of the code running to fast for the clipboard to keep up with it sometimes. This makes sense to me because when I run the macro from a document on a network drive, it runs without a hitch.
I thought that I would be able to simply add a wait command with Application.Wait, but it turns out that Word 2010 doesn't support this command; it's only in Excel.
Does anyone have ideas as to the root of this problem, possible solutions, or any way to give Word 2010 a wait command? Thanks.
For completeness, the following code mimics the Excel `Application.Wait' method from this question.
Dim tmpStart
tmpStart = Timer
Do
DoEvents
Loop While (tmpStart + 1) > Timer
With my Tool we are scanning excel files and generating reports. My problem is some excel sheets are password protected and getting pup-up while scanning and it halts the Tool to run further.
Could someone let me know the solution, how to overcome with this problem. I just need to skip the sheet and continue with scanning without any user intervention.
Thank You,
Sugam
The workbook has a HasPassword property i.e. (C#):
Workbook book = GetYourWorkbook();
if (book.HasPassword)
{
// Ignore!
}
else
{
// Perform your operations here
}