Использование переменной для сохранения пути к файлу, а затем открытия, копирования, вставки и закрытия книг с переменной - PullRequest
0 голосов
/ 30 апреля 2019

Поэтому я пытаюсь дать пользователю возможность выбрать файл, из которого я хочу импортировать (копировать и вставить) содержимое из листов этого файла в текущую книгу. Я смог сделать это путем жесткого кодирования пути к файлу в коде, но у меня возникли проблемы с тем, чтобы сделать то же самое с переменной для хранения пути к файлу выбранного файла перед открытием, копированием, вставкой и закрытием файла. Все последнее работает отлично, я просто застрял на переменной части.

Как я уже сказал, я смог сделать это путем жесткого кодирования пути к файлу в подпрограммах open & close (вы поймете, что я имею в виду через минуту), но не знаю, как настроить и использовать переменную для разных подпрограмм

Option Explicit
Public InputFile As String

Sub OpenWorkbook()
    'attempt to let the variable equal to the filepath in a cell
    Worksheets("Input_Parameters").Range("F9").Value = InputFile
    'I was able to reference directly the hardcoded filepath here, having an issue with putting it in a variable
    Workbooks.Open InputFile
End Sub

Sub CloseWorkbook()
    'this will need altering also
    Workbooks("InputFile").Close SaveChanges:=True
End Sub

Sub SelectInput()
     Dim FileSelect As Variant
     Dim wb As Workbook
     Dim i As Integer
     Application.ScreenUpdating = False
     FileSelect = Application.GetOpenFilename(filefilter:="Excel Files,*.xl*", _
     MultiSelect:=False)
     If FileSelect = False Then
     MsgBox "Select the file name"
     Exit Sub
     End If
     Worksheets("Input_Parameters").Range("F9").Value = FileSelect
     'attempting to let the value equal a global variable
     Set InputFile = FileSelect
End Sub


Sub Import()
    Dim PRC As String
    PRC = Worksheets("Input_Parameters").Cells(17, "B").Value

OpenWorkbook
'this first reference is what I was playing with, the rest is what worked when hardcoded
Workbooks("InputFile").Worksheets("Run_Map").Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("Run_Map").Range("A2:Z500")

Workbooks("Mock_OneSourceOfTruth_1.xlsx").Worksheets("Reporting_Map").Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("Reporting_Map").Range("A2:Z500")

Workbooks("Mock_OneSourceOfTruth_1.xlsx").Worksheets("Variable_Map").Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("Variable_Map").Range("A2:Z500")

Workbooks("Mock_OneSourceOfTruth_1.xlsx").Worksheets("Product_Map_" & PRC).Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("Product_Map_ETY").Range("A2:Z500")

Workbooks("Mock_OneSourceOfTruth_1.xlsx").Worksheets("Subproduct_Map").Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("Subproduct_Map").Range("A2:Z500")

Workbooks("Mock_OneSourceOfTruth_1.xlsx").Worksheets("Currency_Map").Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("Currency_Map").Range("A2:Z500")

Workbooks("Mock_OneSourceOfTruth_1.xlsx").Worksheets("FX_Map").Range("A2:Z500").Copy _
ThisWorkbook.Worksheets("FX_Map").Range("A2:Z500")

CloseWorkbook
End Sub

Мне комфортно со всем кодом, и как он работает, я просто хочу получить некоторое представление о переменных, как я могу это сделать? объявить переменную глобально? Как мне это сделать? какие-нибудь другие варианты? Могу ли я даже ссылаться на путь к файлу в подпрограмме OpenWorkbook () как на переменную, а не на жестко заданный путь к файлу?

1 Ответ

0 голосов
/ 30 апреля 2019

Всякий раз, когда мне нужно скопировать данные, я считаю невероятно полезным придерживаться краткой обработки переменных, то есть одной переменной для источника - независимо от (например, рабочей книги, рабочего листа, диапазона,ячейка, индекс строки, индекс столбца и т. д.) и одна для цели.

Во-вторых, я бы порекомендовал сохранять переменные как можно более закрытыми.Если вы хотите передать значение как результат Sub, замените его Sub на Function и позвольте результату быть возвращаемым значением этой функции.

Наконец, это также помогает сохранитькаждая подпрограмма макроса, которая явно не предназначена для вызова также из других макросов Private, так что у каждого макроса есть свой отдельный контекст в файле модуля.

При этом, я думаю, кодВы ищете выглядит примерно так:

Option Explicit

