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配列攻略5:DropRowsメソッドの実装

0
Last updated at Posted at 2026-04-29

はじめに

配列操作の Filter(フィルタ) 機能を実現するために、本連載では処理を次の3つの部品に分解して設計してきました。

  1. Where:条件に合う「行番号」を特定する
  2. PickRows:特定の行を「抽出」する
  3. DropRows:特定の行を「除外」する

前回の記事では、指定した行だけを取り出す PickRows を実装しました。今回はその対となる、指定した行を取り除く DropRows メソッドを実装します。

DropRowsの役割

DropRows は、引数で渡された行番号を 除外(削除) して、残りの行だけで新しい配列を再構築するメソッドです。

PickRows との違い

PickRowsDropRowsの2つは相反するメソッドです。
例えば、5行のデータ(1行目はヘッダー)があり、3行目と4行目を除外したい場合:

元データ
1  ID, Name  (Header)
2  01, Apple
3  02, Orange <-- 除外対象
4  03, Banana <-- 除外対象
5  04, Cherry

rows = [3,4]
DropRowsの結果
1  ID, Name
2  01, Apple
5  04, Cherry

つまり

  • PickRows = 指定行だけ抽出する
  • DropRows = 指定行以外を抽出する

という対になる関係になります。

なぜ DropRows が必要なのか?

「条件に一致したものを取り出す」のが Where + PickRows ですが、実務では「削除条件を指定した方がシンプル」という場面も多くあります。
PickRowsDropRows を使い分けることで、抽出も削除も自由自在に行えるようになります。

DropRowsのシグネチャ

Public Function DropRows(ByRef vData As Variant, _
                         ByRef rows() As Long) As Variant
  • vData:元となる2次元配列
  • rows:削除対象となる行番号配列
  • 戻り値:指定行が除外された新しい2次元配列

DropRowsの実装

「除外する行」を指定する代わりに、「除外されない行(残す行)」のリストを裏側で作って PickRows に丸投げするという戦略をとります。

実装
Public Function DropRows(ByRef vData As Variant, _
                         ByRef rows() As Long) As Variant

    '--- Setup --------------------------------
    Dim tr As TableBounds
    tr = GetTableBounds(vData)

    '--- ガード句:除外リストが空の場合はそのまま返す ---
    On Error Resume Next
    Dim rowCount As Long
    rowCount = UBound(rows) - LBound(rows) + 1

    ' rowsが未初期化なら「除外なし」として元データをそのまま返す
    If Err.Number <> 0 Then
        DropRows = vData
        Err.Clear
        On Error GoTo 0
        Exit Function
    End If
    
    On Error GoTo 0
    
    '--- 除外リストを高速判定用に変換 ----------------
    ' Dictionaryを使って除外対象をマーク(Existsで高速判定するため)
    Dim dropMap As Object
    Set dropMap = CreateObject("Scripting.Dictionary")
    Dim i As Long
    For i = LBound(rows) To UBound(rows)
        dropMap(rows(i)) = True
    Next i

    ' 削除不要ならそのまま配列を返す
    If dropMap.count = 0 Then
        DropRows = vData
        Exit Function
    End If

    '--- 「残す行」の配列を作成 --------------------
    ' 元のデータ行を走査し、除外リストにない行番号だけを抽出
    Dim keepRows() As Long
    ReDim keepRows(1 To tr.rowCount) ' 最大サイズで確保
    
    Dim r As Long
    Dim cnt As Long
    cnt = 0
    
    ' データ行を走査し、除外対象でない行番号だけをストック
    For r = tr.FirstRow + 1 To tr.LastRow
        If Not dropMap.Exists(r) Then
            cnt = cnt + 1
            keepRows(cnt) = r
        End If
    Next r

    '--- 実行 ----------------------------------
    ' 「残す行」のリストを PickRows に渡して配列を再構築
    If cnt = 0 Then
        ' 全て除外された場合:ヘッダーのみの配列を返す等の処理
        ' (※PickRowsの仕様に準拠)
        Dim emptyRows() As Long
        DropRows = PickRows(vData, emptyRows)
    Else
        ' 有効な行だけをリサイズして PickRows へ渡す
        ReDim Preserve keepRows(1 To cnt)
        DropRows = PickRows(vData, keepRows)
    End If

End Function

PickRows の仕様変更について(2026.04.29)
以前の記事で紹介した PickRows の実装コードを修正しました。内容はエラーハンドリングの追加です。記事をシンプルにするためエラーハンドリングはなしにしようと考えていましたが、ある程度そのまま使えるように最低限のものは入れるようにしたいと思います。

DropRows実装のポイント

  1. PickRowsへの「丸投げ」による共通化
    今回の最大の特徴は、自前で配列コピーを行わず、最後は必ず PickRows を呼んでいる点です。(DRY原則)

    • 削除対象が1つもないとき ⇒ vData をそのまま返す
    • すべて削除されたとき ⇒ 空の配列を PickRows に渡し、ヘッダーのみ返してもらう
    • 一部削除されたとき ⇒ 残す行リストを PickRows に渡す

    このように「配列を新しく作る」という重い処理を一箇所(PickRows)に集約することで、コードの保守性が格段に向上します。

  2. 「除外」を「残す」に変換する
    DropRows の核となるロジックは、以下の変換処理です。
    ・入力: 捨てたい行リスト (rows)
    ・変換: 元データ全体から rows を除いた「残したい行リスト」を作成
    ・出力: PickRows(vData, 残したい行リスト)
    この変換を行う際、Dictionary オブジェクトの .Exists メソッドを利用することで、大量のデータがあっても「この行は除外対象か?」を高速に判定しています。

  3. 関心の分離
    この設計により、各メソッドの役割が明確になります。
    ・PickRows:指定された行を物理的にコピーし、新しい配列を作る
    ・DropRows:どの行を残すべきかを判断し、指示書を作る

使用例

Where メソッドと組み合わせることで、「特定の条件に一致しないデータを除外する」といった操作が直感的に記述できます。

使用例
Dim rows() As Long
Dim cnt As Long
Dim result As Variant

' 在庫数が0の行番号を取得
cnt = Where(vData, "Stock", opEqual, 0, rows)

' 在庫0の行を除外して新しい配列を作成
' (※cnt=0 の場合は DropRows 内部でそのまま vData が返されます)
result = DropRows(vData, rows)

次回

これで、データの抽出PickRowsと除外DropRowsという、配列操作の両輪が揃いました。
次回は、これらの部品を組み合わせて、いよいよ本丸である Filter メソッド を完成させます。

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?