我正在使用 OFFSET/INDIRECT 从多个工作簿中提取数组。它们的格式彼此相似,因此我想对所有格式使用一个公式,即“偏移/间接”。
这是我到目前为止 A2 中的内容:
=OFFSET(INDIRECT("'"&A1&"'!$A$1"),MATCH("Total",INDIRECT("'"&A1&"'!$A:$A"),0),0,2,3)
A1 是源工作簿的名称 - 例如:My Workbook.xlsx。然后在 A4 中我有不同源工作簿的名称,只需将公式复制到 A5 即可:
=OFFSET(INDIRECT("'"&A4&"'!$A$1"),MATCH("Total",INDIRECT("'"&A4&"'!$A:$A"),0),0,2,3)
等等。但是,我可能有 50 个工作簿需要从中提取数据,并且每当我需要查看数据时都打开所有 50 个工作簿并不理想。我尝试制作一个简单的宏来一次打开所有 50 个工作簿,但最终我仍然不得不关闭它们,这很乏味。
=OFFSET(INDIRECTVBA("'"&A1&"'!$A$1"),MATCH("Total",INDIRECTVBA("'"&A1&"'!$A:$A"),0),0,2,3)
我得到了#VALUE!错误。我该如何解决?这是 VBA 中的内容:
Public Function INDIRECTVBA(ref_text As String)
INDIRECTVBA = Application.ThisCell.Parent.Range(ref_text)
End Function
Public Sub FullCalc()
Application.CalculateFull
End Sub
我知道即使我解决了这个问题,我仍然有 OFFSET 功能,这也需要打开源工作簿。这种不需要我打开所有资料书的“偏移/间接”设置的替代方案是什么?
如果有任何困惑,请告诉我。
INDIRECT
VBA 替代方案A1, A4, A7,... etc.
中输入数据(源工作簿名称)时,以及当源工作簿。工作表模块
Sheet1
.xlsm
(.xlsb
)。View Code
。Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
UpdateFromClosedWorkbooks Target
End Sub
Sheet1
但在您的情况下可能会有所不同。ThisWorkbook
模块
ThisWorkbook
。Sheet1
)。ThisWorkbook
模块)中,粘贴以下代码。Option Explicit
Private Sub Workbook_Open()
UpdateFromClosedWorkbooks
End Sub
标准模块
Module1
Insert Module
。Option Explicit
Sub UpdateFromClosedWorkbooks(Optional ByVal Target As Variant)
On Error GoTo ClearError
' Source (Closed Workbook)
Const SRC_FOLDER_PATH As String = "C:\Test" ' *****
Const SRC_SHEET_NAME As String = "Sheet1" ' *****
Const SRC_SEARCH_STRING As String = "Total"
Const SRC_COLUMN As String = "A"
Const SRC_ROW_OFFSET As Long = 1
Const SRC_COLUMN_OFFSET As Long = 0
' Both (the numbers from your formula)
Const ROWS_COUNT As Long = 2
Const COLUMNS_COUNT As Long = 3
' Destination (Workbook Containing This Code)
Const DST_FIRST_CELL As String = "A1"
Const DST_ROW_OFFSET As Long = 1
Const DST_ROWS_GAP As Long = 0
Const DST_COLUMN_OFFSET As Long = 0
Dim dws As Worksheet
If IsMissing(Target) Then ' for 'Workbook_Open'
Set dws = Sheet1 ' the sheet's code name ' *****
Else ' for 'Worksheet_Change'
Set dws = Target.Worksheet
End If
Dim dcrg As Range, drCount As Long
With dws.Range(DST_FIRST_CELL)
drCount = dws.Cells(dws.Rows.Count, .Column).End(xlUp).Row - .Row + 1
If drCount < 1 Then Exit Sub
Set dcrg = .Resize(drCount)
End With
Dim drOffset As Long: drOffset = ROWS_COUNT + DST_ROWS_GAP + 1
Dim durg As Range, irg As Range, r As Long
For r = 1 To drCount Step drOffset
If durg Is Nothing Then
Set durg = dcrg.Cells(r)
Else
Set durg = Union(durg, dcrg.Cells(r))
End If
Next r
If IsMissing(Target) Then ' for 'Workbook_Open'
Set irg = durg
Else ' for 'Worksheet_Change'
Set irg = Intersect(durg, Target)
If irg Is Nothing Then Exit Sub
End If
Dim drg As Range, dcell As Range, icell As Range
Dim sName As String, sPath As String, sSheet As String, sAddress As String
Application.EnableEvents = False
For Each icell In irg.Cells
sName = icell.Value
Set dcell = icell.Offset(DST_ROW_OFFSET, DST_COLUMN_OFFSET)
Set drg = dcell.Resize(ROWS_COUNT, COLUMNS_COUNT)
sPath = SRC_FOLDER_PATH & "\" & sName
If Len(Dir(sPath)) = 0 Then
drg.ClearContents
Else
sSheet = "'" & SRC_FOLDER_PATH & "\[" & sName & "]" _
& SRC_SHEET_NAME & "'!"
dcell.Formula = "=MATCH(""" & SRC_SEARCH_STRING & """," & sSheet _
& SRC_COLUMN & ":" & SRC_COLUMN & ",0)"
'dcell.Calculate
If IsNumeric(dcell.Value) Then
sAddress = dws.Cells(dcell.Value, SRC_COLUMN) _
.Offset(SRC_ROW_OFFSET, SRC_COLUMN_OFFSET).Address(0, 0)
drg.Formula = "=" & sSheet & sAddress
End If
End If
Next icell
ProcExit:
On Error Resume Next
Application.EnableEvents = True
On Error GoTo 0
Exit Sub
ClearError:
MsgBox "Run-time error '" & Err.Number & "':" & vbLf & vbLf _
& Err.Description, vbCritical
Resume ProcExit
End Sub
Set dws = Sheet1 ' the sheet's code name ' *****
并将 Sheet1
替换为记住的工作表代码名称(请注意,没有引号)。