はもちくわ

コードについて自分なりの解釈を書いてます。

【ExcelVBA】小技4 2次元配列を1行選んで消すユーザー関数

ExcelCSV→配列→CSVのような使い方してると「配列データの任意の行を消す」機会がでてきます。
PHPではunset(配列[id])という便利な命令がありますが、VBAには用意がない。

VBAじゃなくてExcel上でやってよ〜」とマイクロソフトさんが言ったとか言わないとか(笑) まあ、そりゃそうですよね。そのためのアプリなんだから(笑)



そういうことで自分で作成しました。

仕組みとしては、消す行番号のうしろから1つずつ繰り上げて上書きして、 そのあとに配列のデータ数を再宣言して最後のデータを無視する方法です。

 

コードです。


Function array_unset(arr() As Variant, n AS Long) As Variant()

Dim i As Long, j As Integer, r As Long, c As Integer

'2次元配列の行列データ数を取ります。

r = UBound(arr,2)’2次元目をRowと見立てる
c = UBound(arr,1)’1次元目をColumnと見立てる

’消したいデータ位置をスタートして、最大数の1個前までループ
For i = n To r - 1
  '列方向に項目数ループ
    For j = 0 To c
       arr(j, i) = arr(j, i+1)
    Next j
Next i

ReDim Preserve arr(c, r - 1)’1個減らしてデータを残して再宣言

array_unset = arr ’データを戻します

End Function

VBA上で使うには

2次元配列名 = array_unset(2次元配列名,消したい行番号)

と、こんな感じで使います。
「2次元配列名」は同じでも変えてもOK。
配列を関数に渡して同じ名前に戻すでも、別の配列名でコピーをつくるでもいいです。
配列から関数が受け取ったあとに項目数とデータ数を調べているので、特に気にせずに行削除できるかと思います。
ただ、1つ注意点がありまして、関数に渡す配列はVariantにしているため、他の形式だとエラーになります。そこを変えたい時はFuntionの宣言を変えるなどカスタムが必要です。

関数化しないなら、コード内のarrを任意の配列にすればOKです。コピー配列で消したい時は、処理前に配列名(コピー先)=配列名(コピー元)で作って、コピーの方を処理すればいいですね。

 

現在VBAでシステムを作成中で煮詰まったので気分転換にさっき作ったユーザー関数を書いてみました。
本当はブラウザでJavaScript使ったほうが処理が早いし、ローカルで仮想サーバー使わせてくれればPHPも使えるのにOKでなかったのでVBAです。いや〜処理が遅い。。。動いているのか心配になるわ(笑)

追記:2023年9月7日

自作システムですぐにこの関数の不具合がでました(笑)
そのとき現場で直したのですが、この記事は直してなかったのに気が付きましたので、直すことにします。(笑)


Function array_unset(arr() As Variant, n AS Long) As Variant()

Dim i As Long, j As Integer, r As Long, c As Integer

'2次元配列の行列データ数を取ります。

r = UBound(arr,2)’2次元目をRowと見立てる
c = UBound(arr,1)’1次元目をColumnと見立てる


If n=0 and r=0 then

    'もし配列が1レコードしかなく、それを消す場合
    ReDim1(c,0)

Else

  '消すデータが最後では無い場合
  If n<r then
        ’消したいデータ位置をスタートして、最大数の1個前までループ
        For i = n To r - 1
          列方向に項目数ループ
            For j = 0 To c
                arr(j, i) = arr(j, i+1)
            Next j
        Next i
    End If
    
  ’上で1個減らしたのでデータ数を減らして末尾のデータも一緒に消す
    'なので、消すデータが最後の場合はこの処理だけで解決
    ReDim Preserve arr(c, r - 1)

End If

array_unset = arr ’データを戻します

End Function

この配列レコードが1つしか無いということが少なくて、全く想定もしてなかったので、長いこと不備が見つからず正常に動いちゃってました(笑)
見つかってよかったけど、もっとちゃんとデバックしないとなぁってこのとき思いました。
これ以来、、、、、まあ、、、以前よりはだいぶマシになってますが、まだまだバグだらけのものをリリースしちゃってます(笑)