Pick folder routine going to Error handler - Excel

2019-09-12 16:02发布

Below is code that allows the user to choose a folder and opens files within the folder. It essentially does this:

  1. On open, look for filepath saved in worksheet in workbook based on username. If doesn't exist, then prompt user to find folder, then save filepath in worksheet

  2. From step 1, if filepath is found based on user, use that filepath

  3. Error handler: From step 1, if filepath is found based on user, but that filepath is not in use anymore(i.e. user moved the folder to a different filepath), then have user find the folder again, then update existing record

What i'm experiencing is this:

  1. When there's no entries in the sheet, then it will prompt user to find the folder, but then proceed to the errorhandler and ask the user to find the folder again

    1. When there are entries in the sheet and the file path is working, the errorhandler is still opened and asks the user to find the folder again

If I take out the errorhandler, everything is smooth. It's just that I want to cover the possibility of the user moving the folder , so I want the workbook to prompt the user to find where they moved the folder, and update the existing record in the workbook to the new path

What am I doing wrong here?

Private Sub Workbook_Open()


Dim wkb1 As Workbook
Dim sht1 As Worksheet
Dim wkb2 As Workbook
Dim sht2 As Worksheet
Dim vafiles As Variant
Dim filepath As String
Dim filepath2 As String
Dim filepath3 As String
Dim rw As Long
Dim ws As Worksheet
Dim lastrow As Long
Dim icounter As Long

Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlManual

Set ws = Worksheets("Paths")
rw = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
Set wkb1 = ThisWorkbook
Set sht1 = wkb1.Sheets("Extract")
'======================================================
'Determine if Path was already saved before. If not, prompt user to choose folder
'======================================================
sal = Application.VLookup(Environ("username"), ws.Range("a:b"), 2, 0)
If IsError(sal) Then

MsgBox ("Please choose where your main folder is located. This will be stored so you won't need to look for it again.")
filepath = PICK_A_FOLDER()
ws.Cells(rw, 2) = PICK_A_FOLDER()
ws.Cells(rw, 1) = Environ("username")

Set wkb2 = Workbooks.Open(filepath & "\ Export.xlsx")
Set sht2 = wkb2.Sheets("Sheet1")
sht2.Cells.Copy Destination:=sht1.Range("a1")
Application.CutCopyMode = False
wkb2.Close True

Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
Worksheets("Instructions").Activate
Application.Calculation = xlAutomatic

Else

'======================================================
'If filepath exists, use that one
'======================================================
filepath2 = sal

Set wkb2 = Workbooks.Open(filepath2 & "Export.xlsx")


Set sht2 = wkb2.Sheets("Sheet1")
sht2.Cells.Copy Destination:=sht1.Range("a1")
Application.CutCopyMode = False
wkb2.Close True

End If


'======================================================
'If user has moved their folder, we can find it again and update their record
'======================================================
On Error GoTo Errorhandler

Errorhandler:
MsgBox ("Looks like you've moved your Folder. Please find it so your record will be updated")
filepath3 = PICK_A_FOLDER()

lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
For icounter = 2 To lastrow
If Cells(icounter, 1) = Environ("username") Then
Cells(icounter, 2) = PICK_A_FOLDER()
End If
Next icounter

Set wkb2 = Workbooks.Open(filepath3 & "")
Set sht2 = wkb2.Sheets("Sheet1")
sht2.Cells.Copy Destination:=sht1.Range("a1")
Application.CutCopyMode = False
wkb2.Close True



Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
Worksheets("Instructions").Activate
Application.Calculation = xlAutomatic



End Sub

2条回答
聊天终结者
2楼-- · 2019-09-12 16:12

Actually solved this by taking out the errorhandler and inserting another if statement that captures an invalid directory:

if dir(sal & "Export.xlsx") = "" then
write error handler code
查看更多
smile是对你的礼貌
3楼-- · 2019-09-12 16:30

When a SubRoutine performs more that one task you should consider extracting the individual tasks into separate SubRoutines.

