excel - VBA将公式插入表格非常慢
问题描述
我有一个打开的工作簿,将使用过的单元格变成一个表格,然后将不同的公式注入每一列。我正在注入公式以通过预先将公式向下拖动到比需要的更远的位置来节省文件大小。我必须这样做的 VBA 工作正常,但速度非常慢。我已经运行了性能检查,可以确认缓慢是由公式注入引起的(每秒只能注入 141 行)。我已经完成了基本的计算/屏幕更新相关的优化。还可以做些什么来加快以下代码的速度?(注意我已简化为代码的相关部分):
Sub OptimizeVBA(isOn As Boolean)
Application.Calculation = IIf(isOn, xlCalculationManual, xlCalculationAutomatic)
Application.EnableEvents = Not(isOn)
Application.ScreenUpdating = Not(isOn)
' ActiveSheet.DisplayPageBreaks = Not(isOn)
End Sub
Private Sub Workbook_Open()
OptimizeVBA True
Dim ws As Worksheet
Set ws = Worksheets("Book1")
Dim tbl As ListObject
Set tbl = ws.ListObjects("Table1")
tbl.ListColumns("Dollar Share ").DataBodyRange.Formula = "=IFERROR(([@[Dollar Share ]] - MEDIAN([[Dollar Share ]])) / STDEV.P([[Dollar Share ]]), """")"
tbl.ListColumns("Unit Share ").DataBodyRange.Formula = "=IFERROR(([@[Unit Share ]] - MEDIAN([[Unit Share ]])) / STDEV.P([[Unit Share ]]), """")"
tbl.ListColumns("Units PSPW ").DataBodyRange.Formula = "=IFERROR(([@[Units PSPW ]] - MEDIAN([[Units PSPW ]])) / STDEV.P([[Units PSPW ]]), """")"
tbl.ListColumns("Dollar Growth ").DataBodyRange.Formula = "=IFERROR(IF(OR([@[Dollar Growth ]] = """", [@[Dollars, Yago]] < New_Item_Floor), """", ([@[Dollar Growth ]] - MEDIAN([[Dollar Growth ]])) / STDEV.P([[Dollar Growth ]])), """")"
tbl.ListColumns("Unit Growth ").DataBodyRange.Formula = "=IFERROR(IF(OR([@[Unit Growth ]] = """", [@[Dollars, Yago]] < New_Item_Floor), """", ([@[Unit Growth ]] - MEDIAN([[Unit Growth ]])) / STDEV.P([[Unit Growth ]])), """")"
tbl.ListColumns("Comp Avg % ACV ").DataBodyRange.Formula = "=IFERROR(([@[Comp Avg % ACV ]] - MEDIAN([[Comp Avg % ACV ]])) / STDEV.P([[Comp Avg % ACV ]]), """")"
OptimizeVBA False
End Sub
我知道与 Excel 对象的选择/其他交互很昂贵,但鉴于上述公式不同,我无法找到一种简单的方法来减少每列的单独交互。
笔记:
- 实际上有比上面显示的更多的注入,具有大致相等的字符串长度的不同公式。
- 平均
tbl
会有 16k 行。
在此先感谢您的帮助!
解决方案
我将在这里为您提供我的测试,因为这是太多的注释代码。
我更改了您的代码以直接粘贴公式。我测试为字符串(由于缺少您的表格设置),它基本上是即时的。所以肯定有一些与桌子有关的恶作剧发生。请在你的桌子上试试。您只需要根据需要调整范围/工作表:
Private Sub Workbook_Open()
OptimizeVBA True
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Range("A2:A200000").Formula = "=IFERROR(([@[Dollar Share ]] - MEDIAN([[Dollar Share ]])) / STDEV.P([[Dollar Share ]]), """")"
ws.Range("B2:B200000").Formula = "=IFERROR(([@[Unit Share ]] - MEDIAN([[Unit Share ]])) / STDEV.P([[Unit Share ]]), """")"
ws.Range("C2:C200000").Formula = "=IFERROR(([@[Units PSPW ]] - MEDIAN([[Units PSPW ]])) / STDEV.P([[Units PSPW ]]), """")"
ws.Range("D2:D200000").Formula = "=IFERROR(IF(OR([@[Dollar Growth ]] = """", [@[Dollars, Yago]] < New_Item_Floor), """", ([@[Dollar Growth ]] - MEDIAN([[Dollar Growth ]])) / STDEV.P([[Dollar Growth ]])), """")"
ws.Range("E2:E200000").Formula = "=IFERROR(IF(OR([@[Unit Growth ]] = """", [@[Dollars, Yago]] < New_Item_Floor), """", ([@[Unit Growth ]] - MEDIAN([[Unit Growth ]])) / STDEV.P([[Unit Growth ]])), """")"
ws.Range("F2:F200000").Formula = "=IFERROR(([@[Comp Avg % ACV ]] - MEDIAN([[Comp Avg % ACV ]])) / STDEV.P([[Comp Avg % ACV ]]), """")"
OptimizeVBA False
End Sub
您的评论问题:如何使用自动填充来完成此类任务:
Sub autof()
Cells(1, 1).Value = 1
Cells(1, 2).Value = 2
Range(Cells(1, 1), Cells(1, 2)).AutoFill Range(Cells(1, 1), Cells(10, 2)), xlFillCopy
End Sub
推荐阅读
- android - Android 的 /data/system/packages.xml 证书数据
- kubernetes - 将 kustomize 用于手动 CD 与 tekton 自动 CI/CD
- python - 如何在文本文件中添加函数
- c# - C# WPF 绑定到 ObjectDataProvider 的方法
- java - 如何将一个 Apache HTTP 服务器与运行在同一 linux 服务器上的两个 apache tomcat 实例连接起来
- r - R数据框由df.x中的多列合并
- robotframework - 机器人框架在失败中停止拆卸执行
- c# - ASP.NET Core 3.0:禁用 ASP0000 不要在“ConfigureServices”中调用“IServiceCollection.BuildServiceProvider”
- javascript - 每小时50分钟刷新页面的JS代码
- c++ - 内存模型,负载获取语义实际上是如何工作的?