【簡単エクセル/Excel VBA マクロ】異なるファイル(複数ファイル)間のデータマッチング(照合・突合)第2版|アプリ事例 #010

アフィリエイト広告を利用しています。
Information
運営者・ポテ

いつもありがとうございます。

皆さん、こんにちは。ご覧いただきありがとうございます。

“日々の業務にちょうどいい自動化を”──

業務改善アプリケーションの開発を行っている ソフトデザイン工房 です。

この記事は、以前お届けした「異なるファイル間のデータマッチング(照合・突合)方法」の第2版です。

この第1版では、変数名のつけ方やコード全体の汎用性に、いくつか改善の余地がありました。

そこで今回は、改善した第2版をお届けします。

前回の第1版と今回の第2版の主な違いは、下表の通りです。

項目第1版第2版
変数名の意味明確化fa_row_idx などの略語が多く、処理対象が不明瞭になりやすいbase_rowcheck_value など、対象の役割が明示され、可読性が向上
コメント逐語的で冗長な説明が多く、コードの流れが読みづらいコンパクトかつ構造的なコメントで、コード全体の見通しが良くなる
マジックナンバー排除列番号などを直接数値で指定しており、修正時にリスクが高いBASE_TARGET_COL のような定数化により、意図が明確になり、メンテナンス性が向上
可読性ネストや長い行が多く、視線の移動が多くなる折り返しやインデントにより、視線移動が少なく、処理のブロックが把握しやすい
拡張性ファイル名や列番号などがベタ書きされ、再利用や変更に弱いファイル名・列番号を定数として外出しすることで、設定変更が容易に
処理の汎用性処理内容が固定されており、他の照合処理に転用しづらい比較処理の構造が抽象化されており、今後の追加処理にも対応しやすい
Information
  • マジックナンバー
    コードの中に直接書かれた意味の分からない数字のこと。たとえば、13をそのまま使うと、何の列(または行)か分からなくなりやすく、修正ミスの原因になります。
  • 抽象化
    「抽象化」という言葉の日本語的な意味は、物ごとの細かな違いを取り除き、共通する本質や特徴だけを取り出して考えることです。
    プログラミングの文脈では、特定の処理やデータの「中身」に立ち入らず、共通の仕組みとして整理することを指します。たとえば「比較処理」だけを汎用化すれば、どんなデータにも再利用できるようになります。

この記事が、あなたのVBAマクロの価値をさらに高める一助となれば幸いです。

VBAを活用して、自分自身や身近なコミュニティに合ったアプリケーションを作成し、仕事量は半分に、成果は2倍に──そんな未来を目指すあなたを応援しています。

VBAで「異なるファイル(複数ファイル)間のデータマッチング(照合・突合)」を行う方法(第2版)

アプリケーションの仕様

以下のようなファイル・フォルダ構成を例にとります。

your_folder/
  ├── BaseFile.xlsx
  ├── CheckFile.xlsx
  └── データをマッチングする.xlsm

データをマッチングする.xlsm が、VBAコードを記述するファイルです。

このVBAアプリケーションは、次ように動作します。

対象ファイルを読み込む

データをマッチングする.xlsmBaseFile.xlsxCheckFile.xlsx を読み込み、両者のデータを照合します。

データマッチング結果の出力

両者のデータの一致が見つかった場合は、その情報をデバッグ出力します。

なお、BaseFile.xlsxCheckFile.xlsxのシートの中身は、次のとおりです。

ExcelシートのA列に、上から順に「りんご」「バナナ」「さくらんぼ」「いちじく」「ぶどう」と入力されている。
BaseFile.xlsx
ExcelシートのA列に、上から順に「バナナ」「みかん」「ぶどう」「すいか」「もも」と入力されている。
CheckFile.xlsx

コードの実装

上述のアプリケーションを実現するコードと、その実行結果を示します。

Option Explicit


