VBA error '91' - cannot find source of error - vba

I'm trying to open a file to access information in the third worksheet. The .FileDialog works fine and I can select a file, but I keep getting run-time error '91' because of the line Set wbR = wb.Worksheets(3) near the bottom of this section of code because wb.Worksheets(3) = <Object variable or With block variable not set>. This leads me to believe my Set wb = Workbooks.Open(myFile) does not work and returns Nothing, but after looking through how other people have opened files using .FileDialog, I can't see how mine is different and wouldn't function. Any help or advice would be much appreciated.
'Set variables
Dim wb As Workbook 'Workbook to open
Dim wbR As Worksheet 'This is the raw data on the new workbook
Dim wsL As Worksheet 'Worksheet in current file
Dim myFile As String 'File to open
Dim FilePicker As FileDialog
'Set light chain hit worksheet
Set wsL = ThisWorkbook.Worksheets(3)
'Optimizes Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve target file
Set FilePicker = Application.FileDialog(msoFileDialogFilePicker)
'Opens folder-picking window
With FilePicker
.Title = "Select a file."
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myFile = Dir(.SelectedItems(1))
End With
'If folder is not selected
NextCode:
myFile = myFile
If myFile = "" Then GoTo ResetSettings
'Set variable equal to opened workbook
Set wb = Workbooks.Open(myFile)
'Ensure Workbook has opened before moving on to next line of code
DoEvents
'Sets worksheet for importing
Set wbR = wb.Worksheets(3)
*the macro continues past this last line but it doesn't get to it yet because of this error

Sorry, I have to use the answer box to do this because there is code involved. But No, you're doing fine. This is how debugging works. Now that we know which lines are not working we will try to find out why. Now try to change
wsL = ThisWorkbook.Worksheets(3)
to
wsL = ThisWorkbook.Worksheets(1)
or
wsL = ThisWorkbook.Worksheets("PUTnameOFsheetHere")
to see if it sets or not. If so then we know there is some kind of problem with WorkSheets(3).
Now we'll try to find why "Set wb = Workbooks.Open(myFile)" is not working. Tunr on your macro recording. Got to "File" on the menu and select "Open." The dialog box will open. Search for your file in the dialog box and open it. Go back to your original workbook and stop recording. Find the recorded macro and you will see the exact line That Excel used to open the file. It should be something like:
Workbooks.Open Filename:="C:\Files\CNC TEST.xlsx"
Now run your script with PF8 and hover over "myFile" after it is initialized. Does it's value match the path and filename of the recorded macro file?

Related

How to open document from Macro without Activating

