ホーム / お役立ち記事 / マクロ入りのブックを比べると全部「違う」と出る理由|VBAのコードはソースで差分比較する
Knowledge
マクロ入りの Excel ブック(.xlsm)を何冊か比べると、マクロが同じでも vbaProject.bin のバイトは違って出ます。入れ物には保存のしかたで変わってよい値が入るためです。お客様から受け取った6冊でも、バイトは全部違い、ソースは同じでした。原因の切り分け、VBA のコードの差分比較をモジュールごとのソースで行う手順、落とし穴、比べ方が正しいかの確かめ方を、弊社の実測と公開の仕様でまとめます。
マクロ入りの Excel ブック(.xlsm)を何冊か受け取り、マクロが同じかをファイルの比較で確かめると、マクロが同じでも「違う」と出ることがあります。
マクロの入れ物の vbaProject.bin には、ソースのほかに、保存のしかたで変わってよい値が入るためです。
マクロが同じかは、vbaProject.bin のバイトではなく、モジュールごとに取り出した VBA のソースで比べます。弊社がお客様から受け取った6冊でも、vbaProject.bin のバイトは全部違い、ソースで比べると同じでした。
この記事は、マクロ入りのブックを何冊も引き継ぐ・1つにまとめる業務の担当者・情報システムの担当者に向けて書きます。
原因の切り分け、見分け方、比べ方、落とし穴、比べ方が正しいかの確かめ方を、弊社が作ったブックでの実測(2026年11月1日)と、Microsoft の公開の仕様で整理します。
.xlsm は ZIP で、マクロは xl/vbaProject.bin という1つの部品に入っています。この部品は、中にさらに「プロジェクトの情報」「モジュールごとのソース」などの小さな部品を持つ入れ物です。
Microsoft が公開している VBA のファイルの仕様(MS-OVBA)によると、この入れ物には、ソースのほかに次の2種類の値が入ります。
どちらも、マクロのソースとは別の値です。ソースが同じでも、vbaProject.bin のバイトが同じになるとは限りません。
そのため、vbaProject.bin のハッシュや大きさが違うことは、マクロが違う証拠になりません。
弊社は、同じ VBA のモジュール2本を入れたブックを3冊作りました。2冊は別々に新しく作って保存し、1冊は1冊目を開いて保存し直しただけです。
| 項目 | 内容 |
|---|---|
| 実測の日 | 2026年11月1日 |
| ブックを作った道具 | LibreOffice 26.2.4.2(macOS 27.0) |
| 比べた道具 | oletools 0.60.2 の olevba(Python 3.14.6) |
| ブック | 同じソースのモジュール2本を入れた .xlsm を3冊 |
結果は、3冊とも vbaProject.bin のバイトが違い、olevba で取り出したソースは3冊とも同じでした。vbaProject.bin の大きさは、3冊とも5,120バイトで同じでした。
別々に作った2冊では、違いはプロジェクトの情報の部品の中だけでした。プロジェクトの識別子と、保護・パスワード・表示の状態を暗号化して書いた3つの文字列が、保存ごとに違いました。ソースの入った部品は同じでした。
開いて保存し直しただけの1冊では、ソースの入った部品のバイトも違いました。取り出して比べると、ソースの末尾に空の行が1行増えていました。
この試しは、LibreOffice で保存したブックだけで行いました。Excel で保存したときに、どの部品がどれだけ変わるかは、弊社は確かめていません。
弊社がお客様から受け取ったマクロ入りのブック6冊でも、vbaProject.bin を比べると、6冊ともバイトが違いました。
olevba でモジュールごとのソースを取り出して比べると、モジュールは名前もソースも6冊とも同じでした。
バイトの違いだけを見ると、同じマクロが6通りあるように見えます。様式を1つにそろえるかどうかの判断は、ソースで比べてから行います。
「マクロが違う」と出たときは、何で比べたかを先に確かめます。比べ方ごとに、分かることが違います。
| 比べ方 | 分かること |
|---|---|
| ファイル全体のハッシュ・大きさ | ブックのどこかが違う。マクロが違うかは分からない |
| vbaProject.bin のハッシュ・大きさ | マクロの入れ物のどこかが違う。マクロが違うかは分からない |
| モジュールごとのソース | マクロのコードが同じか |
大きさも当てになりません。弊社が古い形式のブックを .xlsm に変えたとき、vbaProject.bin は LibreOffice で変えた版が8,704バイト、Excel で保存した版が30,720バイトでした。
この2つをソースで比べると、違いは Attribute の行の有無だけでした。
ソースで比べて違いが出たら、次の順で分けます。
Attribute の行は、モジュールの名前・マクロの説明・ショートカットキーの割り当てなどを書く行です。保存の道具によって落ちたり書き方が変わったりするので、コードの行と分けて見ます。
弊社が実際に通した手順は次のとおりです。比べるのは、モジュールごとに取り出したソースです。
pip install oletools)oletools は、Office のファイルを調べる公開の道具です。
公式の説明では、olevba は Excel 2007 以降の .xlsm に対応し、Python の VBA_Parser の extract_macros で、モジュールごとのソースを取り出せます。
次のコードは、1冊目を基準に、2冊目以降のブックとソースを比べます。弊社の試しのブックで、変えた1行だけが差分に出ることを確かめています。
import sys
import difflib
from oletools.olevba import VBA_Parser
def modules(path):
vp = VBA_Parser(path)
try:
out = {}
for _f, _s, name, code in vp.extract_macros():
lines = code.replace("\r\n", "\n").replace("\r", "\n").split("\n")
out[name] = "\n".join(ln.rstrip() for ln in lines).strip()
return out
finally:
vp.close()
base, *others = sys.argv[1:]
a = modules(base)
print(base, "モジュール", len(a), "本")
for path in others:
b = modules(path)
for name in sorted(set(a) | set(b)):
if a.get(name) == b.get(name):
continue
print(path, name, "違う")
old = (a.get(name) or "").split("\n")
new = (b.get(name) or "").split("\n")
for ln in difflib.unified_diff(old, new, lineterm="", n=0):
print(" ", ln)
print(path, "比べ終わり")
使い方は python compare_vba.py 基準.xlsm 比べる1.xlsm 比べる2.xlsm です。違うモジュールがなければ、ブックごとに「比べ終わり」だけが出ます。
1行目のモジュールの本数が0なら、マクロが無いか、取り出しに失敗しています。
中身を目で見るだけなら、コマンドの olevba -c ブック.xlsm でソースだけを出せます。
弊社の実測(oletools 0.60.2)では、コマンドの出力は既定で Attribute の行を省き、--attr を付けると出ました。上のコードの extract_macros は、Attribute の行も含めて返しました。
バイトの違いを「マクロの違い」と読む上のお客様の6冊では、バイトだけを見るとマクロが6通りあるように見えました。ソースで比べ直すと同じでした。
末尾に空の行が1行増えただけで「違う」と出たLibreOffice で開いて保存し直しただけで、ソースの末尾に空の行が1行増えました。行ごとの空白をそろえるだけでは「違う」のままで、先頭と末尾の空の行を除くと同じと出ました。
形式を変えたら、Attribute の行が落ちた古い形式(.xls)のマクロ入りのブックを LibreOffice で .xlsm に変えると、コードの行は残り、Attribute の行(マクロの説明やショートカットキーの割り当てを書く行)が落ちました。
Excel で保存し直した版には残っていました。
シートの部品のバイトも違ったお客様の同じ様式のブックどうしでは、入力に使わないシートの部品のバイトにも、ブックによって違う物がありました。セルの値で比べ直すと、違うセルはありませんでした。
比べた結果が「全部同じ」のとき、本当に同じなのか、比べ方が違いを拾えていないのかは、結果だけでは区別できません。次の手順で、比べ方そのものを確かめます。
弊社の試しでは、1行変えたブックは変えたモジュールだけが「違う」と出て、保存し直しただけのブックは「同じ」と出ました。この2つがそろって、比べ方が使えると判定しました。
比べる冊数が少なく、Python を動かせて、知りたいのが「コードが同じか」だけなら、自力で足ります。上のコードは、仮想環境と oletools だけで動きます。
自力の壁は次の3つです。
外注の分かれ目は、比べた後に、マクロが何をしているかを読み解き、使われていない処理や重複している処理を見分ける必要があるかです。外注するなら、見積もりを比べる前に次の3点を確かめてください。
ゴムマリでは、作った人がいなくなったマクロ・アドインの解読を、マクロ・VBA解読/リファクタリングとして承ります。
読める仕様書と、使われていない処理・重複している処理を洗い出した残す・捨てるの判断メモをお渡しします。続けて頼むと、同じ結果を出す再実装と、新旧を全件で突き合わせた照合の記録もお渡しします。
料金は5万円から、期間は1週間からです。ファイルをお送りいただくと、無料のファイル診断で、規模と着手前の額をお返しします。マクロの外注の相場は業務自動化の外注費用まとめに整理しています。進め方は相談からご連絡ください。
手元のマクロ入りのブックを2冊選び、olevba -c で両方のソースを出して、モジュールの名前と本数をそろえて見てください。本数が同じで、名前ごとのソースが同じなら、バイトが違ってもマクロは同じです。
違うモジュールがあれば、そのモジュールだけ行の差分を出し、どちらの版を残すかを決めます。決める前に、そのマクロが何をしているかを書き出しておくと、残す理由を後から説明できます。
既存の Excel の様式にプログラムで値を書き込むときに、マクロの部品が消える理由は、Excel帳票への自動書き込みでファイルが壊れる理由にまとめています。
ワークスアプリケーションズで大手企業向けERPの営業と導入を担当し、外資系SaaS企業と国内大手放送局で販路と新規事業の立ち上げ、AI学習用データを扱うAIスタートアップ2社でマーケティングと営業を担った。2024年10月から生成AIの実装に入り、いまは大手企業の現場で、AIエージェントを要件定義から運用まで手がけている。
Ask
専門業務AI-BPO
マクロ・VBA解読/リファクタリング
作った人が辞めて誰も直せないExcelマクロ・アドインを、読める仕様書にして返します。続けて頼むと、同じ結果を出す形に作り直し、新旧の全件照合レポートをつけます。まずは無料のファイル診断で、規模と着手前の額をお返しします。
5万円〜(1週間〜)
Related
Excel の台帳を Notion へ移すには、表の形とキーを決め、型を決めてリレーションと一緒に取り込み、数式と集計を作り直してから、件数・キー・値・先頭のゼロ・空の値・リレーション・計算の結果の7つで照合します。Notion の公式ヘルプと API の文書の決まりと、弊社が管理表の約2千明細を移し、Notion で計算した残が移したすべてのロットで元の表と一致した照合の手順でまとめます。
活用ガイドNotion AI に書類を作らせて照合するときは、手順を Notion AI への指示書、読めば決まる処理を添付のコード、1回ごとの結果を記録のデータベースに分けます。弊社の導入の事例の試作では、同じ題材で、文章の指示は発注番号を3回のうち2回誤り、添付のコードは2回とも誤りませんでした。分け方の問い、進める手順、誤りを仕込む照合の進め方を、弊社の記録でまとめます。
FAQ
そうとは限りません。vbaProject.bin には、ソースのほかに、保存のしかたで変わってよい値が入ります。弊社が LibreOffice で同じソースのマクロを3回保存したブックでは、3冊ともバイトが違い、ソースは同じでした。マクロが同じかは、モジュールごとに取り出したソースで比べます。
弊社は Excel では確かめていません。LibreOffice で試すと、別々に保存した2冊はプロジェクトの識別子と、保護などを暗号化して書いた3つの文字列が違い、開いて保存し直しただけの1冊はソースの末尾に空の行が1行増えていました。
コードの行は同じです。ただし Attribute の行には、マクロの説明やショートカットキーの割り当てが入ります。弊社が古い形式のブックを LibreOffice で .xlsm に変えたときは、この行が落ちました。使い方に関わる行なので、違いが Attribute の行だけでも中身を見ます。
限りません。ブックの動きは、シートの式・名前の定義・参照設定・フォームの部品にも左右されます。ソースの比べはそこを見ません。弊社はお客様のブックで、ソースに加えて、同じ様式のブックどうしで入力に使わないシートのセルの値も比べ、同じであることを確かめました。