如何告诉macros在特定行上执行代码?

以前,我创build了一个Excel工作表,它从主表中获取数据,并根据第一列中键入的内容在选定列上执行索引与匹配公式。

我想到的代码是:

Private Sub Worksheet_Change(ByVal Target As Range) If Not Intersect(Target, Range("a4:a9999")) Is Nothing Then With Me.Range("b4:b9999") .Formula = "=IF(ISNA(INDEX(MasterEntry,MATCH(A4,table[Project No],FALSE),2)),"""",INDEX(MasterEntry,MATCH(A4,table[Project No],FALSE),2))" .Value = .Value End With With Me.Range("c4:c9999") .Formula = "=IF(ISNA(INDEX(MasterEntry,MATCH(A4,table[Project No],FALSE),3)),"""",INDEX(MasterEntry,MATCH(A4,table[Project No],FALSE),3))" .Value = .Value End With End If End Sub 

工作原理是当第一列检测到a4到a9999范围内的任何更改时,它将根据范围更改b和c列中的所有值。

目前我正在尝试修改它,以便数据只会根据我select的行进行更改。 例如,如果我只改变了A5中的数据,我希望B5和C5只执行代码,其他代码保持不变。

是否可以使用worksheet_change来执行此操作,还是需要另一种方法?

作为这个问题的延伸,如果我想让同一个函数在表中工作,会发生什么? 用于表格版本的代码是这样的:

 Private Sub worksheet_change(ByVal target As Range) If Not Intersect(target, Me.ListObjects("ProjectEntry").ListColumns("Asset No").DataBodyRange) Is Nothing Then With Me.Range("ProjectEntry[Description]") .Formula = "=IF(ISNA(INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),2)),"""",INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),2))" .Value = .Value End With With Me.Range("ProjectEntry[Preventive Stroke]") .Formula = "=IF(ISNA(INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),3)),"""",INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),3))" .Value = .Value End With End If End Sub 

如果范围是一个表,我将如何在函数中编码?

假设您一次只更改一个单元格,更改相当简单 – 使用Target指定要更改的内容:

 Private Sub Worksheet_Change(ByVal Target As Range) If Not Intersect(Target, Range("a4:a9999")) Is Nothing Then With Target.Offset(0, 1) .FormulaR1C1 = "=IF(ISNA(INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),2)),"""",INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),2))" .Value = .Value End With With Target.Offset(0, 2) .FormulaR1C1 = "=IF(ISNA(INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),3)),"""",INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),3))" .Value = .Value End With End If End Sub 

在指定公式时,我更改了代码以使用R1C1表示法,因为我发现在这种情况下更容易阅读。 例如,在A1表示法中,您需要使用B列中的公式

  .Formula = "=IF(ISNA(INDEX(MasterEntry,MATCH(A" & Target.Row & ",table[Project No],FALSE),2)),"""",INDEX(MasterEntry,MATCH(A" & Target.Row & ",table[Project No],FALSE),2))" 

如果您希望清除A列中的单元格时B和C列中的单元格,只需添加一个If语句:

 Private Sub Worksheet_Change(ByVal Target As Range) If Not Intersect(Target, Range("a4:a9999")) Is Nothing Then If IsEmpty(Target.Value) Then 'Clear column B and C if column A is empty Target.Offset(0, 1).Resize(1, 2).Clear Else With Target.Offset(0, 1) .FormulaR1C1 = "=IF(ISNA(INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),2)),"""",INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),2))" .Value = .Value End With With Target.Offset(0, 2) .FormulaR1C1 = "=IF(ISNA(INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),3)),"""",INDEX(MasterEntry,MATCH(RC1,table[Project No],FALSE),3))" .Value = .Value End With End If End If End Sub 

回答问题的第二部分,以下代码显示如何仅更新表格的编辑行。

请注意,我已经从插入公式到工作表中更改为在VBA中进行计算并将值插入到工作表中:

 Private Sub Worksheet_Change(ByVal Target As Range) If Intersect(Target, Me.Range("ProjectEntry[Asset No]")) Is Nothing Then Exit Sub Dim Ä As Excel.Application: Set Ä = Excel.Application Dim varMatchRowNum As Variant Dim varValue As Variant varMatchRowNum = Ä.Match(Target.Value2, Ä.Range("DieMaster[Asset No]"), 0) With Ä.Range("DieMaster").ListObject.ListColumns varValue = Ä.Index(.Item(2).DataBodyRange, varMatchRowNum) Me.Range("ProjectEntry[Description]").EntireColumn.Cells(Target.Row).Value _ = IIf(IsError(varValue), vbNullString, varValue) varValue = Ä.Index(.Item(3).DataBodyRange, varMatchRowNum) Me.Range("ProjectEntry[Preventive Stroke]").EntireColumn.Cells(Target.Row).Value _ = IIf(IsError(varValue), vbNullString, varValue) End With End Sub 

请注意Application.的用法Application. 而不是WorksheetFunction. 访问工作表函数。 这与Varianttypesvariables的使用结合使用,可以捕获匹配失败时发生的错误。