将公式添加到单元格的VBA

我正在尝试写一些VBA,将标题文本添加到3个单元格,然后填充公式一直到最后一行。 我已经写了下面,它写入标题没有问题,但是当它到达我的第一个.Formula它抛出一个

应用程序定义或对象定义的错误

什么需要改变,以便这个macros将成功执行? (公式直接从单元格中的公式中获得,所以我知道它们至less在“前端”是有效的公式)

 Function Gre() Range("E2").Select ActiveCell.FormulaR1C1 = "Under" Range("F2").Select ActiveCell.FormulaR1C1 = "Over" Range("G2").Select ActiveCell.FormulaR1C1 = "Result" With Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row) .Formula = "=IF(C2<B2,B2-C2,"")" End With With Range("F2:F" & Cells(Rows.Count, "C").End(xlUp).Row) .Formula = "=IF(C2>B2,C2-B2,0)" End With With Range("G2:G" & Cells(Rows.Count, "C").End(xlUp).Row) .Formula = "=IF(F2>0,'Issue',"")" End With End Function 

这个问题很可能是你用公式逃避了引号。

你需要的是:

 .Formula = "=IF(C2>B2,B2-C2,"""")" 

例如第一个。 其他引号也需要翻倍。

作为一个侧面说明,最好还是指定你正在使用的工作表:

  Dim ws as worksheet Set ws = Sheets("mySheet") ws.Range("E2").FormulaR1C1 = "Under" 

等等

如果你不这样做,你有时会在运行代码时发生错误。

  1. 正如OpiesDad所build议的那样,为了尽量减less歧义,请避免使用ActiveCell等。
  2. 与直接分配给单元格相比,使用“ Select也会降低性能。
  3. 我敢肯定,你需要通过加倍报价,在VBA中的Excel公式中的引号转义,所以一个正常的空string变成"""" 。 你也有一个公式中的单引号的Issue ,我很确定会在Excel中的错误; 这也应该在双引号中。
  4. 我很难弄清楚Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row)实际上是做了什么,但是听起来好像你想要selectE2最后使用的表单行。 避免Rows.Count或只是泛指一张表的行,因为这将行10 ^ 31。 使用Worksheet.UsedRange从内容的第一行和第一列到内容的最后一行和第一列。 这也包括空string,有时可能有点棘手,但通常比处理数以千计的额外行更好。

也,

  1. 如果只包含一个语句,则不需要使用With ,尽pipe它不会导致任何问题。

  2. 除非你有理由,否则我不会混合使用Range.FormulaRange.FormulaR1C1

     Function Gre() Dim ws as Worksheet Set ws = ActiveSheet Dim used as Range Set used = ws.UsedRange Dim lastRow as Integer lastRow = used.Row + used.Rows.Count - 1 ws.Range("E2").Formula = "Under" ws.Range("F2").Formula = "Over" ws.Range("G2").Formula = "Result" ws.Range("E2:E" & lastRow).Formula = "IF(C2<B2, C2-B2, """")" ws.Range("F2:F" & lastRow).Formula = "IF(C2<B2, C2-B2, 0)" ws.Range("G2:G" & lastRow).Formula = "IF(F2>0, ""Issue"", """")" End Function 
  1. 第一个问题是select细胞。 这要求macrosselect单元,然后确定单元地址。 如果您需要实际select一个单元格,请使用Application.ScreenUpdating = False 。 然后macros不必显示单元格的光标select。 在下面的公式分配代码行中删除select和合并范围将获得一些速度/效率。

    Range("E2").FormulaR1C1 = "Under"

  2. Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row)是select空白列(行1048576)中最后一个单元格的代码版本,然后使用Ctrl键和确定最低/最后使用的单元格的向上键。 由于列是空白的,所以每次都会得到1的行数。 既然你在找最后一行 倒数倒数可能会更快。 我最喜欢的方法是一个循环。 在循环内增加一个variables,同时查找最后一行。 然后,variables可以用来代替你的自下而上的策略。

     t = 0 Do Until Range("C2").Offset(t, 0).Value = "" t = t + 1 Loop With Range("E2:E" & t) .Formula = "=IF(C2<B2,B2-C2,"""")" End With` 
  3. 就像TSQL一样,引号字符也需要自己的引用字符。

     .Formula = "=IF(C2<B2,B2-C2,"""")" 
  4. 在这种情况下,可以使用范围Fillup VBA函数来从底部填充所有单元格,并使用公式公式计算Excel公式参考相对性。 下面的代码从循环计数器的范围开始。 接下来,我们设置一个variables等于Excel中的总行数减去对应于计数器行的行。 然后,我们通过必要的行调整原始区域的大小,并使用FillDown函数向下复制第一个公式。
  5. 这是最终的代码。 这将填充从Excel最后一行开始的范围。

      Sub Gre() Range("E2").FormulaR1C1 = "Under" Range("F2").FormulaR1C1 = "Over" Range("G2").FormulaR1C1 = "Result" Do While Range("e2").Offset(t, 0).Value <> "" t = t + 1 Loop Range("E2").Offset(t, 0).Formula = "=IF(C2<B2,B2-C2,"""")" r1 = Range("e2").EntireColumn.Rows.Count r2 = Range("E2").Offset(t, 0).Row Range("E2").Offset(t, 0).Resize(r1 - r2, 1).FillDown Range("F2").Offset(t, 0).Formula = "=IF(C2>B2,C2-B2,0)" Range("F2").Offset(t, 0).Resize(r1 - r2, 1).FillDown Range("G2").Offset(t, 0).Formula = "=IF(F2>0,""Issue"","""")" Range("G2").Offset(t, 0).Resize(r1 - r2, 1).FillDown End Sub 

除了使用双引号之外,您可能需要在前两个公式中使用0,否则可能会计算为空string。 这可能会给最后一个公式带来意想不到的结果,即不正确地返回“问题”。

如果您的数据和3个新列之间没有空白列,则可以使用CurrentRegion来确定行数:

 Range("E2:E" & Cells.CurrentRegion.Rows.Count).Formula = "=if(C2'<'B2,B2-C2,0)" Range("F2:F" & Cells.CurrentRegion.Rows.Count).Formula = "=if(C2>B2,C2-B2,0)" Range("G2:G" & Cells.CurrentRegion.Rows.Count).Formula = if(F2>0,""Issue"","""")"