' Entry point of macro
Sub Import()
    Dim SourceWb As Workbook
    Dim TargetWb As Workbook

    ' Prevents Excel from showing the opening and closing
    Application.ScreenUpdating = False

    ' The target is this workbook
    Set TargetWb = ThisWorkbook

    ' Let the user select the workbook
    Set SourceWb = OpenSourceWorkbook
    If SourceWb Is Nothing Then
        ' The user has cancelled the selection.
        ' We can be fairly sure they'll assume that clicking "Cancel"
        ' cancels the operation, so we can just exit the macro
        ' without further notice.

        Application.ScreenUpdating = True
        Exit Sub
    End If

    If SourceWb Is TargetWb Then
        MsgBox "Cannot copy from and to the same workbook." & vbCrLf & vbCrLf & _
            "Cancelling the import.", vbExclamation, "Invalid source file"

        Application.ScreenUpdating = True
        Exit Sub
    End If

    ' Store whether so far everything worked
    Dim Success As Boolean

    ' Copy the desired data, but stop if something goes wrong
    Success = CopyData(SourceWb, TargetWb, "Run_Map", "A2:Z500")
    If Success Then Success = CopyData(SourceWb, TargetWb, "Reporting_Map", "A2:Z500")
    If Success Then Success = CopyData(SourceWb, TargetWb, "Variable_Map", "A2:Z500")
    If Success Then Success = CopyData(SourceWb, TargetWb, "Product_Map_ETY", "A2:Z500")
    If Success Then Success = CopyData(SourceWb, TargetWb, "Subproduct_Map", "A2:Z500")
    If Success Then Success = CopyData(SourceWb, TargetWb, "Currency_Map", "A2:Z500")
    If Success Then Success = CopyData(SourceWb, TargetWb, "FX_Map", "A2:Z500")

    ' Close the user-selected source workbook
    Call SourceWb.Close(SaveChanges:=False)

    If Success Then
        MsgBox "All data was copied successfully.", vbInformation, "Success"
    End If
    ' In the other case we triggered a message box earlier,
    ' so no need to report that again.

    ' Re-enable the screen updating - and we're done!
    Application.ScreenUpdating = True
End Sub

Private Function OpenSourceWorkbook() As Workbook
    Dim SelectedFilePath As Variant

    SelectedFilePath = Application.GetOpenFilename(filefilter:="Excel Files,*.xl*", _
    MultiSelect:=False)

    If SelectedFilePath = False Then
        ' The user has cancelled the dialog
        ' Set the result to Nothing
        Set OpenSourceWorkbook = Nothing
    Else
        ' Open the file and set it as result
        Set OpenSourceWorkbook = Workbooks.Open(SelectedFilePath)
    End If

End Function

Private Function CopyData(SourceWb As Workbook, TargetWb As Workbook, _
        WorksheetName As String, Range As String) As Boolean

    Dim SourceWs As Worksheet
    Dim TargetWs As Worksheet
    Dim SourceArea As Range
    Dim TargetArea As Range

    ' Try to obtain the source worksheet
    Set SourceWs = TryGetWorksheetByName(SourceWb, WorksheetName)
    If SourceWs Is Nothing Then
        ' Source worksheet not found. Report error and abort.
        MsgBox "The file you selected does not appear to be a valid source for the data." & vbCrLf & _
            "It does not have a worksheet named '" & WorksheetName & "'." & vbCrLf & vbCrLf & _
            "Cancelling the import.", vbExclamation, "Invalid source file"

        ' Return failure
        CopyData = False
        Exit Function
    End If

    ' Try to obtain the target worksheet
    Set TargetWs = TryGetWorksheetByName(TargetWb, WorksheetName)
    If TargetWs Is Nothing Then
        ' Target worksheet not found. Report error and abort.
        MsgBox "Cannot copy the data to the target workbook since it" & vbCrLf & _
            "does not have a worksheet named '" & WorksheetName & "'." & vbCrLf & vbCrLf & _
            "Cancelling the import.", vbExclamation, "Invalid target file"

        ' Return failure
        CopyData = False
        Exit Function
    End If

    ' Range to copy from and to
    Set SourceArea = SourceWs.Range(Range)
    Set TargetArea = TargetWs.Range(Range)

    ' Finally, copy the data
    Call SourceArea.Copy(Destination:=TargetArea)

    ' Return success
    CopyData = True
End Function

Private Function TryGetWorksheetByName(Wb As Workbook, WorksheetName As String) As Worksheet
    Set TryGetWorksheetByName = Nothing
    On Error Resume Next
        Set TryGetWorksheetByName = Wb.Sheets(WorksheetName)
    On Error GoTo 0
End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...