配列

【VBA】配列の要素を指定して削除する関数(コピペですぐ使える)

記事内に商品プロモーションを含む場合があります

こんにちはhokkyokunです。

配列の要素を指定して削除する関数
を紹介いたします。

配列は要素数の再宣言が面倒で
あまり使わないんだよ

特定の要素を一気に消すのも面倒だし…

配列はプログラミングの基本ですが、
VBAは配列が不親切な設計になっています。

コピペですぐ使える関数を作りましたのでご紹介します。
以下の二つの関数を作りました。

  1. 特定の要素を最初に現れた一つだけ消す関数
    remove_Elm関数
  2. 特定の要素を配列から全て消す関数
    remove_Elm_All関数

これらの関数を使うと以下のメリットがあります。

  • 要素数の再宣言などの調整を
    一切考えないで済みます。
  • 配列の処理ミスでエラーで
    止まることが激減します!
  • コードを書かずに以下の使い分けが可能です!
    ①一つだけ要素を消す
    ②一気に同じ要素を全て消す

ググってみましたが、
配列で位置を指定して削除するコードを公開している人は多いですが、
あまり要素の値を指定して削除するコードを公開している人は少ないです

ご自身のお仕事自動化にぜひ活用してみてください。

なぜ関数を作ったか?⇒VBAの配列は不親切

VBAと他言語の違い

VBAはお手軽に始められて、
実務の効率化に直で影響を与えることができる素晴らしいツールなのですが、

VBAは他のプログラミング言語に比べて不親切なつくり方をしている
ことが多いです。
実際に比べてみました。

下記記事は
株価データから月当たりの価格変動率を計算し、
グラフ化するプログラムを
VBAとPythonで書いてみたものです。

記事を見て頂ければわかりますが、
VBAの方が基本的にはコード量が多くなります。

それだけ、機能が不親切ということです。

配列は特にひどい

なかでもVBAの配列は特にひどいです。
試しに、配列から最初に現れた特定の要素を削除するプログラムを書いてみました

書いててなんですが、特に中身を読まなくてもいいです(笑)
配列から削除するだけなのにとにかく長い(笑)

Sub test_remove_array()

Dim arr As Variant
Dim arrs As Variant '元になる配列。ここから特定の要素を削除する
Dim results As Variant  '削除後の配列。これを求める。
Dim target As Variant  '特定の要素
Dim i As Long

'適当に配列を用意
arrs = Array("a", "b", "c", "d", "b")

'ターゲットとする要素
target = "b"


'配列の要素を一つずつ確認する。
'特定の要素が現れたらFor文を抜けて次の処理に向かう
'特定の要素が現れる前の要素は全てresultsに入れる
For Each arr In arrs
    If arr <> target Then
        If i = 0 Then
            ReDim results(i)
        Else
            ReDim Preserve results(i)
        End If
        results(i) = arr
        i = i + 1
        
    Else
        Exit For
    End If
Next

'targetを「b」とした場合、i=1になっているはず
'つまり、arrsの「0」番目はresultsに格納している
'i+1=2番目以降のarrsの要素を問答無用でresultsに格納する
Do While i < UBound(arrs)
    If i = 0 Then
        ReDim results(i)
    Else
        ReDim Preserve results(i)
    End If
    
    results(i) = arrs(i + 1)
    i = i + 1
Loop


Dim msg As String
For Each arr In results
    msg = msg & arr & ","
Next
Debug.Print Left(msg, Len(msg) - 1)
'>>a,c,d,b
End Sub

配列はプログラムの基本なのに
ただ、要素を指定して削除するだけで大変ですね。

いちいち書いていられないことだけ
理解していただければと思います。

  • 配列から要素を消すコードはめんどくさい
  • 普通はこんなのいちいち書いていられない

remove_Elm関数 特定の要素を一つだけ削除する関数

特定の要素のうち、最初に現れた分を削除します。

  • 関数名
    remove_Elm( arrs , elm)
  • 引数
    ① arrs : 配列(データ型はVariant)
    ② elm : 要素(データ型はVariant)
  • 戻り値
    なし(配列から特定の要素のうち、最初に現れた一つを削除されています。)

コード

こちらをコピペしてお使いください

注意点は必ずお読みください

Function remove_Elm(ByRef arrs As Variant, ByVal elm As Variant)
    Dim arr As Variant
    Dim results As Variant  '削除後の配列。これを求める。
    Dim i As Long
    
    '配列が空の場合は何もせずに終了
    If Not Is_correct_array(arrs) Then
        Exit Function
    End If
    
    '配列の要素を一つずつ確認する。
    '特定の要素が現れたらFor文を抜けて次の処理に向かう
    '特定の要素が現れる前の要素は全てresultsに入れる
    For Each arr In arrs
        If arr <> elm Then
            If i = 0 Then
                ReDim results(i)
            Else
                ReDim Preserve results(i)
            End If
            results(i) = arr
            i = i + 1
            
        Else
            Exit For
        End If
    Next
    
    '特定の要素が現れた位置プラス1以降の処理です。
    '問答無用でresultsに格納する
    Do While i < UBound(arrs)
        If i = 0 Then
            ReDim results(i)
        Else
            ReDim Preserve results(i)
        End If
        
        results(i) = arrs(i + 1)
        i = i + 1
    Loop
    
    'resultsの結果を元の配列に入れる
    '=戻り値ではなく、引数が変更される
    '=call remove_Elm()で使用する
    arrs = results
    
