Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba excel-如果工作表中的一列被更新,则更新多个列_Vba_Excel_Excel 2010_Worksheet Function - Fatal编程技术网

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

Vba excel-如果工作表中的一列被更新,则更新多个列,vba,excel,excel-2010,worksheet-function,Vba,Excel,Excel 2010,Worksheet Function,我有多张工作表,所有工作表中的一列包含同一列(比如“名称”)。在每一列中,“名称”是一个对应的“状态”列。每个“名称”列可能包含来自一个或多个工作表的相同记录。如果“状态”列中的一条记录被更新,我希望获得其对应的“名称”列值,然后搜索所有工作表,如果它也有相同的“名称”记录,我应该能够根据第一次“状态”更新的值更新其对应的“状态”值 现在,我能够从网络上搜索一个有效的答案(见下文),问题是它只能以一种方式工作。我可以更新工作表中的值(比如sheet1),它也可以更新一个或多个工作表中的值。但是,

我有多张工作表,所有工作表中的一列包含同一列(比如“名称”)。在每一列中,“名称”是一个对应的“状态”列。每个“名称”列可能包含来自一个或多个工作表的相同记录。如果“状态”列中的一条记录被更新,我希望获得其对应的“名称”列值,然后搜索所有工作表,如果它也有相同的“名称”记录,我应该能够根据第一次“状态”更新的值更新其对应的“状态”值

现在,我能够从网络上搜索一个有效的答案(见下文),问题是它只能以一种方式工作。我可以更新工作表中的值(比如sheet1),它也可以更新一个或多个工作表中的值。但是,当我尝试更新另一个工作表(不是sheet1)中的值时,它返回一个错误
方法“查找对象范围”失败

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


请帮助。谢谢。

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

在OP澄清以下内容后编辑

  • 要在硬编码的工作表名称中搜索,因为找不到在所有其他工作表中过滤它们的通用模式

  • 名称
    状态
    列在工作表中要搜索的每一行的第1行中都有相应的“名称”和“状态”标题

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

将此代码放入此工作簿的代码窗格:

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
选项显式
Const STATUSHEADER为String=“Status”
Const NAMESHEADER As String=“Names”
私有子工作簿(ByVal Sh作为对象,ByVal目标作为范围)
将名称值设置为字符串
将sht变暗为工作表
作为变体的名称

Dim firstUpdatedRowIndex,只要“您的代码错误,因为您试图偏移D列左侧的11列

在OP澄清以下内容后编辑

  • 要在硬编码的工作表名称中搜索,因为找不到在所有其他工作表中过滤它们的通用模式

  • 名称
    状态
    列在工作表中要搜索的每一行的第1行中都有相应的“名称”和“状态”标题

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

将此代码放入此工作簿的代码窗格:

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
选项显式
Const STATUSHEADER为String=“Status”
Const NAMESHEADER As String=“Names”
私有子工作簿(ByVal Sh作为对象,ByVal目标作为范围)
将名称值设置为字符串
将sht变暗为工作表
作为变体的名称

Dim firstUpdatedRowIndex只要每个工作表都有问题,“名称”和“状态”列就不同。而且,不应该搜索所有工作表。工作簿上有些工作表不应该是搜索的一部分。那么“状态”和“名称”的模式是什么“跨工作表的列位置?“如何在哪里搜索工作表?”埃林桑托斯,请回答我的问题,让我帮你解决好吗?如果通过标题值找到列(即任何表格中的“名称”列是第1行标题为“名称”的列),则代码可以轻松调整,您不需要硬编码其中的任何内容,只需硬编码这些列的标题名称(例如:“名称”和“状态”)只有一小部分工作表需要搜索,所以工作表名称是我搜索的基础,至于列,它们的位置只是随机的<代码>名称
和状态
只是随机插入的<代码>名称
列始终位于<代码>状态
列之前。问题是,对于每张工作表,“名称”和“状态”列各不相同。而且,不应搜索所有工作表。工作簿中有一些工作表不应作为搜索的一部分。那么,工作表中“状态”和“名称”列位置的模式是什么?“如何在哪里搜索工作表?”埃林桑托斯,请回答我的问题,让我帮你解决好吗?如果通过标题值找到列(即任何表格中的“名称”列是第1行标题为“名称”的列),则代码可以轻松调整,您不需要硬编码其中的任何内容,只需硬编码这些列的标题名称(例如:“名称”和“状态”)只有一小部分工作表需要搜索,所以工作表名称是我搜索的基础,至于列,它们的位置只是随机的<代码>名称和状态只是随机插入的<代码>名称列始终位于
状态
列之前。