如何定义 DIAG 函数?

Posted

技术标签:

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

我想定义一个 VBA 函数:

    返回矩阵主对角线元素的列向量; 返回一个正方形对角矩阵,其中向量的元素在主对角线上; 自动返回矩阵/向量,无需按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 形式调用时出现错误 【参考方案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

【讨论】:

以上是关于如何定义 DIAG 函数?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle如何查看日志

详解Python-Numpy库的函数diagonal()并附函数diagonal()与函数diag()的区别

如何关闭和删除无模式的 qt 对话框

矩阵中diag啥意思

diag名词解释

R语言使用upper.tri函数lower.tri函数diag函数改变matrix矩阵上三角形下三角形对角线的数值