店舗ごとの在庫データや、システムから出力された売上データ。「商品IDをキーにして、2つの表の差分を比較したい!」という場面、実務で本当によくありますよね。
しかし、スプレッドシートのVLOOKUP関数で数千件のデータを突合しようとすると、重くて画面がフリーズ…。
「GAS(Google Apps Script)を使えば自動化できそうだけど、どうコードを書けばいいかわからない!」と悩んでいませんか?
この記事では、「やりたいことは明確なのに、GASの書き方がわからない初級者」に向けて、2つの2次元配列データを一瞬で比較・結合する最強のテクニックをご紹介します。
コードはコピペで動くように用意してあるので、まずはご自身の環境で試してみてください!
1. なぜ、データ比較のGASは「エラー」になりやすいのか?
GASを学び始めた方が、2つのデータを比較しようとしたとき、よくやってしまう書き方があります。
それは「for文の中に、さらにfor文を書く(ループのネスト)」という方法です。

実はこれ、データ量が増えるとGASの実行時間制限(6分ルール)に引っかかってエラーになってしまいます。
❌ NGな探し方(for文のネスト)
「かえで薬局」の棚にある薬を1つ手に取るたびに、「いちょう薬局」の棚の端から端まで歩いて同じ薬を探す作業。
もしデータが1,000件ずつあった場合、1,000回 × 1,000回 = 100万回も探す作業が発生してしまいます。
これでは時間がいくらあっても足りませんよね。
2. 解決策は、データを「辞書」にしておくこと
この問題を解決する魔法のテクニックが、オブジェクト {} を使った「辞書化」です。
⭕️ 正解の探し方(辞書化)
探される側(いちょう薬局)のデータを、あらかじめ「商品IDのインデックス付き辞書」に作り替えておく。
GASでは、データを { 'A001': [データの中身] } のように、「見出し(キー)」と「中身(値)」のセットにしておくことができます。
これなら、かえで薬局の薬を手に取ったとき、辞書をパッと引くだけで一瞬でいちょう薬局のデータが見つかります。
3. 【コピペOK】複数拠点のデータを高速比較するサンプルコード
それでは、実際のコードを見てみましょう。
今回は「かえで薬局」と「いちょう薬局」の在庫一覧データ(2次元配列)を読み込み、共通の「薬品ID」をキーにして突合し、在庫の差分を出すスクリプトです。
まずは以下のコードを、ご自身のGASエディタにコピペして実行してみてください。
function compareInventoryFast() {
// ① データの準備(実際はスプレッドシート等から取得した2次元配列)
// 並び順:[薬品ID, 薬品名, 在庫数, カテゴリ]
const kaedeData = [
['A001', 'ロキソプロフェン', 500, '内服薬'],
['A002', 'ムコスタ', 300, '内服薬'],
['X999', '管理薬剤師手当', 1, '人員'] // ← 合算してはいけないノイズデータ
];
const ginkgoData = [
['A001', 'ロキソプロフェン', 400, '内服薬'],
['A003', 'カロナール', 200, '内服薬'],
['X999', '応援事務', 1, '人員'] // ← 合算してはいけないノイズデータ
];
// ② 事前処理:ノイズデータ(人員など)を除外する
const isNotPersonnel = (row) => row[3] !== '人員';
const cleanKaede = kaedeData.filter(isNotPersonnel);
const cleanGinkgo = ginkgoData.filter(isNotPersonnel);
// ③ 比較される側(いちょう薬局)のデータを「辞書化 {}」する
const ginkgoObj = {};
for (let i = 0; i < cleanGinkgo.length; i++) {
const row = cleanGinkgo[i];
const itemId = row[0]; // 薬品ID(0番目の列)を見出しにする
ginkgoObj[itemId] = row; // IDを見出しとして、行のデータを丸ごと格納
}
// ④ ベースデータ(かえで薬局)を順番に見て、辞書と突き合わせる
const result = [];
for (let i = 0; i < cleanKaede.length; i++) {
const kaedeRow = cleanKaede[i];
const itemId = kaedeRow[0]; // 探したい薬品ID
// 辞書に見出し(薬品ID)があるか一発で確認!
if (ginkgoObj[itemId]) {
const ginkgoRow = ginkgoObj[itemId];
const diff = kaedeRow[2] - ginkgoRow[2]; // 在庫数の差分を計算
// 結果を新しい配列として保存:[ID, 薬品名, かえで在庫, いちょう在庫, 差分]
result.push([itemId, kaedeRow[1], kaedeRow[2], ginkgoRow[2], diff]);
} else {
// 辞書になかった(いちょう薬局に在庫がない)場合
result.push([itemId, kaedeRow[1], kaedeRow[2], 0, kaedeRow[2]]);
}
}
// ⑤ 抽出結果の確認(ログ出力)
console.log(result);
}
4. あなたのデータに合わせてカスタマイズ!
コピペで動くことを確認したら、次はご自身の業務データに合わせてコードを書き換えてみましょう。変更するポイントは主に以下の2つです。
📌 ポイント1:キーとなる「列」の番号を変更する
プログラミングの世界では、配列(列)の番号は「0」から始まります。
- A列 =
0 - B列 =
1 - C列 =
2
サンプルコードの const itemId = row[0]; は、「A列の薬品IDをキーにする」という意味です。もし比較したいIDがC列にある場合は、ここを row[2] に変更してください。
📌 ポイント2:抽出したい結果の形を変える
コードの後半にある result.push([...]) の部分が、最終的に出力されるデータの中身です。
ご自身がスプレッドシートに書き出したい列の順番に合わせて、kaedeRow[0](かえでのA列)などを自由に組み合わせてみてください。
5. 【実務のリアル】比較前の「ゴミ取り」を忘れずに
最後に、実務でシステムを組む際の重要なワンポイントアドバイスです。
業務システムからCSVなどで出力した生データには、純粋な在庫や売上以外に「人員計算用のダミーデータ」や「小計行」などのノイズが混ざっていることがよくあります。
これをそのまま突合してしまうと、二重計上や思わぬエラーの原因になります。
サンプルコードの「② 事前処理」で filter を使っているのはそのためです。
「データを比較する前に、不要なゴミを取り除いておく」。このひと手間をコードに組み込めるようになると、現場で重宝される実用的なツールに一気に進化します!
まとめ:GASでデータ処理の限界を突破しよう
VLOOKUPやfor文のネストは処理が重くなる原因。- データを
{}で「辞書化」すれば、検索スピードが劇的に上がる。 - 実務データは、比較する前に
filterで綺麗にする。
「やりたいことは分かっているのに…」と足踏みしていた方は、ぜひこの「辞書化」のテクニックを使って、GASでの自動化を一歩前に進めてみてください!
