How to resume the Loop after Error Handling? - excel

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

Related

Looping for dynamic pictures

So I have created a dynamic selection list for excel using vba. see below
Below is the code
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Target.Address = "$A$2" Then
Call PanggilPhoto
End If
End Sub
Sub PanggilPhoto()
Application.ScreenUpdating = False
Dim myObj
Dim Foto
Set myObj = ActiveSheet.DrawingObjects
For Each Foto In myObj
If Left(Foto.Name, 7) = "Picture" Then
Foto.Select
Foto.Delete
End If
Next
Dim CommodityName1 As String, CommodityName2 As String, T As String
myDir = ThisWorkbook.Path & "\"
CommodityName1 = Range("A2")
T = ".png"
Range("C15").Value = CommodityName
On Error GoTo errormessage:
ActiveSheet.Shapes.AddPicture Filename:=myDir & CommodityName1 & T, _
linktofile:=msoFalse, savewithdocument:=msoTrue, Left:=190, Top:=10, Width:=140,
Height:=90
errormessage:If Err.Number = 1004 Then
Exit Sub
MsgBox "File does not exist." & vbCrLf & "Check the name of the Commodity!"
Range("A2").Value = ""
Range("C10").Value = ""
End If
Application.ScreenUpdating = True
End Sub
foto is a predefined data list in the sheet.
So the question is instead of doing it for one cell how can I create a loop of some sort to do it for multiple cells? I need it to import mulitple images on one macro run
found a solution
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Target.Address = "$A$2" Then
Call schedules
End If
End Sub
Sub schedules()
Worksheets("Picture").Activate
Application.ScreenUpdating = False
Dim myObj
Dim Foto
Set myObj = ActiveSheet.DrawingObjects
For Each Foto In myObj
If Left(Foto.Name, 7) = "Picture" Then
Foto.Select
Foto.Delete
End If
Next
Dim CommodityName1 As String, CommodityName2 As String, T1 As String, T2 As String
Dim i As Integer, j As Integer, k As Integer
j = 0
For i = 2 To 100
myDir = "C:\Users\User\Desktop\ESTIMATING SHEETS\test\rebar shapes" & "\"
CommodityName1 = Range("A" & i)
T1 = ".png"
On Error GoTo errormessage:
ActiveSheet.Shapes.AddPicture Filename:=myDir & CommodityName1 & T1, _
linktofile:=msoFalse, savewithdocument:=msoTrue, Left:=230, Top:=j, Width:=140, Height:=80
errormessage:
If Err.Number = 1004 Then
Exit Sub
MsgBox "File does not exist." & vbCrLf & "Check the name of the rebar!"
Range("A" & i).Value = ""
Range("C10").Value = ""
End If
Application.ScreenUpdating = True
i = i + 11
j = j + 190
Next i
End Sub

How pull multiple ranges as a function parameter using VBA?

I've seen some examples of how to get multiple ranges as a function parameter, but given my data structure, I haven't been able to get this to work.
When the mouse is on Age, for example, and the function is run, it is to grab the highlighted cells as a range, since I'll be using these data for charts.
Here's how the data is:
Here's the piece of code that deals with the data CURRENTLY - if those cells are manually selected and the script is run.
Public Sub sMigrateFixToList(blnTranspose As Boolean, _
strMigrationType As String, _
MultiRng As Range)
Dim strProcedure As String
Dim lngLastRow As Long
Dim strDestRange As String
Dim lngNumRows As Long
Dim lngNumCols As Long
Dim k As Long
Dim t As Long
' Enable Error Handler
On Error GoTo Err_Handler
' Name Proc for Error Handler Mesasage
strProcedure = "sMigrateToList"
If ActiveSheet.Name <> "Sheet1" Then
Call MsgBox("Go to the right sheet")
GoTo Exit_Proc:
End If
Application.ScreenUpdating = False
k = MigrationList.UsedRange.Rows.Count
t = IIf(k = 1, 2, k + 2)
objRange.Copy
MigrationList.Cells(t, 1).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=blnTranspose
Select Case strMigrationType
Case "T"
MigrationList.Cells(t - 1, 1).Value2 = "<<TABLE>>"
End Select
Application.ScreenUpdating = True
Exit_Proc:
On Error Resume Next
Exit Sub
Err_Handler:
Select Case Err.Number
Case 1004
Err.Clear
Call MsgBox("Não pode selecionar blocos de células não alinhados.", _
vbInformation + vbOKOnly, _
g_STR_ERRMESSTITLECRITICAL)
Case Else
Call MsgBox("Error number: " & Err.Number & vbCrLf & _
"Description: " & Err.Description & vbCrLf & _
"Code: " & strProcedure, _
vbCritical + vbOKOnly, _
g_STR_ERRMESSTITLECRITICAL)
End Select
Resume Exit_Proc
End Sub
The idea is to have this range made of multiple ranges fixed and pass it to other function being called below as a parameter:
Public Sub sMigrateToListAsTable()
Call sMigrateToList(False, "T", Selection)
End Sub
Thank you!

