Несоответствие типа аргумента ByRef в Excel VBA

Я работаю с VBA. Я написал функцию определения пользователя, которая принимает string, обрабатывает ее и возвращает очищенный string. Я не уверен, что с ним не так. Я не могу назвать это и попросить обработать мою строку и вернуть ее. Я думаю, что есть ошибка в том, как я определяю или возвращаю его.

Public Function ProcessString(input_string As String) As String
    ' The temp string used throughout the function
    Dim temp_string As String

    For i = 1 To Len(input_string)
        temp_string = Mid(input_string, i, 1)
        If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then
            return_string = return_string & temp_string
        End If
    Next i
    return_string = Mid(return_string, 1, (Len(return_string) - 1))
    ProcessString = return_string & ", "
End Function

И я использую эту функцию следующим образом

Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)

Фамилия - это строковая переменная, обычно она выглядит как Lastname*****, и я пытаюсь удалить все звезды за ней. Верните Lastname без звезд.

Я получил Compile error: ByRef arugment type mismatch, когда попытался запустить это. Я использую Windows XP с Office 2003.

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

Private Sub CommandButton2_Click()
' In my original production code I have a chain of these
' Like this Dim last_name, first_name, street, apt, city, state, zip As String
Dim last_name As String

' I get the last name from a fixed position of my file. Because I am 
' processing it from another source which I copied and pasted into excel
last_name = Mid(Range("A4").Value, 20, 13)

' Insert the data into the corresponding fields in the database worksheet
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)

Ответ 1

Я подозреваю, что вы неправильно настроили last_name в вызывающем абоненте.

С утверждением Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)

это будет работать, только если last_name - строка, т.е.

Dim last_name as String

появляется в вызывающем устройстве где-то.

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

Два исправления:

1) Измените свою функцию на Public Function ProcessString(ByVal input_string As String) As String

2) поставьте Dim last_name As String в вызывающем абоненте, прежде чем использовать его.

(1) работает, потому что для ByVal при входе в функцию, которая принуждает ее к правильному типу данных, копируется input_string. Это также приводит к лучшей стабильности программы, поскольку функция не может изменить переменную в вызывающем.

Ответ 2

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

Например, существует процедура, которая делает некоторые манипуляции с данными: на основе идентификатора возвращает информацию о номере и количестве. ID как постоянное значение, другие два аргумента - переменные.

Public Sub GetPNQty(ByVal ID As String, PartNumber As String, Quantity As Long)

следующий основной код дает мне "несоответствие аргументов ByRef":

Sub KittingScan()  
Dim BoxPN As String
Dim BoxQty, BoxKitQty As Long

  Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty) 

End sub

и следующий работает также:

Sub KittingScan()
Dim BoxPN As String
Dim BoxQty As Long
Dim BoxKitQty As Long

  Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty)

End sub

Ответ 3

Я изменил несколько вещей для работы с Option Explicit, и код работал отлично с ячейкой, содержащей "abc.123", которая вернула "abc.12,". Ошибок компиляции не было.

Option Explicit ' This is new

Public Function ProcessString(input_string As String) As String
    ' The temp string used throughout the function
    Dim temp_string As String
    Dim i As Integer ' This is new
    Dim return_string As String ' This is new
    For i = 1 To Len(input_string)
        temp_string = Mid(input_string, i, 1)
        If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then
            return_string = return_string & temp_string
        End If
    Next i
    return_string = Mid(return_string, 1, (Len(return_string) - 1))
    ProcessString = return_string & ", "
End Function

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

Ответ 4

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

Public Function ProcessString(input_string As String) As String
    ProcessString=Replace(input_string,"*","")
End Function

Ответ 5

Что-то не так с этой строкой, попробуйте вот так:

Worksheets(data_sheet).Range("C2").Value = ProcessString(CStr(last_name))