I've been working on a macro where at one point I need to open a document, copy and edit some data, and then return to the previous document to continue with the Macro. I have a fileDialog that I run to let the user choose the document, but the problem is that this then activates the document, causing the screen to flash even with ScreenUpdating off. Is there an alternative to Workbooks.Open I can use that won't activate the new document? A setting in Workbooks.Open I can change to prevent it from activating? A way to stop the screen from flashing upon the document activating? Here is the code for the fileDialog and a few lines on each side:
Set fileDialog = Application.fileDialog(msoFileDialogFilePicker)
Application.ScreenUpdating = False
With fileDialog
.InitialFileName = "C:\Users\User\Documents"
.AllowMultiSelect = False
.Filters.Clear
.Title = dialogTitle
If .Show = False Then
Application.ScreenUpdating = True
MsgBox "No file chosen. Click Import Contact List to try again."
Exit Sub
End If
strPathFile = .SelectedItems(1)
End With
Set wbSource = Workbooks.Open(Filename:=strPathFile)
Any solution would be greatly appreciated.
My assumption is that you want to let the user open a file, leave it open, but make your workbook active afterwards so the opened file remains "in the background" for the user to navigate to later on. You've noticed some annoying flicker and came here for answers.
The only way I could reproduce the behavior you describe, with code similar to yours, is when I opened a file that was already opened in the same Excel session (see 3rd use case below). Notice that your code doesn't close the just opened workbook, so the first time you run it, you're in use case 2 below, and the second time you run it, you're in use case 3 below.
If, however, you can close the workbook at the end of your process, you'll be in the 1st use case below and all should be fine.
Let's see if anybody can come up with solutions to use cases 2 and 3.
This first use case typically doesn't introduce flicker:
Application.ScreenUpdating = False
Application.EnableEvents = False 'For good measure.
Set myWb = Application.Workbooks.Open("... path of some workbook that's not already open ...")
'... Do stuff ...
myWb.Close
Application.EnableEvents = True
Application.ScreenUpdating = True
I can't make the other 2 use cases below behave as desired.
Second use case is when the workbook must be left opened at the end of the process described above, but not active, all without any flickering. Whatever I've tried, the opened workbook becomes the active one upon leaving the code:
Application.ScreenUpdating = False
Application.EnableEvents = False 'For good measure.
Set myWb = Application.Workbooks.Open("... path of some workbook that's not already open ...")
'... Do stuff ...
'myWb.Close 'Here, the workbook is left opened.
ThisWorkbook.Activate 'Trying...
Application.EnableEvents = True
Application.ScreenUpdating = True
ThisWorkbook.Activate 'Trying harder...
'Be my guest...
'Note: Application.OnTime eventually calling ThisWorkbook.Activate doesn't count!
Third use case is an oddity and probably what happens to OP. Take the second use case above but open a workbook that's already opened in the same Excel instance. After a flicker even though ScreenUpdating = False during the operations (not cool), the code will leave with ThisWorkbook as the active one (cool!) .
I've tried playing with myWb.Windows(1).Visible = False, DoEvents, you name it, to no avail. Your comments are welcome.
EDIT (3 years later)
A dirty workaround is to open the workbook, then immediately set its IsAddin property to True. This will remove it from Excel's UI and leave the workbook with executing code at the front, no matter what. The caveat is you now have to manage the opened workbook's visibility (e.g. setting IsAddin = False when the user wishes to see it) and lifetime (e.g. closing it when exiting your application's workbook). But it's doable.
On opening a workbook, you can hide the workbook or activate ThisWorkbook in order no to show the just opened workbook.
Sub OpenAndHide()
Dim wbSource As Workbook
Dim FileDialog As FileDialog
Dim dialogTitle As String
Dim strPathFile As String
Set FileDialog = Application.FileDialog(msoFileDialogFilePicker)
dialogTitle = "Open And Hide"
With FileDialog
.InitialFileName = "C:\Users\User\Documents"
.AllowMultiSelect = False
.Filters.Clear
.Title = dialogTitle
If .Show = False Then
Application.ScreenUpdating = True
MsgBox "No file chosen. Click Import Contact List to try again."
Exit Sub
End If
strPathFile = .SelectedItems(1)
End With
Set wbSource = Workbooks.Open(Filename:=strPathFile)
ThisWorkbook.Activate
'// Hide the workbook
'strPathFile = GetFilenameFromPath(strPathFile)
'Windows(strPathFile).Visible = False
End Sub
Function GetFilenameFromPath(ByVal strPath As String) As String
' Returns the rightmost characters of a string upto but not including the rightmost '\'
' e.g. 'c:\winnt\win.ini' returns 'win.ini'
If Right$(strPath, 1) <> "\" And Len(strPath) > 0 Then
GetFilenameFromPath = GetFilenameFromPath(Left$(strPath, Len(strPath) - 1)) + Right$(strPath, 1)
End If
End Function
You can try
Set wbSource = Workbooks.Open(Filename:=strPathFile)
Workbooks(name of users workbook).Activate
or
Set wbSource = Workbooks.Add(trPathFile)
Hope it helps.

Unwanted Print Setup

So I'm experiencing some weird behavior while trying to open a new workbook (checkwb). When the new workbook opens it opens a "Print Setup" dialog box for every single page in the workbook. Furthermore, after clicking "OK" ~200 times the code runs fine, but if I close checkwb and try to run the code again it is unable to open checkwb until I close Excel entirely and reopen, at which point the print dialogs reappear. Here's my (incomplete) code:
Sub Check()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim homewb As Workbook
Dim checkwb As Workbook
Dim ws As Worksheet
Dim namestr As String
Dim checkarray() As Double
Set homewb = Workbooks("BranchTable Calc B31.3.xlsm")
Set checkwb = Workbooks.Open("Z:\Agrium\Redwater\E130040CP ~ Pipe Spec
Update\M-Mech\20-Eng\Calcs\Final WT Calcs All Specs\New Bechtel Agrium
comments.xlsm")
For Each ws In homewb.Sheets
If ws.Name = "Cover" Or ws.Name = "Pipe Dims" Then
Else:
namestr = ws.Name & " Weld"
checkarray() = GetCheckValues(checkwb, namestr)
End If
Next
checkwb.Close
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
I've read weird errors like this can occur from corrupted files but the code shouldn't be able to open the file at all if it was corrupt by my understanding.
Setting the page view for all sheets in the target workbook to "Normal" mode fixed this problem. Thanks to Ricardo Rodrigues for the tip!

VBA Workbook.Open(File) returns Nothing

EDIT: After lots of help and not having a clue what's going on, it worked using a different method of opening (see #JohnMuggin's help below)--so I un-commented my original code and suddenly it works.
I've only found one other instance of Workbook.Open("file") returning nothing (Link to Q). However, their problem was because of calling Workbook.Open("file") in a user-defined function (to my understanding). Here, I am calling it in a Sub, but am having the same issue and can't find a solution. I am using Excel 2013.
Private Sub CommandButton2_Click()
'Set variables
Dim wb As Workbook 'Workbook to open
Dim wbR As Worksheet 'This is the raw data on the new workbook
Dim wsL As Worksheet 'Worksheet in current file
Dim myFile As String 'File to open
Dim FilePicker As FileDialog
'Set light chain hit worksheet
Set wsL = ThisWorkbook.Worksheets(3)
'Optimizes Speed
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FilePicker = Application.FileDialog(msoFileDialogFilePicker)
'Opens folder-picking window
With FilePicker
.Title = "Select a file."
.AllowMultiSelect = False
If .Show = True Then
myFile = .SelectedItems(1)
Else: GoTo NextCode
End If
End With
'If folder is not selected
NextCode:
myFile = myFile
If myFile = "" Then GoTo ResetSettings
'Set variable equal to opened workbook
Set wb = Workbooks.Open(myFile)
The macro continues, but the last line Set wb = Workbooks.Open(myFile) sets wb as Nothing. This does not produce any errors until I call wb farther down in the code.
An earlier line, Set wsL = ThisWorkbook.Worksheets(3), also sets wsL as Nothing.
I have checked each line and values using the debugger, and have determined myFile is the proper path, file name, and extension.
If you have a copy of the workbook open (in a different folder) with the same name as the one your VBA is trying to open, it fails silently. The ActiveWorkbook solution appears to work - as you have at least one workbook open already - and that is active - but its not the one you think it is.
I imagine it it could be a common mistake - as while developing a VBA project you might have a copy of the target workbook open to check on column numbers etc.
And at the very last try this little sub. If it doesn't open your workbook then there is a problem with the path or filename
Sub opendfghj()
Dim wb As Workbook
Workbooks.Open Filename:="C:\Users\User\Desktop\Templates and Example data\Repeat Tests\file.xlsx"
Set wb = ActiveWorkbook
wb.Worksheets("Sheet1").Range("A1") = "It Works"
End Sub

Macro that runs a Macro that opens files and save them as value - Runtime Error 1004

I keep getting this 1004 runtime error. I have slimmed my programing down some so it’s not so Programception. I think it may have to do with using Excel 2010 to save .xls files. Not sure.
When Auto_Root.xls opens it runs Sub auto_open() which opens
Panel.xls
Panel opens and runs Sub Update() which sequentially opens 7 files
in different directories all called Auto_Update.xls
Auto_Update.xsl opens and runs Sub Flat which each open a number of
files sequentially and saves a flat copy of themselves in another
directory.
I have opened each of the 7 Auto_Update.xls files and have run them independently and they run with no errors. When I run them all from Auto_Root I get a runtime error 1004. And CurrentWB.Save is highlighted on one of the files. I even replaced CurrentWB.Save as CurrentWB.SaveAs Filename:=TargetFile, FileFormat:=xlNormal and recieved the same runtime error.
Attached is the code I have.
AutoRoot.xls!Auto Update
Sub auto_open()
Application.CutCopyMode = False
Dim PanelFilePath As String
Dim PanelFileName As String
Dim PanelLocation As String
Dim PanelWB As Workbook
PanelFilePath = "D:\umc\UMC Production Files\Automation Files\"
PanelFileName = "Panel.xls"
PanelLocation = PanelFilePath & Dir$(PanelFilePath & PanelFileName)
Set PanelWB = Workbooks.Open(Filename:=PanelLocation, UpdateLinks:=3)
PanelWB.RunAutoMacros Which:=xlAutoOpen
Application.Run "Panel.xls!Update"
PanelWB.Close
Call Shell("D:\umc\UMC Production Files\Automation Files\Auto.bat", vbNormalFocus)
Application.Quit
End Sub
Panel.xls!Update
Sub Update()
Dim RowNumber As Long
Dim AutoUpdateTargetFile As String
Dim AutoUpdateWB As Workbook
For RowNumber = 1 To (Range("AutoUpdate.File").Rows.Count - 1)
If (Range("AutoUpdate.File").Rows(RowNumber) <> "") Then
AutoUpdateTargetFile = Range("Sys.Path") & Range("Client.Path").Rows(RowNumber) & Range("AutoUpdate.Path ").Rows(RowNumber) & Range("AutoUpdate.File").Rows(RowNumber)
Set AutoUpdateWB = Workbooks.Open(Filename:=AutoUpdateTargetFile, UpdateLinks:=3)
AutoUpdateWB.RunAutoMacros Which:=xlAutoOpen
Application.Run "Auto_Update.xls!Flat"
AutoUpdateWB.Close
End If
Next RowNumber
End Sub
AutoUpdate.xls!Flat
Sub Flat()
Dim RowNumber As Long 'Long Stores Variable
Dim SheetNumber As Long
Dim TargetFile As String 'String Stores File Path
Dim BackupFile As String
Dim CurrentWB As Workbook 'Workbook Stores Workbook
For RowNumber = 1 To (Range("File").Rows.Count - 1)
'Loops through each file in the list and assigns a workbook variable.
If (Range("File").Rows(RowNumber) <> "") Then
TargetFile = Range("Sys.Path") & Range("Path").Rows(RowNumber) & Range("File").Rows(RowNumber) 'Target File Path
BackupFile = Range("Report.Path") & Range("Path").Rows(RowNumber) & Range("SubFolder") & Range("File").Rows(RowNumber) 'Backup File Path
Set CurrentWB = Workbooks.Open(Filename:=TargetFile, UpdateLinks:=3) 'Sets CurrentWB = to that long name. This becomes the name of the workbook.
CurrentWB.RunAutoMacros Which:=xlAutoOpen 'Enables Macros in Workbook
CurrentWB.SaveAs Filename:=TargetFile, FileFormat:=56
For SheetNumber = 1 To Sheets.Count 'Counts Worksheets in Workbook
Sheets(SheetNumber).Select 'Selects All Worksheets in Workbook
If (Sheets(SheetNumber).Name <> "What If") Then
Sheets(SheetNumber).Unprotect ("UMC626") 'Unprotects Workbook
Cells.Select 'Selects Data in Workbook
Range("B2").Activate
With Sheets(SheetNumber).UsedRange
.Value = .Value
End With
Sheets(SheetNumber).Protect Password:="UMC626", DrawingObjects:=True, Contents:=True, Scenarios:=True 'Protects Workbook
End If
Next SheetNumber 'Runs Through Iteration
Sheets(1).Select
Range("A1").Select 'Saves each workbook at the top of the page
CurrentWB.SaveAs Filename:=BackupFile, FileFormat:=56, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False 'Saves Workbook in Flatten File Location
CurrentWB.Close 'Closes Workbook
End If 'Ends Loop
Next RowNumber 'Selects Another Account
End Sub
What I have done so far.
Each Individual AutoUpdate file works when ran on its on.
If Application.Run"Auto_Update.xls!Flat" is removed from Panel.xls!Update it opens and closes all of the AutoUpdate.xls files with no error.
If I link Panel.xls!Update to only 3 of the 7 AutoUpdate files.... any 3. It runs with no errors.
I just can't seem to get it to run all 7 without saying Runtime Error 1004.
I found a microsoft work around code. Not sure how to implement it though.
Sub CopySheetTest()
Dim iTemp As Integer
Dim oBook As Workbook
Dim iCounter As Integer
' Create a new blank workbook:
iTemp = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
Set oBook = Application.Workbooks.Add
Application.SheetsInNewWorkbook = iTemp
' Add a defined name to the workbook
' that RefersTo a range:
oBook.Names.Add Name:="tempRange", _
RefersTo:="=Sheet1!$A$1"
' Save the workbook:
oBook.SaveAs "c:\test2.xls"
' Copy the sheet in a loop. Eventually,
' you get error 1004: Copy Method of
' Worksheet class failed.
For iCounter = 1 To 275
oBook.Worksheets(1).Copy After:=oBook.Worksheets(1)
'Uncomment this code for the workaround:
'Save, close, and reopen after every 100 iterations:
If iCounter Mod 100 = 0 Then
oBook.Close SaveChanges:=True
Set oBook = Nothing
Set oBook = Application.Workbooks.Open("c:\test2.xls")
End If
Next
End Sub
http://support.microsoft.com/kb/210684/en-us
Based on the document from Microsoft linked below this is a known issue.
Copying worksheet programmatically causes run-time error 1004 in Excel
I'm not sure how many sheets this loop in Flat but it appears that is the issue. Specifically the quote:
This problem can occur when you give the workbook a defined name and then copy the worksheet several times without first saving and closing the workbook
Due to the levels that you have created using separate workbooks I would suggest starting with limiting the scope of your Update subroutine. There are many designs for something like that but I might start with passing an integer argument back and fourth between Auto Open and Update. That way you can close and reopen Panel.xls multiple times and start exactly where you left off.
Its not clear from your text, but is your procedure "Flat" inside the files you are opening and if so is it being called by the auto open macro?
It sounds like you want to only be running your macro from your original workbook, and not firing the ones in the auto open macro of the workbooks you open.
If this is indeed the case, I do something similar in one of my workbooks, where I have an "upgrade" wizard that fires when the work book is opened, however because I am upgrading, the other workbook I open, also has the upgrade wizard, and so that used to fire as well. I resolved this by opening the other workbook in a hidden instance of excel, and within my auto open macro, I have a line of code that queries the visible state of the workbook, and does not fire if it is hidden. So in the below code its the "And Me.Application.visible" that controls if the wizard is run
'Check if the ODS code is populated or default xxx, if so invoke the upgrade wizard
'but only if the application is visible
If (ActiveWorkbook.Names("Trust_ODS_Code").RefersToRange.Value = "xxx" _
Or Len(ActiveWorkbook.Names("Trust_ODS_Code").RefersToRange.Value) = 0) _
And Me.Application.visible = True Then
'run the upgrade wizard
frmCSCWizardv8.Show
End If
This requires that you open your workbooks in a separate excel instance. The below code is the snippet of code that does this, hope this is enopugh for you to get the idea
Dim lRet
Dim i As Integer, j As Integer
Dim FoundSheet As Boolean
'Because the wizard opens the old DCS in a hidden instance of Excel, it is vital that we close this if
'anything goes wrong, so belt and braces, close it every time the user presses the button
'Switch off the error handling and the display alerts to avoid any error messages if the old dcs has
'never been opened and the hidden instance does not exist
Application.DisplayAlerts = False
On Error Resume Next
book.Close SaveChanges:=False
app.Quit
Set app = Nothing
Application.DisplayAlerts = True
'set error handling
On Error GoTo Err_Clr
'populate the status bar
Application.StatusBar = "Attempting to open File"
'Default method Uses Excel Open Dialog To Show the Files
lRet = Application.GetOpenFilename("Excel files (*.xls;*.xlsx;*.xlsm;*.xlsb), *.xls;*.xlsx;*.xlsm;*.xlsb")
'If the user selects cancel update the status to tell them
If lRet = False Then
Me.lstOpenDCSStatus.AddItem "No file selected"
'if the user has selected a file try to open it
Else
'This next section of code creates a new instance of excel to open the selected file with, as this allows us to
'open it in the background
OldDCS = lRet
Application.StatusBar = "Attempting to open File - " & lRet
app.visible = False 'Visible is False by default, so this isn't necessary, but makes readability better
Set book = app.Workbooks.Add(lRet)
Application.StatusBar = "Opened File - " & lRet

Ignore "Do you wish to save" box on exit of excel

I have a script that opens an excel file and runs a macro, then quits the file. Since the file is in read only mode, and the script makes temporary changes to the file, when the script calls myExcelWorker.Quit() excel asks if I want to save my changes and I must click 'no'. Is there any way to exit the program and skip this box?
' Create a WshShell to get the current directory
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
' Create an Excel instance
Dim myExcelWorker
Set myExcelWorker = CreateObject("Excel.Application")
myExcelWorker.Visible = True
' Tell Excel what the current working directory is
' (otherwise it can't find the files)
Dim strSaveDefaultPath
Dim strPath
strSaveDefaultPath = myExcelWorker.DefaultFilePath
strPath = WshShell.CurrentDirectory
myExcelWorker.DefaultFilePath = strPath
' Open the Workbook specified on the command-line
Dim oWorkBook
Dim strWorkerWB
strWorkerWB = strPath & "\BugHistogram_v2.xlsm"
Set oWorkBook = myExcelWorker.Workbooks.Open(strWorkerWB)
' Build the macro name with the full path to the workbook
Dim strMacroName
strMacroName = "CreateImagesButton_Click"
on error resume next
' Run the calculation macro
myExcelWorker.Run strMacroName
if err.number <> 0 Then
' Error occurred - just close it down.
End If
err.clear
on error goto 0
' oWorkBook.Save ' this is ignored because it's read only
myExcelWorker.DefaultFilePath = strSaveDefaultPath
' Clean up and shut down
Set oWorkBook = Nothing
' Don’t Quit() Excel if there are other Excel instances
' running, Quit() will
' shut those down also
if myExcelWorker.Workbooks.Count = 0 Then
myExcelWorker.Quit
End If
myExcelWorker.Quit()
Set myExcelWorker = Nothing
Set WshShell = Nothing
ActiveWorkbook.Close False (to close the workbook)
Application.Quit (to quit Excel - doesn't prompt to save changes)
From Microsoft Support's How to suppress "Save Changes" prompt when you close a workbook in Excel:
To force a workbook to close without saving any changes, type the
following code in a Visual Basic module of that workbook:
Sub Auto_Close()
ThisWorkbook.Saved = True
End Sub
Because the Saved property is set to True, Excel responds as though the workbook has already been saved and no changes have
occurred since that last save.
The DisplayAlerts property of the program can be used for the same
purpose. For example, the following macro turns DisplayAlerts off,
closes the active workbook without saving changes, and then turns
DisplayAlerts on again.
Sub CloseBook()
Application.DisplayAlerts = False
ActiveWorkbook.Close
Application.DisplayAlerts = True
End Sub
You can also use the SaveChanges argument of the Close method.
The following macro closes the workbook without saving changes:
Sub CloseBook2()
ActiveWorkbook.Close savechanges:=False
End Sub
The answer you have above is for VBA - you can address this in your VBS directly by using
oWorkBook.Close False
Set oWorkBook = Nothing
in place of
Set oWorkBook = Nothing