業務で大量のExcelファイルを扱っていると、「他のブックの中から特定の文字列を検索して、周辺のデータも取得したい」という場面があります。
この記事では、Excel VBA + ADO を使って、他のブックの全シートを開かずに検索し、検索されたセル周辺の任意範囲のデータを取得する方法をご紹介します。
特徴
- 他のExcelファイルを開かずにデータを検索(ADO使用)
- 読み取り専用アクセスで安全
- 全シート対象
- 行/列検索の切り替えが可能
- 検索結果のセルを基準に、マイナス方向も含めた範囲指定が可能
- 結果に シート名とセルアドレス を含む
実装コード(VBA関数)
以下のコードを標準モジュールに貼り付けてください。
Function SearchExcelAllSheetsWithADO( _
targetFilePath As String, _
searchByRow As Boolean, _
searchTargetIndex As Long, _
keyword As String, _
readRows As Long, _
readCols As Long, _
rowOffset As Long, _
colOffset As Long _
) As Variant
On Error GoTo ErrHandler
Dim conn As Object
Dim rs As Object
Dim query As String
Dim resultList As Collection
Dim sheetList As Collection
Dim rowData() As Variant
Dim i As Long, j As Long, k As Long
Dim sheetName As Variant
Set resultList = New Collection
' ADO接続(読み取り専用)
Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & targetFilePath & ";" & _
"Extended Properties='Excel 12.0;HDR=YES;IMEX=1;ReadOnly=True';"
' シート一覧取得
Set sheetList = New Collection
Dim cat As Object
Set cat = CreateObject("ADOX.Catalog")
Set cat.ActiveConnection = conn
Dim tbl As Object
For Each tbl In cat.Tables
If Right(tbl.Name, 1) = "$" Or InStr(tbl.Name, "$'") > 0 Then
sheetList.Add tbl.Name
End If
Next
' 各シート処理
For Each sheetName In sheetList
query = "SELECT * FROM [" & sheetName & "]"
Set rs = CreateObject("ADODB.Recordset")
rs.Open query, conn, 1, 1
If Not rs.EOF Then
Dim data As Variant
data = rs.GetRows
Dim rowCount As Long: rowCount = UBound(data, 2)
Dim colCount As Long: colCount = UBound(data, 1)
If searchByRow Then
For i = 0 To rowCount
If searchTargetIndex - 1 <= colCount Then
If Not IsNull(data(searchTargetIndex - 1, i)) Then
If InStr(CStr(data(searchTargetIndex - 1, i)), keyword) > 0 Then
ReDim rowData(0 To readRows * readCols + 1)
rowData(0) = Replace(sheetName, "$", "")
rowData(1) = Cells(i + 1, searchTargetIndex).Address(False, False)
For j = 0 To readRows - 1
For k = 0 To readCols - 1
Dim targetRow As Long: targetRow = i + j + rowOffset
Dim targetCol As Long: targetCol = searchTargetIndex - 1 + k + colOffset
If targetRow >= 0 And targetRow <= rowCount And targetCol >= 0 And targetCol <= colCount Then
rowData(j * readCols + k + 2) = data(targetCol, targetRow)
Else
rowData(j * readCols + k + 2) = ""
End If
Next k
Next j
resultList.Add rowData
End If
End If
End If
Next i
Else
If searchTargetIndex - 1 <= rowCount Then
For i = 0 To colCount
If Not IsNull(data(i, searchTargetIndex - 1)) Then
If InStr(CStr(data(i, searchTargetIndex - 1)), keyword) > 0 Then
ReDim rowData(0 To readRows * readCols + 1)
rowData(0) = Replace(sheetName, "$", "")
rowData(1) = Cells(searchTargetIndex, i + 1).Address(False, False)
For j = 0 To readRows - 1
For k = 0 To readCols - 1
Dim targetRow As Long: targetRow = searchTargetIndex - 1 + j + rowOffset
Dim targetCol As Long: targetCol = i + k + colOffset
If targetRow >= 0 And targetRow <= rowCount And targetCol >= 0 And targetCol <= colCount Then
rowData(j * readCols + k + 2) = data(targetCol, targetRow)
Else
rowData(j * readCols + k + 2) = ""
End If
Next k
Next j
resultList.Add rowData
End If
End If
Next i
End If
End If
End If
rs.Close
Set rs = Nothing
Next
conn.Close
Set conn = Nothing
Set cat = Nothing
If resultList.Count > 0 Then
ReDim outputArr(1 To resultList.Count)
For k = 1 To resultList.Count
outputArr(k) = resultList(k)
Next k
SearchExcelAllSheetsWithADO = outputArr
Else
SearchExcelAllSheetsWithADO = Empty
End If
Exit Function
ErrHandler:
MsgBox "エラーが発生しました:" & vbCrLf & Err.Description, vbExclamation
If Not rs Is Nothing Then If rs.State = 1 Then rs.Close
If Not conn Is Nothing Then If conn.State = 1 Then conn.Close
Set rs = Nothing
Set conn = Nothing
Set cat = Nothing
SearchExcelAllSheetsWithADO = Empty
End Function
使用例
Sub TestSearch()
Dim results As Variant
results = SearchExcelAllSheetsWithADO( _
"C:\temp\sample.xlsx", _
True, ' True = 行で検索 / False = 列で検索
2, _
"検索キーワード", _
3, ' 行数
2, ' 列数
-1, ' 行オフセット(-1行から開始)
0) ' 列オフセット(その列から)
If Not IsEmpty(results) Then
Dim i As Long, j As Long
For i = LBound(results) To UBound(results)
Debug.Print "シート: " & results(i)(0), "セル: " & results(i)(1)
For j = 2 To UBound(results(i))
Debug.Print results(i)(j)
Next j
Next i
Else
MsgBox "該当なし"
End If
End Sub
パラメータの意味
注意点
- ADOを使うには Microsoft.ACE.OLEDB.12.0 がインストールされている必要があります。
.xlsx
ファイルは Excel 2007以降用の形式です。- フィルタや数式などがある場合、値のみ取得されます。
- セルに改行がある場合、取得内容に注意してください。
引数名 | 内容 |
---|---|
targetFilePath |
検索対象のExcelファイルのフルパス |
searchByRow |
行方向に検索するか(True )、列方向か(False ) |
searchTargetIndex |
行または列番号(1から) |
keyword |
検索キーワード |
readRows |
検索ヒットセルを基準に、取得する行数 |
readCols |
検索ヒットセルを基準に、取得する列数 |
rowOffset |
検索セルからの行方向オフセット(負数で上方向) |
colOffset |
検索セルからの列方向オフセット(負数で左方向) |
最後に
大量のExcelファイルを横断的に検索し、情報を抽出したい場面で非常に有用な手法です。
本記事のコードを活用して、検索・抽出の自動化にぜひご活用ください!
コメント