VBA error when saving workbook sheet in new file location during data refresh - vba

I am having issues with my VBA code and am by no means an expert with VBA. This code is tied to product usage data for 30 clients. The current workbook I am using contains multiple tabs but I only want to focus on one tab, the "Template" tab, as my desired output. What I am trying to set up is a macro with an auto save of each individual clients data into its own new workbook in a specific folder location. So basically I only want one tab(ie sheet) saved out of the entire workbook for each client.
The list of clients comes from a data validation list that is tied to a table. Within the macro itself is a .RefreshAll since the data needs to be refreshed for each individual client to produce the output needed in the "Template" tab. The underlying data is tied to both Power Query and T-SQL linked to a MS SQL Server. This is what I am seeing:
When the file is saved I receive a
run time error '1004'
so the saving of the new file fails. In addition, the data refresh needs to run and finish for each individual client before moving on the the next. Which I do not believe is occurring.
Here is how I want the macro to work:
Data refresh begins for first client in data validation drop down list
Refresh completes
"Template" sheet is copy and saved from workbook into a new workbook
New workbook is placed in a new file location
File name includes client name, today's date, and .xlsx extension
VBA code is removed from file that was copied.
Steps 1-6 repeat for the next client until it has gone through entire list of
clients.
Here is the current code I am working with:
Sub ClientDataRefresh()
With ActiveWorkbook.Worksheets("Output")
Dim r As Long, i As Long
r = Range("Clients").Cells.Count
For i = 1 To r
Range("C5") = Range("Clients").Cells(i)
ActiveWorkbook.RefreshAll
Worksheets("Output").Range("A1:O10").Columns.AutoFit
With ActiveWorkbook.Worksheets("Template")
LR = .Cells(Rows.Count, 7).End(xlUp).Row
10: If .Cells(LR, 7) = "" Then LR = LR - 1: GoTo 10
.PageSetup.PrintArea = "$A$1:$I$" & LR
End With
thisDate = Replace(Date, "\", " - ")
thisName = Sheets("Template").Range("H7").Text
filePath = "C:\Users\nalanis\Documents\Sales\"
Application.DisplayAlerts = False
ActiveWorkbook.Worksheets("Template").Select
ActiveWorkbook.Worksheets("Template").Copy
ActiveWorkbook.Worksheets("Template").SaveAs Filename:=filePath & thisName & thisDate & ".xlsx", FileFormat:=xlOpenXMLWorkbook
Application.DisplayAlerts = True
Next i
End With
End Sub
Any feedback is most appreciative. Thank you
NEW CODE
Sub ClientDataRefresh()
With ActiveWorkbook.Worksheets("Output")
Dim r As Long, i As Long
r = Range("Clients").Cells.Count
For i = 1 To r
Range("C5") = Range("Clients").Cells(i)
ActiveWorkbook.RefreshAll
DoEvents
Worksheets("Output").Range("A1:O10").Columns.AutoFit
thisDate = Replace(Date, "/", "-")
thisName = Sheets("Template").Range("H7").Text
filePath = "C:\Users\nalanis\Dropbox (Decipher Dev)\Analytics\Sales\"
Application.DisplayAlerts = False
ActiveWorkbook.Worksheets("Template").Select
ActiveWorkbook.Worksheets("Template").Copy
ActiveWorkbook.Worksheets("Template").SaveAs Filename:=filePath & thisName & " " & "Usage Report" & " " & thisDate & ".xlsx", FileFormat:=xlOpenXMLWorkbook
Application.DisplayAlerts = True
Next i
End With
With ActiveWorkbook.Worksheets("Template")
LR = .Cells(Rows.Count, 7).End(xlUp).Row
10: If .Cells(LR, 7) = "" Then LR = LR - 1: GoTo 10
.PageSetup.PrintArea = "$A$1:$I$" & LR
End With
End Sub
.PageSetup.PrintArea = "$A$1:$I$" & LR
End With
Next c
End Sub

Change this:
thisDate = Replace(Date, "\", " - ")
to this:
thisDate = Replace(Date, "/", " - ")

Related

Code does not contiue after file is opened via dialogue

I'm quite confused right now... I have two modules open_files and start_comparison. From start_comparison I'm calling open_files, which is supposed to open the file open dialogue. The user is then supposed to select one file and hit open. Via start_comparison the user is supposed to open two files. However sometimes (this is where I'm confused) the code opens the first file, but then simply exit's start_comparison occasionally. Sometimes it works, sometimes not, and I have no clue when and why. Below is the code.
What I thought is: When the file dialogue is displayed, one can double click the file and the file will be openend, which would trigger a hidden exit. However, I couldn't confirm this hypthesis. When I step through, everything works fine.
What is your idea about the problem?
Sub start_comparison()
Dim cell As Range
Dim control_file_storage_bins As Range
Dim last_row_CONTROLFILE As Long
Application.ScreenUpdating = False
Set ws_control_file = ActiveWorkbook.ActiveSheet
Range("A2:Z1048576").Clear
Call open_files("PHYSICAL STOCK", 1)
Call open_files("STORAGE BINS", 2)
'Copy stock information
With ws_control_file
.Range("A2:A" & last_row_PHYSICALSTOCK).Value = ws_physical_stock.Range("B2:B" & last_row_PHYSICALSTOCK).Value
.Range("B2:B" & last_row_PHYSICALSTOCK).Value = ws_physical_stock.Range("C2:C" & last_row_PHYSICALSTOCK).Value
.Range("C2:C" & last_row_PHYSICALSTOCK).Value = ws_physical_stock.Range("J2:J" & last_row_PHYSICALSTOCK).Value
.Range("D2:D" & last_row_PHYSICALSTOCK).Value = ws_physical_stock.Range("K2:K" & last_row_PHYSICALSTOCK).Value
.Range("E2:E" & last_row_PHYSICALSTOCK).Value = ws_physical_stock.Range("E2:E" & last_row_PHYSICALSTOCK).Value
End With
Set control_file_storage_bins = ws_control_file.Range("A2:A" & last_row_PHYSICALSTOCK)
For Each cell In rng_STORAGEBIN
If (WorksheetFunction.CountIf(control_file_storage_bins, cell.Value) = 0) Then 'Storage Bin empty
With ws_control_file
last_row_CONTROLFILE = .Cells(Rows.Count, "A").End(xlUp).Row + 1
.Cells(last_row_CONTROLFILE, "A").Value = cell.Value
.Range("B" & last_row_CONTROLFILE & ":E" & last_row_CONTROLFILE).Value = "BIN EMPTY"
End With
End If
Next cell
wb_physical_stock.Close (False)
wb_storage_bins.Close (False)
Application.ScreenUpdating = True
MsgBox "Success!"
End Sub
Other procedure:
Sub open_files(file_type As String, wb_object As Integer)
Dim last_row_STORAGEBIN As Long
MsgBox "Please select the relevant " & file_type & " extract!"
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.Show
Workbooks.Open (.SelectedItems(1))
Select Case wb_object
Case 1 'Physical Stock
Set wb_physical_stock = ActiveWorkbook
With wb_physical_stock
Set ws_physical_stock = ActiveSheet
last_row_PHYSICALSTOCK = ws_physical_stock.Cells(Rows.Count, "A").End(xlUp).Row
End With
Case 2 'Storage Bins
Set wb_storage_bins = ActiveWorkbook
With wb_storage_bins
Set ws_storage_bins = ActiveSheet
last_row_STORAGEBIN = ws_storage_bins.Cells(Rows.Count, "A").End(xlUp).Row - 1
Set rng_STORAGEBIN = ws_storage_bins.Range("A2:A" & last_row_STORAGEBIN)
End With
End Select
End With
End Sub
In case, here is the private variable declaration:
Private wb_physical_stock As Workbook, wb_storage_bins As Workbook
Private ws_physical_stock As Worksheet, ws_storage_bins As Worksheet, ws_control_file As Worksheet
Private last_row_PHYSICALSTOCK As Long
Private rng_STORAGEBIN As Range
EDIT: I was now checking the procedure open_files with breakpoints. If I set a breakpoint BEFORE Workbooks.Open and run from there again with F5 everything is fine. However, if I set a breakpoint AFTER Workbooks.Open, the breakpoint isn't even triggered. Any ideas?
EDIT2: Previously the macro was started via a short-cut. Now I changed that to an ActiveX-Control and it works fine. Same tested with simple forms and buttons (form control).
If you suspect that opening a file triggers some code, disable events before opening it - this will prevent to execute any (autoexec-) macros withing that file.
Another topic that you should address is that the user might press the "Cancel"-button, else you will run into a runtime error. You can check this with the result of the show-method, it will return False if the dialog was cancelled
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
if .Show then
application.EnableEvents = False
Workbooks.Open (.SelectedItems(1))
application.EnableEvents = True
(...)
else
' You have to make up your mind what to do in that case...
end if
end with

Excel VBA - Loop through folder and add certain parts of names to cells in workbook

I'm trying to perform a simple exercise - (1) merge several tabs (each from separate file) into single file ("macro-file"), (2) rename all tabs in accordance with certain cells in these tabs.
Each tab is effectively a bank statement (in different currencies), so all tabs are of the same structure. I've found a macro (I'm not a specialist in VBA, so this is more about "find and adapt" than "write by myself") to merge them all, so there is no problem with step 1.
However, when I'm trying to rename all tabs at once, I'm getting a conflict - there are three tabs relating to Escrow Account and four tabs relating to Ordinary Account, and there is an intersection in currencies between accounts (each account has USD and EUR, for example).
Currently I have the following code to rename the tabs:
Sub RenameSheet ()
Dim rs As Worksheet
For Each rs In Sheets
If rs.Index > 2 Then
rs.Name = rs.Range("D4")
End If
Next rs
End Sub
What I'm looking for is the solution for problem: if file in a given folder (same as the macro-file) contains "ESCROW", then cell value in cell "D4" in the tab merged to macro-file should be changed from "USD" (let it be a USD bank statement) to "Escrow USD".
The macro should be able to check all files in folder (this is Loop, as far as I understand) and rename respectful cells at once.
Here is the example of code I tried to write-down (unsucessfully though):
Sub RenameSheet ()
Dim fName As String, wb As Workbook, rs As Worksheet
For Each rs In Sheets
If rs.Index > 2 Then
Const myPath As String = "C:\Users\my folder"
If Right(myPath, 1) <> "\" Then fPath = myPath & "\"
fName = Dir(fPath & "*Full*.xlsx*")
v = "ESCROW"
Do Until fName <> ""
If InStr(1, fName, v) > 0 Then
rs.Name = "ESCROW" + rs.Range("D4")
Else
rs.Name = rs.Range("D4")
End If
Loop
End If
Next rs
End Sub
If any of you could help me somehow, I will be grateful.
Any questions are welcome (I understand my language can be a bit tricky).
UPDATE. Current code for tabs merging is below (again, that's not mine, only googled it and inserted to my file, works perfectly):
Sub MergeExcelFiles()
Dim fnameList, fnameCurFile As Variant
Dim countFiles, countSheets As Integer
Dim wksCurSheet As Worksheet
Dim wbkCurBook, wbkSrcBook As Workbook
fnameList = Application.GetOpenFilename(FileFilter:="Microsoft Excel Workbooks (*.xls;*.xlsx;*.xlsm),*.xls;*.xlsx;*.xlsm", Title:="Choose Excel files to merge", MultiSelect:=True)
If (vbBoolean <> VarType(fnameList)) Then
If (UBound(fnameList) > 0) Then
countFiles = 0
countSheets = 0
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set wbkCurBook = ActiveWorkbook
For Each fnameCurFile In fnameList
countFiles = countFiles + 1
Set wbkSrcBook = Workbooks.Open(FileName:=fnameCurFile)
For Each wksCurSheet In wbkSrcBook.Sheets
countSheets = countSheets + 1
wksCurSheet.Copyafter:=wbkCurBook.Sheets(wbkCurBook.Sheets.Count)
Next
wbkSrcBook.Close SaveChanges:=False
Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Procesed " & countFiles & " files" & vbCrLf & "Merged " & countSheets & " worksheets", Title:="Merge Excel files"
End If
Else
MsgBox "No files selected", Title:="Merge Excel files"
End If
End Sub
There are a few things here and there that I changed before getting to the point:
Reordered and renamed some variables for (hopefully) simplicity
Changed the filter on documents to just *.xl* and added a secondary file filter later with Instr(file, ".xl")
Utilized the With statement for changing the Application settings
But, the important new bit comes in during the loop on each sheet in the source workbook. It does the checks that you used in the initial code - checking if index > 2 and whether "ESCROW" is in the filename - then changes the name accordingly via a With statement.
Sub MergeExcelFiles()
Dim fnameList, fnameCurFile As Variant
Dim wbkDestBook, wbkCurSrcBook As Workbook
Dim countFiles, countSheets As Long
Dim wksCurSheet As Worksheet
fnameList = Application.GetOpenFilename( _
FileFilter:="Microsoft Excel Workbooks (*.xl*),*.xl*", _
Title:="Choose Excel files to merge", _
MultiSelect:=True)
If (vbBoolean <> VarType(fnameList)) Then
If (UBound(fnameList) > 0) Then
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
Set wbkDestBook = ActiveWorkbook
For Each fnameCurFile In fnameList
If InStr(LCase$(fnameCurFile), ".xl") > 0 Then 'second file filter 'prevents e.g. shortcuts (.html files) that can get this far
Set wbkCurSrcBook = Workbooks.Open(filename:=fnameCurFile)
For Each wksCurSheet In wbkCurSrcBook.Sheets
wksCurSheet.copy after:=wbkDestBook.Sheets(wbkDestBook.Sheets.count)
'renaming here
If wbkDestBook.Sheets.count > 2 Then
With wbkDestBook.Sheets(wbkDestBook.Sheets.count)
If InStr(UCase$(fnameCurFile), "ESCROW") Then
.Name = "ESCROW " & .Range("D4").Value2
Else
.Name = .Range("D4").Value2
End If
End With
End If
'end of renaming
countSheets = countSheets + 1
Next
wbkCurSrcBook.Close SaveChanges:=False
countFiles = countFiles + 1
End If
Next
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
MsgBox "Procesed " & countFiles & " files." & vbCrLf & "Merged " & countSheets & " worksheets.", Title:="Merge Excel files"
End If
Else
MsgBox "No files selected", Title:="Merge Excel files"
End If
End Sub

Using VBA to Import multiple text files with different delimiters

UPDATED CODE AND ISSUES (5/9/2018 1:53PM Eastern)
I am encountering problems trying to import multiple data text files into a fixed worksheet ("Raw Data") using two different delimiters. I am using Application.GetOpenFilename to allow the user to select multiple text files from a folder. The files contain a header row which is semicolon delimited, then several lines of data which is comma delimited. In a single text file, this format can be repeated several times (this is an inspection log file which records and appends data to the same text file for each inspection run, i.e. header line1, some rows of data, header line 2, more rows of data, header line 3, more rows of data, etc.)
I've tried a few approaches to solve this based on other examples I've found on StackOverflow.com but I can't seem to successfully mesh the solutions together to come up with a solution that imports single or multiple text files with two different delimiters within each file. I cannot change the format or content of the original text files, so I can't search and replace different delimiters to a single delimiter.
Here are the remaining issues I'm running into with the attached VBA code:
When importing more than one text file, a blank line is inserted between the files which breaks the .TextToColumns section. It is also asking to replace existing data when importing the second file selected. Is there a more efficient or better way to import data from multiple text files using both commas and semicolons as delimiters?
Within a fixed path on the local hard drive, each new order number creates a new sub-folder to store .txt data files (i.e. C:\AOI_DATA64\SPC_DataLog\IspnDetails\123456-7). Is there a way the user can be prompted to enter a sub-folder name (123456-7) and the VBA script will automatically import all .txt files from this sub-folder, rather than using Application.GetOpenFilename?
Here is a truncated version of one of the data files I'm trying to import. The actual file does not have spaces between the rows of data. I separated them in this example to clearly show each line in the text file.
[StartIspn];Time=04/19/18 12:43:15;User=yeseniar;MachineID=WINDOWS-TEFJCS1;Side=T;DoubleSided;IsOnline=1;IA_Idx=1;SN_Idx=0;IT=0;SPC_Db=1;SPC_Txt=1;TxtFmt=10;E_Rpt=1;D_Img=1;FeedMode=0;
KC17390053F,VIA5F,M North,A8,85.0,45.0,96.0,23.2,9.9,0.0,0.0,0.0,59.0,0.0,0.0,0.0,
KC17390053F,VIA3F,M North,A8,85.0,45.0,96.0,22.3,22.9,0.0,0.0,0.0,59.0,0.0,0.0,0.0,
KC17390053F,FMI1F,S South,A13,12.3,0.0,1.0,3.5,3.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
KC17390053F,FMI13F,S South,A13,12.3,0.0,1.0,3.5,3.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
[StartIspn];Time=04/19/18 14:28:10;User=yeseniar;MachineID=WINDOWS-TEFJCS1;Side=B;DoubleSided;IsOnline=1;IA_Idx=1;SN_Idx=0;IT=0;SPC_Db=1;SPC_Txt=1;TxtFmt=10;E_Rpt=1;D_Img=1;FeedMode=0;
KC17390066B,VIA5B,M North,A8,70.0,50.0,92.0,-38.8,-3.7,0.0,0.0,0.0,50.0,0.0,0.0,0.0,
KC17390066B,VIA6B,M North,A8,70.0,50.0,93.0,-37.7,-23.6,0.0,0.0,0.0,50.0,0.0,0.0,0.0,
KC17390066B,FMI12B,S South,A13,4140.4,0.0,2.0,3.5,129.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
KC17390066B,FMI24B,S South,A13,2128.7,0.0,2.0,3.5,119.1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
Here is what I have so far for importing multiple text files:
Sub Import_DataFile()
' Add an error handler
On Error GoTo ErrorHandler
' Speed up this sub-routine by turning off screen updating and auto calculating until the end of the sub-routine
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Define variable names and types
Dim OpenFileName As Variant
Dim i As Long
Dim n1 As Long
Dim n2 As Long
Dim fn As Integer
Dim RawData As String
Dim rngTarget As Range
Dim rngFileList As Range
Dim TargetRow As Long
Dim FileListRow As Long
Dim dLastRow As Long
Dim destCell As Range
' Select the source folder and point list file(s) to import into worksheet
OpenFileName = Application.GetOpenFilename( _
FileFilter:="AOI Inspection Results Data Files (*.txt), *.txt", _
Title:="Select a data file or files to import", _
MultiSelect:=True)
' Import user selected file(s) to "Raw Data" worksheet
TargetRow = 0
Set destCell = Worksheets("Raw Data").Range("B1")
For n2 = LBound(OpenFileName) To UBound(OpenFileName)
fn = FreeFile
Open OpenFileName(n2) For Input As #fn
Application.StatusBar = "Processing ... " & OpenFileName(n2)
Do While Not EOF(fn)
Line Input #fn, RawData
TargetRow = TargetRow + 1
Worksheets("Raw Data").Range("B" & TargetRow).Formula = RawData
Loop
Next n2
Close #fn
Set rngTarget = Worksheets("Raw Data").Range("B1" & ":" & Worksheets("Raw Data").Range("B1").End(xlDown).Address)
With rngTarget
.TextToColumns Destination:=destCell, DataType:=xlDelimited, _
TextQualifier:=xlNone, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=True, Comma:=True, Space:=False, Other:=False, OtherChar:="|", _
FieldInfo:=Array(1, 1), TrailingMinusNumbers:=True
End With
Else: MsgBox "The selected file is not the correct format for importing data."
Exit Sub
End If
Next
' Create a number list (autofill) in Col A to maintain original import sort order
dLastRow = Worksheets("Raw Data").Cells(Rows.Count, "B").End(xlUp).Row
Worksheets("Raw Data").Range("A1:A" & dLastRow).Font.Color = RGB(200, 200, 200)
Worksheets("Raw Data").Range("A1") = "1"
Worksheets("Raw Data").Range("A2") = "2"
Worksheets("Raw Data").Range("A1:A2").AutoFill Destination:=Worksheets("Raw Data").Range("A1:A" & dLastRow), Type:=xlFillDefault
Worksheets("Raw Data").Range("F1:Q" & dLastRow).NumberFormat = "0.0"
' Auto fit the width of columns for RAW Data
Worksheets("Raw Data").Columns("A:Z").EntireColumn.AutoFit
' Turn screen updating and auto calculating back on since file processing is now complete
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
' Reset to defaults in the event of a processing error during the sub-routine execution
ErrorHandler:
Application.StatusBar = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
If Err.Number <> 0 Then
' Display a message to the user including the error code in the event of an error during execution
MsgBox "An error number " & Err.Number & " was encountered!" & vbNewLine & _
"Part or all of this VBA script was not completed.", vbInformation, "Error Message"
End If
End Sub
Many questions... Let me give some hints.
Prompting the user for working directory :
Dim fDlg As FileDialog ' dialog box object
Dim sDir As String ' selected path
Dim iretval As Long ' test
Set fDlg = Application.FileDialog(msoFileDialogFolderPicker)
sDir = conDEFAULTPATH ' init
With fDlg
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = sDir
iretval = .Show
If iretval = -1 Then sDir = .SelectedItems(1)
End With
Set fDlg = Nothing ' drop object
If sDir = vbNullString Then
MsgBox "Invalid directory"
Else
If Right$(Trim$(sDir), 1) <> Application.PathSeparator Then _
sDir = Trim$(sDir) & Application.PathSeparator' append closing backslash to pathname
End If
Collecting files to a buffer
Dim FileBuf(100) as string, FileCnt as long
FileCnt=0
FileBuf(FileCnt)=Dir(sDir & "*.txt")
Do While FileBuf(FileCnt) <> vbnullstring
FileCnt = FileCnt + 1
FileBUf(FileCnt) = Dir
Loop
Reducing number of delimiters: simply use replace
RawData = Replace(RawData, ";", ",")
For the blank line I have no clue, though it might be a result of a blank line in the source file, maybe the EOF. So what if you check the line before copying:
If len(trim(RawData)) > 0 Then
TargetRow = TargetRow + 1
Worksheets("Raw Data").Range("B" & TargetRow) = RawData
End If
Please note that I've removed .Formula. You are working with values.
For setting target range: You should omit .Address. For selecting last cell in a range, you should use .End(xlUp) this way:
Set rngTarget = Worksheets("Raw Data").Range("B1" & ":" & Worksheets("Raw Data").Range("B1").End(xlUp))
I prefer using direct cell references, so - as you exactly know the last row - I would do it this way:
Set rngTarget = Worksheets("Raw Data").Range(Cells(1, 2), Cells(TargetRow, 2))
Good Luck!

Making excel macro for file scanning more stable

I was curious if anybody could provide suggestions on how I can make an excel macro more stable.
The macro prompts the user for a path to a folder containing files to scan. The macro then iterates for every file in this folder.
It opens the excel file, scans Column D for the word fail, then copies that row of data to the data sheet in the excel file where this macro is programmed.
For the most part the macro runs perfectly but sometimes I get run time errors or 'excel has stopped working' errors. I can scan through 5000+ files at a time and the macro takes a while to run.
Any suggestions would be appreciated. Thanks!
Sub findFail()
Dim pathInput As String 'path to file
Dim path As String 'path to file after being validated
Dim fileNames As String 'path to test file
Dim book As Workbook 'file being tested
Dim sheet As Worksheet 'sheet writting data to
Dim sh As Worksheet 'worksheet being tested
Dim dataBook As Workbook 'where data is recorded
Dim row As Long 'row to start writting data in
Dim numTests As Long 'number of files tested
Dim j As Long 'counter for number of files tested
Dim i As Long 'row currently being tested
Dim lastRow As Long 'last row used
Dim startTime As Double 'time when program started
Dim minsElapsed As Double 'time it took program to end
Application.ScreenUpdating = False
j = 0
i = 1
row = 2
Set dataBook = ActiveWorkbook
Set sheet = Worksheets("Data")
sheet.Range("A2:i1000").Clear
startTime = Timer
'-----Prompt for Path-----
pathInput = InputBox(Prompt:="Enter path to files. It must have a \ after folder name.", _
Title:="Single Report", _
Default:="C:\Folder\")
If pathInput = "C:\Folder\" Or pathInput = vbNullString Then 'check to make sure path was inputed
MsgBox ("Please enter a valid file path and try again.")
Exit Sub
Else
path = pathInput 'path = "C:\Temp\212458481\" ' Path for file location
fileNames = Dir(path & "*.xls") 'for xl2007 & "*.xls?" on windows
'-----begin testing-----
Do While fileNames <> "" 'Loop until filename is blank
Set book = Workbooks.Open(path & fileNames)
Set sh = book.Worksheets(1)
lastRow = sh.UsedRange.Rows(sh.UsedRange.Rows.Count).row
If sh.Cells(lastRow, 2).Value - sh.Cells(1, 2).Value >= 0.08333333 Then
Do While sh.Range("D" & i).Value <> "" 'loop untile there are no rows left to test
If sh.Range("D" & i).Value = "Fail" Then 'record values if test result is false
sheet.Range("A" & row).Value = book.Name
sheet.Range("B" & row).Value = Format(sh.Range("B" & i).Value - sh.Range("B1").Value, "h:mm:ss")
sheet.Range("C" & row).Value = sh.Range("A" & i).Value
sheet.Range("D" & row).Value = Format(sh.Range("B" & i).Value, "h:mm:ss")
sheet.Range("E" & row).Value = sh.Range("C" & i).Value
sheet.Range("F" & row).Value = sh.Range("D" & i).Value
sheet.Range("G" & row).Value = sh.Range("E" & i).Value
sheet.Range("H" & row).Value = sh.Range("F" & i).Value
sheet.Range("I" & row).Value = sh.Range("G" & i).Value
row = row + 1
Exit Do
End If
i = i + 1
Loop
j = j + 1
dataBook.Sheets("Summary").Cells(2, 1).Value = j
End If
book.Close SaveChanges:=False
fileNames = Dir()
i = 1
Loop
numTests = j
Worksheets("Summary").Cells(2, "A").Value = numTests
minsElapsed = Timer - startTime
Worksheets("Summary").Cells(2, "B").Value = Format(minsElapsed / 86400, "hh:mm:ss")
End If
End Sub
Without the same dataset as you we, can not definitively supply an answer but I can recommend the below which is related to the error you are seeing.
Try freeing/destroying the references to book and sh.
You have a loop that sets them:-
Do While fileNames <> "" 'Loop until filename is blank
Set book = Workbooks.Open(path & fileNames)
Set sh = book.Worksheets(1)
However the end of the loop does not clear them, ideally it should look as below:-
Set sh = Nothing
Set book = Nothing
Loop
This is a better way to handle resources and should improve memory usage.
As a poor example, without it your code is saying, sh equals this, now it equals this instead, now it equals this instead, now it equals this instead, etc...
You end up with the previous reference that was subsequently overwritten being a sort of orphaned object that is holding some space in memory.
Depending on your case, you may use the following to make it faster -by turning off excel processes that you don't really need at the time of your macro execution-
Sub ExcelBusy()
With Excel.Application
.Cursor = xlWait
.ScreenUpdating = False
.DisplayAlerts = False
.StatusBar = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With
End Sub
In your sub
Dim startTime As Double 'time when program started
Dim minsElapsed As Double 'time it took program to end
Call ExcelBusy
...
As a comment, you never set back screenupdating to true in your sub, that may lead to strange behavior in excel, you should turn everything to default after you are done with your stuff.
OT: Some processes can't be optimized any further -sometimes-, by what you are saying -scanning over 5k files?- surely it's going to take a time, you need to work in how to communicate the user that is going to take a while instead -perhaps an application status bar message or a user form showing process?-.

Wait for big files to open in Excel

I've been trying to loop over a bunch of big .csv files in VBA. Each of them is approximately 50MB. At every iteration I open a new CSV to manipulate data but when the .csv is opening there is a downloading message saying that the file is opening and the progress bar always gets stuck at some point while the VBA is waiting for it to finish.
Actually the .csv is opened because if I click "cancel" on the progress bar the code continues running well but I have to do a manual action at every iteration.
My guess is that VBA goes to the next step while the file is not opened or something like that so maybe if I do a Sleep or something like that it could work but what I tried did not work for now. (I already tried Application.EnableEvents = False). Here is my code:
Sub GetOptions()
Application.DisplayAlerts = False
Application.EnableEvents = False
Set Dates = Sheets("Dates")
Set Res = Sheets("Options")
Dim dateToday As Date
ETF = "SPY"
nrows = Dates.Cells(Rows.Count, 1).End(xlUp).Row
For i = 708 To nrows
If Dates.Cells(i, 2).Value = "B" Then
dateToday = Dates.Cells(i, 1).Value
dateYear = Year(dateToday)
stringOpening = "P:\Options Database\CSV\" & dateYear & "\bb_" & dateYear & "_" & GetMonth(dateToday) & "\bb_options_" & Format(dateToday, "yyyymmdd") & ".csv"
Workbooks.Open stringOpening, UpdateLinks:=0, ReadOnly:=True
Set Options = Workbooks("bb_options_" & Format(dateToday, "yyyymmdd")).Sheets(1)
Do things...
Workbooks("bb_options_" & Format(dateToday, "yyyymmdd")).Close SaveChanges:=False
End If
Next i
End Sub
A trick would be :
to open them as Read/Write files,
wait for the Write status which indicates that it is fully opened
set back the file to Read Only
This code loops until the file goes into a Write status :
Sub myWaitForFileOpen()
Dim wb As Workbook
Set wb = Application.Workbooks.Open("C:\File.xls")
Do Until wb.ReadOnly = False
wb.Close
Application.Wait Now + TimeValue("00:00:01")
Set wb = Application.Workbooks.Open("C:\File.xls")
Loop
'Then the code that needs that Workbook open here!
'Or Call That other macro here!
End Sub
Here is your full code, that will open the CSV in Read/Write until it is fully loaded and then put it back to read only :
Sub GetOptions()
Dim wB As Workbook
Application.DisplayAlerts = False
Application.EnableEvents = False
Set Dates = Sheets("Dates")
Set Res = Sheets("Options")
Dim dateToday As Date
ETF = "SPY"
nrows = Dates.Cells(Rows.Count, 1).End(xlUp).Row
For i = 708 To nrows
If Dates.Cells(i, 2).Value = "B" Then
dateToday = Dates.Cells(i, 1).Value
dateYear = Year(dateToday)
stringOpening = "P:\Options Database\CSV\" & dateYear & "\bb_" & dateYear & "_" & GetMonth(dateToday) & "\bb_options_" & Format(dateToday, "yyyymmdd") & ".csv"
Set wB = Workbooks.Open(stringOpening, UpdateLinks:=0, ReadOnly:=False)
Do Until wB.ReadOnly = False
wB.Close
Application.Wait Now + TimeValue("00:00:01")
Set wB = Application.Workbooks.Open("C:\My Files\AAA.xls")
Loop
wB.ReadOnly = True
Set Options = wB.Sheets(1)
Do
'things...
Loop
wB.Close SaveChanges:=False
End If
Next i
End Sub
If you want to open the file and use it immediately Excel might
give an error because Excel activates file opening process and goes to execute next statement. A quick and dirty workaround for not very long files is to introduce an extra code that is not related to a file thus keeping Excel busy while file is going through the opening process.