我正在为我的团队创建一个小工具来对订单项进行重新定价。我基本上已经完成了所有工作,并认为为他们保存数据摘要以及为他们删除更多的手动工作会很好。
我对 VBA 还很陌生,我仍然使用宏作为拐杖来启动我的代码,然后从那里进行编辑。我发现此时在 VBA 中创建数据透视表超出了我的能力范围,因此只能在宏中创建基本的 SUMIF 和 COUNTIF 公式。它适用于有限的 我有行/列计数,但我希望它是动态的,特别是每个公式引用中的行计数。 列标题始终是静态的,但行会根据我们需要重新评估的发货量而变化。我知道我可以将单元格引用设置为一些非常高的数字,但我担心这会影响性能(如果不会,请告诉我,我会很乐意这样做)。
这就是我现在拥有的。我用于宏的数据集只有 64 行,这将在 SUMIF 和 COUNTIF 公式中得到证明。最后一点:标题为“列总计”的部分可以单独保留,该部分将是静态的,因为它实际上是摘要的输出,并且将
始终位于这些单元格中。
Sub TestTable()
'
' TestTable Macro
'
' Keyboard Shortcut: Ctrl+t
'Summary Sheet
'Naming Summary Columns
Worksheets("Summary").Select
Range("B3").Select
ActiveCell.FormulaR1C1 = "Mail Class"
Range("C3").Select
ActiveCell.FormulaR1C1 = "Count of Postage"
Range("D3").Select
ActiveCell.FormulaR1C1 = "Sum of Postage"
Range("E3").Select
ActiveCell.FormulaR1C1 = "Sum of Rerate"
Range("F3").Select
ActiveCell.FormulaR1C1 = "Sum of Difference"
'List unique Mail Classes
Worksheets("Summary").Select
Range("B4").Select
ActiveCell.FormulaR1C1 = _
"Ground Advantage"
Range("B5").Select
ActiveCell.FormulaR1C1 = _
"Priority"
'Count Unique Mail Classes
Range("C4").Select
ActiveCell.FormulaR1C1 = _
"=COUNTIF('Test Sheet'!R3C1:R64C1,""Ground Advantage"")"
Range("C5").Select
ActiveCell.FormulaR1C1 = "=COUNTIF('Test Sheet'!R3C1:R64C1,""Priority"")"
Range("C3").Select
' Sum of Postage
Range("D4").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF('Test Sheet'!R3C1:R64C1,""Ground Advantage"",'Test Sheet'!R3C4:R64C4)"
Range("D5").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF('Test Sheet'!R3C1:R64C1,""Priority"",'Test Sheet'!R3C4:R64C4)"
'Sum of Rerate
Range("E4").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF('Test Sheet'!R3C1:R64C1,""Ground Advantage"",'Test Sheet'!R3C5:R64C5)"
Range("E5").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF('Test Sheet'!R3C1:R64C1,""Priority"",'Test Sheet'!R3C5:R64C5)"
'Sum of Difference
Range("F4").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF('Test Sheet'!R3C1:R64C1,""Ground Advantage"",'Test Sheet'!R3C6:R64C6)"
Range("F5").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF('Test Sheet'!R3C1:R64C1,""Priority"",'Test Sheet'!R3C6:R64C6)"
'Column Totals
Range("C6").Select
ActiveCell.FormulaR1C1 = _
"=SUM('Summary'!R4C3:R5C3)"
Range("D6").Select
ActiveCell.FormulaR1C1 = _
"=SUM('Summary'!R4C4:R5C4)"
Range("E6").Select
ActiveCell.FormulaR1C1 = _
"=SUM('Summary'!R4C5:R5C5)"
Range("F6").Select
ActiveCell.FormulaR1C1 = _
"=SUM('Summary'!R4C6:R5C6)"
Range("G6").Select
ActiveCell.FormulaR1C1 = _
"Grand Total"
'Formatting Cells and Data type
Cells.Select
Cells.EntireColumn.AutoFit
Range("D4:F6").Select
Selection.Style = "Currency"
Range("C3").Select
End Sub
如果有更好的方法以更干净、动态的方式完成我正在做的事情,我愿意倾听。我一直在阅读 VBA 文档,但由于我的经验有限,我不确定什么可以真正做到这一点。
Range("B3").Select
ActiveCell.FormulaR1C1 = "Mail Class"
写
Range("B3").FormulaR1C1 = "Mail Class"
至于使范围动态化,有很多选择。这里有一些:桌子
将测试表上的数据制成表格。选择数据并按 Ctrl+T 或功能区上的“插入 - 表格”。然后这些行
Range("C4").Select
ActiveCell.FormulaR1C1 = _
"=COUNTIF('Test Sheet'!R3C1:R64C1,""Ground Advantage"")"
假设您将表命名为 tblTest 并且第一列的标题为“类型”,则新公式为
Range("C4").FormulaR1C1 = "=COUNTIF(tblTest[Type],""Ground Advantage"")"
当您在表中添加或删除行时,此引用(称为结构化表引用)始终指向整个表。
既然您将地面优势标签放在 B4 中,那么该公式可能应该是
Range("C4").FormulaR1C1 = "=COUNTIF(tblTest[Type],B4)"
从最后一行开始,使用 .End 方法向上移动,直到到达包含内容的最后一行。
Dim lLastRow As Long
lLastRow = Sheets("Test sheet").Range("A1048576").End(xlUp).Row
Range("C4").FormulaR1C1 = "=COUNTIF('Test Sheet'!R3C1:R" & lLastRow & "C1,B4)"
由于公式只是一个字符串,您可以插入找到的最后一行来代替硬编码的 64。已用范围
工作表有一个UsedRange属性。您可以使用 Intersect 方法将列限制为仅使用的范围部分。当您添加和删除行时,UsedRange 可能会有点不正常。但它永远不会太小,只会太大。由于您只是出于性能原因限制这一点,所以这不会成为问题。
Dim rRange As Range
Dim sh As Worksheet
Set sh = Sheets("Test Sheet")
Set rRange = Intersect(sh.Columns(1), sh.UsedRange)
Range("C4").FormulaR1C1 = "=COUNTIF('Test Sheet'!" & rRange.Address(, , xlR1C1) & ",B4)"
如果工作表的UsedRange是A1:K256,那么Intersect命令将返回A1:A256。然后我使用 Address 属性和选项 xlR1C1 参数来构建作为公式的字符串。
在相交中使用整列有点快捷。如果您确实需要从第 3 行开始,您可以将其更改为
Set rRange = Intersect(sh.Range("A3:A1048576"), sh.UsedRange)