Ошибка byref argument type mismatch vba

Добрый день, уважаемый форумчани!ниже пользовательская функция, которая ругается на Ошибку: Compile error:  ByRef argument type mismatchКод Function GETLASTWORD(ByVal Text As String, Optional Separator As Variant) Dim lastword As String If IsMissing(Separator) Then Separator = " " End If lastword = StrReverse(Text) lastword = Left(lastword, InStr(1, lastword, Separator, vbTextCompare)) GETLASTWORD = StrReverse(replace(lastword, Separator, "")) End Function ...
 

azma

Пользователь

Сообщений: 314
Регистрация: 03.12.2017

#1

29.06.2020 12:56:07

Добрый день, уважаемый форумчани!
ниже пользовательская функция, которая ругается на Ошибку: Compile error:  ByRef argument type mismatch

Код
Function GETLASTWORD(ByVal Text As String, Optional Separator As Variant)

Dim lastword As String

If IsMissing(Separator) Then
 Separator = " "
End If
lastword = StrReverse(Text)
lastword = Left(lastword, InStr(1, lastword, Separator, vbTextCompare))

GETLASTWORD = StrReverse(replace(lastword, Separator, ""))

End Function

как можно от этого избавиться?
функция в отделенной книге работает без проблем, а я добавил её в мою надстройку и начала ругаться.

Прикрепленные файлы

  • Screen Capture #001.png (41.66 КБ)

 

sokol92

Пользователь

Сообщений: 4429
Регистрация: 10.09.2017

Один из возможных вариантов — в Вашей надстройке переопределена функция Replace. Если это так, то подобного рода вещи (называть свои функции так же, как стандартные) не желательны. Замена в приведенном выше примере Replace на VBA.Replace может помочь.

 

azma

Пользователь

Сообщений: 314
Регистрация: 03.12.2017

sokol92, Спасибо большое!

 

Jerry.Sweer

Пользователь

Сообщений: 60
Регистрация: 11.01.2017

#4

21.10.2020 18:20:07

Друзья помогите с той же проблемой.
Ниже вписан код. При использовании в коде функции выдает ошибку «ByRef argument type mismatch»
Как лечить?

Благодарен заранее.

Код
Public Function Equalist(t1 As String, t2 As String) As Variant
    Dim h As Long, l As Long
        For h = Len(t1) To 1 Step -1
            For l = 1 To Len(t1) - h + 1
                If t2 Like "*" & Mid(t1, l, h) & "*" Then
                    If h > Equalist Then
                        Equalist = h
                        Exit Function
                    End If
                End If
            Next
        Next
End Function

____________________________________________________________­____________________________________________________________­__

Код
Public Sub Test4()


Dim i As Long, w As Long, ob As Long, LR As Long, c As Long
Dim Line1 As Object
Dim t As Single
Dim j As Worksheet
Dim NomerDokumenta As Integer, KodTovara As Integer, Naimenovanie As Integer, RaznicaKolvo _
As Integer, RaznicaGrn As Integer, Hozoperaciya As Integer

't = Timer

LR = Cells(Rows.Count, 1).End(xlUp).Row

ReDim B(1 To LR), D(1 To LR), E(1 To LR), R(1 To LR), S(1 To LR), U(1 To LR) As Variant

Set j = Sheets(3)

NomerDokumenta = j.Cells.Find("№ документа").Column
KodTovara = j.Cells.Find("Код товара").Column
Naimenovanie = j.Cells.Find("Наименование товара").Column
RaznicaKolvo = j.Cells.Find("Разница, кол-во").Column
RaznicaGrn = j.Cells.Find("Разница, грн").Column
Hozoperaciya = j.Cells.Find("Хоз.операция").Column

