【发布时间】:2018-08-21 20:56:26
【问题描述】:
我有循环遍历用户选择范围的第 5 列的代码,如果第 5 列中的当前单元格符合条件,则将同一行中的下 10 个单元格添加到范围中。在所有内容的末尾,如果单元格 A1 为空,它将对单元格 A1 中的最终范围求和。
Sub SumItems()
Dim selectedRange As Range
Set selectedRange = Selection
Dim sumRange As Range
Dim i As Long
For i = 1 To selectedRange.Rows.Count
If selectedRange(i, 5) = "Yes" Then
If sumRange Is Nothing Then
Set sumRange = Range(selectedRange(i, 5).Offset(0, 1), selectedRange(i, 5).Offset(0, 10))
Else
Set sumRange = Union(sumRange, Range(selectedRange(i, 5).Offset(0, 1), selectedRange(i, 5).Offset(0, 10)))
End If
End If
Next i
If Not sumRange Is Nothing Then
If IsEmpty(Range("A1")) Then
Range("A1").Formula = "=SUM(" + sumRange.Address(False, False) + ")"
Else
MsgBox "Cannot paste in cell A1, it is not empty."
Exit Sub
End If
Else
MsgBox "No matching rows were found."
Exit Sub
End If
End Sub
我运行它的床单很长。所以 sumRange 通常是工作表中许多不同区域的联合。我注意到一旦 sumRange.Areas.Count 超过 18,我就会遇到 Range("A1").Formula 语句的问题。 sumRange.Address(False, False) 字符串在第 18 个区域后被截断。我相信这是因为 .Address 字符串长度太长,刚好与这张表的 18 个区域重合。
我开发了一个临时解决方案,但它限制了子例程可以处理的区域数量,并且笨重且冗长。如果 sumRange 有超过 18 个区域,我设置了临时范围变量以将其拆分为,并且 IF 语句现在读取如下内容:
If Not sumRange Is Nothing Then
If IsEmpty(Range("A1")) Then
If sumRange.Areas.Count > 18 Then
Dim k As Long
Dim tmpSumRange1 As Range
Dim tmpSumRange2 As Range
Dim tmpSumRange3 As Range
' And so on...
For k = 1 To sumRange.Areas.Count
If k <= 18 Then
If tmpSumRange1 Is Nothing Then
Set tmpSumRange1 = sumRange.Areas(k)
Else
Set tmpSumRange1 = Union(tmpSumRange1, sumRange.Areas(k))
End If
ElseIf k > 18 And k <= 36 Then
If tmpSumRange2 Is Nothing Then
Set tmpSumRange2 = sumRange.Areas(k)
Else
Set tmpSumRange2 = Union(tmpSumRange2, sumRange.Areas(k))
End If
ElseIf k > 36 And k <= 54 Then
If tmpSumRange3 Is Nothing Then
Set tmpSumRange3 = sumRange.Areas(k)
Else
Set tmpSumRange3 = Union(tmpSumRange3, sumRange.Areas(k))
End If
ElseIf
' And so on until I get to k = 180...
End If
Next k
If Not tmpSumRange1 Is Nothing And tmpSumRange2 Is Nothing And tmpSumRange3 Is Nothing Then
Range("A1").Formula = "=SUM(" + tmpSumRange1.Address(False, False) + ")"
ElseIf Not tmpSumRange1 Is Nothing And Not tmpSumRange2 Is Nothing And tmpSumRange3 Is Nothing Then
Range("A1").Formula = "=SUM(" + tmpSumRange1.Address(False, False) + "," + tmpSumRange2.Address(False, False) + ")"
ElseIf Not tmpSumRange1 Is Nothing And tmpSumRange2 Is Nothing And Not tmpSumRange3 Is Nothing Then
Range("A1").Formula = "=SUM(" + tmpSumRange1.Address(False, False) + "," + tmpSumRange2.Address(False, False) + "," + tmpSumRange3.Address(False, False) + ")"
ElseIf
' And so on all the way up to tmpSumRange10...
End If
Else
Range("A1").Formula = "=SUM(" + sumRange.Address(False, False) + ")"
End If
Else
MsgBox "Cannot paste in cell A1, it is not empty."
Exit Sub
End If
Else
MsgBox "No matching rows were found."
Exit Sub
End If
我知道肯定有比这更好的解决方案。我在搜索中没有找到任何东西。我也没有找到遇到同样问题的人。我需要 A1 单元格中包含 SUM 公式以及其中的范围,否则我只需对子例程中的值求和并插入值而不是公式。
【问题讨论】:
-
你能举例说明这些地址是什么样的吗?因为我认为限制不是由区域数量强加的,而是由地址的字符串长度强加的。如果是这样,我很确定这里还有其他相关的解决方案来处理“非常长”的公式评估。
-
我认为你在正确的轨道上。但是,不要硬编码三个临时变量,而是将其作为表示范围的集合或数组来执行,并且您应该始终检查 255 个字符的限制,而不是区域的大小,这样它就更灵活,更不容易出错如果工作表/工作簿的结构发生变化。
-
啊,当我这样做时,它抱怨太多争论。我刚刚查了一下,Excel 函数的最大参数限制为 255 个(嗯,这个数字似乎很熟悉)。所以看起来我将不得不检查有多少参数和错误,如果它大于 255?
-
取决于您想要使用它的复杂程度。当然,您可以在工作表中添加一堆
Names,每个都可以由 255 个单独的范围定义。但我认为一般来说,如果你遇到这个问题,考虑彻底检查你的应用程序是个好主意。你不应该(通常)处理复杂的公式,如果你是,也许你只需要在 VBA 中进行评估,并从工作表上的按钮/等处按需获取它,而不是公式。 -
感谢您的所有帮助,大卫。我很感激。主要的是我需要公式可以粘贴到其他纸张上并可以重复使用。我现在正在经历绝对最坏的情况,所以我怀疑我是否会有一个包含 255 个参数的公式。很高兴知道它的局限性,所以我会弄清楚如何检查我提供的公式的参数数量,如果它有太多错误就会出错。
标签: excel vba subroutine