【问题标题】:How to define a DIAG function?如何定义 DIAG 函数?
【发布时间】:2022-01-23 12:52:28
【问题描述】:

我想定义一个 VBA 函数:

  1. 返回矩阵主对角线元素的列向量;
  2. 返回一个正方形对角矩阵,其中向量的元素在主对角线上;
  3. 自动返回矩阵/向量,无需按Ctrl Shift Enter;

我正在处理这段代码:

Public Function DIAG(matrix As Variant) As Variant

Dim i As Long
Dim j As Long
Dim nRows As Long
Dim nCols As Long
Dim tempArray As Variant

nRows = matrix.Rows.Count
nCols = matrix.Columns.Count

For i = 1 To nRows
    For j = 1 To nCols
        If i = j Then
           tempArray(i) = matrix(i, j)
        End If
    Next j
Next i

DIAG = tempArray

End Function

这仅用于该功能的第一个目的,但它不起作用。我明白了:

#VALUE

【问题讨论】:

  • 哪行代码给出了这个错误?为什么使用Variant 而不是Range? ...?
  • @Dominique 我在输入公式的单元格中得到#VALUE,代码没有错误
  • 你的意思是nRows = matrix.CountnRows = matrix.Rows.Count 一样吗?
  • 该错误意味着函数在以 UDF 形式调用时出现错误

标签: excel vba matrix diagonal


【解决方案1】:

我认为您的应用程序结构有问题:您确定您的函数所在的模块可以从您的 Excel 工作簿中访问吗?

作为一个例子,我做了一个类似的函数,我在我的 Excel 工作簿中使用了它(在一个单元格中,我输入了公式 =DIAG(J5:Q25))并且一切正常,特此截图:

糟糕,我刚刚尝试了其他方法,但出现了相同的错误消息:

Public Function DIAG(matrix As Variant) As Variant
 Dim tempArray As Variant

 tempArray(1) = 1
 tempArray(2) = 2
 DIAG = tempArray
End Function

您确定可以将整个矩阵甚至一维数组作为函数的返回值返回,并这么容易地调用它吗?

为了您的信息,我尝试了这个,在一个单元格中使用=DIAG(J5:Q25),在两个单元格中,并作为一个数组公式。

【讨论】:

  • 刚刚检查了一下,看起来一切正常,就像你的截图一样
  • 我相信返回一个数组是问题所在:我相应地编辑了我的答案。
  • 恐怕已经构建的函数无法返回任何数组,这就是错误的原因,如果调用为 UDF。如果从测试 Sub 中调用,它将返回更多 elocvent 错误。如果没有声明维度,或者是ReDimtempArray就不能这样加载...如果加载了,可以返回数组!
  • @FaneDuru:所以你对作者的声明是“如果你创建一个用户定义的函数,称为UDF,那么首先通过在宏中调用它来测试它,并且只有当这个工作正常,您可以直接从 Excel 中使用它。"。感谢您的建议!
  • 您可以以这种方式“翻译”该声明,我同意... :) 最好将 translation 放在我的答案末尾,改进它,我思考。感谢您的建议!
【解决方案2】:

当调用 UDF 时,您的函数会返回这样的错误,如果我正确理解了您想要什么,请使用下一个改编函数:

Public Function DIAG(matrix As Range) As Variant
 Dim i As Long, j As Long, k As Long, nRows As Long, nCols As Long
 Dim tempArray As Variant

 nRows = matrix.Count: nCols = matrix.Columns.Count

 ReDim tempArray(nRows * nCols) 'without this step it will return an error when try loading
 For i = 1 To nRows
    For j = 1 To nCols
        If i = j Then
           tempArray(k) = matrix(i, j): k = k + 1
        End If
    Next j
 Next i
 ReDim Preserve tempArray(k - 1) 'preserving only the elements keeping data
 DIAG = tempArray
End Function

中间数组应该是 ReDim,然后只保留保存数据的元素...

结束语句(@Dominique 建议):如果您创建了一个用户定义的函数,称为 UDF,则首先通过在宏中调用它来测试它,并且仅当它返回您的需要,没有任何错误,您可以直接从单元格中调用它。

【讨论】:

    【解决方案3】:

    @FaneDuru 的代码确实帮助了我,但我成功地以这种方式编写了我的 UDF:

    Public Function DIAG(matrix As Range) As Variant
    
    Dim i As Long, j As Long, nRows As Long, nCols As Long
    Dim tempArray As Variant
    
    nRows = matrix.Rows.Count
    nCols = matrix.Columns.Count
    
    If nCols = 1 Then
     
     ReDim tempArray(nRows - 1, nRows - 1)
    
     For i = 1 To nRows
      tempArray(i - 1, i - 1) = matrix(i)
     Next i
    
    Else
    
     If nCols = nRows Then
    
     ReDim tempArray(nRows - 1, 0)
    
     For i = 1 To nRows
      For j = 1 To nCols
       If i = j Then
        tempArray(i - 1, 0) = matrix(i, j)
       End If
      Next j
     Next i
    
     Else
      tempArray = CVErr(xlErrValue)
     End If
    
    End If
    
    DIAG = tempArray
    
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      相关资源
      最近更新 更多