Excel 带正除数或无除数的零除法(vba)

Excel 带正除数或无除数的零除法(vba),excel,vba,divide-by-zero,Excel,Vba,Divide By Zero,我不熟悉Excel中的宏和vba。目前,我正在为工作中的发票模板处理vba宏。 然而,我运行的是一个除法为零的错误,我很难找到它的原因。 有时会弹出两行特定的代码。。 第一部分: VATRMB = 0 第二部分: VATRMB = VATRMB + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) Dim VATRMB存储如下: Dim startRow As Integer, e

我不熟悉Excel中的宏和vba。目前,我正在为工作中的发票模板处理vba宏。 然而,我运行的是一个除法为零的错误,我很难找到它的原因。
有时会弹出两行特定的代码。。
第一部分:

    VATRMB = 0
第二部分:

    VATRMB = VATRMB + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593)))
Dim VATRMB存储如下:

        Dim startRow As Integer, endRow As Integer, VATRMB As Single, VATEUR As Single, VATUSD As Single, VATRMBCell As Range, VATEURCell As Range, VATUSDCell As Range
:
On Error Resume Next
VarX = 10
VarX = 10
:
在我看来,这些线永远不会出现零除错误。在第一种情况下,没有任何除数,而在第二种情况下,它总是正的。
你们有谁知道为什么这会导致错误吗?这可能与sub被多次调用、重用同一个vate有关吗?它应该在每次调用sub后重置,对吗?或者,这可能与我指定VATRMB为单身这一事实有关吗?这适用于“小”(小于1000000)浮点数,对吗

编辑:
1.添加了用于调用Dim存储的精确线路

2.下面是使用的完整代码块,可能有助于澄清一两件事:

'Debug.Print Tab(10); ("Items will be searched in rows " & startRow & " thru " & endRow) 'Serves for debugging and testing
For i = startRow To endRow 'Loop the following code through all rows mentioned above
    If ActiveSheet.Range("B" & i).Find("Membership") Is Nothing Then 'If nothing is returned when searching for "Membership"; i.e. if the item in this row is not a membership payment
        If Not ActiveSheet.Range("H" & i).Find("RMB") Is Nothing Then 'If the value for this item is RMB denoted
            'Debug.Print Tab(20); "Item on Row " & i & " is RMB denoted, VAT = " & ((ActiveSheet.Range("I" & i).Value / (1 + 0.0593)) * 0.0593) 'Serves for debugging and testing
            VATRMB = VATRMB + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) 'Add row's VAT to VAT total
        End If
        If Not ActiveSheet.Range("H" & i).Find("EUR") Is Nothing Then 'If the value for this item is EUR denoted
            'Debug.Print Tab(20); "Item on Row " & i & " is EUR denoted, VAT = " & ((ActiveSheet.Range("I" & i).Value / (1 + 0.0593)) * 0.0593)  'Serves for debugging and testing
            'MsgBox VATEUR + 0.0593 * ActiveSheet.Range("I" & i).Value / (1 + 0.0593)
            VATEUR = VATEUR + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) 'Add row's VAT to VAT total
        End If
        If Not ActiveSheet.Range("H" & i).Find("USD") Is Nothing Then 'If the value for this item is USD denoted
            'Debug.Print Tab(20); "Item on Row " & i & " is USD denoted, VAT = " & ((ActiveSheet.Range("I" & i).Value / (1 + 0.0593)) * 0.0593)  'Serves for debugging and testing
            VATUSD = VATUSD + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) 'Add row's VAT to VAT total
        End If
    Else 'Else, i.e. if the row contains a membership payment, then essentially nothing happens
        'Debug.Print Tab(20); ("Item on Row " & i & " is a membership payment; no VAT paid.") 'Serves for debugging and testing
    End If
Next

因此,我试图做的基本上是遍历发票中的所有项目,从startRow到endRow,并通过解析“type”字符串(B列)来确定该项目是否为会员付款。然后,根据是否为会员付款确定增值税,并检查支付的货币。付款金额以浮点数形式存储在第一列。