VBA to Update and Replace in Workbooks causes crashing

Please bear with me. My code is probably complete shit, so I appreciate all feedback! So what this does is, on my main workbook, there are a bunch of UNC hyperlinks in Row M, that link to files in a section drive.
What this code does:
Go down the list of hyperlinks in Column M, opens them up and executes the code inside of the "With WBSsource".
First, it searches for instances of the incorrect filepath (st) inside each of the cells formulas (NOT VALUES), and increments a counter using InStr (t), then after the worksheet has been searched, if the final count (c) is more than 0, meaning the search found at least one incorrect filepath, it will proceed to the next step.
It does a Cells.Replace on a worksheet (ws.) basis (at the FORMULA level)
Cells per worksheet are all done, it should save the workbook and close it before moving onto the next one.
Any links that could not be opened will appear in a final popup.
It is by Step 3 that it starts to run sluggish and crash.
I'm trying my best to get this automated and saving the workbooks. Then, once they're all updated, running this code again would be much faster cause it won't have to replace everything again.
Sub List_UpdateAndSave()
Dim lr As Long
Dim i As Integer
Dim WBSsource As Workbook
Dim FileNames As Variant
Dim msg As String
Dim ws As Worksheet
Dim r As Range, t As Long, c As Integer
' Update the individual credit models
With ThisWorkbook.ActiveSheet
lr = .Cells(.Rows.Count, "M").End(xlUp).Row
FileNames = .Range("M2:M" & lr).Value
End With
For i = LBound(FileNames, 1) To UBound(FileNames, 1)
On Error Resume Next
If FileNames(i, 1) Like "*.xls*" Then
Set WBSsource = Workbooks.Open(FileNames(i, 1), _
ReadOnly:=False, _
Password:="", _
UpdateLinks:=3)
If Err = 0 Then
With WBSsource
Application.DisplayAlerts = False
ActiveWorkbook.Final = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
st = "\\corp\Accounts\" 'Search Phrase
n = "\\corp\StackOverflow\Accounts\" 'New Phrase
c = 0
For Each ws In WBSsource.Worksheets
ws.Activate
t = 0
On Error Resume Next
For Each r In ws.Cells.SpecialCells(xlCellTypeFormulas)
t = InStr(1, r.Formula, st)
If t > 0 Then
c = c + 1
End If
Next r
Next ws
If c > 0 Then
'MsgBox ws.Name & Chr(10) & (c)
ws.Cells.Replace st, n
End If
.UpdateLink Name:=ActiveWorkbook.LinkSources, Type:=xlExcelLinks
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
.Save
.Close True
End With
Else
msg = msg & FileNames(i, 1) & Chr(10) & Chr(10)
On Error GoTo 0
End If
End If
Set WBSsource = Nothing
Next i
If Len(msg) > 0 Then
'MsgBox "The Following Files Could Not Be Opened" & _
' Chr(10) & msg, 48, "Error"
Set objShell = CreateObject("Wscript.Shell")
objShell.Popup "The Following Files Could Not Be Opened" & _
Chr(10) & Chr(10) & msg, 48, "Error"
End If
Application.DisplayAlerts = True
End Sub
It's not completely crap. I just learned that we could create an array with this.
FileNames = .Range("M2:M" & lr).Value
It may crash since there's no range limit on the 3rd step. Try getting the last row and column on each worksheet, then create a range based on that.
With ws
' Get end cells
With .Cells.SpecialCells(xlCellTypeLastCell)
intLastRow = .Row
intLastCol = .Column
End With
For each r in .Range(.Cells(1,1), .Cells(intLastRow, intLastCol))
' Check formula if it contains specific string
t = InStr(1, r.Formula, st)
If t > 0 Then
c = c + 1
End If
' Replace formula with new string
r.Formula = Replace(r.Formula, st, n)
Next r
End With
Edit: Here's the full code. Let me know if this works for you.
Option Explicit
' Update the individual credit models
Sub List_UpdateAndSave()
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
On Error GoTo ErrorHandler
' Declaration
Dim i As Long
Dim arrLinks As Variant
Dim strLinksErr As String
' Initialization
Dim strPathCur As String: strPathCur = "\\corp\Accounts\" ' search phrase
Dim strPathNew As String: strPathNew = "\\corp\StackOverflow\Accounts\" ' new phrase
With ThisWorkbook.ActiveSheet
' Get links from sheet
arrLinks = .Range("M2:M" & .Cells.SpecialCells(xlCellTypeLastCell).Row).Value
End With
For i = LBound(arrLinks, 1) To UBound(arrLinks, 1)
' Check for Excel links
If VBA.InStr(1, arrLinks(i, 1), ".xls", vbTextCompare) > 0 Then
FnExcelUpdateLinks arrLinks(i, 1), strPathCur, strPathNew
Else
' Add to list of links that could not be opened
strLinksErr = strLinksErr & arrLinks(i, 1) & Chr(10)
End If
Next i
ErrorHandler:
' Display any errors
If Err.Number <> 0 Then MsgBox Err.Description, vbCritical, "Error " & Err.Number
' Display any non-Excel links
If strLinksErr <> "" Then
MsgBox "The following files could not be opened:" & _
Chr(10) & strLinksErr, 48, "Error"
End If
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub
Function FnExcelUpdateLinks(ByVal strWbkPath As String, ByRef strPathCur As String, ByRef strPathNew As String)
Dim intLastRow As Long, intLastCol As Long
Dim wbkTmp As Workbook
Dim shtTmp As Worksheet
Dim rngCell As Range
' Open link as workbook
Set wbkTmp = Workbooks.Open(strWbkPath, ReadOnly:=False, Password:="", UpdateLinks:=3)
With wbkTmp
For Each shtTmp In .Worksheets
With shtTmp
' Get end cells
With .Cells.SpecialCells(xlCellTypeLastCell)
intLastRow = .Row
intLastCol = .Column
End With
For Each rngCell In .Range(.Cells(1, 1), .Cells(intLastRow, intLastCol))
If VBA.InStr(1, rngCell.Formula, strPathCur) > 0 Then
rngCell.Formula = Replace(rngCell.Formula, strPathCur, strPathNew)
End If
Next rngCell
End With
Next shtTmp
.UpdateLink Name:=.LinkSources, Type:=xlExcelLinks
.Save
.Close True
End With
End Function

