Vba excel-如果工作表中的一列被更新,则更新多个列
我有多张工作表,所有工作表中的一列包含同一列(比如“名称”)。在每一列中,“名称”是一个对应的“状态”列。每个“名称”列可能包含来自一个或多个工作表的相同记录。如果“状态”列中的一条记录被更新,我希望获得其对应的“名称”列值,然后搜索所有工作表,如果它也有相同的“名称”记录,我应该能够根据第一次“状态”更新的值更新其对应的“状态”值 现在,我能够从网络上搜索一个有效的答案(见下文),问题是它只能以一种方式工作。我可以更新工作表中的值(比如sheet1),它也可以更新一个或多个工作表中的值。但是,当我尝试更新另一个工作表(不是sheet1)中的值时,它返回一个错误Vba excel-如果工作表中的一列被更新,则更新多个列,vba,excel,excel-2010,worksheet-function,Vba,Excel,Excel 2010,Worksheet Function,我有多张工作表,所有工作表中的一列包含同一列(比如“名称”)。在每一列中,“名称”是一个对应的“状态”列。每个“名称”列可能包含来自一个或多个工作表的相同记录。如果“状态”列中的一条记录被更新,我希望获得其对应的“名称”列值,然后搜索所有工作表,如果它也有相同的“名称”记录,我应该能够根据第一次“状态”更新的值更新其对应的“状态”值 现在,我能够从网络上搜索一个有效的答案(见下文),问题是它只能以一种方式工作。我可以更新工作表中的值(比如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行标题为“名称”的列),则代码可以轻松调整,您不需要硬编码其中的任何内容,只需硬编码这些列的标题名称(例如:“名称”和“状态”)只有一小部分工作表需要搜索,所以工作表名称是我搜索的基础,至于列,它们的位置只是随机的<代码>名称和状态只是随机插入的<代码>名称列始终位于状态
列之前。