I am trying to open Excel and use information in multiple sheets at different times to automate a Word document.
Judging by the status of the local variables through debugging, Excel seems to launch successfully and the Workbook object is also assigned successfully. However, when the "DB Schedules" worksheet is activated, the ActiveSheet variable remains empty and fails to use the property "Name", instead throwing an "Object Required" error and jumping to the finally block.
The path of the workbook and the name of the sheet are both correct, yet even before activating an arbitrary sheet the ActiveSheet variable is empty. The sheet is known to contain information, and I have tried with multiple files just to be sure.
Sub CompileReport()
Dim XLInstance As Object
Dim XLWorkbook As Object
Dim XLPath As String
XLPath = "C:\Users\SaracchiG\OneDrive - AECOM\Documents\M11 Jn7A\GC300 Certificates\" & _
"Construction Compliance\Certificates Data Project_Name.xlsx"
On Error Resume Next
Set XLInstance = GetObject(, "Excel.Application")
XLInstance.Quit
If Err Then
Set XLInstance = CreateObject("Excel.Application")
End If
On Error GoTo Finally
Set XLWorkbook = XLInstance.Workbooks.Open(XLPath, ReadOnly:=True)
'Testing it all works (doesn't!)
XLWorkbook.Worksheets("DB Schedules").Activate
MsgBox ActiveSheet.Name
MsgBox ActiveWorkbook.Name
'Do some stuff with different sheets
Finally:
XLWorkbook.Close
XLInstance.Quit
End Sub
You don't have to activate the sheet to work with it
'Do some stuff with different sheets
With XLWorkbook.Worksheets("DB Schedules")
MsgBox .Name
MsgBox .Parent.Name
End With
Related
I have two workbooks. One is macro enabled that scrapes data together and puts in nicely formatted into another plain workbook. This helps with security issues for users who can't run macros.
I have done a lot without issue, but here I'm stuck. I made a very simple example:
Sub Test()
Dim appExcel As Excel.Application
Dim wDatabase As Workbook
Dim ob As ListObject
Set appExcel = CreateObject("Excel.Application")
'DOESN'T WORK when run from another workbook
Set wDatabase = appExcel.Workbooks.Open("C:\Test\Book1.xlsx")
'WORKS when macro run in the book with the table (and above line commented out)
'Set wDatabase = ActiveWorkbook
Set ob = wDatabase.Sheets("Sheet1").ListObjects("Table1")
ob.Resize Range("$B$3:$D$13")
'Save changes
wDatabase.Save
wDatabase.Close
End Sub
Two workbooks: Book1.xlsx and Book2.xlsm
Book1.xlsx has a table ("Table1") on "Sheet1" in cells B3 to D14. I want to make it B3 to D13.
If I run the macro with that worksheet active (as shown with the commented out code). It works fine. When I try to do it from another workbook, it errors out. Sometimes it will say "Run-time error '1004': This action won't work on multiple selections." Other times Excel enters a corrupt mode and say
"Run-time error '-2147023170 (800706be0)'; Automation error. The
remote procedure call failed."
I cannot find a reason!
The range should resize.
*Edit: Changing this worked!
Set wDatabase = Workbooks.Open("C:\Test\Book1.xlsx") Thanks chris neilsen!
Resize a Table Using Another Instance of Excel (Error Handling)
Sub Test()
Dim IsSuccess As Boolean
On Error GoTo ClearError ' start error-handling routine...
Dim xlApp As Excel.Application: Set xlApp = New Excel.Application
Dim wb As Workbook: Set wb = xlApp.Workbooks.Open("C:\Test\Book1.xlsx")
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1")
Dim lo As ListObject: Set lo = ws.ListObjects("Table1")
' If you want to see how it works when an error occurs,
' uncomment the Err.Raise line.
' Create a breakpoint and in the Task Manager locate the new instance
' under Background Processes. If you don't use 'Quit', it will remain
' open after the procedure exits.
'Err.Raise 13
' With 'F8', step through the rest of the code to see its flow.
' In the Task Manager see how the instance is gone.
lo.Resize ws.Range("B3:D13") ' the header row needs to be 3
IsSuccess = True
ProcExit:
On Error Resume Next ' prevent endless loop if error in the following lines
If Not wb Is Nothing Then wb.Close IIf(IsSuccess, True, False)
If Not xlApp Is Nothing Then xlApp.Quit
On Error GoTo 0
Exit Sub
ClearError: ' ... continue error-handling routine
Debug.Print "Run-time error '" & Err.Number & "':" & vbLf & Err.Description
Resume ProcExit ' redirect to exit routine
End Sub
I need to automate moving stuff from excel into PowerPoint. I build put together a macro, which works fine and it is basically running in PowerPoint, accessing Excel, taking some range of nicely formatted tables, and pasting as enhanced metafile:
Function CopyFromExcelToPPT(excelFilePath As String, sheetName As String, rngCopy As String, dstSlide As Long, Optional shapeTop As Long, Optional shapeLeft As Long, Optional shapeHeight As Long, Optional shapeWidth As Long)
On Error GoTo ErrorHandl 'Handle Errors
'Set Variables and Open Excel
Dim eApp As Excel.Application, wb As Excel.Workbook, ppt As PowerPoint.Presentation
Set eApp = New Excel.Application
eApp.Visible = False
Set wb = eApp.Workbooks.Open(excelFilePath)
Set ppt = ActivePresentation
'Copy cells in Excel
wb.Sheets(sheetName).Range(rngCopy).Copy
'Paste into first slide in active PowerPoint presentation
ppt.Slides(dstSlide).Shapes.PasteSpecial ppPasteEnhancedMetafile
'Close and clean-up Excel
eApp.CutCopyMode = False
wb.Close SaveChanges:=False
eApp.Quit
Set wb = Nothing: Set eApp = Nothing
'Move the new shape if left/top provided
If Not (IsMissing(shapeTop)) Then
With ppt.Slides(dstSlide).Shapes(ppt.Slides(dstSlide).Shapes.Count)
.Left = shapeLeft
.Top = shapeTop
End With
End If
'Resize the shape if height/width provided
If Not (IsMissing(shapeHeight)) Then
With ppt.Slides(dstSlide).Shapes(ppt.Slides(dstSlide).Shapes.Count)
.Height = shapeHeight
.Width = shapeWidth
End With
End If
'Put them to the back
With ppt.Slides(dstSlide).Shapes(ppt.Slides(dstSlide).Shapes.Count)
While .ZOrderPosition > 2
.ZOrder msoSendBackward
Wend
End With
CopyFromExcelToPPT = True
Exit Function
ErrorHandl:
'Make sure to close the workbook and Excel and return False
On Error Resume Next
If Not (eApp Is Nothing) Then
wb.Close SaveChanges:=False
eApp.CutCopyMode = False
eApp.Quit
End If
CopyFromExcelToPPT = False
End Function
The problem is, that I need to run this like 80x, and after each 5 loads I need to run a macro in that source excel, which will update data. Therefor I tried to either keep excel open during this macro, and manually lunch that macro, or ideally incorporate all of this into this PowerPoint macro.
I tried different approaches, however, I am not able to make it work, I am getting always errors.
Firstly I tried to to create another function handling running macro, and eventually chain it together with main function in main sub:
Function CallTopsheetMacro(excelFilePath As String, sheetName As String)
On Error GoTo ErrorHandl 'Handle Errors
'Set Variables and Open Excel
Dim eApp As Excel.Application, wb As Excel.Workbook
Set eApp = New Excel.Application
eApp.Visible = True
Set wb = eApp.Workbooks.Open(excelFilePath)
wb.Run "'...\excel.xlsb'!macro_01"
wb.Wait (Now + TimeValue("0:00:10"))
'Close and saves Excel
wb.Close SaveChanges:=True
wb.Wait (Now + TimeValue("0:00:10"))
eApp.Quit
Set wb = Nothing: Set eApp = Nothing
MsgBox ("Done!")
CallTopsheetMacro = True
Exit Function
ErrorHandl:
'Make sure to close the workbook and Excel and return False
On Error Resume Next
If Not (eApp Is Nothing) Then
wb.Close SaveChanges:=False
eApp.CutCopyMode = False
eApp.Quit
End If
CallTopsheetMacro = False
End Function
But this functions did basically nothing, only opens and closes excel, waiting is not even reflecting. Then I tried with both sessions (main PowerPoint taking the pictures, and excel which is providing pictures and running macros) running, as I would avoid manually triggering macros and wasting time with open/close excels which is pretty bulky:
Function CallTopsheetMacroActive()
On Error GoTo ErrorHandl 'Handle Errors
'Set Variables and Open Excel
Dim eApp As Excel.Application
Set eApp = GetObject("..\excel.xlsb", "Excel.Application")
eApp.Visible = True
'Run macro
eApp.Run "'...\excel.xlsb'!macro_01"
MsgBox ("Done!")
Exit Function
ErrorHandl:
'Make sure to close the workbook and Excel and return False
On Error Resume Next
If Not (eApp Is Nothing) Then
wb.Close SaveChanges:=False
eApp.CutCopyMode = False
eApp.Quit
End If
End Function
This one is doing nothing. Then I tried to examine the syntax for GetObject, even with small testing scripts, but it is not working. I have even added references for scrrun.dll, as I have 64bit and it was suggested in couple of similar topics, but of no help. For a simple code like this:
Sub GetObject_Testing()
Dim MyExcel As Excel.Workbook
Dim MySheet As Worksheet
Dim MyFilePath As String
'Set MyExcel = GetObject("Excel.Application")
MyFilePath = "...\excel.xlsb"
Set MyExcel = GetObject(MyFilePath, "Excel.Application")
For Each MySheet In MyExcel.Sheets
Debug.Print MySheet.Name
Next MySheet
End Sub
I am getting run.time error 432 (file name or class name not found during automation operation).
I have no idea what I may be doing wrong, and just to make sure I am providing whole code, just in case I have some error somewhere.
Would appreciate any suggestions which will help to solve this.
PS: Doing this from PowerPoint, because when I tried to the same from Excel, I was getting error that there is not enough memory to start PowerPoint.
Thanks!
I posted a question recently on interacting with another WB in a separate instance of Excel.
How to add Open Workbook to "Application.Workbooks" collection and/or interact with Workbook
But I had hardcoded the copy/paste range for testing, and now I'm having trouble with coping the entire worksheet to the "main wb". Eg: xlApp.Worksheets(1).Copy After:=Application.ActiveWorkbook.Sheets(1)
I get the error Copy Method of Worksheet Failed and ideas how to adjust this to work?
Public Sub Copy_External_WB()
Dim xlApp As Excel.Application, xlBook As Worksheet, i As Long
For i = 1 To 10
On Error Resume Next
Set xlApp = GetObject("Book" & i).Application
If Err.Number = -2147221020 Then
Err.Clear: On Error GoTo 0
Else
On Error GoTo 0
Exit For
End If
Next i
If Not xlApp Is Nothing Then
Set xlBook = xlApp.Worksheets(1)
Debug.Print xlApp.hWnd, Application.hWnd
Else
MsgBox "No Excel session with Book(1 - 10) open could be found..."
xlApp.Quit: Exit Sub
End If
'Dim CopyFrom As Range
'Set CopyFrom = xlBook.Range("A1:AQ56")
'Dim DS As Worksheet
'Set DS = ThisWorkbook.Worksheets("Merged")
'DS.Range("A1:AQ56").Resize(CopyFrom.Rows.Count).Value = CopyFrom.Value
xlApp.Worksheets(1).Copy After:=Application.ActiveWorkbook.Sheets(1)
xlApp.DisplayAlerts = False
xlApp.Quit
xlApp.DisplayAlerts = True
Set xlApp = Nothing
End Sub
You cannot copy a whole sheet object between different Excel instances.
Options:
Use VBA to save the other workbook to file, then open it in the instance where your code is running, and copy the sheet to your workbook
Copy (eg) the UsedRange from the other instance's worksheet, then paste in your primary instance workbook
With an already-opened workbook, I want to create a copy of a worksheet ("Template") and re-name it with the value I have in an array. When I debug the code the copy is created when I execute the line but I still get an error 424: object required.
I've tried On Error Resume Next but since I already used On Error GoTo in my sub it isn't read.
Dim oXL As Excel.Application 'Requires loading "Microsoft Excel 16.0 Object Library" from Tools -> References
Dim oWB As Excel.Workbook
Set oXL = New Excel.Application
Set oWB = oXL.Workbooks.Open(FileName:=WorkbookToWorkOn) 'Opens Excel
oXL.Visible = True 'Shows Excel window while running code. Set to false after finished editing.
Dim ws As Worksheet
For i = LBound(seller_names) To UBound(seller_names)
'On Error Resume Next 'Doesn't work
Set ws = oXL.ActiveWorkbook.Sheets("Template").Copy(After:= _
oXL.ActiveWorkbook.Sheets(oXL.ActiveWorkbook.Sheets.Count))
ws.name = seller_names(i)
Next i
Sheets.Copy doesn't return a reference to the copied sheet, so you need to first copy the sheet, then get a reference to it:
With oXL.ActiveWorkbook
.Sheets("Template").Copy After:= .Sheets(.Sheets.Count)
Set ws = .Sheets(.Sheets.Count)) '<< get the copy
ws.name = seller_names(i)
End With
On Error Resume Next should always work - but is not always a good solution - unless you have "Break on all errors" enabled in your VBA Options.
I'm making a ExcelComparer but I bump into a probably obvious error, I clearly missed something.
I run a vba macro in Excel 2007
The exact error I get is "Run-time Error 13: Type Mismatch"
This happens when the loop tries to fetch the second worksheet.name .
So, the first sheetname is returned fine
Below you find the macro
Thanks in advance,
L
Sub compare()
Dim strWorkbook1, strWorkbook2 As String
Dim Workbook1, Workbook2 As Workbook
strWorkbook1 = Worksheets("Sheet1").Range("C5") & Worksheets("Sheet1").Range("D5")
strWorkbook2 = Worksheets("Sheet1").Range("C6") & Worksheets("Sheet1").Range("D6")
Set xlapp = CreateObject("Excel.application")
Set Workbook1 = xlapp.Workbooks.Open(strWorkbook1)
xlapp.Visible = False
Dim ws As Worksheet
For Each ws In Workbook1.Sheets
'ws.Select
If Not ws.Visible = xlSheetVeryHidden Then
MsgBox (ws.Name)
End If
Next ws
xlapp.Close
End Sub
Use this for your For loop:
For Each ws In Workbook1.Worksheets
From MSDN the difference between the Sheets and Worksheets properties are:
This property does not return macro sheets, charts, or dialog sheets.
Use the Sheets property to return those sheets as well as worksheets.
You can also use the specialized properties Excel4MacroSheets and
Excel4IntlMacroSheets to return macro sheets and the Charts property
to return charts.
[Edited my original response as I had tested with different variables rendering my comment incorrect]
In addition the back end of your code will fail as you can't set the Excel Application to close with this line xlapp.Close
You should
close the automated workbook (Workbook1.Close False)
quit the automated application (xlapp.Quit)
Ensure the automated application is destroyed (Set xlapp = Nothing)a
The working part of your code should look like this
Dim ws As Worksheet
For Each ws In Workbook1.WorkSheets
If Not ws.Visible = xlSheetVeryHidden Then MsgBox (ws.Name)
Next ws
Workbook1.Close False
xlapp.Quit
Set xlapp = Nothing
End Sub