End Function

注意点

①サブ関数

関数中にサブ関数を使っています。
Is_correct_array関数です。

配列の処理は繊細で、
空の状態だと、エラーが発生する場合があり、
配列の状態を見極める必要があります。

こちらがコードです。

Function Is_correct_array(ByVal arrs As Variant)
    Dim a As Long
    
    'なんでもいいが、エラーを生じさせる
    On Error GoTo err
    a = UBound(arrs)

    'エラーが生じたときエラー番号で9か13の場合はFalse
err:
    If err.number = 9 Or err.number = 13 Then
        Is_correct_array = False
    Else
        Is_correct_array = True
    End If
    
End Function

詳しい解説はこちらを確認してみてください

【VBA】配列が空かどうかを判定する関数とエラー回避する関数 わかること 配列が空の状態は2種類①エラーが発生する状態②エラーが出ずEmptyが要素として入った状態 配列の状態を把握するこ...

②配列の宣言の仕方

配列の宣言の仕方にはいろいろとありますが、
下記のように宣言してください。

Dim 配列名 as Variant

例えば
Dim arrs as Variant
のように宣言します。

arrsの後に()(2)などをつけないのがポイントです。

このように宣言しないと
以下のようなエラーが発生する可能性があります。

()に数値をあらかじめ入れるのは静的配列といいます。

が、実務では全く使う機会はありません。

私は社内で大規模なシステムをVBAでくんだりもしますが、
静的配列を使う必要に迫られたことは一度もありません

実際に使ってみます

使ってみます。

Sub test_Function_remove_Elm()
    Dim arrs As Variant
    
    arrs = Array("a", "b", "c", "d", "b", "b")
    Call remove_Elm(arrs, "b")
    
    'arrsの中身を確認
    Debug.Print Join(arrs, ",")
    '>>a,c,d,b,b
    
End Sub

remove_Elm_All関数 特定の要素を全て消す関数

  • 関数名
    remove_Elm_All( arrs , elm)
  • 引数
    ① arrs : 配列(データ型はVariant)
    ② elm : 要素(データ型はVariant)
  • 戻り値
    なし(配列から特定の要素がすべて削除されています。)

コード

こちらをコピペしてお使いください

注意点は必ずお読みください

Function remove_Elm_All(ByRef arrs As Variant, ByVal elm As Variant)

    Dim arr As Variant
    Dim results As Variant  '削除後の配列。これを求める。
    Dim i As Long
    
    '配列が空の場合処理せず終了する
    If Not Is_correct_array(arrs) Then
        Exit Function
    End If
    
    '特定の要素は格納せず、他の要素は全てresultsに入れる
    For Each arr In arrs
        If arr <> elm Then
            If i = 0 Then
                ReDim results(i)
            Else
                ReDim Preserve results(i)
            End If
            results(i) = arr
            i = i + 1
        End If
    Next
    arrs = results
    
End Function

注意点

remove_Elm関数と同様です。
こちらをご確認ください(ページ内ジャンプします)

実際に使ってみます

使ってみます。

Sub test_Function_remove_Elm_All()
    Dim arrs As Variant
    
    arrs = Array("a", "b", "c", "d", "b", "b")
    
    Call remove_Elm_All(arrs, "b")
    
    'arrsの中身を確認
    Debug.Print Join(arrs, ",")
    '>>a,c,d
End Sub

まとめ

いかがでしょうか。
まとめてみます。

まとめ
  • 配列から要素を指定して削除する関数を作成
  • 配列から指定した要素のうち、最初の一つだけ削除する関数
    remove_Elm関数
  • 配列から指定した要素を全て削除する関数
    remove_Elm_All関数

配列を便利に使いやすくする関数を作っています。

VBAの学習方法をまとめました。

VBA(マクロ)のおすすめの学習方法 こんにちはhokkyokunです。 VBAを学ぶことで確実に業務は効率化し、余裕をもって仕事をすることができるようになります。 ...

VBAを高コスパで、短期間で学ぶにはUdemyがおすすめです。
Udemyは良質の学習プラットフォームですが、
動画数が多すぎてどれを見ればよいか迷います。

おすすめの講師をまとめました。

【Udemyは講師で選べ!】UdemyがVBA学習に最適な理由とおすすめのVBA講師 こんにちはhokkyokunです。 巨大学習プラットホームUdemyの中からVBAに関する動画について講師に焦点を当ててまとめま...