Base Problem
I have the following that runs daily on a schedule:
batch file --> vbscript --> two macros
However, after working without issue for months, I am now getting the following error:
1004: Cannot run the macro 'M1DelimiterSetupErrDescription'. The macro may not be available in this workbook or all macros may be disabled.
The above error is occurring on this line in the below VBScript:
ErrDescriptionResult = xlApp.Run ("M1DelimiterSetupErrDescription")
What I've Tried
Through trial and error, I've discovered several things:
Running the macros manually works, including M1DelimiterSetupErrDescription
Opening the .xlsm file as NOT read-only doesn't resolve the issue
Moving the problematic ErrDescriptionResult = xlApp.Run ("M1DelimiterSetupErrDescription") to an earlier location in the code, before the ErrNumberResult = xlApp.Run ("M1DelimiterSetupErrNumber") line, causes it to run without issue.
Opening the .xlsm file does bring up the yellow "Enable Macros" button/bar, but doesn't bring up the Trusted Document prompt after pushing the button. I don't know why that is - that's unusual.
Batch file:
pushd (directory)
cscript "Provider File Automation.vbs"
IF ERRORLEVEL 1 EXIT /b %ERRORLEVEL%
VBScript:
Option Explicit
Dim xlApp
Dim xlBook
Dim ErrNumberResult
Dim ErrDescriptionResult
'Have to use this for the Get Excel.Application lines
On Error Resume Next
'Make sure there's no error pre-registered for some reason
If Err.Number <> 0 Then Err.Clear
ErrNumberResult = 0
'Get Excel ready to work
Set xlApp = GetObject("","Excel.Application")
If xlApp <> "Microsoft Excel" Then Msgbox xlApp
If xlApp is Nothing Then Set xlApp = CreateObject("Excel.Application")
'Check for errors
If Err.Number <> 0 Then
Msgbox Err.Number & ": " & Err.Description & " The script will now quit."
WScript.Quit Err.Number
End If
'Change the delimiter
Set xlBook = xlApp.Workbooks.Open("(directory)\Provider File Automation v1.05.xlsm", 0, True)
ErrNumberResult = xlApp.Run ("M1DelimiterSetupErrNumber")
ErrDescriptionResult = xlApp.Run ("M1DelimiterSetupErrDescription")
If xlApp.Workbooks.Count = 1 Then xlApp.DisplayAlerts = False
xlApp.Quit
xlApp.DisplayAlerts = True
'Check for errors
If ErrNumberResult <> 0 Then
Msgbox ErrNumberResult & ": " & ErrDescriptionResult & " The script will now quit."
WScript.Quit ErrNumberResult
End If
Set xlBook = Nothing
Set xlApp = Nothing
'Get Excel ready to work again
Set xlApp = GetObject("","Excel.Application")
If xlApp <> "Microsoft Excel" Then Msgbox xlApp
If xlApp is Nothing Then Set xlApp = CreateObject("Excel.Application")
'Check for errors
If Err.Number <> 0 Then
Msgbox Err.Number & ": " & Err.Description & " The script will now quit."
WScript.Quit Err.Number
End If
'Create the provider file and change the delimiter back
Set xlBook = xlApp.Workbooks.Open("(directory)\Provider File Automation v1.05.xlsm", 0, True)
ErrNumberResult = xlApp.Run ("M2ProviderFileAutomationErrNumber")
ErrDescriptionResult = xlApp.Run ("M2ProviderFileAutomationErrDescription")
If xlApp.Workbooks.Count = 1 Then xlApp.DisplayAlerts = False
xlApp.Quit
xlApp.DisplayAlerts = True
'Check for errors
If ErrNumberResult <> 0 Then
Msgbox ErrNumberResult & ": " & ErrDescriptionResult & " The script will now quit."
WScript.Quit ErrNumberResult
End If
Set xlBook = Nothing
Set xlApp = Nothing
.xlsm module:
Option Explicit
Private Declare Function SetLocaleInfo _
Lib "kernel32" Alias "SetLocaleInfoA" ( _
ByVal Locale As Long, _
ByVal LCType As Long, _
ByVal lpLCData As String) As Boolean
Private Declare Function GetUserDefaultLCID% Lib "kernel32" ()
Private Const LOCALE_SLIST = &HC
Private Const LOCALE_NAME_USER_DEFAULT = vbNullString
'Private Const LOCALE_USER_DEFAULT = "0x0400"
'Get Locale Info
Private Declare Function GetLocaleInfoEx _
Lib "kernel32" ( _
ByVal lpLocaleName As String, _
ByVal LCType As Long, _
ByVal lpLCData As String, _
ByVal cchData As Long) As Long
Private Declare Function GetLastError Lib "kernel32" () As Long
Function M1DelimiterSetupErrNumber() As Long
M1ChangeDelimiterToPipe
M1DelimiterSetupErrNumber = Err.Number
End Function
Function M1DelimiterSetupErrDescription() As String
M1DelimiterSetupErrDescription = Err.Description
End Function
Sub M1ChangeDelimiterToPipe()
Dim lngTryAgainCtr As Long
Dim strListSeparator As String
Dim lpLCData As String
Dim Long1 As Long
lngTryAgainCtr = 0
TryAgain:
lngTryAgainCtr = lngTryAgainCtr + 1
'Change delimiter to pipe
' Call SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, "|")
Call SetLocaleInfo(GetUserDefaultLCID(), LOCALE_SLIST, "|")
'Check to make sure setting separator as pipe worked correctly
Long1 = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, lpLCData, 0)
'Make sure that Long1 came out with an appropriate value, exit with error number if it didn't
If Long1 = 0 Then
If lngTryAgainCtr < 3 Then
GoTo TryAgain
Else
Err.Number = 1
Err.Description = "GetLocaleInfoEx() failed, returned value of 0"
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
Exit Sub
End If
Else
strListSeparator = String$(Long1, 0)
Long1 = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, strListSeparator, Long1)
If InStr(strListSeparator, "|") = 0 Then
If lngTryAgainCtr < 3 Then
GoTo TryAgain
Else
If GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, strListSeparator, Long1) <> 0 Then Debug.Print GetLastError
Err.Number = 2
Err.Description = "Changing list separator to pipe unsuccessful."
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
Exit Sub
End If
End If
'Close workbook to allow Excel to reset its memory of delimiter
'Show alerts if more workbooks open
' If Workbooks.Count = 1 Then Application.DisplayAlerts = False
' Application.Quit
End If
End Sub
Function M2ProviderFileAutomationErrNumber() As Long
M2ProviderFileAutomation
M2ProviderFileAutomationErrNumber = Err.Number
End Function
Function M2ProviderFileAutomationErrDescription() As String
M2ProviderFileAutomationErrDescription = Err.Description
End Function
Sub M2ProviderFileAutomation()
'
' M2ProviderFileAutomation Macro
'
' Keyboard Shortcut: Ctrl+Shift+W
'
Dim strProvFileSaveLoc As String 'Full File Name
Dim strProvFileUnzipped As String 'Location of Text File after Unzipping
Dim strProvFileEITcsv As String 'Location where csv is saved
Dim strProvFileWebAddr As String 'web address
Dim oXMLHTTP As Object
Dim Long1 As Long
Dim strListSeparator As String
Dim lpLCData As String
'Check to make sure Part 1 ran correctly and separator is pipe
Long1 = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, lpLCData, 0)
'Make sure that Long1 came out with an appropriate value, exit with error number if it didn't
If Long1 = 0 Then
Err.Number = 1
Err.Description = "GetLocaleInfoEx() failed, returned value of 0"
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
Exit Sub
Else
strListSeparator = String$(Long1, 0)
Long1 = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, strListSeparator, Long1)
If InStr(strListSeparator, "|") = 0 Then
If GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, strListSeparator, Long1) <> 0 Then Debug.Print GetLastError
Err.Number = 3
Err.Description = "Part 2 detects non-pipe list separator."
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
Exit Sub
Else
'Makes things go faster
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'Save the provider file
strProvFileWebAddr = (web address)
strProvFileSaveLoc = (path)
strProvFileUnzipped = (path)
'Delete any in the way files
'Automated provider file folder - unzipped folder contents
If Dir(strProvFileUnzipped) <> "" Then
Kill strProvFileUnzipped
RmDir (path1)
RmDir (path2)
RmDir (path3)
RmDir (path4)
End If
'archive zip file
If Dir((potentially existing archive file path)) <> "" Then Kill ((potentially existing archive file path))
'archive text file
If Dir((potentially existing archive file2 path)) <> "" Then Kill ((potentially existing archive file2 path))
'You can also set a ref. to Microsoft XML, and Dim oXMLHTTP as MSXML2.XMLHTTP
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP")
oXMLHTTP.Open "GET", strProvFileWebAddr, False 'Open socket to get the website
oXMLHTTP.Send 'send request
'Wait for request to finish
Do While oXMLHTTP.readyState <> 4
DoEvents
Loop
Dim oResp() As Byte
oResp = oXMLHTTP.responseBody 'Returns the results as a byte array
'Create local file and save results to it
Dim Int1 As Integer
Int1 = FreeFile()
If Dir(strProvFileSaveLoc) <> "" Then Kill strProvFileSaveLoc
Open strProvFileSaveLoc For Binary As #Int1
Put #Int1, , oResp
Close #Int1
'Clear memory
Set oXMLHTTP = Nothing
'Unzip zipped provider file
Dim objShell As Object
Set objShell = CreateObject("Shell.Application")
'Has to be variants, can't be strings
Dim varFLProviderFileAutomationFolder As Variant
varFLProviderFileAutomationFolder = (path)
Dim varProviderFileSaveLocation As Variant
varProviderFileSaveLocation = strProvFileSaveLoc
objShell.Namespace(varFLProviderFileAutomationFolder).CopyHere objShell.Namespace(varProviderFileSaveLocation).items
On Error Resume Next
Dim objFileSystemObject As Object
Set objFileSystemObject = CreateObject("scripting.filesystemobject")
objFileSystemObject.DeleteFolder Environ("Temp") & "\Temporary Directory*", True
On Error GoTo 0
'Excel changes to provider file
Workbooks.OpenText strProvFileUnzipped, DataType:=xlDelimited, _
TextQualifier:=xlTextQualifierDoubleQuote, Other:=True, Otherchar:="|", FieldInfo:=Array(Array(1, 2), _
Array(2, 2), Array(3, 2), Array(4, 2), Array(5, 2), Array(6, 2), Array(7, 2), Array(8, 2), Array(9, 2), _
Array(10, 2), Array(11, 2), Array(12, 2), Array(13, 2), Array(14, 2), Array(15, 2), Array(16, 2), _
Array(17, 2), Array(18, 2), Array(19, 2), Array(20, 2), Array(21, 2), Array(22, 2), Array(23, 2), _
Array(24, 2))
ActiveWorkbook.Sheets(1).Rows(1).Delete
ActiveWorkbook.Sheets(1).Columns("B:C").Replace What:="""", Replacement:="'", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
ActiveWorkbook.Sheets(1).Columns("G").Replace What:="""", Replacement:="'", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
strProvFileEITcsv = (path)
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs Filename:=strProvFileEITcsv, FileFormat:=xlCSV, local:=True
Application.DisplayAlerts = True
'Don't have permission to copy from folder
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs Filename:=(path), FileFormat:=xlCSV, local:=True
Application.DisplayAlerts = True
ActiveWorkbook.Close False
'Change delimiter back to comma
Call SetLocaleInfo(GetUserDefaultLCID(), LOCALE_SLIST, ",")
'Move zip file to archive
If Dir((potential archive file path)) = "" Then
Name strProvFileSaveLoc As (potential archive file path)
Else
Err.Number = 4
Err.Description = "Zip file already exists in archive."
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
End If
'Move txt file to archive
If Dir((potential archive file2 path)) = "" Then
Name strProvFileUnzipped As (potential archive file2 path)
Else
If Err.Number <> 4 Then
Err.Number = 5
Err.Description = "Text file already exists in archive."
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
GoTo SkipRMDir
Else
Err.Number = 6
Err.Description = "Zip and text files already exists in archive."
' MsgBox Err.Number & ": " & Err.Description & " The script will now quit."
GoTo SkipRMDir
End If
End If
'Cleanup
RmDir (path1)
RmDir (path2)
RmDir (path3)
RmDir (path4)
' MsgBox "Provider file done."
SkipRMDir:
Application.ScreenUpdating = True
Application.Calculation = xlAutomatic
'Show alerts if more workbooks open
' If Workbooks.Count = 1 Then Application.DisplayAlerts = False
' Application.Quit
End If
End If
End Sub
This stopped occurring as inexplicably as it started. Can no longer recreate. So I suppose one possible answer is just to wait.
Related
This is a scirpt which is supposed to add picture into a Powerpoint Placeholders based on the value of selected cells in an Excel File. Whenever there is an error, the script is supposed to go to the error handling line, fixed it and resume back from where the error was.
However, when the script encounters an error, it will run the error handling line, then end sub. How can I make it resume from where the error was detected?
For example, let's say we have an error on this line
On Error GoTo ERIB
For IB = 6
The script will go to error handling
ERIB:
oSld1.Shapes.AddPicture( _
FileName:="D:\Users\Transparent\AnorMale.png", _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, Left:=50, Top:=30, Width:=100, Height:=50).Select
After the above code, it will proceed to line ERIE then End Sub.
Instead, I would like the script to continue running from For IB = 7 until the end of the script.
Here's the code
Dim I As Integer
Dim oXL As Object 'Excel.Aplication
Dim OWB As Object 'Excel.workbook
Dim oSld1 As Slide
Dim oSld2 As Slide
Set oXL = CreateObject("Excel.Application")
Set OWB = oXL.Workbooks.Open(FileName:="D:\Users\1. Working\Working.xlsm")
Set oSld1 = ActivePresentation.Slides(1)
Set oSld2 = ActivePresentation.Slides(2)
------------------------------------------------------------------------
On Error GoTo ERIB
For IB = 5 To 7
oSld1.Shapes.AddPicture( _
FileName:="D:\Users\Transparent\" & OWB.Sheets("Listing").Range("B" & CStr(IB)).Value & "_hof.png", _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, Left:=50, Top:=30, Width:=100, Height:=50).Select
Next IB
On Error GoTo ERIE
For IE = 5 To 7
oSld2.Shapes.AddPicture( _
FileName:="D:\Users\Transparent\" & OWB.Sheets("Listing").Range("E" & CStr(IE)).Value & "_hof.png", _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, Left:=50, Top:=30, Width:=100, Height:=50).Select
Next IE
OWB.Close
oXL.Quit
Set OWB = Nothing
Set oXL = Nothing
Exit Sub
ERIB:
oSld1.Shapes.AddPicture( _
FileName:="D:\Users\Transparent\AnorMale.png", _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, Left:=50, Top:=30, Width:=100, Height:=50).Select
ERIE:
oSld1.Shapes.AddPicture( _
FileName:="D:\Users\Transparent\AnorMale.png", _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, Left:=50, Top:=30, Width:=100, Height:=50).Select
End Sub
You can simply put an statement Resume Next at the end of your error handler:
Sub test1()
Dim myValues, sum As Long, count As Long, i As Long
myValues = Array(2, 4, "A", 5, 10)
On Error GoTo ERRHANDLER
For i = LBound(myValues) To UBound(myValues)
sum = sum + myValues(i)
count = count + 1
Next i
Debug.Print "Sum: " & sum & " Count: " & count
Exit Sub
ERRHANDLER:
Debug.Print "error: " & Err.Number, Err.Description
Resume Next
End Sub
Or you can jump to a label:
Sub test2()
Dim myValues, sum As Long, count As Long, i As Long
myValues = Array(2, 4, "A", 5, 10)
On Error GoTo ERRHANDLER
For i = LBound(myValues) To UBound(myValues)
sum = sum + myValues(i)
count = count + 1
CONTINUELOOP:
Next i
Debug.Print "Sum: " & sum & " Count: " & count
Exit Sub
ERRHANDLER:
Debug.Print "error: " & Err.Number, Err.Description
Resume CONTINUELOOP
End Sub
However, consider two things:
a) if you already expect that something specific might fail (in your case adding the picture), it's maybe better to handle that locally. If your main problem is that the AddPicture fails because the image fail is missing, you should check the existance to avoid the error (use for example the Dir-command).
Sub test3()
Dim myValues, sum As Long, count As Long, i As Long
myValues = Array(2, 4, "A", 5, 10)
For i = LBound(myValues) To UBound(myValues)
On Error Resume Next
sum = sum + myValues(i)
If Err.Number <> 0 Then
If Err.Number <> 13 Then Err.Raise Err.Number ' An error occurred and it wasn't Type mismatch
Err.Clear
Else
count = count + 1
End If
On Error Goto 0
Next i
Debug.Print "Sum: " & sum & " Count: " & count
Exit Sub
End Sub
b) You need to be careful what you do in your error handler: If the AddPicture in the error handler fails, it will raise another error and this time it will not be caught. Consider to write a MyAddPicture-routine that does the error handling internally without affecting the rest of your code.
You should consider using a try function so that you encapsulate the error and don't have to go jumping all over the place.
The code below compiles without error but as I don't have your images it hasn't been tested.
Sub Test()
Dim I As Integer
Dim oXL As Object 'Excel.Aplication
Dim OWB As Object 'Excel.workbook
Dim oSld1 As Slide
Dim oSld2 As Slide
Set oXL = CreateObject("Excel.Application")
Set OWB = oXL.Workbooks.Open(Filename:="D:\Users\1. Working\Working.xlsm")
Set oSld1 = ActivePresentation.Slides(1)
Set oSld2 = ActivePresentation.Slides(2)
Dim myParams As Variant
myParams = Array("", msoTrue, msoTrue, 50, 30, 100, 50)
Dim mySLide As PowerPoint.Slide
Const myError As Long = 42 ' put your own error number here
'------------------------------------------------------------------------
For IB = 5 To 7
myParams(0) = "D:\Users\Transparent\" & OWB.Sheets("Listing").Range("B" & CStr(IB)).Value & "_hof.png"
If Not TryAddPictureToSlide(oSld1, myParams, mySLide) Then
myParams(0) = "D:\Users\Transparent\AnorMale.png"
If Not TryAddPictureToSlide(oSld1, myParams, mySLide) Then
Err.Raise _
myError, _
"Could not add " & myParams(0)
End If
End If
'Do whatever needs to be done with myShape
Next IB
For IE = 5 To 7
myParams(0) = "D:\Users\Transparent\" & OWB.Sheets("Listing").Range("E" & CStr(IE)).Value & "_hof.png"
If Not TryAddPictureToSlide(oSld2, myParams, mySLide) Then
myParams(0) = "D:\Users\Transparent\AnorMale.png"
If Not TryAddPictureToSlide(oSld2, myParams, mySLide) Then
Err.Raise _
myError, _
"Could not add " & "D:\Users\Transparent\" & OWB.Sheets("Listing").Range("E" & CStr(IE)).Value & "_hof.png"
End If
End If
Next
'Do whatever needs to be done with myShape
OWB.Close
oXL.Quit
Set OWB = Nothing
Set oXL = Nothing
End Sub
Public Function TryAddPictureToSlide(ByRef ipSlide As PowerPoint.Slide, ByRef ipParams As Variant, opShape As PowerPoint.Shape) As Boolean
On Error Resume Next
Set opShape = _
ipSlide.Shapes.AddPicture _
( _
Filename:=ipParams(0), _
LinkToFile:=ipParams(1), _
SaveWithDocument:=ipParams(2), _
Left:=ipParams(3), _
Top:=ipParams(4), _
Width:=ipParams(5), _
Height:=ipParams(6))
TryAddPictureToSlide = Err.Number = 0
Err.Clear
End Function
I copied code from another site that opens every Excel file on a path and sets the password to "".
I have 480 Excel files on that path, and the code stops whenever it encounters a corrupted file.
Is there a way to identify every file that is corrupted?
Is there a way to avoid corrupted files?
Sub RemovePasswords()
Dim xlBook As Workbook
Dim strFilename As String
Const fPath As String = "C:\Path\" 'The folder to process, must end with "\"
Const strPassword As String = "openpassword" 'case sensitive
Const strEditPassword As String = "editpassword" 'If no password use ""
strFilename = Dir$(fPath & "*.xls") 'will open xls & xlsx etc
While Len(strFilename) <> 0
Application.DisplayAlerts = False
Set xlBook = Workbooks.Open(FileName:=fPath & strFilename, _
Password:=strPassword, _
WriteResPassword:=strEditPassword)
xlBook.SaveAs FileName:=fPath & strFilename, _
Password:="", _
WriteResPassword:="", _
CreateBackup:=True
xlBook.Close 0
Application.DisplayAlerts = True
strFilename = Dir$()
Wend
End Sub
On the other hand, whenever the code encounters a corrupted file it just stops and doesn't let me know which file is corrupted.
I know that there is a way to put a "if" to skip this errors, but I don't know how to do it.
Please, try the next adapted code:
Sub RemovePasswords()
Dim xlBook As Workbook, strFilename As String
Const fPath As String = "C:\Path\" 'The folder to process, must end with "\"
Const strPassword As String = "openpassword" 'case sensitive
Const strEditPassword As String = "editpassword" 'If no password use ""
strFilename = dir$(fPath & "*.xls") 'will open xls & xlsx etc
While Len(strFilename) <> 0
On Error Resume Next 'skip the error, if the case
Set xlBook = Workbooks.Open(fileName:=fPath & strFilename, _
password:=strPassword, _
WriteResPassword:=strEditPassword)
If err.Number = 0 Then 'if no error:
Application.DisplayAlerts = False
xlBook.saveas fileName:=fPath & strFilename, _
password:="", _
WriteResPassword:="", _
CreateBackup:=True
xlBook.Close 0
Application.DisplayAlerts = True
End If
On Error GoTo 0 'restart raising errors when the case
strFilename = dir$()
Wend
End Sub
I would change the code suggested by FaneDuru a little, in order to comply to your first demand. This code will output corrupt filenames in the debug panel.
Sub RemovePasswords()
Dim xlBook As Workbook
Dim strFilename As String
Const fPath As String = "C:\Path\" 'The folder to process, must end with "\"
Const strPassword As String = "openpassword" 'case sensitive
Const strEditPassword As String = "editpassword" 'If no password use ""
strFilename = Dir$(fPath & "*.xls") 'will open xls & xlsx etc
Application.DisplayAlerts = False
On Error Resume Next
While Len(strFilename) <> 0
Set xlBook = Workbooks.Open(FileName:=fPath & strFilename, _
Password:=strPassword, WriteResPassword:=strEditPassword)
If err.Number = 0 Then
xlBook.SaveAs FileName:=fPath & strFilename, _
Password:="", WriteResPassword:="", CreateBackup:=True
xlBook.Close 0
Else
Debug.Print strFilename 'This will output corrupt filenames in the debug pane
err.Clear
End If
strFilename = Dir$()
Wend
On Error GoTo 0
Application.DisplayAlerts = True
End Sub
I put down together the following code. It basically loops through a path and converts all of the Excel workbooks into PDF.
I would like to setup the print area based on cell references. Cell C8 and D8
C8 = Column A - start of print area
D8 = Column M - end of print area
For example, I want the print area to start from column A - M. However, the current code prints everything, past column M
If settingsSheet.Range("C8").Value = vbNullString Or settingsSheet.Range("D8").Value = vbNullString Then
GoTo ABC
Else
reportColumnsAddr = settingsSheet.Range("C8").Value & ":" & settingsSheet.Range("D8").Value
Set reportSheet = Sheets(reportSheetName)
reportSheet.PageSetup.PrintArea = reportSheet.Columns(reportColumnsAddr).Address
End If
ABC:
Full code
Option Explicit
Private Sub CommandButton1_Click()
Dim MyFolder As String, MyFile As String
Dim StartTime As Double
Dim MinutesElapsed As String
Dim Filename As String
Dim Cell As String
Dim Counter As Long
If ThisWorkbook.Sheets("Sheet1").Range("C7").Value = vbNullString Then
MsgBox "Enter Tab Name"
Exit Sub
End If
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Title = "Select a Folder"
If .Show = True Then
MyFolder = .SelectedItems(1)
End If
If .SelectedItems.Count = 0 Then Exit Sub
Err.Clear
End With
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
Application.Calculation = xlCalculationAutomatic
MyFile = Dir(MyFolder & "\", vbReadOnly)
StartTime = Timer
Do While MyFile <> ""
DoEvents
On Error GoTo 0
Workbooks.Open Filename:=MyFolder & "\" & MyFile, UpdateLinks:=False
Dim settingsSheet As Worksheet 'Source
Dim reportSheet As Worksheet 'To convert to PDF
Dim targetColumnsRange As Range 'feeds from source
Dim targetRowsRange As Range
Dim reportSheetName As String 'source sheet with the target's sheet name
Dim reportColumnsAddr As String
Dim reportRowsAddr As String
Dim WidthFit As String
Dim LengthFit As String
Set settingsSheet = ThisWorkbook.Worksheets("Sheet1") ' source
' Gather the report sheet's name
reportSheetName = settingsSheet.Range("C7").Value ' good
WidthFit = settingsSheet.Range("G8").Value
LengthFit = settingsSheet.Range("G9").Value
On Error Resume Next
Set reportSheet = Sheets(reportSheetName)
On Error GoTo 0
If reportSheet Is Nothing Then
MsgBox "No Sheet Named '" & reportSheetName & "' in This Workbook!"
Exit Sub
End If
If settingsSheet.Range("C8").Value = vbNullString Or settingsSheet.Range("D8").Value = vbNullString Then
GoTo ABC
Else
reportColumnsAddr = settingsSheet.Range("C8").Value & ":" & settingsSheet.Range("D8").Value
Set reportSheet = Sheets(reportSheetName)
reportSheet.PageSetup.PrintArea = reportSheet.Columns(reportColumnsAddr).Address
End If
ABC:
If WidthFit = "YES" Then
With reportSheet.PageSetup
.Zoom = False
.FitToPagesWide = 1
End With
End If
If LengthFit = "YES" Then
With reportSheet.PageSetup
.Zoom = False
.FitToPagesTall = 1
End With
End If
Filename = ActiveWorkbook.Name
Cell = Replace(Filename, ".xlsx", ".PDF")
reportSheet.Select
If settingsSheet.Range("J8").Value = "Landscape" Then
reportSheet.PageSetup.Orientation = xlLandscape
Else
reportSheet.PageSetup.Orientation = xlPortrait
End If
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
ThisWorkbook.Path & "\" & Cell, _
Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=True, OpenAfterPublish:=False
Counter = Counter + 1
0
Workbooks(MyFile).Close SaveChanges:=False
MyFile = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
MinutesElapsed = Format((Timer - StartTime) / 86400, "hh:mm:ss")
MsgBox "Successfully Converted " & Counter & " Files in " & MinutesElapsed & " minutes", vbInformation
End Sub
Your error is you have set IgnorePrintAreas:=True, _ in reportSheet.ExportAsFixedFormat
That said, there are many other issues in your code:
Implicit ActiveWorkbook references
Unnecessary repetition of code in the loop
Case sensitive tests
Misleading variable names
Unnecessary use of GoTo
Malformed error handling
Could try to open non xlsx files
Incomplete checks of user Settings entry
Here's a refactor of your code
Private Sub CommandButton1_Click()
Dim MyFolder As String, MyFile As String
Dim StartTime As Double
Dim TimeElapsed As String
Dim Filename As String
Dim PdfFileName As String
Dim Counter As Long
Dim Orientation As XlPageOrientation
Dim settingsSheet As Worksheet 'Source
Dim reportSheet As Worksheet 'To convert to PDF
Dim targetColumnsRange As Range 'feeds from source
Dim targetRowsRange As Range
Dim reportSheetName As String 'source sheet with the target's sheet name
Dim reportColumnsAddr As String
Dim reportRowsAddr As String
Dim WidthFit As String
Dim LengthFit As String
Dim wb As Workbook
' Set a reference to the settings sheet
Set settingsSheet = ThisWorkbook.Worksheets("Sheet1") ' source
With settingsSheet
If .Range("C7").Value = vbNullString Then
MsgBox "Enter Tab Name"
Exit Sub
End If
If .Range("C8").Value = vbNullString Or .Range("D8").Value = vbNullString Then
MsgBox "Enter Valid Columns"
Exit Sub
End If
reportColumnsAddr = .Range("C8").Value & ":" & .Range("D8").Value
On Error Resume Next
Set targetColumnsRange = .Columns(reportColumnsAddr)
On Error GoTo 0
If targetColumnsRange Is Nothing Then
MsgBox "Enter Valid Columns"
Exit Sub
End If
Set targetColumnsRange = Nothing
reportSheetName = .Range("C7").Value ' good
WidthFit = .Range("G8").Value
LengthFit = .Range("G9").Value
Orientation = IIf(StrComp(.Range("J8").Value, "Landscape", vbTextCompare) = 0, xlLandscape, xlPortrait)
End With
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Title = "Select a Folder"
If .Show = True Then
MyFolder = .SelectedItems(1)
End If
If .SelectedItems.Count = 0 Then Exit Sub
Err.Clear
End With
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
Application.Calculation = xlCalculationAutomatic
MyFile = Dir(MyFolder & "\*.xlsx", vbReadOnly)
StartTime = Timer()
Do While MyFile <> ""
DoEvents
On Error Resume Next
Set wb = Workbooks.Open(Filename:=MyFolder & "\" & MyFile, UpdateLinks:=False)
On Error GoTo 0
If wb Is Nothing Then
MsgBox "Failed to open " & MyFolder & "\" & MyFile
GoTo CleanUp
End If
Set reportSheet = Nothing
On Error Resume Next
Set reportSheet = wb.Worksheets(reportSheetName)
On Error GoTo 0
If reportSheet Is Nothing Then
MsgBox "No Sheet Named '" & reportSheetName & "' in This Workbook!"
GoTo CleanUp
End If
reportSheet.PageSetup.PrintArea = reportColumnsAddr
If StrComp(WidthFit, "YES", vbTextCompare) = 0 Then
With reportSheet.PageSetup
.Zoom = False
.FitToPagesWide = 1
End With
End If
If StrComp(LengthFit, "YES", vbTextCompare) = 0 Then
With reportSheet.PageSetup
.Zoom = False
.FitToPagesTall = 1
End With
End If
PdfFileName = Replace(wb.Name, ".xlsx", ".PDF")
reportSheet.PageSetup.Orientation = Orientation
reportSheet.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=ThisWorkbook.Path & "\" & PdfFileName, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
Counter = Counter + 1
wb.Close SaveChanges:=False
MyFile = Dir
Loop
CleanUp:
On Error Resume Next
wb.Close False
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
TimeElapsed = Format((Timer() - StartTime) / 86400, "hh:mm:ss")
MsgBox "Successfully Converted " & Counter & " Files in " & TimeElapsed, vbInformation
End Sub
I am currently using Application.GetOpenFilename with MultiSelect:=True to allow the user to select one or more files within a folder, then importing the data from all of the files into a worksheet. If multiple files are selected, the data from each file is appended to the data from the previous file until all of the selected files are imported.
I now have an instance where text files are stored in subfolders of a specific folder, with the subfolders created based on order numbers. I am now trying to define the parent folder as a variable, allow the user to input the subfolder name using Application.InputBox, then automatically import the data from all .txt files in the user-specified subfolder. I'm getting hung up with a Run-time error '53', File not found error. I know using the GetOpenFilename approach creates an array of the filenames, and I tried to replicate this by creating an array of the file names but I'm obviously missing something.
I'm basically trying to import all .txt files from something like the following:
C:\AOI_DATA64\SPC_DataLog\IspnDetails\ user defined subfolder \ *.txt
Code that works using Application.GetOpenFilename:
' Define that variables must be defined manually and will never be defined automatically
Option Explicit
' Hold specific variables in memory for use between sub-routines
Public DDThreshold As Variant
Public FileName As String
Public FilePath As String
Public OpenFileName As Variant
Public OrderNum As Variant
Public SaveWorkingDir As String
Public SecondsElapsed As Double
Public StartTime As Double
Public TimeRemaining As Double
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 DefaultOpenPath As String
Dim SaveWorkingDir As String
Dim OpenFileName As Variant
Dim WholeFile As String
Dim SplitArray
Dim LineNumber As Integer
Dim chkFormat1 As String
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 aLastRow As Long
Dim bLastRow As Long
Dim cLastRow As Long
Dim dLastRow As Long
Dim destCell As Range
' Set the default path to start at when importing a file
'On Error Resume Next
If Len(Dir("C:\AOI_DATA64\SPC_DataLog\IspnDetails", vbDirectory)) = 0 Then
DefaultOpenPath = "C:\"
Else
DefaultOpenPath = "C:\AOI_DATA64\SPC_DataLog\IspnDetails\"
End If
' When opening another file for processing, this section will save the previously opened file directory
'On Error Resume Next
If SaveWorkingDir = CurDir Then
ChDrive SaveWorkingDir
ChDir SaveWorkingDir
Else
ChDrive DefaultOpenPath
ChDir DefaultOpenPath
End If
' Select the source folder and point list file(s) to import into worksheet
'On Error GoTo ErrorHandler
OpenFileName = Application.GetOpenFilename( _
FileFilter:="AOI Inspection Results Data Files (*.txt), *.txt", _
Title:="Select a data file or files to import", _
MultiSelect:=True)
' Cancel the file import if the user exits the file import window or selects the Cancel button
If Not IsArray(OpenFileName) Then
MsgBox "" & vbNewLine & _
" No files were selected." & vbNewLine & _
"" & vbNewLine & _
" Import AOI Inspection Results Data Files was aborted.", vbInformation, "File Import Cancelled"
Exit Sub
End If
' Clear contents and reset formatting of cells in all worksheets
aLastRow = Worksheets("AOI Inspection Summary").Cells(Rows.Count, "B").End(xlDown).Row
bLastRow = Worksheets("Raw Data").Cells(Rows.Count, "A").End(xlDown).Row
cLastRow = Worksheets("Parsed Data").Cells(Rows.Count, "A").End(xlDown).Row
Worksheets("AOI Inspection Summary").Range("E6:L14").ClearContents
If aLastRow > 0 Then
Worksheets("AOI Inspection Summary").Range("B24:L" & aLastRow).ClearContents
Worksheets("AOI Inspection Summary").Range("B24:L" & aLastRow).ClearFormats
End If
If bLastRow > 0 Then
Worksheets("Raw Data").Range("A1:Q" & bLastRow).ClearContents
Worksheets("Raw Data").Range("A1:Q" & bLastRow).ClearFormats
End If
If cLastRow > 0 Then
Worksheets("Parsed Data").Range("A1:Q" & cLastRow).ClearContents
Worksheets("Parsed Data").Range("A1:Q" & cLastRow).ClearFormats
End If
Worksheets("AOI Inspection Summary").Range("E6:L9").NumberFormat = "#" 'Format cells to Text
Worksheets("AOI Inspection Summary").Range("E10:L13").NumberFormat = "#,000" 'Format Cells to Number with commas
Worksheets("AOI Inspection Summary").Range("E14:L14").NumberFormat = "0.00%" 'Format cells to Percent
Worksheets("Raw Data").Columns("A:Z").EntireColumn.ColumnWidth = 8.09
Worksheets("Parsed Data").Columns("A:Z").EntireColumn.ColumnWidth = 8.09
' Update "Defect Density Threshold" to default value unless user entered a new value
If DDThreshold > 0 Then
Worksheets("AOI Inspection Summary").Range("E10").Value = DDThreshold
Else
Worksheets("AOI Inspection Summary").Range("E10").Value = "3,000,000"
End If
' Save the user selected open file directory as the default open file path while the worksheet is open
SaveWorkingDir = CurDir
' Timer Start (calculate the length of time this sub-routine takes to complete after selecting file(s) to import)
StartTime = Timer
' Check selected input file format for YesTech AOI Inspection Results format
Const chkYesTech = "[StartIspn]"
For n1 = LBound(OpenFileName) To UBound(OpenFileName)
fn = FreeFile
Open OpenFileName(n1) For Input As #fn
Application.StatusBar = "Processing ... " & OpenFileName(n1)
WholeFile = Input(LOF(fn), #fn)
SplitArray = Split(WholeFile, vbCrLf)
LineNumber = 1
chkFormat1 = SplitArray(LineNumber - 1)
Close #fn
If InStr(1, chkFormat1, chkYesTech, vbBinaryCompare) > 0 Then
MsgBox OpenFileName(n1) & vbNewLine & " has been verified as a YesTech AOI Inspection Results Data File"
' Import user selected YesTech AOI Inspection Results Data File(s) to "Raw Data" worksheet
Application.DisplayAlerts = False
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)
' Import data from file into Raw Data worksheet
Do While Not EOF(fn)
Line Input #fn, RawData
If Len(Trim(RawData)) > 0 Then
TargetRow = TargetRow + 1
Worksheets("Raw Data").Range("B" & TargetRow) = RawData
End If
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
Application.DisplayAlerts = True
Else: MsgBox OpenFileName(n1) & vbNewLine & " is not a YesTech AOI Inspection Results Data File."
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"
' List open file name(s) on spreadsheet for user reference
Worksheets("AOI Inspection Summary").Range("E9").Font.Name = "Calibri"
Worksheets("AOI Inspection Summary").Range("E9").Font.Size = 9
Worksheets("AOI Inspection Summary").Range("E9").Font.Bold = False
Worksheets("AOI Inspection Summary").Range("E9").Font.Color = RGB(0, 0, 255)
FileListRow = 0
Set rngFileList = Worksheets("AOI Inspection Summary").Range("E9")
For i = LBound(OpenFileName) To UBound(OpenFileName)
' Add imported file name hyperlink to imported files in list of imported files
' rngFileList.Offset(FileListRow, 0) = OpenFileName(i)
rngFileList.Hyperlinks.Add Anchor:=rngFileList, _
Address:=OpenFileName(i), _
ScreenTip:="Imported File Number " & FileListRow + 1, _
TextToDisplay:=OpenFileName(i)
Worksheets("AOI Inspection Summary").Range("E7").Value = OpenFileName(i)
FileListRow = FileListRow + 1
Next i
' Auto fit the width of columns for RAW Data
Worksheets("Raw Data").Columns("A:Z").EntireColumn.AutoFit
' Timer Stop (calculate the length of time this sub-routine took to complete)
SecondsElapsed = Round(Timer - StartTime, 2)
' Turn screen updating and auto calculating back on since file processing is now complete
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
' Display a message to report the sub-routine processing time after file selection including the number of data rows that have been imported
MsgBox "AOI Inspection Results processed and imported in " & SecondsElapsed & " seconds" & " ." & vbNewLine & _
" Successfully imported " & (TargetRow) & " rows of data.", vbInformation, "Data Import Results"
' 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 user including 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
Call Create_Report
End Sub
And here's my attempt at defining the parent folder, asking the user for the subfolder name using Application.InputBox, and loading all of the *.txt filenames into an array to be imported:
' Define that variables must be defined manually and will never be defined automatically
Option Explicit
' Hold specific variables in memory for use between sub-routines
Public DDThreshold As Variant
Public FileName As String
Public FilePath As String
Public OpenFileName As Variant
Public OrderNum As Variant
Public SaveWorkingDir As String
Public SecondsElapsed As Double
Public StartTime As Double
Public TimeRemaining As Double
Sub OrderLineNum()
' Add an error handler
'On Error GoTo ErrorHandler
' Speed up sub-routine by turning off screen updating and auto calculating
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Define variable names and data types
Dim DefaultOpenPath As String
Dim SaveWorkingDir As String
Dim OrderNum As Variant
Dim GetFile As String
Dim FileCount As Long
Dim OpenFileName() As String
ReDim OpenFileName(1000)
Dim WholeFile As String
Dim SplitArray
Dim LineNumber As Integer
Dim chkFormat1 As String
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 aLastRow As Long
Dim bLastRow As Long
Dim cLastRow As Long
Dim dLastRow As Long
Dim destCell As Range
' Set the default path to start at when importing a file
' On Error Resume Next
If Len(Dir("C:\AOI_DATA64\SPC_DataLog\IspnDetails", vbDirectory)) = 0 Then
DefaultOpenPath = "C:\"
Else
DefaultOpenPath = "C:\AOI_DATA64\SPC_DataLog\IspnDetails\"
End If
' When opening another file for processing, save the previously opened file directory
' On Error Resume Next
If SaveWorkingDir = CurDir Then
ChDrive SaveWorkingDir
ChDir SaveWorkingDir
Else
ChDrive DefaultOpenPath
ChDir DefaultOpenPath
End If
' Open InputBox to get order-line number from user
OrderNum = Application.InputBox(prompt:= _
"Enter Order-Line Number (e.g. 12345678-9)", _
Title:="Password Required for This Function", _
Default:="", _
Left:=25, _
Top:=25, _
HelpFile:="", _
HelpContextID:="", _
Type:=2)
If OrderNum = "" Then
MsgBox "No Order Number entered. No data will be imported.", vbInformation, "Invalid Order Number"
Exit Sub
ElseIf OrderNum = "0" Then
MsgBox "Order Number cannot be 0. No data will be imported.", vbInformation, "Invalid Order Number"
Exit Sub
ElseIf OrderNum = False Then
MsgBox "User cancelled. No data will be imported.", vbInformation, "User Cancelled"
Exit Sub
End If
' Create an array of filenames found in the Order-Line Number sub-folder
GetFile = Dir$(CurDir & "\" & OrderNum & "\" & "*.txt")
Do While GetFile <> ""
OpenFileName(FileCount) = GetFile
GetFile = Dir$
FileCount = FileCount + 1
Loop
ReDim Preserve OpenFileName(FileCount - 1)
' Save the user selected open file directory as the default open file path while the worksheet is open
SaveWorkingDir = CurDir
' Timer Start (calculate the length of time this sub-routine takes to complete after selecting file(s) to import)
StartTime = Timer
' Cancel the file import if the Order-Line Number subfolder doesn't exist
If Not IsArray(OpenFileName) Then
MsgBox "" & vbNewLine & _
" No files were selected." & vbNewLine & _
"" & vbNewLine & _
" Import AOI Inspection Results Data Files was aborted.", vbInformation, "File Import Cancelled"
Exit Sub
End If
' Clear contents of cells and data worksheets
aLastRow = Worksheets("AOI Inspection Summary").Cells(Rows.Count, "B").End(xlDown).Row
bLastRow = Worksheets("Raw Data").Cells(Rows.Count, "A").End(xlDown).Row
cLastRow = Worksheets("Parsed Data").Cells(Rows.Count, "A").End(xlDown).Row
Worksheets("AOI Inspection Summary").Range("E6:L14").ClearContents
If aLastRow > 0 Then
Worksheets("AOI Inspection Summary").Range("B24:L" & aLastRow).ClearContents
Worksheets("AOI Inspection Summary").Range("B24:L" & aLastRow).ClearFormats
End If
If bLastRow > 0 Then
Worksheets("Raw Data").Range("A1:Q" & bLastRow).ClearContents
Worksheets("Raw Data").Range("A1:Q" & bLastRow).ClearFormats
End If
If cLastRow > 0 Then
Worksheets("Parsed Data").Range("A1:Q" & cLastRow).ClearContents
Worksheets("Parsed Data").Range("A1:Q" & cLastRow).ClearFormats
End If
' Update "Defect Density Threshold" to default value unless user entered a new value
If DDThreshold > 0 Then
Worksheets("AOI Inspection Summary").Range("E10").Value = DDThreshold
Else
Worksheets("AOI Inspection Summary").Range("E10").Value = "3,000,000"
End If
'Check selected input file format for YesTech AOI Inspection Results format
Const chkYesTech = "[StartIspn]"
For n1 = LBound(OpenFileName) To UBound(OpenFileName)
fn = FreeFile
Open OpenFileName(n1) For Input As #fn
Application.StatusBar = "Processing ... " & OpenFileName(n1)
WholeFile = Input(LOF(fn), #fn)
SplitArray = Split(WholeFile, vbCrLf)
LineNumber = 1
chkFormat1 = SplitArray(LineNumber - 1)
Close #fn
If InStr(1, chkFormat1, chkYesTech, vbBinaryCompare) > 0 Then
MsgBox OpenFileName(n1) & vbNewLine & " has been verified as a YesTech AOI Inspection Results Data File"
' Import user selected YesTech AOI Inspection Results Data 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
If Len(Trim(RawData)) > 0 Then
TargetRow = TargetRow + 1
Worksheets("Raw Data").Range("B" & TargetRow) = RawData
End If
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 OpenFileName(n1) & vbNewLine & " is not a YesTech AOI Inspection Results Data File."
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"
' List open file name(s) on spreadsheet for user reference
Worksheets("AOI Inspection Summary").Range("E9").Font.Name = "Calibri"
Worksheets("AOI Inspection Summary").Range("E9").Font.Size = 9
Worksheets("AOI Inspection Summary").Range("E9").Font.Bold = True
Worksheets("AOI Inspection Summary").Range("E9").Font.Color = RGB(0, 0, 255)
FileListRow = 0
Set rngFileList = Worksheets("AOI Inspection Summary").Range("E9")
For i = LBound(OpenFileName) To UBound(OpenFileName)
Debug.Print OpenFileName(i)
' Add imported file name or hyperlink to imported files in list of imported files
' rngFileList.Offset(FileListRow, 0) = OpenFileName(i)
rngFileList.Offset(FileListRow, 0).Hyperlinks.Add Anchor:=rngFileList.Offset(FileListRow, 0), _
Address:=OpenFileName(i), _
ScreenTip:="Imported File Number " & FileListRow + 1, _
TextToDisplay:=OpenFileName(i)
rngFileList.Offset(FileListRow, 0).Font.Name = "Calibri"
rngFileList.Offset(FileListRow, 0).Font.Size = 9
rngFileList.Offset(FileListRow, 0).Font.Color = RGB(0, 0, 255)
FileListRow = FileListRow + 1
Next i
' Auto fit the width of columns for RAW Data
Worksheets("Raw Data").Columns("A:Z").EntireColumn.AutoFit
' Timer Stop (calculate the length of time this sub-routine took to complete)
SecondsElapsed = Round(Timer - StartTime, 2)
' Turn screen updating and auto calculating back on since file processing is now complete
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
' Display a message to report the sub-routine processing time after file selection including the number of data rows that have been imported
MsgBox "AOI Inspection Results processed and imported in " & SecondsElapsed & " seconds" & " ." & vbNewLine & _
" Successfully imported " & (TargetRow) & " rows of data.", vbInformation, "Data Import Results"
' 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 user including 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
Any ideas or suggestions for a better approach would be greatly appreciated.
As mentioned in my comment, there's a lot going on in your post. However, focusing on this
I am now trying to define the parent folder as a variable, allow the user to input the subfolder name using Application.InputBox, then automatically import the data from all .txt files in the user-specified subfolder.
I have a solution - you can create an array that stores each file (both the path and file name), which you should be able to use to get the file names and then do whatever you need:
Sub import_files()
Dim files As String
Dim parentDir As String
parentDir = InputBox("Please input the directory you want to import files from")
If parentDir = "" Then Exit Sub 'If they hit "Cancel" or don't put anything.
' parentDir = GetFolder() 'UNCOMMENT THIS if you want the user to select a folder via "Windows Explorer"
files = LoopThroughFiles(parentDir, "txt")
' Debug.Print (files)
Dim iFiles() As String
iFiles() = Split(files, ",")
Dim i As Long
For i = LBound(iFiles) To UBound(iFiles)
If iFiles(i) <> "" Then
Debug.Print ("File located: " + parentDir + "\" + iFiles(i))
' THIS IS YOUR ARRAY, `iFILES`, SO HERE IS WHERE YOU DO STUFF
End If
Next i
End Sub
Private Function LoopThroughFiles(inputDirectoryToScanForFile, filenameCriteria) As String
'https://stackoverflow.com/a/45749626/4650297
Dim tmpOut As String
Dim StrFile As String
'Debug.Print "in LoopThroughFiles. inputDirectoryToScanForFile: ", inputDirectoryToScanForFile
StrFile = Dir(inputDirectoryToScanForFile & "\*" & filenameCriteria)
Do While Len(StrFile) > 0
' Debug.Print StrFile
tmpOut = tmpOut + "," + StrFile
StrFile = Dir
Loop
LoopThroughFiles = tmpOut
End Function
Function GetFolder() As String
' https://stackoverflow.com/a/26392703/4650297
Dim fldr As FileDialog
Dim sItem As String
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = Application.DefaultFilePath
If .Show <> -1 Then GoTo NextCode
sItem = .SelectedItems(1)
End With
NextCode:
GetFolder = sItem
Set fldr = Nothing
End Function
Edit: I added a method to have the user select the folder via a more "traditional" Windows Explorer type window, instead of pasting in a path string. Either one should work for you though, let me know any questions.
Please find the VBA code below:
Sub Select_File_Or_Files_Mac()
Dim MyPath As String
Dim MyScript As String
Dim MyFiles As String
Dim MySplit() As String
Dim a As String
Dim mybook As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim LastCell2 As Range
Dim cell As Variant
Dim Column As Integer
Dim rowno As Integer
On Error GoTo ErrHandler:
MyPath = MacScript("return (path to documents folder) as String")
'Or use MyPath = "Macintosh HD:Users:Ron:Desktop:TestFolder:"
' In the following statement, change true to false in the line "multiple
' selections allowed true" if you do not want to be able to select more
' than one file. Additionally, if you want to filter for multiple files, change
' {""com.microsoft.Excel.xls""} to
' {""com.microsoft.excel.xls"",""public.comma-separated-values-text""}
' if you want to filter on xls and csv files, for example.
MyScript = _
"set applescript's text item delimiters to "","" " & vbNewLine & _
"set theFiles to (choose file of type " & _
" {""org.openxmlformats.spreadsheetml.sheet.macroenabled""} " & _
"with prompt ""Please select a file or files"" default location alias """ & _
MyPath & """ multiple selections allowed true) as string" & vbNewLine & _
"set applescript's text item delimiters to """" " & vbNewLine & _
"return theFiles"
MyFiles = MacScript(MyScript)
MsgBox MyFiles
'On Error GoTo 0
MySplit = Split(MyFiles, ":")
MsgBox MySplit
'For N = LBound(MySplit) To UBound(MySplit)
a = MySplit(UBound(MySplit()))
MsgBox a
' Get the fi le name only and test to see if it is open.
'Fname = Right(MySplit(N), Len(MySplit(N)) - InStrRev(MySplit(N), Application.PathSeparator, , 1))
'If bIsBookOpen(Fname) = False Then
'MsgBox MySplit
'Set mybook = Nothing
'On Error Resume Next
Set mybook = Workbooks.Open(a)
Set ws1 = ThisWorkbook.Worksheets("User_Financial_Input")
Set ws2 = mybook.Worksheets("User_Financial_Input")
ws2.Activate
With ws2
Set LastCell2 = ws2.Range("InputCells_User_Financial_Input")
MsgBox LastCell2
End With
ws2.Select
ws1.Activate
For Each cell In LastCell2
Column = cell.Column
rowno = cell.Row
ws1.Cells(rowno, Column) = cell.value
Next
ErrHandler:
If Err.Number = 9 Then
Answer = MsgBox(Err.Description & Err.Number, vbCritical, "Error")
ElseIf Err.Number = 1004 Then
Answer = MsgBox(Err.Description & Err.Number, vbCritical, "Error")
ElseIf Err.Number = 0 Then
Else
Answer = MsgBox(Err.Description & Err.Number, vbCritical, "Error")
End If
End Sub
There is some problem in the line Set mybook = Workbooks.Open(a). I am getting "Type 13" mismatch error.