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

时间:2017-09-07 02:38:24

标签: excel vba excel-vba

以前我创建了一个Excel工作表,它从主表中获取数据并执行Index&根据第一列中键入的内容匹配所选列的公式。

我想出的代码是:

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列中的所有值。

目前我正在尝试修改它,以便数据只会根据我选择的行进行更改。例如,如果我只更改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

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

2 个答案:

答案 0 :(得分:1)

假设您一次只更改一个单元格,则更改相当简单 - 使用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))"

如果您希望清除B列和B列中的细胞。 C清除A列中的单元格时,只需添加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

答案 1 :(得分:0)

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

请注意,我已经从将公式插入到工作表,到在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.代替WorksheetFunction.来访问工作表函数。这与Variant类型变量的使用相结合,允许我们捕获匹配失败时发生的错误。