【发布时间】:2018-08-03 09:31:47
【问题描述】:
大家早上好,
vba 将公式转换为 excel 时遇到问题:
我有这个代码:
'Tramos para calcular el total, mañana, tarde y noche
TramoIni = Array(4, 20, 36, 4)
TramoFin = Array(51, 35, 51, 19)
'Formulas
FormulaTramo = _
Array("=SUMIFS('Mapa Turnos'!C[4],'Mapa Turnos'!C1,RC1,'Mapa Turnos'!C3,RC2)/30", _
"=R[-1]C*(1-SUM(R[5]C:R[8]C))", _
"=IFERROR(IF(IFERROR((R[13]C*R[-1]C*1800)/R[3]C,0)/R[2]C>1,1," _
& "IFERROR((R[13]C*R[-1]C*1800)/R[3]C,0)/R[2]C),0)", _
"=sla(IF(R[-2]C=0,0,IF(R[-2]C<1,1,R[-2]C)),INDIRECT(ADDRESS(MATCH(RC2,Objetivos!C2,0),4," _
& ",,""Objetivos"")),R[1]C,R[2]C)", _
"=IF(AND(R[-7]C>0,R[-11]C=0),""SI"",""NO"")", _
"=1", _
"=1", _
"=SUM(RC1:RC2)", _
"=R[-11]C-R[-2]C", _
"=CallCapacity(R[-12]C,INDIRECT(ADDRESS(MATCH(RC2,Objetivos!C2,0),3," _
& ",,""Objetivos"")),INDIRECT(ADDRESS(MATCH(RC2,Objetivos!C2,0),4,,,""Objetivos"")),R[-8]C)", _
"=IF(R[-1]C>R[-10]C,R[-10]C,R[-1]C)", "=Utilisation(R[-14]C,R[-11]C,R[-10]C)")
LastRow = ws.Range("A100000").End(xlUp).Row
Col = ws.Range("XDF4").End(xlToLeft).Column
ColTotal = ws.Cells.Find("Total").Column
ColF = ColTotal - 1
ColMañana = ws.Cells.Find("Mañana").Column
ColTarde = ws.Cells.Find("Tarde").Column
ColNoche = ws.Cells.Find("Noche").Column
For i = 1 To UBound(KPI)
ws.Range(ws.Cells(4, 1), ws.Cells(LastRow, Col)).AutoFilter Field:=3, Criteria1:=KPI(i)
If KPI(i) <> "5.Pronóstico" And KPI(i) <> "92.Requeridos" Then
With ws.Range(ws.Cells(5, 4), ws.Cells(LastRow, ColF)).SpecialCells(xlCellTypeVisible)
.FormulaR1C1 = "'" & FormulaTramo(i - 1)
End With
End If
For x = 0 To UBound(TramoIni)
'Formulas total, mañana, tarde y noche
FormulaTotal = _
Array("=SUM(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ")/2", _
"=SUM(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ")/2", _
"=IFERROR(IF(SUMPRODUCT(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ",R[2]C" & TramoIni(x) & _
":R[2]C" & TramoFin(x) & ")/R[2]C>1,1,SUMPRODUCT(RC" & TramoIni(x) & _
":RC" & TramoFin(x) & ",R[2]C" & TramoIni(x) & ":R[2]C" & TramoFin(x) & ")/R[2]C),0)", _
"=IFERROR(SUMPRODUCT(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ",R[1]C" & TramoIni(x) & _
":R[1]C" & TramoFin(x) & ")/R[1]C,0)", _
"=SUM(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ")", _
"=SUM(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ")/2", _
"=IF(COUNTIF(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ",""SI"")>0,""SI"",""NO"")", _
"=IFERROR(SUM(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ")/2,0)", _
"=SUM(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ")", _
"=IF(R[-2]C>R[-10]C,R[-10]C,R[-2]C)", _
"=IFERROR(IF(SUMPRODUCT(RC" & TramoIni(x) & ":RC" & TramoFin(x) & ",R[-14]C" & _
TramoIni(x) & ":R[-14]C" & TramoFin(x) & ")/R[-14]C>1,1,SUMPRODUCT(RC" & _
TramoIni(x) & ":RC" & TramoFin(x) & ",R[-14]C" & TramoIni(x) & ":R[-14]C" & _
TramoFin(x) & ")/R[-14]C),0)")
With ws.Range(ws.Cells(5, TramoFin(0) + x + 1), ws.Cells(LastRow, TramoFin(0) + x + 1)). _
SpecialCells(xlCellTypeVisible)
.FormulaR1C1 = "'" & FormulaTotal(i - 1)
End With
Next x
Next i
ws.Rows(4).AutoFilter
x = ws.Range("A100000").End(xlUp).Row
i = ws.Range("XDF4").End(xlToLeft).Column
ws.Range(ws.Cells(5, 4), ws.Cells(x, i)).Value = ws.Range(ws.Cells(5, 4), ws.Cells(x, i)).Value
这只是一些包含公式的数组和它们应该开始取值的列。
问题是 if、countif 和 sum 在转到 excel 时没有获取单元格引用:
正如您在上面看到的,每个公式都有相同的单元格引用,即 vba 所拥有的那个。
但是稍后我们将其转换为excel时(最后一行代码):
如您所见 sumproducts 运行良好,但其余部分实际上是 RC 列和应该是 VBA 上的列引用的行。
有什么想法可以做到这一点吗?我需要这样工作,因为这个工作表最多可以有 7k 行和 50 多列,其中有 80% 的公式,所以在每个循环中引入公式需要很长时间,而不是我这样做,所以他们都在重新计算同时。
这种方式仍然需要很长时间来计算,我不知道是否有更有效的方式来输入这么多公式,其中包括 erlangs 和自定义函数。
任何帮助将不胜感激!谢谢!
【问题讨论】:
-
这是一些非常可怕的代码。即使不是不可能,也很难遵循。请查看如何创建 minimal reproducible example 并尝试减少代码以便仅包含导致问题的部分。
-
您好 @Srijan 在使用 VBA 引用时:R[2]C 表示从您所在的同一列向下 2 行,R2C 表示第 2 行和您所在的列。“[] " 用于偏移量,我需要获取 RC20:RC35 表示这一行,第 20 列到此行第 35 列,如果使用 [],则表示此行距此处 20 列,此行距此处 35 列。
-
请注意,该术语是相对单元格引用,而不是“VBA 引用”。 (A1 单元格符号在 VBA 中也可以正常工作。)
-
如果问题是单元格符号样式变得混乱,那么您应该*切换到
R1C1或A1符号;工作表和代码,而不是来回走动。他们不能很好地合作。您可以通过启用File>Options>Formulas>"R1C1 Reference Style"中的设置中的复选框来单独使用 R1C1 -
尝试将左侧最后一行的
.Value更改为.FormulaR1C1。 因为每次宏插入公式时计算时间太长,宏会在公式前写一个 ',所以它是文本而不是公式 - 更好的处理方法是禁用自动计算。