Excel VBA - 配列と Replace 関数を使った文字列置検索(部分一致)置換処理メモ
Excel VBA で配列と Replace 関数を使って文字列を検索(部分一致)・置換する VBA コードを公開します。
前回の記事 では検索対象の文字列に対して完全一致したものだけ置換しましたが、今回は部分一致した文字列を置換する記事内容となっています。
Excel と Excel Visual Basic Editor(VBE)の環境設定については 以前公開した記事 より、VBA コードの基本的な内容については こちらの記事 よりご確認ください。
配列と Replace 関数を使った文字列置検索(部分一致)置換用サンプルファイル(xlsx ファイル)
配列と Replace 関数を使った文字列置検索(部分一致)置換用のサンプルファイル(xlsx ファイル)を公開します。
サンプルデータは Start Point さんのところで公開しているコピペで使える都道府県一覧リスト・県庁所在地一覧 を加工しています。
こちらで作成した 文字列置換前置換後A.xlsx ファイル と 文字列置換前置換後B.xlsx ファイル を用意しました。ファイル名リンクをクリックすると Google ドライブからダウンロードするようにしています。
文字列置換前置換後A.xlsx ファイル は VBA コードを実行する前の状態、文字列置換前置換後B.xlsx ファイル は VBA コード実行後の処理結果内容となっています。
いずれも xlsx ファイルとなっており VBA コードは含まれていません。VBA コードを実行するにはファイル拡張子が xlsm(マクロ有効ブック)となっている必要がありますが、xlsm 形式での配布は念のため避けています。
VBA コードを実行するには 文字列置換前置換後A.xlsx ファイル をダウンロード後 xlsm 形式に保存、以降各セクションで紹介している VBA コードを各自追加して実行してもらう形としています。
VBA コードの追加方法は VBE のプロジェクトエクスプローラー(Ctrl + R キー)画面にて、開いている VBAProject(ファイル名.xlsm)→「標準モジュール」を開き、右クリックから「挿入」→「標準モジュール」でクリック、追加した標準モジュールに VBA コードを貼り付けることで動作できるようにしています。
一部 VBA コード内にある Call ステートメントを使った Function プロシージャの呼び出し については、呼び出し先標準モジュールのプロパティ(F4 キー)画面から(オブジェクト名)欄を設定するのが前提となっています。
セル検索(部分一致)置換処理については指定した文字列があるセル内容を、配列と Replace 関数を組み合わせて部分一致で検索して置換する VBA コードを公開します。VBA コードと詳細な内容については 次のセクション で説明します。
配列に格納した全データの部分一致による逐次検索置換処理のため、大量のデータ件数を用いた場合は処理速度に大きな影響を受ける可能性があります。
配列と Replace 関数を使った文字列置検索(部分一致)置換処理 VBA サンプルコード
以下、配列と Replace 関数を使った文字列置検索(部分一致)置換処理 VBA サンプルコードです。
この VBA コードはシート「文字列置換前置換後シート」の地方区分単位(A 列)で、1つのセルにセル内改行でまとめられた B 列(都道府県)と C 列(県庁所在地)の各セルを 2次元配列に格納します。別シート「都道府県文字列置換リスト」と「県庁所在地文字列置換リスト」であらかじめ用意した検索文字列と置換文字列も 2次元配列に格納して、2次元配列に格納した文字列の検索(部分一致)と置換を Replace 関数を使って行うものとなっています。
Replace 関数を使って置換対象文字列の検索と置換(ここでは日本語名から英語名に置換)を行い、その結果を D 列(都道府県)と E 列(県庁所在地)に反映します。
この配列と Replace 関数を使った置換方法は こちらのサイト で紹介している配列を使用した高速置換 VBA コードと内容は同じです。
対象の文字列が置換できているかどうか確認できるように、元のセルへ上書きはせず隣の空きセルに転記しています。反映先のセルがわかりやすいように、あらかじめ該当セルを罫線で囲んでいます。
セル検索(部分一致)置換処理部分以外の基本的な VBA コードについては 以前公開した記事内容 を参照してください。
次のセクション では配列と Replace 関数を使った文字列置検索(部分一致)置換処理がある VBA コード部分について内容を説明します。
2次元配列に格納した文字列を Replace 関数で検索(部分一致)と置換
' Instr 関数で検索文字列を検索、Replace 関数でセル内にある検索文字列を置換文字列に置換(都道府県文字列置換リスト)
For i = LBound(data1, 1) To UBound(data1, 1) ' 配列 data1 の 1次元最大要素までループ処理
For k = LBound(data2, 1) To UBound(data2, 1) ' 配列 data2 の 1次元最大要素までループ処理
' If InStr(data1(i, 1), data2(k, 1)) > 0 Then ' Instr 関数で配列 data1 の i 行 1列目セル内文字列の中から、配列 data2 の k 行 1列目で指定した文字列を検索して位置を返す
' If 文で InStr 関数で文字列を検索して位置を返した場合(> 0)
data1(i, 1) = Replace(data1(i, 1), data2(k, 1), data2(k, 2)) ' 配列 data1 の i 行 1列目セル内文字列から配列 data2 の k 行 1列目の文字列を検索、配列 data2 の k 行 2列目の文字列に置換して配列 data1 の i 行 1列目に代入
' End If
Next k
Next i
' Instr 関数で検索文字列を検索、Replace 関数でセル内にある検索文字列を置換文字列に置換(県庁所在地文字列置換リスト)
For i = LBound(data1, 1) To UBound(data1, 1) ' 配列 data1 の 1次元最大要素までループ処理
For k = LBound(data3, 1) To UBound(data3, 1) ' 配列 data3 の 1次元最大要素までループ処理
' If InStr(data1(i, 2), data3(k, 1)) > 0 Then ' Instr 関数で配列 data1 の i 行 2列目セル内文字列の中から、配列 data3 の k 行 1列目で指定した文字列を検索して位置を返す
' If 文で InStr 関数で文字列を検索して位置を返した場合(> 0)
data1(i, 2) = Replace(data1(i, 2), data3(k, 1), data3(k, 2)) ' 配列 data1 の i 行 2列目セル内文字列から配列 data3 の k 行 1列目の文字列を検索、配列 data3 の k 行 2列目の文字列に置換して配列 data1 の i 行 2列目に代入
' End If
Next k
Next i
2次元配列 data1・data2・data3 に格納した文字列と Replace 関数を使って検索と置換処理をします。途中 InStr 関数を含んだ If 文ありますが、なくても Replace 関数だけで置換処理が可能なためコメントアウトしています。InStr 関数については後述。
2次元配列 data1 には置換対象となるシート「文字列置換前置換後シート」の B・C 列の都道府県・県庁所在地セルを格納、2次元配列 data2 にはシート「都道府県文字列置換リスト」にセットした A・B 列の検索文字と対の置換文字を格納、2次元配列 data3 にはシート「県庁所在地文字列置換リスト」にセットした A・B 列の検索文字と対の置換文字を格納しています。
64~71 行目で都道府県を日本語から英語に置換、74~81 行目で県庁所在地を同じように置換する処理に分けています。検索・置換で参照している 2次元配列が違うだけで(2次元配列 data2 と data3)で処理の流れ・コードは同じです。
64行目は For 文とカウンタ変数 i と LBound・UBound 関数を使って、置換対象の文字列を格納した 2次元配列 data1 の 1次元最大要素(行相当)までループ処理、次の 65行目では For 文とカウンタ変数 k と LBound・UBound 関数を使って、検索文字列と置換文字列を格納した 2次元配列 data2 の 1次元最大要素(行相当)までループ処理をします。
68行目で Replace 関数に引数を指定してカウンタ変数分の置換を処理します。
第 1引数に置換の対象となる文字列を格納した 2次元配列(data1 の i(カウンタ変数)行 1列目)を指定、第 2引数に検索する文字列を格納した 2次元配列(data2 の k(カウンタ変数)列 1列目)を指定、第 3引数に置換する文字列を格納した 2次元配列(data2 の k(カウンタ変数)列 2列目)を指定します。
Replace 関数での処理結果を、Replace 関数の第 1引数で指定した 2次元配列(data1 の i(カウンタ変数)行 1列目)に代入することで置換することができます。検索文字列が見つからなければ置換なしで、2次元配列 data1 の i(カウンタ変数)行 1列目は変更なしとなります。
74~81 行目のコードは 64~71 行目と処理の流れはまったく同じです。違う点は 2次元配列 data2(都道府県検索・置換文字列)から 2次元配列 data3(県庁所在地検索・置換文字列)に変更しているだけとなっています。
以上が配列と Replace 関数を使った検索・置換処理の流れになります。
66行目及び 76行目で InStr 関数を使った If 文を使用しています。
これは InStr 関数の第 1引数に検索の対象となる文字列を格納した 2次元配列(data1 の i(カウンタ変数)行 1列目)を指定、第 2引数に 第 1引数の中から検索する文字列を格納した 2次元配列(data2 の k(カウンタ変数)列 1列目)を指定しています。
この InStr 関数を使うことで 第 1引数の 2次元配列 data1 で指定した文字列の中から、第 2引数の 2次元配列 data2で指定した文字列を検索して、最初に見つかった文字位置を返します。
これを If 文で 0 以上(> 0
)であるかどうか判定させることで、置換対象の文字列があるかどうか調べることができます。ただ、今回の場合では Replace 関数で必要な処理が足りているため、InStr 関数を使わなくても置換できるようになっています。検索と置換が違う複数の条件がある場合に、InStr 関数と Replace 関数を組み合わせて使うことになるでしょう。
ちなみに InStr 関数のコメントアウトを外しても処理結果は同じになります。
Excel VBA コードメモリリーク対策について
X(Twitter) にて教えてもらいましたが、LBound と UBound 関数を使用した VBA コードの書き方によってはメモリリークが起きる可能性があるようです。
ただ、指摘のあった関数による VBA コードのメモリリークについて日本語で言及している情報が少なく、今回公開した VBA コードが原因でメモリリークが起きるかどうか確認できていません。(こちらで単純にメモリリークに気づいていないというのもあります)
X(Twitter) で紹介してもらった こちらのサイト ではメモリリークする・しないコードの書き方が紹介されています。以下各セクションではこの書き方にならって、コード内容を書き直したメモリリーク対策版 VBA コードを公開します。
メモリリークが起きないとされているコード内容に修正しただけなので、実際にメモリリークが起きないかどうかまでは確認していません。
基本的に関数の返り値を一度変数に格納して、その変数を使用する方法に書き換えた内容となっています。各コードについて元の VBA コードから追加・変更した箇所をハイライトで表示しています。
配列と Replace 関数を使った文字列置検索(部分一致)置換処理 VBA サンプルコード メモリリーク対策版
- Excel および Excel Visual Basic Editor(VBE)を快適に使うための環境設定メモ
- Excel VBA - 連想配列(Dictionary オブジェクト)を使った大量データ高速抽出・集計処理メモ
- Excel VBA - 配列を使った列高速入れ替え処理メモ
- Excel VBA - 配列を使ったセル検索(完全一致)置換処理メモ
- Excel VBA - 配列と Replace 関数を使った文字列置検索(部分一致)置換処理メモ(現在開いているページ)
- Excel VBA - 配列と Select Case ステートメントを使ったシート・セル操作メモ
- Excel VBA - 区切り文字を使ったグループ単位別各行セル内文字列連結処理メモ
- Excel VBA - 区切り文字で文字列が連結されたセルからグループ単位別に行分割処理メモ
- Excel VBA - グループ別セル色分け(2色交互・複数色)処理メモ