Как вызвать функцию со списком и еще одним аргументом в VBA? - PullRequest
2 голосов
/ 01 октября 2019

Моя цель - создать небольшую программу / макрос в VBA Excel, которая автоматически исправляет имена столбцов. Я бы хотел сделать так, чтобы Subs для каждого отдельного имени столбца cell. Каждый из этих Subs имеет Array строк, которые содержат ключевые слова, по которым будет производиться поиск. Если значение ячейки является точно одной из строк, значение будет фиксированным. Однако то, как они будут исправлены, зависит от имени столбца, и поэтому каждую из этих подпрограмм нужно будет создавать отдельно.

Теперь я создал Sub, который вызывает всех отдельных cell крепление Subs. Я также сделал Function, который проверяет, содержит ли соответствующий cell одно из ключевых слов. Однако я не могу понять, как правильно передать информацию о Array доступных для поиска строк и соответствующие cell в Sub. При попытке вызвать функцию FindMatch () появляется сообщение «Ошибка времени выполнения» 13: несоответствие типов.

Function FindMatch(textArr() As String, cell As Range) As Boolean
    FindMatch = False
    Dim testCell As Range
    Dim i As Integer

' Range.Find() each string in the Array. If one of the Strings is found, FindMatch is true
    For i = 0 To UBound(textArr)
        Set testCell = cell.Find(What:=textArr(i), LookIn:=xlValues, LookAt:=xlWhole)

        If Not testCell Is Nothing Then
            FindMatch = True
        End If

    Next i

End Function

Она вызывается здесь:

Sub FindCr(cell As Range)

    Dim match As Boolean
    match = False

    Dim textArr() As String
    ' I get the type mismatch error here.
    textArr = Array("Cr", "Bag ", " Dog")

    match = FindMatch(textArr, cell)

    If match Then
' Do stuff depending on the column, for example:
        HighlightRange cell
    End If
End Sub

А вот основной Sub, который вызывает отдельные Sub-команды поиска и исправления. Он также вызывается из большого основного цикла, который проходит через весь диапазон ячеек имен столбцов.

Public Sub fixColumnNames(cell As Range)
    'Do find-and-fix functions for all possible column names
    FindCr cell
End Sub

Обратите внимание, я не хотел использовать ParamArray, потому что мне также нужно было передать cellв функции FindMatch (). Я считаю, что ParamArray используется только тогда, когда в вызове есть неопределенное количество аргументов. Я не хочу, чтобы cell входил в ParamArray.

Я пытался изменить объявления FindMatch и Dim textArr () на As Variant, но он действительно испортил функцию Range.Find (),Он начал сопоставлять все виды неправильных ключевых слов, когда ему дали Variant. Например:

Function FindMatch(textArr() As Variant, cell As Range) As Boolean

И

Dim textArr() As Variant
textArr = Array("Cr", "Bag ", " Dog")
match = FindMatch(textArr, cell)

Так что, если у вас есть альтернативный подход для передачи списка строк в функцию с другими дополнительными аргументами, пожалуйста, научите меня. Или, если вы знаете, что вызывает проблемы, мы будем благодарны за помощь.

Ответы [ 2 ]

2 голосов
/ 01 октября 2019

Я не совсем уверен, почему у вас возникли проблемы, но это прекрасно работает для меня. Так как у вас были проблемы с ParamArray, я пошел дальше и включил это в код для демонстрационных целей.

Sub FindCr(cell As Range)

    If FindMatch(cell, "Cr", "Bag ", " Dog") Then
        MsgBox "There was a match!"
    End If

End Sub

Function FindMatch(ByVal cell As Range, ParamArray textArr() As Variant) As Boolean

    Dim i As Long
    For i = 0 To UBound(textArr)

        If Not cell.Find(What:=textArr(i), LookIn:=xlValues, LookAt:=xlWhole) Is Nothing Then
            FindMatch = True
            Exit Function
        End If

    Next

End Function

Я немного сократил его для удобства чтения. Вы никогда не демонстрировали то, что передавали в качестве аргумента Cell, но убедитесь, что вы полностью определяете диапазон.

Dim Cell As Range
Set Cell = Thisworkbook.Worksheets(1).Range("A1")

будет примером полностью квалифицированного диапазона.

1 голос
/ 01 октября 2019

Вы не можете воздействовать на массив строк следующим образом:

textArr = Array("Cr", "Bag ", " Dog")

Чтобы использовать эту форму воздействия, textArr должен быть вариантом.

Если вы все еще хотите использовать строку,используйте редим и одиночную аффектацию. Например:

dim textArr() as String
...
Redim Preserve textArr(1)
textArr(0) = "Cr"
...
Redim Preserve textArr(2)
textArr(1) = "Bag"

И так далее, или вы можете сделать это в цикле, или если вы знаете длину конечного массива, просто Dim его с правильной длиной

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...