Issues executing a ADO Macro from new sheet

I'm trying to execute a macro from a new worksheet with a button so that it runs in another worksheet (named "ARF Export").
Unfortunately I don't know how to set the worksheet I want the macro to run in to ("ARF Export"). Please could you advise me on how to proceed?
The error I get when I run this code in a different sheet is:
Error 3265 Item cannot be found in the collection corresponding to the requested name or ordinal in procedure export_data
When I step into Debug I don't get an error until the end but it skips through my For Loop on line 38 next i
for x = 2 To nextrow
DatabaseData.AddNew
For i = 1 To 35
DatabaseData(Cells(1, i).Value) = Worksheets("ARF Export").Cells(x, i).Value
Next i
DatabaseData.Update
Next x
All code below---
Option Explicit
Sub CopyDatatoAccess()
Dim DatabaseConn As ADODB.Connection
Dim DatabaseData As ADODB.Recordset
Dim Pathway
Dim x As Long, i As Long
Dim nextrow As Long
On Error GoTo errorhandler:
Pathway = Worksheets("ARF Export").Range("AR2").Value
nextrow = Worksheets("ARF Export").Range("As2").Value
Set DatabaseConn = New ADODB.Connection
If Worksheets("ARF Export").Range("A2").Value = "" Then
MsgBox "ARF form is not present for Upload"
Exit Sub
End If
DatabaseConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Pathway
Set DatabaseData = New ADODB.Recordset
DatabaseData.Open Source:="ARFs", _
ActiveConnection:=DatabaseConn, _
CursorType:=adOpenDynamic, _
LockType:=adLockOptimistic, _
Options:=adCmdTable
For x = 2 To nextrow
DatabaseData.AddNew
For i = 1 To 35
DatabaseData(Cells(1, i).Value) = Worksheets("ARF Export").Cells(x, i).Value
Next i
DatabaseData.Update
Next x
DatabaseData.Close
DatabaseConn.Close
Set DatabaseData = Nothing
Set DatabaseConn = Nothing
MsgBox "The ARF is now uploaded"
Application.ScreenUpdating = True
Worksheets("ARF Export").Cells.Range("AK2").Value = Worksheets("ARF Export").Cells.Range("AK4").Value
Worksheets("ARF Export").Cells.Range("AK5").Value = Worksheets("ARF Export").Cells.Range("AK4").Value + 1
On Error GoTo 0
Exit Sub
errorhandler:
Set DatabaseData = Nothing
Set DatabaseConn = Nothing
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Export_Data"
End Sub
Thanks for the help
-Turns out I needed to reference DatabaseData(Cells(1, i).Value) once i did this
For x = 2 To nextrow
DatabaseData.AddNew
For i = 1 To 35
DatabaseData(Worksheets("ARF Export").Cells(1, i).Value) = Worksheets("ARF Export").Cells(x, i).Value
Next i
DatabaseData.Update
Next x
It worked great. Thank you for your help all!

VBScript suddenly can't run macro after months of no issues

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.

Resources