【问题标题】:VBA won't translate vba reference into excel referenceVBA 不会将 vba 参考转换为 excel 参考
【发布时间】: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 中也可以正常工作。)
  • 如果问题是单元格符号样式变得混乱,那么您应该*切换到R1C1A1 符号;工作表和代码,而不是来回走动。他们不能很好地合作。您可以通过启用 File&gt;Options&gt;Formulas&gt;"R1C1 Reference Style" 中的设置中的复选框来单独使用 R1C1
  • 尝试将左侧最后一行的.Value 更改为.FormulaR1C1因为每次宏插入公式时计算时间太长,宏会在公式前写一个 ',所以它是文本而不是公式 - 更好的处理方法是禁用自动计算。

标签: vba excel


【解决方案1】:

问题的MCVE:

Range("A1").FormulaR1C1 = "'" & "=SUM(RC20:RC25)"
Range("A1").Value = Range("A1").Value

RC 符号中的公式分配给Value 属性。 Excel 尝试识别公式类型。这个公式中只有绝对引用,所以它看起来像有效的 A1 表示法相对公式。

一些包含相对引用(带方括号)的公式被正确识别为 RC 表示法 - 因为那些不是有效的 A1 公式。

为了解决这个问题,需要将带有公式的数组分配给FormulaR1C1属性:

ws.Range(ws.Cells(5, 4), ws.Cells(x, i)).FormulaR1C1 = ws.Range(ws.Cells(5, 4), ws.Cells(x, i)).Value

在代码执行期间避免长时间计算的更好方法是禁用自动计算:

Application.Calculation = xlCalculationManual
'all code here
Application.Calculation = xlCalculationAutomatic

【讨论】:

  • 谢谢!结果很好。 PS:在我所有的宏运行之前,这个宏首先运行: Sub AhorroMemoria() Application.ScreenUpdating = False Application.EnableEvents = False Application.DisplayAlerts = False Application.Calculation = xlCalculationManual End Sub 仍然如此缓慢,我想是因为excel 必须进行大量的计算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多