For c = 1 To 3
    ' Первый заход
    For i = 2 To LR
        B(i) = j.Cells(i, NomerDokumenta)
        D(i) = j.Cells(i, KodTovara)
        E(i) = j.Cells(i, Naimenovanie)
        R(i) = j.Cells(i, RaznicaKolvo)
        S(i) = j.Cells(i, RaznicaGrn)
        U(i) = j.Cells(i, Hozoperaciya)
    Next i
    
    For w = 2 To UBound(B())
        For i = 2 To UBound(B())
            If IsEmpty(j.Cells(w, 30)) And IsEmpty(j.Cells(i, 30)) Then
                If Equalist(E(w), E(i)) > 20 Then
                    If R(w) < 0 And R(i) > 0 Then
                        If Abs(j.Cells(w, 18)) > Abs(j.Cells(i, 18)) Then
                            If Abs(Abs(S(w) / R(w)) - Abs(S(i) / R(i))) < 20 Then
                                If w < i Then
                                    j.Rows(w + 1).Insert Shift:=xlDown
                                    j.Rows(w + 1).FillDown
                                    j.Cells(w + 1, 18) = -j.Cells(i + 1, 18)
                                    j.Cells(w, 18) = j.Cells(w, 18) + j.Cells(i + 1, 18)
                                    j.Cells(w + 1, 30) = "Четвертый круг 1_" & w
                                    j.Cells(i + 1, 30) = "Четвертый круг 1_" & w
                                        LR = Cells(Rows.Count, 1).End(xlUp).Row
                                            ReDim B(1 To LR), D(1 To LR), E(1 To LR), R(1 To LR), S(1 To LR), U(1 To LR) As Variant
                                                For ob = 2 To LR
                                                    B(ob) = j.Cells(ob, NomerDokumenta)
                                                    D(ob) = j.Cells(ob, KodTovara)
                                                    E(ob) = j.Cells(ob, Naimenovanie)
                                                    R(ob) = j.Cells(ob, RaznicaKolvo)
                                                    S(ob) = j.Cells(ob, RaznicaGrn)
                                                    U(ob) = j.Cells(ob, Hozoperaciya)
                                                Next ob
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next i
    Next w

End Sub

Изменено: Jerry.Sweer21.10.2020 22:40:40

 

Дмитрий(The_Prist) Щербаков

Пользователь

Сообщений: 14009
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

#5

21.10.2020 18:37:08

Коды ОЧЕНЬ желательно оформлять соответствующим тегом(кнопка <…> в панели редактора сообщений). Без оформления тегами очень неудобно коды читать.
Ошибка банальная — у Вас массивы имеют тип VAriant, а функция Equalist требует тип String. Посему исправляется очень просто:

Код
If Equalist(Cstr(E(w)), Cstr(E(i))) > 20 Then

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Jerry.Sweer

Пользователь

Сообщений: 60
Регистрация: 11.01.2017

#6

21.10.2020 22:48:52

Спасибо большое.  

This repository has been archived by the owner on Aug 31, 2018. It is now read-only.

Permalink

Cannot retrieve contributors at this time

title keywords f1_keywords ms.prod ms.assetid ms.date

ByRef argument type mismatch

vblr6.chm1011308

vblr6.chm1011308

office

6adca657-8620-e3f1-3587-e317f988979c

06/08/2017

An argument passed ByRef (by reference), the default, must have the precise data type expected in theprocedure. This error has the following cause and solution:

  • You passed an argument of one type that could not be coerced to the type expected.

    For example, this error occurs if you try to pass an Integer variable when a Long is expected. If you want coercion to occur, even if it causes information to be lost, you can pass the argument in its own set of parentheses. For example, to pass the Variant argument MyVar to a procedure that expects an Integer argument, you can write the call as follows:

Dim MyVar 
MyVar = 3.1415 
Call SomeSub((MyVar)) 
 
Sub SomeSub (MyNum As Integer) 
MyNum = MyNum + MyNum 
End Sub
Placing the argument in its own set of parentheses forces evaluation of it as an [expression](vbe-glossary.md). During this evaluation, the fractional portion of the number is rounded (not truncated) to make it conform to the expected argument type. The result of the evaluation is placed in a temporary location, and a reference to the temporary location is received by the procedure. Thus, the original  `MyVar` retains its value.

 **Note**  If you don't specify a type for a [variable](vbe-glossary.md), the variable receives the default type,  **Variant**. This isn't always obvious. For example, the following code declares two variables, the first, `MyVar`, is a  **Variant**; the second, `AnotherVar`, is an  **Integer**.
Dim MyVar, AnotherVar As Integer 

For additional information, select the item in question and press F1 (in Windows) or HELP (on the Macintosh).

  • Remove From My Forums
  • Question

  • I have written a user defined function as follows:

    Function SpiralArc(dblThickness As Double, dblTheta As Double) As Double

    SpiralArc = dblThickness * (dblTheta * Sqr(1 + dblTheta ^ 2) + HArcsin(dblTheta)) / 2
    End Function

    I have two variables declared as doubles,

    dblTapethickness and dblThetaInner

    I am passing them to SpiralArc as follows.

    dblLoopLengthInner = SpiralArc(dblTapethickness, dblThetaInner)

    I get a compile error of argument type mismatch, and the first variable is highlighted.

    Any thoughts?

    Thanks!


    Bill Hardin

