需要改进低效的宏(公式计算慢和查找/替换慢)

huangapple go评论86阅读模式
英文:

Need to improve inefficient macro (Slow formula calculations and find/replace)

问题

以下是翻译好的部分:

I have two different files with almost identical columns. One of them is much larger than the other (one is about 20k rows, the other about 180k), though, and the macro does not run as well on the larger one. So this has led me to believe my code is inefficient. Specifically, when I step into each line by line, the parts that seem to take the longest are the "find and replace," and the formulaR1C1 additions.

我有两个几乎相同列的不同文件。其中一个文件比另一个文件大得多(一个大约有20,000行,另一个大约有180,000行),但宏在较大的文件上运行效率不高。因此,我认为我的代码效率不高。具体来说,当我逐行调试代码时,似乎花费最长时间的部分是“查找和替换”以及formulaR1C1的添加。

I've read that using arrays can improve efficiency, but I'm having a hard time finding the best way to implement them.

我读过使用数组可以提高效率,但我很难找到最佳实现方法。

Specifically, this portion where I try to remove dollar signs from a string, it seems to take even longer than just using sheet.range.replace(xxx, xx, xx,).

具体来说,在我尝试从字符串中去掉美元符号的这一部分,似乎比只是使用sheet.range.replace(xxx, xx, xx,)花费更长时间。

'Initial code to remove $ from range
'初始代码用于从范围中移除$符号
Dim ws As Worksheet
Dim lrow As Long
lrow = ws.Cells(Rows.Count, 4).End(xlUp).Row
ws.Range("BG:BG, BI:BI").Replace what:="$", Replacement:="", lookat:=xlPart

'Attempt at improving speed
'尝试提高速度
Dim Array1 As Variant
Set Array1 = ws.Range("BG2:BG" & lrow)
For Each cell In Array1
cell.Value = Replace(cell.Value, "$", "")
Next cell
Dim Array2 As Variant
Set Array2 = ws.Range("BI2:BI" & lrow)
For Each cell In Array2
cell.Value = Replace(cell.Value, "$", "")
Next cell

Also wondering if I should work on trying to add several different calculations like below to loop through arrays instead of printing directly to the worksheet. These are just some examples of the formulas used.

还在思考是否应该尝试添加类似以下的多个计算来循环遍历数组,而不是直接打印到工作表。这只是一些使用的公式示例。

ws.Range("B2:B" & lrow).FormulaR1C1 = "=rc[-1]&&""-""&rc[1]"
ws.Range("P2:P" & lrow).FormulaR1C1 = "=rc[1]+rc[2]+rc[3]"
ws.Range("V2:V" & lrow).FormulaR1C1 = "=if(rc[-1]=0,0,rc[-10]/rc[-1])"
ws.Range("AY2:AY" & lrow).FormulaR1C1 = "=rc[-1]*rc[-39]"
wsnetwork.Range("B2:B" & lrow2).FormulaR1C1 = "XLOOKUP(RC[-1],'Base'!C4,'Base'!C11)"
wsnetwork.Range("D2:D" & lrow2).FormulaR1C1 = "if(RC[-2] = 0 , RC[-1] , RC[-2])"
wsnetwork.Range("I2:I" & lrow2).FormulaR1C1 = "iferror(RC[-3] / RC[-1], 0)"

英文:

I have two different files with almost identical columns. One of them is much larger than the other (one is about 20k rows, the other about 180k), though, and the macro does not run as well on the larger one. So this has led me to believe my code is inefficient. Specifically, when I step into each line by line, the parts that seem to take the longest are the "find and replace", and the formulaR1C1 additions.

I've read that using arrays can improve efficiency, but I'm having a hard time finding the best way to implement them.

Specifically, this portion where I try to remove dollar signs from a string, it seems to take even longer than just using sheet.range.replace(xxx, xx, xx,).

'Initial code to remove $ from range  
Dim ws As Worksheet
Dim lrow As Long
lrow = ws.Cells(Rows.Count, 4).End(xlUp).Row
ws.Range("BG:BG, BI:BI").Replace what:="$", Replacement:="", lookat:=xlPart

'Attempt at improving speed
Dim Array1 As Variant
Set Array1 = ws.Range("BG2:BG" & lrow)
    For Each cell In Array1
        cell.value = Replace(cell.value, "$", "")
    Next cell
Dim Array2 As Variant
Set Array2 = ws.Range("BI2:BI" & lrow)
    For Each cell In Array2
        cell.value = Replace(cell.value, "$", "")
    Next cell

Also wondering if I should work on trying to add several different calculations like below to loop through arrays instead of printing directly to the worksheet. These are just some examples of the formulas used.

ws.Range("B2:B" & lrow).FormulaR1C1 = "=rc[-1]&""-""&rc[1]"
ws.Range("P2:P" & lrow).FormulaR1C1 = "=rc[1]+rc[2]+rc[3]"
ws.Range("V2:V" & lrow).FormulaR1C1 = "=if(rc[-1]=0,0,rc[-10]/rc[-1])"
ws.Range("AY2:AY" & lrow).FormulaR1C1 = "=rc[-1]*rc[-39]"
wsnetwork.Range("B2:B" & lrow2).FormulaR1C1 = "=XLOOKUP(RC[-1],'Base'!C4,'Base'!C11)"
wsnetwork.Range("D2:D" & lrow2).FormulaR1C1 = "=if(RC[-2] = 0 , RC[-1] , RC[-2])"
wsnetwork.Range("I2:I" & lrow2).FormulaR1C1 = "=iferror(RC[-3] / RC[-1], 0)"

答案1

得分: 0

为了更高效,你需要将数据读入数组,然后在数组内进行操作,最后将数组填充回区域。就像下面这样:

Dim ws As Worksheet

data = ws.Range("BG1:BG" & ws.UsedRange.Rows.Count).Value

for i = 2 to ubound(data, 1)
    data(i, 1) = Replace(data(i, 1), "$", "")
next i

ws.Range("BG1:BG" & ws.UsedRange.Rows.Count) = data

data = ws.Range("BI1:BI" & ws.UsedRange.Rows.Count).Value

for i = 2 to ubound(data, 1)
    data(i, 1) = Replace(data(i, 1), "$", "")
next i

ws.Range("BI1:BI" & ws.UsedRange.Rows.Count) = data
英文:

To be more efficient, you need to read the data into array, then do things within array, then backfill array into range. Just like below.

Dim ws As Worksheet

data = ws.Range("BG1:BG" & ws.UsedRange.Rows.Count).Value

for i = 2 to ubound(data, 1)
    data(i, 1) = Replace(data(i, 1), "$", "")
next i

ws.Range("BG1:BG" & ws.UsedRange.Rows.Count) = data

data = ws.Range("BI1:BI" & ws.UsedRange.Rows.Count).Value

for i = 2 to ubound(data, 1)
    data(i, 1) = Replace(data(i, 1), "$", "")
next i

ws.Range("BI1:BI" & ws.UsedRange.Rows.Count) = data

huangapple
  • 本文由 发表于 2023年2月24日 05:23:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550446.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定