excel - 如果更新了其中一个工作表中的列,则更新多列

excel - Update multiple columns if a column from one of the worksheet is updated

我有多个 sheet,所有 sheet 中的其中一列包含相同的列(比如 "Names")。在每一列 "Names" 中都有对应的 "Status" 列。每个 "Names" 列可能包含来自一个或多个 sheet 的相同记录。如果 "Status" 列中的一条记录被更新,我想得到它对应的 "Names" 列值,然后搜索所有 sheet s,如果它也有相同的 "Names" 记录,我应该能够根据第一个 "Status" 更新的值更新其相应的 "Status" 值。

现在,我能够从网上搜索有效的答案(见下文),问题是它只能以一种方式起作用。我可以从 sheet(比如 sheet1)更新一个值,它也可以从一个或多个作品 sheet 更新一个值。但是当我尝试更新另一个作品sheet(不是sheet1)的值时,它returns 出现错误Method "Find' of object 'Range' failed

示例(这应该在每个作品中sheet,带有列,sheet 名称已更改):

Private Sub Worksheet_Change(ByVal Target As Range)

If Target.Cells.Count > 1 Then Exit Sub
Dim fn2 As Range

If Not Intersect(Target, Range("B:B")) Is Nothing Then
    Set fn2 = Sheets("Sheet1").Range("D:D").Find(Target.Offset(, -11).Value, , xlValues, xlWhole)
    If Not fn2 Is Nothing Then
        fn2.Offset(, 13) = Target.Value
        MsgBox "A record has been updated name_tab tab"
    End If
End If
End Sub

请帮忙。谢谢

您的代码错误是因为您试图偏移 D 列左侧的 11 列

编辑 在 OP 澄清后:

  • to-be-searched-in sheet 要硬编码的名称,因为找不到通用模式来在所有其他工作中过滤它们sheets

  • NamesStatus 列相应地在每个 [=26 的第 1 行中有 "Names" 和 "Status" headers =]to-be-searched-in工作sheet

edited2 以考虑第一个更新行索引(参见带“****”的行)

将此代码放入 ThisWorkbook 代码窗格:

Option Explicit

Const STATUSHEADER As String = "Status"
Const NAMESHEADER As String = "Names"


Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Dim nameValue As String
    Dim sht As Worksheet
    Dim sheetNames As Variant
    Dim firstUpdatedRowIndex As Long '<--| this will store first updated row index  ****

    If Not Proceed(Target) Then Exit Sub

    sheetNames = Array("Sheet0001", "Sheet0002", "Sheet0003") '<--| fill array with sheets-to-be-searched names

    On Error GoTo EXITSUB
    Application.EnableEvents = False

    nameValue = GetNameValue(Target) '<--| get value in the "Names" column corresponding row
    For Each sht In Worksheets(sheetNames) '<--| loop through to-be-searched-in sheets
        If sht.name <> Sh.name Then UpdateSheet sht, nameValue, Target.value, firstUpdatedRowIndex   '****
    Next sht

EXITSUB:
    Application.EnableEvents = True
End Sub


Sub UpdateSheet(sht As Worksheet, nameValue As String, statusValue As Variant, firstUpdatedRowIndex As Long) '****
    Dim namesCol As Long, statusCol As Long
    Dim f As Range

    With sht '<--| refer to current to-be-searched-in sheet
        With .Rows(1).SpecialCells(XlCellType.xlCellTypeConstants) '<--| refer to its 1st row non blank cells range
            namesCol = FindFirstCell(NAMESHEADER, .Cells).Column '<--| get its "Names" column index
            statusCol = FindFirstCell(STATUSHEADER, .Cells).Column '<--| get its "Status" column index
        End With
        Set f = FindFirstCell(nameValue, .Columns(namesCol).SpecialCells(XlCellType.xlCellTypeConstants)) '<--| search its "names" column for the "name" value corresponding to the changed "Status" in the originally changed sheet
        If Not f Is Nothing Then '<--| if any matching cell found in "Names" column ...
            .Cells(f.row, statusCol) = statusValue '<--| update its corresponding "Status" column value
            MsgBox "record in row " & f.row & " has been updated in " & .name & " tab"
            If firstUpdatedRowIndex = 0 Then firstUpdatedRowIndex = f.row '<--| store first updated row  ****
        End If
    End With
End Sub


Function FindFirstCell(value As String, rng As Range) As Range
    Set FindFirstCell = rng.Find(what:=value, lookat:=xlWhole, LookIn:=xlValues, MatchCase:=True)
End Function


Function GetNameValue(Target As Range) As String
    With Target.Parent
        GetNameValue = .Cells(Target.row, FindFirstCell(NAMESHEADER, .Range(.Cells(1, 1), .Cells(1, Target.Column - 1))).Column).value '<--|  search columns preceeding the 'Target' (i.e.: "Status") one for the "Names" column and get its value at the row corresponding to changed "Status" one
    End With
End Function


Function Proceed(rng As Range) As Boolean
    Proceed = rng.Cells.Count = 1 '<--| proceed if only one changed cell
    If Proceed Then Proceed = rng.Offset(-rng.row + 1) = STATUSHEADER '<--| proceed only if the changed cell is a "Status" column
End Function