Answers

  • I have written a user defined function as follows:

    Function SpiralArc(dblThickness As Double, dblTheta As Double) As Double

    SpiralArc = dblThickness * (dblTheta * Sqr(1 + dblTheta ^ 2) + HArcsin(dblTheta)) / 2
    End Function

    I have two variables declared as doubles,

    dblTapethickness and dblThetaInner

    I am passing them to SpiralArc as follows.

    dblLoopLengthInner = SpiralArc(dblTapethickness, dblThetaInner)

    I get a compile error of argument type mismatch, and the first variable is highlighted.

    Any thoughts?

    Thanks!


    Bill Hardin

    Check that the value for dblTapethickness is actually a double.

    I would also use ByVal in the function’s arguments like this:

    Function SpiralArc(ByVal dblThickness As Double, ByVal dblTheta As Double) As Double


    Jeanette Cunningham

    • Marked as answer by

      Tuesday, February 15, 2011 12:24 AM

  • Jeanette is mostly correct: it would be much better to declare the function arguments using ByVal. Why? Because it explicitly tells the user of the function you have no intention of changing the value on the caller. I wish this was the VBA default, but alas
    it is not.

    However, the actual reason you’re getting the error is because of a common mistake with declaring variables. You used this:

    Dim dblTapethickness, dblThetaInner As Double

    The error is in your assumption that dblTapeThickness is now declared as a Double. It is not. It’s a Variant.

    That’s why I always declare one variable per line:
    Dim dblTapethickness As Double
    Dim dblThetaInner As Double

    Or, if you must:
    Dim dblTapethickness As Double, dblThetaInner As Double

    In the ByRef case, VBA’s type coercion is not strong enough, resulting in a compile error. In the ByVal case, type coercion does what most users would expect.

    Not to weird you out, but this would have worked with your original code:
    dblLoopLengthInner = SpiralArc((dblTapethickness), dblThetaInner)
    Per the help file the extra parentheses cause the variable to be evaluated and ‘promoted’ to a double in a temporary variable of the precise type.


    -Tom. Microsoft Access MVP

    • Marked as answer by
      Bill Hardin
      Tuesday, February 15, 2011 12:24 AM

  • Hi Bill

    _VAR_iable data _TYP_e can be checked with the function VARTYPE() ;-)

    Henry

    is there a way to check a variables data type while the code is running?


    Bill Hardin

    • Marked as answer by
      Bill Hardin
      Wednesday, February 16, 2011 10:14 PM

  • Dim dblTapethickness, dblThetaInner As Double

    The above gives dblThetaInner as a double and dblTapethickness as a Variant.

    To make them both a double:

    Dim dblTapethickness As Double
    Dim dblThetaInner As Double

    I like to put each dim statement on a separate line for easier reading and understanding while debugging.

    To test if you get a double while the code is running, I use the immediate window and a debug statement like this:

    Debug.Print «dblTapethickness», dblTapethickness , «dblThetaInner «, dblThetaInner

    When you open the immediate window, you will see the values of each variable and you can check if it is a double.


    Jeanette Cunningham

    • Marked as answer by
      Bill Hardin
      Wednesday, February 16, 2011 10:14 PM

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

В этой статье мы объясняем ошибку, возникшую при использовании Excel VBA ByRef как «Ошибка несоответствия типа аргумента». Перед этим позвольте мне сначала познакомить вас с «By Ref». Переменные — это ключ к любому языку программирования, и VBA не исключение. Мы видели много способов объявления переменных, одним из таких способов объявления переменных является использование слов «ByRef» и «ByValVBA ByVal или «По значению» — это инструкция, которая помогает пользователю сбросить основное значение, т. Е. Заменяя его другой подпроцедурой в Excel. Это обычная практика, когда пользователь получает значение основной процедуры до 0.читать далее. »

Что означает ByRef?

«ByRef» означает «по ссылке», используя это слово, мы можем фактически передавать аргументы процедурам (как для подпрограммы, так и для функции) по ссылке. В этом отличие от своего брата By Val, который по своей природе не гибок, а фиксирован.

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

Код:

Sub Macro1()

    Dim A As Long

    A = 50

   Macro2 A

   MsgBox A
End Sub

Sub Macro2(ByRef A As Long)

    A = A * 10

End Sub

У нас есть две подпроцедуры с именами Macro1 и Macro2 соответственно. Чтобы лучше понять это, запускайте макрос построчно, нажимая клавишу F8.

Пример ошибки 1.1 VBA ByRef

Нажмите клавишу F8, чтобы зафиксировать значение переменной «A» как 50.

Пример ошибки 1.2 VBA ByRef

В следующей строке кода написано «Macro2 A», то есть имя второго макроса, а «A» — это переменная, определенная с помощью слова «By Ref».

Пример ошибки 1.3 VBA ByRef

