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

时间:2016-08-31 01:49:09

标签: excel vba excel-vba excel-2010 worksheet-function

我有多张纸,所有纸张中的一列包含相同的列(例如" Names")。在每个列"名称"是一个相应的"状态"柱。每个"名称"列可以包含来自一个或多个工作表的相同记录。如果其中一个记录在" Status"列已更新,我希望得到相应的"名称"列值,然后搜索所有工作表,如果它也具有相同的"名称"记录,我应该能够更新其相应的"状态"价值基于第一个"状态"更新

现在,我能够从正在运行的网络中搜索答案(见下文),问题是它只能单向运行。我可以从工作表更新一个值(比如sheet1),它可以从一个或多个工作表更新一个值。但是当我尝试更新另一个工作表(而不是sheet1)中的值时,它会返回错误Method "Find' of object 'Range' failed

示例(这应该在每个工作表中,列,工作表名称已更改):

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

请帮忙。感谢。

1 个答案:

答案 0 :(得分:3)

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

在OP澄清之后

编辑

  • 要搜索的工作表名称是硬编码的,因为在所有其他工作表中都没有找到可以过滤它们的常用模式

  • NamesStatus列,相应地,每个待搜索工作表的第1行中都有“名称”和“状态”标题

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