gpt4 book ai didi

arrays - VBA 中的最长公共(public)子序列给出#VALUE!错误

转载 作者:行者123 更新时间:2023-12-04 19:55:01 24 4
gpt4 key购买 nike

我一直在 Excel (365) 中组合一个 UDF 来计算两个字符串之间的最长公共(public)子序列(基于 python https://www.geeksforgeeks.org/printing-longest-common-subsequence/ 中的此实现)。

当我运行 UDF 时,我得到一个#Value!工作表上的错误。我已经完成了一些基本的调试,但我是 VBA 新手,遇到了困难。代码中的消息框语句只是为了进行粗略的调试。

我相信问题出在我对 L 数组的操作上。它似乎到达第一组 for 循环中的第一种情况,然后在评估 L(i, j,) = 0 时退出。有任何关于我哪里出错的指示吗?

在工作表中,我使用 =ClosestMatch("aabbaaaa", "aaaabbaa") 并得到 #VALUE! 结果。

这是我正在尝试的 UDF 的 VBA 代码:

Function ClosestMatch(ByVal x As String, ByVal y As String, Optional ByVal return_String As Boolean = False) As Variant
Dim xLen As Integer
Dim yLen As Integer

xLen = Len(x)
yLen = Len(y)

MsgBox "x = " & x & " y = " & y

'Create Zeroed Array of xLen+1 x yLen+1 dimensions (intentional extra space).
ReDim L((xLen + 1), (yLen + 1)) 'indexing starts at 0.
For i = 0 To (xLen + 1)
For j = 0 To (yLen + 1)
L(i, j) = 0
Next j
Next i

MsgBox "Created 0'ed array L"

'Build dynamic programming table from the bottom up.
'Note that L[xLen][yLen] will contain an integer equal to the length
'of the complete LCS.
'Note that L[i][j] contains the length of the lcs of x[0..i] and y[0..j]
For i = 0 To (xLen + 1)
For j = 0 To (yLen + 1)
If i = 0 Or j = 0 Then
L(i, j) = 0
ElseIf Mid(x, i - 1, 1) = Mid(x, i - 1, 1) Then
L(i, j) = L(i - 1, j - 1) + 1
Else
L(i, j) = WorksheetFunction.Max(L(i - 1, j), L(i, j - 1))
End If
Next j
Next i

'Length of LCS
Dim LCSlen As Integer
LCSlen = L(xLen, yLen)

MsgBox "Length of the LCS is " & LCSlen

'Start from the right-most-bottom-most corner and store chars
'one by on in LCS
Dim LCS As String

LCS = ""
i = xLen
j = yLen

While i > 0 And j > 0
'If current character in x and y are same, then current char
'is part of the LCS. The L[xLen][yLen] is the location of the
'fist charachter we will PUSH onto the front of the LCS string
If Mid(x, i - 1, 1) = Mid(x, i - 1, 1) Then
LCS = Mid(x, i - 1, 1) & Right(LCS, Len(LCS))

'If not same, then find the larger of the two lengths in L[][]
'then go in the direction of the larger value
ElseIf L(i - 1, j) > L(i, j - 1) Then
i = i + 1
Else
j = j + 1
End If
Wend

If return_String Then
ClosestMatch = LCS
Else
ClosestMatch = LCSlen
End If

End Function

最佳答案

Excel“吞掉”用户定义的函数错误并将其包装到 Variant/Error 值中,这样任何引发 VBA 运行时错误的函数都会返回 #VALUE! 调用工作表时出错。

诀窍是删除包装器并直接自己调用该函数。

在 VBIDE 中,按 Ctrl+G 调出立即工具窗口,然后键入 ?通过函数名称及其参数:

?ClosestMatch("aabbaaaa", "aaaabbaa")

?PRINT 的简写,因此如果一切顺利,该函数将返回一个在正下方打印的值:

?ClosestMatch("aabbaaaa", "aaaabbaa")
aa

但是,如果出现任何问题并且函数引发错误,您将收到 VBA 运行时错误提示,并将直接转至工作表中导致 #VALUE! 错误的指令正在看到,通过使用您可以使用的调试器工具,您将能够:

  • 将鼠标悬停在任意变量上即可查看其值
  • 调出locals工具窗口以查看所有变量及其值
  • 当前语句(黄色箭头)设置为函数中的任何其他语句
  • 单步执行 (F8) 代码并一次执行一条语句
  • 放置和删除断点 (F9) 以在特定语句处停止执行
  • 恢复执行 (F5),即使在动态修改代码后也是如此

考虑使用Debug.Print语句而不是MsgBox,打印到立即工具窗口,而不是弹出破坏性消息框。

然后考虑编写几个测试方法,使用各种参数组合调用您的函数,并对结果进行断言:如果函数返回预期输出,则测试通过,否则测试失败。当所有测试通过后,您就知道您的函数将按预期在所有涵盖的情况下工作。 Rubberduck (我几年前开始的一个免费开源 VBIDE 插件项目)为您提供了轻松编写和运行此类单元测试的工具,其静态代码分析可以帮助您避免许多陷阱,初学者陷阱和过时的代码结构(例如,While...Wend 可以编写为更标准的 Do While...Loop 结构)。

关于arrays - VBA 中的最长公共(public)子序列给出#VALUE!错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70241004/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com