Как вы можете видеть выше, в тот момент, когда мы выполняем строку кода «Macro2 A», она переходит к следующему Подпроцедура VBASUB в VBA — это процедура, которая содержит весь код, который автоматически дает инструкцию end sub, а средняя часть используется для кодирования. Оператор Sub может быть как общедоступным, так и частным, а имя подпроцедуры является обязательным в VBA.читать далее из описанной выше процедуры.

Пример ошибки VBA ByRef 1.4

Теперь мы можем видеть, что значение переменной «A» равно 50. Это связано с тем, что мы использовали слово «ByRef» для объявления переменной «A», что совпадает с Макрос1, он получил значение, которое мы присвоили этой переменной «A» из Макрос1.

Теперь в этом макросе (Макрос2) уравнение говорит: A = A * 10, т.е. A = 50 * 100. Нажмите клавишу F8 3 раза, чтобы вернуться к указанному выше макросу (Макрос1).

Пример ошибки 1.5 VBA ByRef

Теперь нажмите еще раз клавишу F8, чтобы увидеть значение переменной «A» в окно сообщения в VBAФункция VBA MsgBox — это функция вывода, которая отображает обобщенное сообщение, предоставленное разработчиком. Этот оператор не имеет аргументов, и персонализированные сообщения в этой функции записываются в двойных кавычках, а для значений предоставляется ссылка на переменную.читать далее.

Пример ошибки 1.6 ByRef VBA

Значение говорит 500.

Несмотря на то, что значение, которое мы присвоили в этом макросе (Macro1), равно 50, с помощью слова ByRef мы фактически запустили подпроцедуру Macro2, сохранив значение переменной «A» из Macro1 и затем выполнив значение A, умножив 10.

3 основных причины несоответствия типа аргумента Byref в VBA

Выше мы видели, как работает «ByRef», но мы обязаны совершить некоторые ошибки, которые неизменно приводили к выбрасыванию Ошибка VBAОбработка ошибок VBA относится к устранению различных типов ошибок, возникающих при работе с VBA. читать далее сообщение как «Несоответствие типа аргумента ByRef».

Это происходит по многим причинам, и в этом разделе мы покажем вам, как исправить эту ошибку и отладить код.

Вы можете скачать этот шаблон Excel для несоответствия типа аргумента VBA ByRef здесь — Шаблон Excel для несоответствия типа аргумента VBA ByRef

Причина ошибки №1 — разные имена переменных

Одна из основных причин появления этой ошибки в Excel VBA связана с тем, что в двух процедурах передаются разные переменные. Например, посмотрите на коды ниже.

Код:

Sub Macro1()

   Dim A As Long
   A = 50

   Macro2 B

   MsgBox A

End Sub

Sub Macro2(ByRef A As Long)

    B = B * 10

End Sub

Причина ошибки аргумента VBA ByRef 1.1

В Macro1 мы использовали переменную «A», а в Macro2 мы использовали переменную «B». Теперь, если вы попытаетесь запустить код, мы получим ошибку VBA как «Несоответствие типа аргумента ByRef».

Ошибка несоответствия типа аргумента ByRef 1

Как вы можете видеть выше, переменная «B» была выделена из-за несоответствия типа имени переменной.

Решение: Чтобы решить эту проблему, нам нужно убедиться, что имена переменных в обеих процедурах являются точными.

Причина ошибки 2: разные типы переменных данных

Несмотря на то, что имена переменных совпадают, это вызывает ошибку, потому что мы присваиваем им тип данных. Посмотрите на приведенный ниже код.

Код:

Sub Macro1()

    Dim A As Integer
    A = 50

    Macro2 A
    MsgBox A

End Sub

Sub Macro2(ByRef A As Long)

    A = A * 10

End Sub

Причина ошибки аргумента VBA ByRef 2.1

В приведенных выше кодах я объявил переменную «A» как целочисленный тип данных в Macro1, а в Macro2 той же переменной был назначен тип данных «Long».

Когда мы запускаем этот код, это вызовет ошибку VBA «Несоответствие типа аргумента ByRef».

Ошибка несоответствия типа аргумента ByRef 2

Это потому, что мы назначили два разных типа данных для одного и того же имени переменной.

Решение: Тип данных в обеих процедурах должен быть одинаковым.

Причина ошибки 3: типы переменных данных отсутствуют в одном макросе

Ошибка Excel VBA «Несоответствие типа аргумента по ссылке» могла произойти из-за того, что тип данных назначен в одном макросе и не назначен в другом макросе.

Код:

Sub Macro1()

    A = 50

    Macro2 A
    MsgBox A

End Sub

