VBA:Excel :配列
【 Tips 】
文字列配列から指定文字列のINDEXを取得する
'** '* 文字列配列から指定文字列のINDEXを取得する '* '* @param sCheckLists {String()} 検索対象配列 '* @param sCheckString {String} 検索文字列 '* @param bSame {bool} True:完全一致 / False:相違 '* @return {Collection} 検出Index '* Public Function mth_GetStrComp( _ sCheckLists() As String, _ sCheckString As String, _ bCompMode_Same As Boolean _ ) As Collection Dim i As Long Dim cltFind_Idx As Collection Set cltFind_Idx = New Collection Dim lFind_Cnt As Long Dim lFind_Idx() As Long For i = LBound(sCheckLists) To UBound(sCheckLists) Dim lCompRes As Long lCompRes = StrComp(sCheckLists(i), sCheckString) If (bCompMode_Same And lCompRes = 0) _ Or (bCompMode_Same = False And lCompRes <> 0) _ Then ReDim Preserve lFind_Idx(lFind_Cnt) cltFind_Idx.Add i lFind_Idx(lFind_Cnt) = i lFind_Cnt = lFind_Cnt + 1 End If Next i Set mth_GetStrComp = cltFind_Idx End Function
特定の文字を含む(含まない) :Filter
Filter(sourcearray, match, [ include, [ compare ]])
Sub test() Dim s(4) As String s(0) = "aaaa" s(1) = "aaaa" s(2) = "adaaa" s(3) = "aagaa" s(4) = "ccc" Dim res res = Filter(s, "aaaa", True) res = Filter(s, "aaaa", False) Debug.Print UBound(res) End Sub
空かどうか確認
'■■■■■■■■■■■■■■■■■■■■■■■■■ '// 配列かどうか/空かどうか確認 '// '■■■■■■■■■■■■■■■■■■■■■■■■■ Private Sub psub_配列かどうか_空かどうか確認() Dim lRes As Long Dim vArr() As Variant '// 空の配列:0 lRes = mth_IsArrayEx(vArr) Debug.Print lRes '// 配列:1 vArr = Array("a", 1) lRes = mth_IsArrayEx(vArr) Debug.Print lRes End Sub '************************************************************************* '機能 : 引数が配列かどうか判断し、配列の場合は空かどうか判断する '戻り値 : 1:配列 / 0:空の配列 / -1:配列でない 'ARG1 : 配列 '************************************************************************* Public Function mth_IsArrayEx(vArr As Variant) As Long On Error GoTo ERR_PROC If IsArray(vArr) Then '// 配列確認 mth_IsArrayEx = IIf(UBound(vArr) >= 0, 1, 0) ' 三項演算子: UBound(vArr) >= 0 then 1 else 0 ' 配列が空の場合、Err=9(インデックスが有効範囲にありません) Else mth_IsArrayEx = -1 '配列でない End If Exit Function ERR_PROC: If Err.Number = 9 Then '// UBound(vArr) mth_IsArrayEx = 0 '// vArr = Empty End If End Function
重複削除
'■■■■■■■■■■■■■■■■■■■■■■■■■ '// 重複削除 '// '■■■■■■■■■■■■■■■■■■■■■■■■■ Private Sub psub_重複削除() Dim arr() arr() = Array(1, 1, 1, 4, 8, 5, 4, 3) Dim vResArr() vResArr = mth_DelSameVal(arr()) End Sub '************************************************************************* '機能 : 重複削除 '戻り値 : 配列 'ARG1 : 配列 '説明 : Dictionaryで配列要素をKey、Valを追加 ' Key重複できないのでErrで追加不可 ' Key(Val)値は、重複削除の値となる '************************************************************************* Public Function mth_DelSameVal(vArrSrc() As Variant) As Variant Dim dic Dim i As Long Set dic = CreateObject("Scripting.Dictionary") On Error Resume Next For i = 0 To UBound(vArrSrc) dic.Add vArrSrc(i), vArrSrc(i) Next mth_DelSameVal = dic.keys Set dic = Nothing End Function
ソート:クイックソート
'■■■■■■■■■■■■■■■■■■■■■■■■■ '// Sort:クイックソート '// '■■■■■■■■■■■■■■■■■■■■■■■■■ Private Sub psub_Sort_クイック() Dim arr() arr() = Array(1, 51, 4, 8, 5, 45, 3, 8) Dim vResArr() vResArr = mth_SortQuick(arr(), LBound(arr), UBound(arr)) End Sub '************************************************************************* '機能 : Sort:クイック '戻り値 : 配列 'ARG1 : 対象配列 'ARG2 : LBound(対象配列) 'ARG3 : UBound(対象配列) '説明 : '************************************************************************* Public Function mth_SortQuick( _ ByRef vargArr() As Variant, _ ByVal lngMin As Long, _ ByVal lngMax As Long _ ) As Variant() Dim i As Long, j As Long Dim vBase As Variant Dim vSwap As Variant vBase = vargArr(Int((lngMin + lngMax) / 2)) i = lngMin j = lngMax Do Do While vargArr(i) < vBase i = i + 1 Loop Do While vargArr(j) > vBase j = j - 1 Loop If i >= j Then Exit Do vSwap = vargArr(i) vargArr(i) = vargArr(j) vargArr(j) = vSwap i = i + 1 j = j - 1 Loop If (lngMin < i - 1) Then Call mth_SortQuick(vargArr, lngMin, i - 1) End If If (lngMax > j + 1) Then Call mth_SortQuick(vargArr, j + 1, lngMax) End If mth_SortQuick = vargArr End Function
Match・Index
Private Sub btnOth__Click() '// 出力データ生成 Dim vArr(2, 5) As Variant Dim r As Long, c As Long For r = LBound(vArr, 1) To UBound(vArr, 1) For c = LBound(vArr, 2) To UBound(vArr, 2) vArr(r, c) = CStr(r) & CStr(c) Next c Next r '// 出力 Dim ws02 As Worksheet: Set ws02 = ThisWorkbook.Worksheets("WS02") Dim rngStartCell As Range Set rngStartCell = ws02.Range("B2") ws02.Cells.Clear Call mth_SetGetCellValArr(vArr, rngStartCell) Set rngStartCell = Nothing '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'Range検索 Dim rngSrc As Range Set rngSrc = ws02.Range("B2").CurrentRegion '// Srh Rec Dim vSrhRecVal As Variant: vSrhRecVal = 10 Dim lSrhRecNo As Long lSrhRecNo = WorksheetFunction.Match(vSrhRecVal, rngSrc.Columns(1), 0) '// Srh Fld Dim vSrhFldVal As Variant: vSrhFldVal = 4 Dim lSrhFldNo As Long lSrhFldNo = WorksheetFunction.Match(vSrhFldVal, rngSrc.Rows(1), 0) '// ResVal Dim vGetVal As Variant '-- FLD -- vGetVal = rngSrc.Columns(lSrhFldNo) '(ex)Arr(1 To 3, 1 To 1) vGetVal = WorksheetFunction.Transpose(rngSrc.Columns(lSrhFldNo)) '(ex)Arr(3,1) -> Arr(1) '-- REC -- vGetVal = rngSrc.Rows(lSrhRecNo) '(ex)Arr(1 To 1, 1 To 6) vGetVal = WorksheetFunction.Transpose(vGetVal) '(ex)Arr(1,6) -> Arr(6,1) vGetVal = WorksheetFunction.Transpose(vGetVal) '(ex)Arr(6,1) -> Arr(6) 'Recが1つしかないので1次元になる '↓ まとめると↓ vGetVal = WorksheetFunction.Transpose(WorksheetFunction.Transpose(rngSrc.Rows(lSrhRecNo))) '-- TABLE -- vGetVal = WorksheetFunction.Index(rngSrc, lSrhRecNo, lSrhFldNo) MsgBox vGetVal '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& '配列検索 '// ResVal vGetVal = WorksheetFunction.Index(WorksheetFunction.Transpose(vArr), lSrhFldNo) '// Fld 1dArr vGetVal = WorksheetFunction.Index(vArr, lSrhRecNo) '// Rec 1dArr vGetVal = WorksheetFunction.Index(vArr, lSrhRecNo, lSrhFldNo) MsgBox vGetVal End Sub
Private Sub btnOth_検索_Click() '// 出力データ生成 Dim vArr(3, 5) As Variant Dim r As Long, c As Long For r = LBound(vArr, 1) To UBound(vArr, 1) For c = LBound(vArr, 2) To UBound(vArr, 2) If r <> 3 Then vArr(r, c) = CStr(r) & CStr(c) Else vArr(r, c) = CStr(r - 2) & CStr(c) End If Next c Next r '// 出力 Dim ws02 As Worksheet: Set ws02 = ThisWorkbook.Worksheets("WS02") Dim rngStartCell As Range Set rngStartCell = ws02.Range("B2") ws02.Cells.Clear Call mth_SetGetCellValArr(vArr, rngStartCell) Set rngStartCell = Nothing '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Dim rngSrhKey As Range Set rngSrhKey = ws02.Range("B2:B5") '// Srh Rec Dim vSrhKey vSrhKey = 10 '// Get RecNos Dim lSrhRecNos() As Long lSrhRecNos = m_検索_アドレス.mth_GetRowNo_Rang(rngSrhKey, vSrhKey) '// 出力開始位置の行Noを「1」として、RecNoを算出 Dim i As Long For i = LBound(lSrhRecNos) To UBound(lSrhRecNos) lSrhRecNos(i) = lSrhRecNos(i) - (ws02.Range("B2").Row - 1) Next i '// Srh Fld Dim rngSrc As Range Set rngSrc = ws02.Range("B2").CurrentRegion Dim vSrhFldVal As Variant: vSrhFldVal = 4 Dim lSrhFldNo As Long lSrhFldNo = WorksheetFunction.Match(vSrhFldVal, rngSrc.Rows(1), 0) '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'Range検索 Dim lSrhRecNo For Each lSrhRecNo In lSrhRecNos '// ResVal Dim vGetVal As Variant '-- FLD -- vGetVal = rngSrc.Columns(lSrhFldNo) '(ex)Arr(1 To 3, 1 To 1) vGetVal = WorksheetFunction.Transpose(rngSrc.Columns(lSrhFldNo)) '(ex)Arr(3,1) -> Arr(1) '-- REC -- vGetVal = rngSrc.Rows(lSrhRecNo) '(ex)Arr(1 To 1, 1 To 6) vGetVal = WorksheetFunction.Transpose(vGetVal) '(ex)Arr(1,6) -> Arr(6,1) vGetVal = WorksheetFunction.Transpose(vGetVal) '(ex)Arr(6,1) -> Arr(6) 'Recが1つしかないので1次元になる '↓ まとめると↓ vGetVal = WorksheetFunction.Transpose(WorksheetFunction.Transpose(rngSrc.Rows(lSrhRecNo))) '-- TABLE -- vGetVal = WorksheetFunction.Index(rngSrc, lSrhRecNo, lSrhFldNo) MsgBox vGetVal '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& '配列検索 '// ResVal vGetVal = WorksheetFunction.Index(WorksheetFunction.Transpose(vArr), lSrhFldNo) '// Fld 1dArr vGetVal = WorksheetFunction.Index(vArr, lSrhRecNo) '// Rec 1dArr vGetVal = WorksheetFunction.Index(vArr, lSrhRecNo, lSrhFldNo) MsgBox vGetVal Next lSrhRecNo End Sub
Match・VLookup
Private Sub btnOth_VlookUp_Click() '// 出力データ生成 Dim vArr(2, 5) As Variant Dim r As Long, c As Long For r = LBound(vArr, 1) To UBound(vArr, 1) For c = LBound(vArr, 2) To UBound(vArr, 2) vArr(r, c) = CStr(r) & CStr(c) Next c Next r '// 出力 Dim ws02 As Worksheet: Set ws02 = ThisWorkbook.Worksheets("WS02") Dim rngStartCell As Range Set rngStartCell = ws02.Range("B2") ws02.Cells.Clear Call mth_SetGetCellValArr(vArr, rngStartCell) Set rngStartCell = Nothing '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'Range検索 Dim rngSrc As Range Set rngSrc = ws02.Range("B2").CurrentRegion '// Srh Rec Dim vSrhRecVal As Variant: vSrhRecVal = 20 Dim lSrhRecNo As Long lSrhRecNo = WorksheetFunction.Match(vSrhRecVal, rngSrc.Columns(1), 0) '// Srh Fld Dim vSrhFldVal As Variant: vSrhFldVal = 3 Dim lSrhFldNo As Long lSrhFldNo = WorksheetFunction.Match(vSrhFldVal, rngSrc.Rows(1), 0) '// ResVal Dim vGetVal As Variant vGetVal = WorksheetFunction.VLookup(vSrhRecVal, rngSrc, lSrhFldNo, False) MsgBox vGetVal '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& '配列検索 '// ResVal '不可 End Sub
【配列とセル】
セル範囲の値を配列に格納
'■■■■■■■■■■■■■■■■■■■■■■■■■ '// セル範囲の値を配列に格納 '// '■■■■■■■■■■■■■■■■■■■■■■■■■ Private Sub psub_セル範囲の値を配列に格納() Dim rngSrc As Range Set rngSrc = ThisWorkbook.Worksheets(1).Range("A1:D25") Dim vResArr() As Variant vResArr = mth_GetCellValArr(rngSrc) Set rngSrc = Nothing End Sub '************************************************************************* '機能 : セル範囲の値取得 '戻り値 : 配列 'ARG1 : Range '説明 : '************************************************************************* Public Function mth_GetCellValArr(rng As Range) As Variant() '======================= '// セルの値を要素に代入 '======================= Dim vArrCell As Variant vArrCell = rng.Value '※indexは「1」から mth_GetCellValArr = vArrCell End Function
指定行(開始・終了行指定)、指定列のセル値を「配列の配列」で返す
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ '// 指定行範囲(開始・終了行指定)、指定列のセル値を '// 「配列の配列:Arr(Row)(Col)」で返す '■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Private Sub psub_指定Row範囲_指定Colリストのセル値を配列の配列で返す() Dim ws As Worksheet Set ws = ThisWorkbook.Worksheets(1) '// 対象行範囲 Dim lRowStartEnd(1) As Long lRowStartEnd(0) = 3: lRowStartEnd(1) = 8 '// 抽出列 Dim lColNos(3) As Long lColNos(0) = 2 lColNos(1) = 3 lColNos(2) = 5 lColNos(3) = Columns("G").Column '// 配列の配列データ取得 Dim vRes_ArrOfArr() vRes_ArrOfArr = mth_GetCellVal_ArrOfArr(ws, lRowStartEnd, lColNos) End Sub '************************************************************************* '機能 : 指定行範囲、指定列番号リストのセル値を配列の配列で返す '戻り値 : 配列の配列 'ARG1 : WorkSheet 'ARG2 : 行範囲配列(開始:終了) 'ARG3 : 対象列番号 '説明 : '************************************************************************* Public Function mth_GetCellVal_ArrOfArr( _ ws As Worksheet, _ lRowStartEnd() As Long, _ lColNos() As Long _ ) As Variant Dim vResDat() As Variant Dim lRow As Long Dim i As Long: i = 0 For lRow = lRowStartEnd(LBound(lRowStartEnd)) To lRowStartEnd(UBound(lRowStartEnd)) ReDim Preserve vResDat(i) '// 列データ Dim sBuf() ReDim sBuf(UBound(lColNos)) Dim j As Long: j = 0 Dim vCol As Variant For Each vCol In lColNos sBuf(j) = ws.Cells(lRow, vCol).Value j = j + 1 Next vResDat(i) = sBuf i = i + 1 Next mth_GetCellVal_ArrOfArr = vResDat End Function
配列の配列を2次元配列で返す
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ '// 配列の配列を2次元配列で返す '// '■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Private Sub psub_配列の配列を2次元配列で返す() Dim ws As Worksheet Set ws = ThisWorkbook.Worksheets(1) '// 対象行範囲 Dim lRowStartEnd(1) As Long lRowStartEnd(0) = 3: lRowStartEnd(1) = 8 '// 抽出列 Dim lColNos(3) As Long lColNos(0) = 2 lColNos(1) = 3 lColNos(2) = 5 lColNos(3) = Columns("G").Column '// 配列の配列データ取得 Dim vRes_ArrOfArr() vRes_ArrOfArr = mth_GetCellVal_ArrOfArr(ws, lRowStartEnd, lColNos) '// 配列の配列から2次元配列 Dim vRes_Arr2d() vRes_Arr2d = mth_ArrayOfArray2Array(vRes_ArrOfArr) End Sub '************************************************************************* '機能 : 配列の配列を2次元配列で返す '戻り値 : 2次元配列 'ARG1 : 配列の配列 '説明 : 配列内の配列は、1次元。 ' 先頭配列の要素数に合わせる '************************************************************************* Public Function mth_ArrayOfArray2Array( _ vArrayOfArray As Variant _ ) As Variant Dim r As Long, c As Long '// Dim vRes_2dArr() ReDim vRes_2dArr(UBound(vArrayOfArray), UBound(vArrayOfArray(0))) For r = LBound(vArrayOfArray) To UBound(vArrayOfArray) '// 1段目配列(行) For c = LBound(vArrayOfArray(c)) To UBound(vArrayOfArray(c)) '// 2段目配列(列) vRes_2dArr(r, c) = vArrayOfArray(r)(c) Next Next mth_ArrayOfArray2Array = vRes_2dArr End Function
配列1D → セルに出力
'■■■■■■■■■■■■■■■■■■■■■■■■■ '// 配列1Dをセルに出力 '// '■■■■■■■■■■■■■■■■■■■■■■■■■ Public Sub psub_配列1Dをセルに出力() Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("WS02") ws.Cells.ClearContents Dim vArr() vArr = Array(1, 3, 5, 4, 2) '// 出力 Dim rngStartCell As Range Set rngStartCell = ws.Range("B2") Call mth_SetCell1DArr(vArr, rngStartCell, "H") ws.Cells.ClearContents Call mth_SetCell1DArr(vArr, rngStartCell, "V") Set rngStartCell = Nothing End Sub '************************************************************************* '機能 : '戻り値 : 'ARG1 : '説明 : '************************************************************************* Public Sub mth_SetCell1DArr( _ vArr() As Variant, _ ByVal rngStartCell As Range, _ ByVal direction As String _ ) '======================= '// '======================= Dim lRowMax As Long: Dim lColMax As Long: Select Case direction Case "H" lRowMax = 1 lColMax = UBound(vArr, 1) - LBound(vArr, 1) + 1 '※出力サイズの設定が必要 rngStartCell.Resize(lRowMax, lColMax).Value = vArr Case "V" lRowMax = UBound(vArr, 1) - LBound(vArr, 1) + 1 lColMax = 1 '※出力サイズの設定が必要 rngStartCell.Resize(lRowMax, lColMax).Value = WorksheetFunction.Transpose(vArr) End Select End Sub
配列2D → セルに出力
'■■■■■■■■■■■■■■■■■■■■■■■■■ '// 配列2Dをセルに出力 '// '■■■■■■■■■■■■■■■■■■■■■■■■■ Public Sub psub_配列2Dをセルに出力() '// 出力データ生成 Dim vArr(2, 5) As Variant Dim r As Long, c As Long For r = LBound(vArr, 1) To UBound(vArr, 1) For c = LBound(vArr, 2) To UBound(vArr, 2) vArr(r, c) = CStr(r) & CStr(c) Next c Next r '// 出力 Dim ws02 As Worksheet: Set ws02 = ThisWorkbook.Worksheets("WS02") Dim rngStartCell As Range Set rngStartCell = ws02.Range("B2") ws02.Cells.Clear Call mth_SetGetCellValArr(vArr, rngStartCell) Set rngStartCell = Nothing Set ws02 = Nothing End Sub '************************************************************************* '機能 : '戻り値 : 'ARG1 : '説明 : '************************************************************************* Public Sub mth_SetGetCellValArr( _ vArr() As Variant, _ rngStartCell As Range _ ) '======================= '// '======================= Dim lRowMax As Long: lRowMax = UBound(vArr, 1) - LBound(vArr, 1) + 1 Dim lColMax As Long: lColMax = UBound(vArr, 2) - LBound(vArr, 2) + 1 '※出力サイズの設定が必要 rngStartCell.Resize(lRowMax, lColMax).Value = vArr End Sub
【参考 】
【VBA入門】配列総まとめ(初期化、ループ操作、コピー、結合、比較) | 侍エンジニア塾ブログ(Samurai Blog)
【VBA入門】配列総まとめ(初期化、ループ操作、コピー、結合、比較) | 侍エンジニアブログ
配列の宣言、初期化、再定義
配列の宣言、定義
Arrayで初期化
ReDimで再定義
Eraseで配列のメモリを解放
2次元配列(多次元配列)の場合
セルと配列
セルの値を要素に代入
要素の値をセルに格納
配列の要素数を取得
ループで配列の要素を操作
Forループ
For Each
配列をコピー
Sortで配列の要素をソート
※Excelシートを使用