Sub MatchFileData()

    
    ' 変数宣言
    Dim base_fp         As String       ' Base File のパス
    Dim base_wb         As Workbook     ' Base Workbook
    Dim base_ws         As Worksheet    ' Base Worksheet
    Dim base_last_row   As Long         ' Base Worksheet の終端行
    Dim base_row        As Long         ' Base Worksheet の行ループ用変数
    Dim base_value      As Variant      ' Base Worksheet のイテレーター値
    
    Dim check_fp        As String       ' Check File のパス
    Dim check_wb        As Workbook     ' Check Workbook
    Dim check_ws        As Worksheet    ' Check Worksheet
    Dim check_last_row  As Long         ' Check Worksheet の終端行
    Dim check_row       As Long         ' Check Worksheet の行ループ用変数
    Dim check_value     As Variant      ' Check Worksheet のイテレーター値
       
    ' 定数設定 ↓ここを修正して使用してください↓
    Const BASE_FILE_NAME    As String = "BaseFile.xlsx"
    Const BASE_TARGET_COL   As Long = 1
    Const CHECK_FILE_NAME   As String = "CheckFile.xlsx"
    Const CHECK_TARGET_COL  As Long = 1


    ' Base File (基準ファイル)を開く
    base_fp = ThisWorkbook.Path & "\" & BASE_FILE_NAME
    Set base_wb = Workbooks.Open(base_fp)
    Set base_ws = base_wb.Worksheets(1)
    base_last_row = base_ws.Cells( _
        base_ws.Rows.Count, BASE_TARGET_COL _
    ).End(xlUp).Row
    
    ' Check File (チェック対象ファイル)を開く
    check_fp = ThisWorkbook.Path & "\" & CHECK_FILE_NAME
    Set check_wb = Workbooks.Open(check_fp)
    Set check_ws = check_wb.Worksheets(1)
    check_last_row = check_ws.Cells( _
        check_ws.Rows.Count, CHECK_TARGET_COL _
    ).End(xlUp).Row
    
        
    ' Base File の行をループ
    For base_row = 1 To base_last_row
        
        ' Base File の値を変数に代入
        base_value = base_ws.Cells(base_row, BASE_TARGET_COL)
            
        ' Check File の行をループ
        For check_row = 1 To check_last_row
            
            ' Check File の値を変数に代入
            check_value = check_ws.Cells(check_row, CHECK_TARGET_COL)
            
            ' Base File の値と Check File の値が一致したら
            If base_value = check_value Then
                
                ' ここに行いたい処理を書く
                Debug.Print check_row, check_value
            
            End If
        
        Next check_row
    
    Next base_row

    ' Cleanup
    base_wb.Close SaveChanges:=False
    check_wb.Close SaveChanges:=False


End Sub

このコードを実行すると、イミディエイトウィンドウに次の結果が返ります。

アプリケーション実行結果
nformation

イミディエイトウィンドウ
各種演算の結果や、処理の途中で変数に代入されている値を表示するなど、プログラムを検証するために使われるツールです。


運営者・ポテ

それでは、順を追って解説していきます。

変数宣言の強制化
Option Explicit

ここでは、Option Explicit を有効にしています。

この設定を使うと、変数を使用する前に必ず宣言が必要になります。これにより、変数のタイプミスや未定義変数によるエラーを防ぎ、コードの安全性と信頼性を高めることができます。

変数の宣言
    ' 変数宣言
    Dim base_fp         As String       ' Base File のパス
    Dim base_wb         As Workbook     ' Base Workbook
    Dim base_ws         As Worksheet    ' Base Worksheet
    Dim base_last_row   As Long         ' Base Worksheet の終端行
    Dim base_row        As Long         ' Base Worksheet の行ループ用変数
    Dim base_value      As Variant      ' Base Worksheet のイテレーター値
    
    Dim check_fp        As String       ' Check File のパス
    Dim check_wb        As Workbook     ' Check Workbook
    Dim check_ws        As Worksheet    ' Check Worksheet
    Dim check_last_row  As Long         ' Check Worksheet の終端行
    Dim check_row       As Long         ' Check Worksheet の行ループ用変数
    Dim check_value     As Variant      ' Check Worksheet のイテレーター値

ここでは、処理対象となる2つのファイルに対応する変数をあらかじめ宣言しています。

変数は Dim 変数名 As データ型 の構文で宣言します。これにより、各変数は As 以降で指定したデータ型の値を格納できるようになります。

ここでは、具体的には、それぞれのファイルに対して、ファイルパス、ブック、シート、最終行、ループ用の行番号、そして比較対象となるセルの値を格納する変数が宣言されています。

変数名には base_check_ の接頭辞を付けておくことで、どちらのファイルに属するものかを明確にし、コードの判読性を良くしています。

また、セルの値を格納する base_valuecheck_value の型に Variant を使用しているのは、文字列や数値など異なるデータ型を柔軟に扱うためです。