Sub Macro2(ByRef A As Long)

    A = A * 10

End Sub

Причина ошибки аргумента VBA ByRef 3.1

В приведенном выше коде Macro1 я не объявил какую-либо переменную, а просто присвоил значение переменной.

С другой стороны, для Macro2 я объявил переменную «A» длинным. Если вы попытаетесь запустить этот код, это вызовет ошибку VBA «Несоответствие типа аргумента ByRef».

Ошибка несоответствия типа аргумента ByRef 3

Решение1: Чтобы избежать подобных ситуаций, первое решение — объявить переменную в обеих процедурах и назначить один и тот же тип данных.

Решение2: альтернатива Решение состоит в том, чтобы сделать объявление переменной обязательным, добавив слово «Option Explicit» в верхней части модуля.

Решение ошибки аргумента VBA ByRef 3.1

Что это будет делать, так это то, что перед тем, как отобразить VBA «Несоответствие типа аргумента ByRef», ошибку, он фактически попросит нас сначала объявить переменную.

Решение ошибки аргумента VBA ByRef 3.2

Так, Вариант ЯвныйПараметр VBA явно обязывает пользователя объявлять все переменные перед их использованием; любая неопределенная переменная вызовет ошибку при выполнении кодирования. Мы можем включить его для всех кодов из опций, требующих объявления переменных.читать далее всегда пригодится в VBA.

То, что нужно запомнить

  • ByRef — это противоположность By Val.
  • ByRef переносит ссылку от одной процедуры к другой.
  • Имя переменной и тип данных должны быть одинаковыми в обеих процедурах.
  • В случае нескольких переменных каждую переменную нужно объявлять отдельно.

УЗНАТЬ БОЛЬШЕ >>

Post Views: 308

1012 / 116 / 2

Регистрация: 26.08.2011

Сообщений: 1,098

Записей в блоге: 2

1

04.04.2012, 23:44. Показов 40102. Ответов 4


Работал достаточно долго с программой. Проверял элементы по отдельности. Делаю сборку программы — и вдруг на все переменные стали появляться такие сообщения. В чем может быть причина?



1



2783 / 715 / 106

Регистрация: 04.02.2011

Сообщений: 1,443

05.04.2012, 00:07

2

Не пишите программ без Option Explicit, пока не приучились к тому, что всякая переменная должна иметь свой тип. Каждому типу данных — свои операции, некоторые значения одних типов можно конвертировать в другой тип данных, например функции преобразования CInt, CDbl, CLng, CStr, CDate. Старайтесь следить, чтобы там где требуется определенный тип данных, данные были достоверно преобразованы в этот тип. Возможно у вас Sub или Function требует один тип, а вы подсовываете ей что-то неудобоваримое.



1



15131 / 6405 / 1730

Регистрация: 24.09.2011

Сообщений: 9,999

05.04.2012, 00:14

3

Цитата
Сообщение от AndreA SN
Посмотреть сообщение

вдруг на все переменные стали появляться такие сообщения

Не на все, а только на передаваемые в подпрограммы или функции.
В проекте, состоящем более чем из ~50 строк,

необходимо

использовать

Option Explicit

, о чем mc-black написал Вам в соседней теме. Поверьте, на написание операторов Dim Вы потратите меньше времени, чем на устранение «странных» ошибок.
Включите в Tools — Options — Editor опцию Require variables declaration, тогда Option Explicit будет появляться автоматически в

новых

модулях.



1



AndreA SN

1012 / 116 / 2

Регистрация: 26.08.2011

Сообщений: 1,098

Записей в блоге: 2

05.04.2012, 00:37

 [ТС]

4

дело в том, что я уже работаю с Option Explicit
Но оказалось, что объявление переменных вида

Visual Basic
1
 Dim i, j As Integer

считает пременную i типом Variant !!!
Стал писать

Visual Basic
1
Dim i As Integer, j As Integer

— ошибки пропали.
Или я тут что-то лишнее придумал?



1



15131 / 6405 / 1730

Регистрация: 24.09.2011

Сообщений: 9,999

05.04.2012, 00:42

5

Цитата
Сообщение от AndreA SN
Посмотреть сообщение

объявление переменных вида
Dim i, j As Integer
считает пременную i типом Variant !

Именно так. В окне Locals в режиме останова это хорошо видно.



1



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

05.04.2012, 00:42

5

Понравилась статья? Поделить с друзьями:
  • Ошибка bcd1695 при обработке вашей транзакции
  • Ошибка busy на фотоаппарате canon
  • Ошибка b224e49 мерседес
  • Ошибка bugsplat scrap mechanic
  • Ошибка bcd 1695 марафон