In this way:

  • You can debug each task independently of the other tasks
  • The logic is simplified into smaller units
  • The code is easier to read
  • You can reduce clutter by placing these SubRoutines into separate modules
  • Possible code reuse

Another unapparent benefit is that by simplifying the function of a SubRoutine it is much easier to remember the routines pattern and reuse the pattern when a similar situation arises.

Note: I often use If Len(...) then which is analogous to If Len(...) > 0 then. I do this to reduce clutter.

Standard Module

Function getSharedFolder() As String
    Dim f As Range
    With Worksheets("Paths")
        Set f = .Range("A1", .Range("A" & .Rows.Count).End(xlUp)).Find(What:=Environ("username"), After:=.Range("A1"), LookAt:=xlWhole)
        If Not f Is Nothing Then
            'Dir([PathName], vbDirectory) returns empty if the [PathName] isn't a folder

            If Len(Dir(f.Offset(0, 1).Value, vbDirectory)) Then
                If Right(f.Offset(0, 1), 1) = "\" Then
                    getSharedFolder = f.Offset(0, 1)
                Else
                    getSharedFolder = f.Offset(0, 1) & "\"
                End If
            End If
        End If
    End With
End Function

Function setSharedFolder() As Boolean
    Dim f As Range
    Dim PathName As String

    PathName = PickSharedFolder
    If Len(PathName) Then

        setSharedFolder = True

        With Worksheets("Paths")
            Set f = .Range("A1", .Range("A" & .Rows.Count).End(xlUp)).Find(What:=Environ("username"), After:=.Range("A1"), LookAt:=xlWhole)
            If f Is Nothing Then Set f = .Range("A1", .Range("A" & .Rows.Count).End(xlUp)).Offset(1)

            f.Value = Environ("username")
            f.Offset(0, 1) = PathName

        End With
    End If
End Function

Function PickSharedFolder() As String

    Application.FileDialog(msoFileDialogFolderPicker).ButtonName = "Select Folder"

    With Application.FileDialog(msoFileDialogFolderPicker)
        .AllowMultiSelect = False
        .Title = "Select Main Folder Location"
        If .Show = -1 And .SelectedItems.Count = 1 Then
            PickSharedFolder = .SelectedItems(1)
        Else: Exit Function
        End If
    End With

End Function

Sub ToggleEvents(EnableEvents As Boolean, Optional DisplayAlerts = True)
    With Application
        .DisplayAlerts = DisplayAlerts
        .EnableEvents = EnableEvents
        .ScreenUpdating = EnableEvents
        .Calculation = IIf(EnableEvents, xlCalculationAutomatic, xlCalculationManual)
    End With
End Sub

Sub UpdateWorkBook(FilePath As String)
    Dim WSSource As Worksheet
    With Workbooks.Open(FilePath)

        Set WSSource = .Sheets("Sheet1")

        If WSSource Is Nothing Then
            MsgBox "Sheet1 not found in " & FILENAME, vbCritical, "Update Cancelled"
        Else
            WSSource.Copy Destination:=ThisWorkbook.Sheets("Extract").Range("A1")
        End If
        .Close True
    End With

End Sub

Workbook Module

Private Sub Workbook_Open()
    Const FILENAME As String = "Export.xlsx"
    Const PROMPT As String = "Press [Yes] to continue or [No] to cancel"
    Dim FilePath As String, Title As String, SharedFolder As String

    ToggleEvents False, False

    Do
        SharedFolder = getSharedFolder()

        If Len(SharedFolder) = 0 Then
            Title = "Folder not found"
        Else
            FilePath = SharedFolder & FILENAME
            If Len(Dir(FilePath)) = 0 Then Title = "File not found"
        End If

        If Len(SharedFolder) = 0 Then
            If MsgBox(PROMPT:=PROMPT, Buttons:=vbYesNo, Title:=Title) = vbYes Then
                setSharedFolder
            Else
                Exit Sub
            End If
        End If
    Loop Until Len(Dir(FilePath))

    UpdateWorkBook FilePath

    ToggleEvents True, True

End Sub
查看更多
登录 后发表回答