Information

イテレーター値
ループ処理の中で、現在の行や列に対応するセルの値を一時的に取り出して使う変数のことです。ここでは、1行ごとに値を読み込んで比較するため、base_valuecheck_value がそれにあたります。

なお、各変数の型の意味は下表の通りです。

データ型種類意味
Workbookオブジェクト型ワークブック全体を表すデータ型です。ファイルを開いたり保存したりする処理に使います。
Worksheetオブジェクト型ワークシートを表すデータ型です。セルの読み書きなど、シート上の操作に使います。
String文字列型文字列を格納するデータ型です。ファイル名やパスなど、テキスト情報に使います。
Long数値型整数を格納するデータ型です。行番号や最終行の取得などに使います。
Variant汎用型どのような型のデータでも格納できるデータ型です。セルの値をそのまま受け取るときに使います。
定数の設定
    ' 定数設定 ↓ここを修正して使用してください↓
    Const BASE_FILE_NAME    As String = "BaseFile.xlsx"
    Const BASE_TARGET_COL   As Long = 1
    Const CHECK_FILE_NAME   As String = "CheckFile.xlsx"
    Const CHECK_TARGET_COL  As Long = 1

ここでは、ファイル名と列番号を定数として定義しています。

Const は、後から値を変更しない前提の固定値を定義するときに使います。

このように定数としてまとめておくことで、ファイル名や対象列をあとから変更したい場合に、コード全体の修正箇所を最小限に抑えることができます

つまり、ここではBaseFile.xlsx の 1列目と、CheckFile.xlsx の 1列目を照合の対象とする設定になっていますが、別のファイルや列番号に変更したい場合は、この部分だけを書き換えれば対応できます。

処理するファイルを開く
    ' Base File (基準ファイル)を開く
    base_fp = ThisWorkbook.Path & "\" & BASE_FILE_NAME
    Set base_wb = Workbooks.Open(base_fp)
    Set base_ws = base_wb.Worksheets(1)
    base_last_row = base_ws.Cells( _
        base_ws.Rows.Count, BASE_TARGET_COL _
    ).End(xlUp).Row
    
    ' Check File (チェック対象ファイル)を開く
    check_fp = ThisWorkbook.Path & "\" & CHECK_FILE_NAME
    Set check_wb = Workbooks.Open(check_fp)
    Set check_ws = check_wb.Worksheets(1)
    check_last_row = check_ws.Cells( _
        check_ws.Rows.Count, CHECK_TARGET_COL _
    ).End(xlUp).Row

ここでは、基準ファイルとチェック対象ファイルを順に開き、さらにそれぞれの最終行を取得しています。

base_fpcheck_fpは、対象ファイルがマクロファイル(ThisWorkbook)と同じフォルダ内にあるという前提で、パスを連結して開いています。

その後、Set を使ってワークブックとワークシートのオブジェクトを取得し、最終行を End(xlUp) を使って求める流れです。

なお、End(xlUp) は「下から上に向かって最初にデータが見つかるセル」を探すExcelの動作を利用した方法です。

このようにして、各ファイルのデータ範囲の終端を正確に把握してから、データマッチング処理に入る流れになっています。

二重ループと IF 文でデータマッチング
    ' Base File の行をループ
    For base_row = 1 To base_last_row
        
        ' Base File の値を変数に代入
        base_value = base_ws.Cells(base_row, BASE_TARGET_COL)
            
        ' Check File の行をループ
        For check_row = 1 To check_last_row
            
            ' Check File の値を変数に代入
            check_value = check_ws.Cells(check_row, CHECK_TARGET_COL)
            
            ' Base File の値と Check File の値が一致したら
            If base_value = check_value Then
                
                ' ここに行いたい処理を書く
                Debug.Print check_row, check_value
            
            End If
        
        Next check_row
    
    Next base_row

ここでは、For...Next ステートメントを二重に使用して、2つのファイルのデータを総当たりで照合しています。

Information

For…Next ステートメントについてはこちらで解説しています:

まず、BaseFile.xlsx の指定列を上から順にループし、各セルの値を base_value に代入します。

次に、CheckFile.xlsx 側でも同様に、各行の値を check_value に取り出し、IF文で両者を比較します。

もし値が一致した場合には、処理ブロック内の Debug.Print により、行番号と値がイミディエイトウィンドウに出力されます。

