0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VBA配列攻略4:PickRowsメソッドの実装

0
Last updated at Posted at 2026-04-07

はじめに

前回はFilterメソッドの前半となる Whereメソッドを実装しました。
VBA配列攻略3:Whereメソッドの実装
今回は後半となる PickRows メソッドを実装します。

実装コードを一部変更しました。2026.04.29
NG時はエラーを返さずヘッダーのみ返す思想としました。

  • 未初期化の行番号配列が渡された場合に「ヘッダーのみ」を返却。
  • On Error Resume NextErr.Clear を採用。
  • 使用例もシンプルにしました。

PickRowsの役割

PickRowsは、行番号配列を使って該当行を抽出し
絞り込まれた新しい配列」を作るメソッドです。
Whereと組み合わせることで配列フィルタ処理を構成する基本的な部品になります。

入力:元データの配列 vData + 行番号配列 rows()
出力:抽出された配列

PickRowsは元データである vData を変更しません。
代わりに、抽出結果を 新しい配列として返します。

このように 元データを変更せず結果を返す設計を「非破壊(non-destructive)」と呼びます。
これにより元データを安全に再利用できるようになり、
デバッグ時にも不具合箇所を追いやすくなるメリットがあります。

シグネチャ

Public Function PickRows(ByRef vData As Variant, _
                         ByRef rows() As Long) As Variant
  • vData:元となる2次元配列
  • rows:抽出対象の行番号配列
  • 戻り値:抽出された2次元配列

実装

Public Function PickRows(ByRef vData As Variant, _
                         ByRef rows() As Long) As Variant

    '--- Setup --------------------------------
    ' 配列境界取得
    Dim tr As TableBounds
    tr = GetTableBounds(vData)
    
    '--- ガード句:行番号リストの空チェック ---
    On Error Resume Next
    Dim rCount As Long
    rCount = UBound(rows) - LBound(rows) + 1
    
    ' rowsが未初期化なら「ヘッダーのみ」を返して終了
    If Err.Number <> 0 Then
        rCount = 0
        Err.Clear
    End If
    
    On Error GoTo 0
    
    ' 要素数が0件の場合の安全策
    If rCount < 0 Then rCount = 0

    '--- Allocate Result -----------------------
    ' 出力配列確保(rCount=0でもヘッダー分 tr.FirstRow は確保される)
    Dim result() As Variant
    ReDim result(tr.FirstRow To tr.FirstRow + rCount, _
                 tr.FirstCol To tr.LastCol)

    '--- Header Copy ---------------------------
    ' ヘッダー行コピー(常に実行)
    Dim c As Long
    For c = tr.FirstCol To tr.LastCol
        result(tr.FirstRow, c) = vData(tr.FirstRow, c)
    Next

    ' 抽出対象がない場合はここで終了
    If rCount = 0 Then
        PickRows = result
        Exit Function
    End If

    '--- Row Transfer --------------------------
    ' (以下、既存のデータコピー処理)
    Dim r As Long
    Dim srcRow As Long
    Dim destRow As Long
    destRow = tr.FirstRow + 1

    For r = LBound(rows) To UBound(rows)
        srcRow = rows(r)
        For c = tr.FirstCol To tr.LastCol
            result(destRow, c) = vData(srcRow, c)
        Next c
        destRow = destRow + 1
    Next r

    '--- Return --------------------------------
    PickRows = result

End Function

実装のポイント

1. 行番号をそのまま利用する

PickRowsは、Whereが返した行番号配列を受け取り、

引数で受け取った行番号
rows = [3, 7, 10]

その行番号をそのまま使って、該当行を新しい配列にコピーします。

行番号をそのまま使う
vData(0, *)  ' ヘッダーが行インデックス0の場合
vData(3, *)
vData(7, *)
vData(10, *)

2. TableBoundsで配列境界を統一

PickRowsでも、前回実装した TableBounds を利用して配列の境界を取得しています。
これにより次のメリットがあります。

  • LBound / UBound を直接書かない
  • 行・列の意味が明確になる
tr.FirstRow
tr.LastRow
tr.FirstCol
tr.LastCol

3. ヘッダー行はPickRows側で追加

Whereでは

For r = tr.FirstRow + 1 To tr.LastRow

としておりヘッダーを除いたデータ行のみを扱います。
PickRowsではヘッダーを追加する処理を入れます。
つまり、

  • Whereが抽出対象を決める
  • PickRowsはヘッダー付きでコピーする

という役割分担になっています。

使用例

Where の結果で処理を分岐します。

Dim rows() As Long
Dim cnt As Long
Dim result As Variant

cnt = Where(vData, "Price", opGreater, 100, rows)

' エラーだった場合(cnt=-1)、処理を分けます。
If cnt > -1 then
    result = PickRows(vData, rows)
End If

このように、Whereで取得した行番号配列を PickRows に渡すことで
条件に一致した行だけを抽出できます。

この設計のメリット

この設計では、vDataの配列そのものではなく
「行番号」という軽量な情報を中心に処理を組み立てています。

1. フィルタと抽出を分離できる

例えば次のように、

rows1 = Where(条件1)
rows2 = Where(条件2)
rows = UniqueValue(rows1, rows2)

result = PickRows(vData, rows)

行番号配列を加工する処理を自由に挟むことができます。

この設計では「行番号配列」を中心に処理を組み立てるため、
様々な処理を組み合わせることができます。

  • Where + PickRows(Filter)
  • Where + DropRows(Delete)
  • SortIndex + PickRows(Sort)
  • 独自ロジック + PickRows または DropRows

2. データコピーを最小化できる

Whereではデータコピーを行わず、行番号だけ保持します。
そのため、複数条件を組み合わせてもデータコピーは最後のPickRowsだけになります。

次回

次回は、PickRowsと対になる DropRows(指定行を除外する処理)を実装します。これにより、データ抽出と削除の両方が行えるようになり、柔軟なデータ操作が可能になります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?