不确定这是否是您问题的答案,因为您需要提供完整的工作簿等来确认。然而,我们可以创建这种类型的“不可能”情况,不仅Div0具有100%的再现性,而且几乎所有错误都具有100%的再现性,如:

VarX = 10  ' we can make this fail with Div0, Overflow or whatever
在我们的测试中,问题实际上不是报告错误的“直接”或“显式”代码,而是错误发生在其他地方,而VBA凭借其无穷的智慧恰好在一个奇怪的时间以奇怪的方式“报告”错误(事实上,它根本不应该报告某些错误,见下文)

您的包是否包含任何外部可执行文件、dll、加载项等

如果是这样的话,那么这很可能是一个开始

如果不是,则错误实际上可能直接或间接发生在您正在访问的范围内,但不一定发生在当前访问的单元格中

下面是一个通过在VBA中作为加载项访问的DLL创建“Div0”的示例:假设您用另一种语言编写了一些代码,这里是Fortran(我们在所有地方都使用隐式None,并且所有内容都正确声明,等等):

编译为DLL并以通常的方式访问

然后假设您有一些VBA作为:

Function VBAFunc(x) as Variant
:
Call FortDLL(x, U)
:
Dim VarU as Variant
:
VarU = U   ; you can replace this with VarU = 10, or whatever, and will get same result/failure
现在,如果x<0,那么DLL将退出,因为Log10不是为x<0定义的。这将抛出一个Fortran运行时错误,并且取决于您如何设置它,您可以让它抛出一个Div0,一个溢出(例如,在Fortran端,Double的MaxExponent是1024,而在VBA端,它大约是308,这取决于许多事情,等等)

现在,即使QQ与VBA端没有任何关系,当VBA代码执行FortDLL()时,它返回U=10,并且它实际上正确地完成了该部分

但是,DLL会抛出一个Div0(或您希望创建的任何内容)错误,并且该“错误消息”会/可以隐藏在调用FortDLL()的返回中

如果您不使用DLL的etc,则在循环等过程中,您的“范围”或其他地方可能发生类似的情况

我们尚未对Dim as Currency“fix”的工作原理进行明确测试,但我们猜测,由于Currency是一种非常特殊的类型(它实际上是一种至少包含两个字段的结构化类型),“错误消息”可能隐藏在其中一个“字段”中,并且可能与您使用的数字大小无关,以及通过“侥幸”(即一种“幸运的侥幸”)来避免崩溃。你可以通过输入太大的数字来测试这一点,并且需要货币类型的完整机器。如果是“幸运的侥幸”,然后有一天,当你不在身边,其他人正在使用你的代码,他们输入一个需要完整货币机器的数字,那么它很可能会崩溃,没有人会知道原因

这里是一个替代测试,假设您在VarX=10这样的直线上发生碰撞,然后按如下所示进行更换/修改:

        Dim startRow As Integer, endRow As Integer, VATRMB As Single, VATEUR As Single, VATUSD As Single, VATRMBCell As Range, VATEURCell As Range, VATUSDCell As Range
:
On Error Resume Next
VarX = 10
VarX = 10
:
…如果这“起作用”(即消除了错误/崩溃),那么您的问题很可能与上面解释的相同(无论是“外部”还是“内部”)。在这种情况下,基本上,“Div0问题”在第一次分配VarX时被视为VBA错误,因为设置了错误陷阱,“第一次”捕获并忽略“DLL端错误”,然后继续

…显然,这只是一个测试,而不是解决方案


这也可能是Excel/Win/Compiler(尤其是对于GCC,编译器版本也是如此,因为它们有时会有一些非常古怪的事情/更改)依赖性,因此再现性和准确行为可能会有所不同。

你能分享你用来调暗变量的准确行吗?有时人们会在该区域出错,不会调暗到他们认为调暗到的程度。你能举一个例子说明你的工作表中的I列中包含了哪些值吗?我在在Excel03和Excel13中进行计算!@matzone,不,它不能!@ChrisSpicer我将其添加到原始消息中,用整行替换上一部分。@AKDADEVIL第I列包含该行项目的单位成本,本质上是一个浮点数。