【问题标题】:Type mismatch when changing argument types passed to a function更改传递给函数的参数类型时类型不匹配
【发布时间】:2018-06-28 13:00:24
【问题描述】:

情况:

我有一个函数RemoveEmptyArrRowCol,它接受两个参数,其中一个是数组(tempArr)。

当第二个参数是 Long 时,一切都很好。当我将第二个参数更改为 String (以及相关的调用变量)时,我得到:

类型不匹配(错误 13)

所以在下面的代码示例中:

  1. Test1 运行良好
  2. Test2 失败

问题:

1) 为什么两者的行为不同?

2) 如何修复第二个版本,使其与第一个版本一样?

3) 当我将字典值(数组)作为第一个参数而不是直接从工作表中读取时,我将如何证明这一点?

我尝试过的:

这似乎是关于 SO 的一个常见问题,我已经查看了其中一些问题;我已将其中一些作为参考放在这个问题的底部。但是,我仍然没有解决为什么这两个子中的第一个有效,而第二个无效?

我尝试了以下不同的组合:

  1. 添加额外的括号
  2. 显式声明tempArr的类型:Dim tempArr() As Variant
  3. 更改部分函数签名:ByRef tempArr() As Variant

看了@Fionnuala 对这个问题的回答MS Access/VBA type mismatch when passing arrays to function/subroutine,我决定尝试使用Call

Call RemoveEmptyArrRowCol2(ws.Range("C4:I129").Value, tempStr)

这已编译,但意味着我需要更改代码的其他部分以确保正确填充 tempArr。如果我这样做,我还不如将函数转换为过程。

按原样,流程是我填充tempArr,在测试示例中,直接从工作表然后移交给另一个子,即

tempArr = RemoveEmptyArrRowCol(ws.Range("C4:I129").Value, tempStr)
ArrayToSheet wb.Worksheets("Test").Range("A1"), tempArr

请注意:问题 3:

在最终版本中,我将从字典中提取的数组作为第一个参数传递,即

tempArr = RemoveEmptyArrRowCol( ArrayDict(tempStr), tempStr)

工作版本:

Option Explicit

Public Sub Test1()

    Dim tempArr() 'variant

    Init

    Dim tempStr As String: tempStr = "Response Times"

    tempArr = RemoveEmptyArrRowCol(ws.Range("C4:I129").Value, categoryDict(tempStr & "Cols"))

End Sub

Private Function RemoveEmptyArrRowCol(ByRef tempArr As Variant, ByVal nCols As Long) As Variant

End Function

失败的版本:

Public Sub Test2()

    Dim tempArr()

    Init

    Dim tempStr As String: tempStr = "Response Times"

    tempArr = RemoveEmptyArrRowCol2(ws.Range("C4:I129").Value, tempStr)

End Sub

Private Function RemoveEmptyArrRowCol2(ByRef tempArr As Variant, ByVal tempStr As String) As Variant

End Function    

当前全功能示例:

Private Function RemoveEmptyArrRowCol(ByRef tempArr As Variant, ByVal tempStr As String) As Variant

    Dim i As Long
    Dim j As Long
    Dim counter As Long
    counter = 0

    Dim tempArr2()

    Dim totCol As Long
    Dim adjColTotal As Long

    totCol = categoryDict(tempStr & "Cols")
    adjColTotal = categoryDict(tempStr & "ColsAdj")

    Select Case tempStr

        Case "ResponseTimes", "NoCCPR"

            ReDim tempArr2(1 To 1000, 1 To adjColTotal)

            For i = 1 To UBound(tempArr, 1)

                If tempArr(i, 2) <> vbNullString Then   'process row

                    counter = counter + 1                'load row to temp array (counter becomes row count)

                    For j = 1 To totCol

                        Select Case j
                            Case Is < 4
                                tempArr2(counter, j) = tempArr(i, j)
                            Case Is > 4
                                tempArr2(counter, j - 1) = tempArr(i, j)
                        End Select

                    Next j

                End If

            Next i

            RemoveEmptyArrRowCol = RedimArrDimOne(tempArr2, adjColTotal, counter)

       Case "Incidents"

    End Select

End Function

其他参考资料:

1)Passing arrays to functions in vba

2)Passing array to function returns compile error

3)Type mismatch error when passing arrays to a function in excel vba

4)Should I use Call keyword in VBA

【问题讨论】:

    标签: arrays excel compiler-errors vba


    【解决方案1】:

    这实际上取决于您的输入和输出,例如RemoveEmptyArrRowCol2 函数中有什么。这是一个选项,tempStr as String 没有失败:

    Public Sub Test2()
        Dim tempArr()
        Dim tempStr As String: tempStr = "Response Times"
        tempArr = RemoveEmptyArrRowCol2(Range("C4:I129").Value, tempStr)
    End Sub
    
    Private Function RemoveEmptyArrRowCol2(ByRef tempArr As Variant, _
                                           ByVal tempStr As String) As Variant
        RemoveEmptyArrRowCol2 = Array(1, 2)
    End Function
    

    例如,如果您删除返回值(Array(1,2),它会失败)但它应该会失败,因为它不返回任何内容。

    【讨论】:

    • 谢谢。重构时,我忘记为返回值添加一个全部捕获。
    • @QHarr - 竖起大拇指,欢迎。总的来说,ByRefByVal 的问题更多。看看我的文章 - vitoshacademy.com/… 在你的例子中,每当一个函数返回返回值时,它都会接受参数 ByVal,而不关心你是否写了 ByRef
    • 所以即使数组改变了,整个函数签名也应该使用 ByVal 编写?
    • @QHarr - 取决于您如何使用它。如果函数不返回值,而只是对变量进行一些更改,那么ByRef 是完全可以的。玩一下你的代码,看看有什么不同。
    • 刚刚意识到我已经重构并且正在使用 tempArr,所以我相信无论如何都应该使用 ByVal。
    【解决方案2】:

    使用“()”将“Dim tempArr As Variant”定义为 Variant-Array

    请向我们展示您的函数“categoryDict”和“ArrayDict”

    “打电话”不是必需品!

    您可以按如下方式访问值:

    Dim r As Long
    Dim c As Long
    For r = 1 To UBound(tempArr, 1)
        For c = 1 To UBound(tempArr, 2)
            Debug.Print tempArr(r, c)
        Next
    Next
    

    【讨论】:

    • 抱歉我错过了这个
    猜你喜欢
    • 2021-05-21
    • 2019-07-28
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 2018-04-15
    • 2013-11-03
    • 1970-01-01
    • 2012-02-14
    相关资源
    最近更新 更多