以前我创建了一个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
如果范围是表格,我将如何在函数中编码?
答案 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类型变量的使用相结合,允许我们捕获匹配失败时发生的错误。