我有多张纸,所有纸张中的一列包含相同的列(例如" 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
请帮忙。感谢。
答案 0 :(得分:3)
您的代码错误,因为您试图偏移D列左侧的11列
在OP澄清之后编辑:
要搜索的工作表名称是硬编码的,因为在所有其他工作表中都没有找到可以过滤它们的常用模式
Names
和Status
列,相应地,每个待搜索工作表的第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