Несоответствие типа аргумента 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))