この部分には、目的に応じて任意の処理(書式変更、別シートへの出力など)を追加することができます。

なお、ここで使用しているループはいわゆる「総当たり」の比較であり、行数が多くなると処理時間が長くなる傾向があります。

必要に応じて、配列を利用して処理を高速化することもできます。

後処理
    ' Cleanup
    base_wb.Close SaveChanges:=False
    check_wb.Close SaveChanges:=False

ここでは、開いたファイルを保存せずに閉じています。SaveChanges:=False は、保存をせずにファイルを閉じる設定を指します。

今回の処理ではファイルに変更は加えていませんが、保存するのかしないのか、意思を持ったコードとするために指定しています。

運営者・ポテ

以上で、解説は終了です。ありがとうございました。

VBAスキルアップの参考情報

近年は、ChatGPTをはじめとするAIの登場によって、学習のスタイルが大きく変わりました。

分からないことがあれば、AIに尋ねれば答えがすぐに見つかる時代です。

とはいえ、AIを使いこなすには、自分自身の基本的な知識や理解力が欠かせません。

全体像をつかむためには、やはり書籍などで体系的に学んでおくことが今でも有効です。

そのうえでAIを活用すれば、自分の理解度に合わせた的確な解説や、応用のヒントを得ることができます。

「学んで基礎を築く → AIで補い発展させる」──このサイクルを重ねることで、VBAスキルは着実に高まっていくでしょう。

VBAのスキルアップ

VBAを学び始めるなら

入門書は、どれを選んでも大きな差はないように感じます。

どれを選ぶかに悩むことに時間をかけるよりも、まずは手頃な一冊を手に取って進めてみるのがおすすめです。

もし迷ったときには、私はインプレス社の「いちばんやさしい」シリーズを選ぶことが多いです。

基礎を超えて力をつけたいなら

私は上級者を目指していましたので、入門書にとどまらず、このような内容の濃い一冊を選んで学んでいました。

今は誰でもAIを活用できる時代になりましたが、上級者を目指す方にとっては、AIをより上手に活用するという意味でも、こうした本は今なお価値があります。

このレベルの本を一冊持っておくことに、損はないでしょう。


資格で能力を証明したいなら

VBAのプログラミング能力を客観的に示したい場合には「VBAエキスパート試験」があります。

特に「スタンダード」の方は上級者向けです。

あなたが社内業務の改善を行う立場であっても、VBAで作成したシステムをお客様に納める立場であっても、この資格は信頼や安心につながるでしょう。

以下の公式テキストが販売されています。



プログラミングの一般教養

「独学プログラマー」というプログラミングの魅力を解説した書籍があります。

これはVBAではなくPythonを題材としていますが、プログラミングの基本的な知識や思考法、仕事の進め方まで幅広く学べます。

今はAIにコードを尋ねれば、答えが返ってくる時代です。

しかし、この本からは「コード」以上に、プログラミングに向き合う姿勢や考え方を学ぶことができるでしょう。


こちらの記事でも紹介しています。もしよろしければご覧ください。

【初心者歓迎】無料相談受付中 

運営者・ポテ

いつもありがとうございます!

限られた時間をより良く使い、日本の生産性を高めたい──

みんなの実用学を運営するソフトデザイン工房では、業務整理や業務改善アプリケーション作成のご相談を承っております。

お気軽にご相談ください。


こちらの記事でも紹介しております。

おわりに

運営者・ポテ

ご覧いただきありがとうございました!

本稿では、「異なるファイル間のデータマッチング(照合・突合)第2版」をお届けいたしました。

お問い合わせやご要望がございましたら、「お問い合わせ/ご要望」フォームまたはコメント欄よりお知らせください。

この記事が皆様のお役に立てれば幸いです。

なお、当サイトでは様々な情報を発信しております。よろしければトップページもあわせてご覧ください。

この記事を書いた人

運営者・ポテソフトデザイン工房|日々の業務にちょうどいい自動化を
■人生を追求する凡人 ■日本一安全で、気の向くままに自分の時間を過ごせる、こだわりのキャンプ場を作るのが夢 ■ソフトデザイン工房運営(個人事業者) - 業務改善アプリケーションをご提供 ■人生は時間そのもの。ひとりでも多くの人が「より良い人生にするために時間を使って欲しい」と願い、仕事のスキルの向上、余暇の充実、資産形成にチャレンジ。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です