ExcelでERP(TROPOS/Epicor)出力のTEST RESULTを個体ID別に横展開する方法|FILTER+CHOOSECOLSでXLOOKUPの先頭値問題を解決

ERP(TROPOS/Epicor)のExcel出力では、検査の種類は「CHARACTERISTIC DESCRIPTION」、値は「TEST RESULT」に縦持ちで並ぶことがあります。GRN/LOT/PCODEごとにColour・Haze・Density…を横に展開する、FILTER+CHOOSECOLS+LOOKUPの実装手順と注意点を解説します。

目次

ERPの検査結果が「縦持ち」で出てくると何が起きる?

ERPからの品質検査・分析結果のエクスポートは、見た目としては「データベースに近い形式」で出力されることが多いです。つまり、1行に1つの測定項目(Characteristic)が入り、どの測定なのかは説明列(CHARACTERISTIC DESCRIPTION)で区別し、測定値は結果列(TEST RESULT)に入ります。

この形式は保存や連携には強い一方で、Excelで「個体(ロットやGRN)ごとにColour/Haze/Densityを横に並べて比較したい」「Power BIで項目別に可視化したい」という場面では、そのままでは扱いづらくなります。

列の例意味よくある値この問題での役割
GRN / LOT / PCODE個体ID(キー)GRN12345、LOT2025-001、PCODE-A横展開の「行キー」
CHARACTERISTIC DESCRIPTION測定項目の説明Colour、Haze、Density…横展開の「列見出し」
TEST RESULT測定値10.2、PASS、0.012…横展開で表示したい値
DATE / REV / UPDATE…更新日時・版など2025/12/01 10:30…重複(更新)時の優先順位に影響

完成形のイメージ(横展開テーブル)

今回のゴールは、Sheet1側に次のような「1行=1個体」の表を作ることです。列は「説明(Characteristic)」の種類ぶん増えます。

個体ID(GRN/LOT/PCODE)ColourHazeDensity…
GRN12345Yellow0.121.03…
GRN12346Amber0.081.02…

なぜXLOOKUPで「先頭の値」問題が起きるのか

XLOOKUP(やVLOOKUP)は、基本的に「検索キーに一致する最初の1件」を返す設計です。ERPの縦持ちデータでは、同じ個体IDに対して複数の測定項目が並ぶため、IDだけで検索すると「Colourの行なのか」「Hazeの行なのか」を区別できず、結果としてそのIDの最初に出てきたTEST RESULTが返り続けます。

もちろん、IDと説明を結合した「複合キー」を作ってXLOOKUPする方法もあります。ただし、ERP出力の行数が多い場合は結合キー列を作るだけで重くなったり、説明名の揺れ(余計なスペース、全角半角、改行)で一致しなかったりします。そこでおすすめなのが、次の考え方です。

解決の考え方:IDで絞った“部分表(サブ配列)”を作ってから引く

ポイントはとてもシンプルで、「まずIDで行を絞る」→「必要列だけを抜く」→「説明で結果を引く」という二段階に分けることです。

処理使う関数狙い
IDの行だけ抽出FILTERその個体の行群(サブ配列)だけにする
説明列+結果列だけ抜くCHOOSECOLS検索対象を最小化し、列番号ミスも把握しやすくする
説明→結果を取得VLOOKUP / XLOOKUPColour列にはColourの結果、Haze列にはHazeの結果を返す

Excelでの実装手順(FILTER+CHOOSECOLS+LOOKUP)

ここからは、ERP出力が入ったシートをQuery1、横展開先をSheet1として説明します。なお、以下の式に出てくる xxx は Query1 の最終行番号に置き換えてください(ここがズレると、重くなる/結果が欠ける/開くだけで固まる、の原因になりやすいです)。

説明(CHARACTERISTIC DESCRIPTION)の一覧をヘッダーとして展開する

まず、横展開テーブルの列見出しを自動生成します。説明名が増減しても列が自動で追従するので、保守が楽になります。

セル式意味
A1=Query1!C1:E1IDなど固定の見出しを持ってくる(運用に合わせて調整)
D1=TRANSPOSE(SORT(UNIQUE(Query1!H2:Hxxx)))説明列のユニーク一覧を作り、横方向に並べる

このとき、説明名に余計なスペースが混じると「同じ項目なのに別物扱い」になりがちです。もし説明名が揺れる場合は、別列に正規化した説明(TRIMなど)を作ってからUNIQUEにかけるのが安定します。

個体ID(GRN/LOT/PCODE)の一覧を作る

次に、1行=1個体となるように、個体IDのユニーク一覧を作ります。

セル式意味
A2=UNIQUE(Query1!C2:Cxxx)個体IDのユニーク一覧(ここではC列が個体キーの想定)

もしGRN/LOT/PCODEが別々の列にあり、3列セットで個体を一意にしたい場合は、Query1側で「結合キー列」を作ってからそれをC列として扱うのが分かりやすいです。

例:Query1の空き列(例:B列)に結合キーを作る

=C2&"|"&D2&"|"&E2

この結合キーをSheet1側のA列に使えば、複合キーでも同じ手順で横展開できます。

“その個体だけ”のサブ配列から固定項目を引く

Sheet1に「LOT」や「PCODE」など固定情報も持たせたい場合は、IDでFILTERした配列から該当列を引きます。固定情報は通常、同一IDなら同じ値なので、先頭行の値を取れれば十分です。

=VLOOKUP($A2, FILTER(Query1!$C$2:$L$xxx, Query1!$C$2:$C$xxx=$A2), 2)

上の式は「IDで絞った行群」から2列目を取る例です。どの列を取るかはQuery1の列構成に合わせて調整してください。

横展開の核心:説明(列見出し)をキーにしてTEST RESULTを返す

いよいよColour/Haze/Density…の列を埋める式です。D2に次の式を入れ、右方向にコピーしてから、必要行まで下方向にコピーします。

=VLOOKUP(D$1, CHOOSECOLS(FILTER(Query1!$C$2:$L$xxx, Query1!$C$2:$C$xxx=$A2), 6, 7), 2, 0)

この式がやっていることを、日本語にすると次の通りです。

  • FILTER:Query1から「IDがA2の行」だけを抜き出す
  • CHOOSECOLS:抜き出した行群から「説明列(6列目)」「結果列(7列目)」だけに絞る
  • VLOOKUP:列見出し(D1の説明名)に一致する行の「結果」を返す

エラー(該当項目が存在しないなど)を空欄にしたい場合は、次のようにIFERRORで包むと表が見やすくなります。

=IFERROR(VLOOKUP(D$1, CHOOSECOLS(FILTER(Query1!$C$2:$L$xxx, Query1!$C$2:$C$xxx=$A2), 6, 7), 2, 0), "")

CHOOSECOLSの列番号がズレる理由と、確実な合わせ方

CHOOSECOLSは「FILTERで作った配列の左端を1列目として数える」ため、FILTERの開始列を変えると列番号も全部変わります。ここを勘で合わせると、存在しない列を指して壊れたり、別の列を引いて気づけなかったりします。

たとえば、FILTER範囲を Query1!$C$2:$L$xxx とした場合、列番号対応は次のようになります。

FILTER範囲内の列番号実際の列例(よくある項目)
1C個体ID(GRN/LOT/PCODE)
2DLOT など
3EPCODE など
6HCHARACTERISTIC DESCRIPTION(説明)
7ITEST RESULT(結果)

自分のデータで「説明がH列、結果がI列」ではない場合は、上の表の考え方で列番号を組み替えてください。列番号が合っているか不安なときは、まず

=CHOOSECOLS(FILTER(Query1!$C$2:$L$xxx, Query1!$C$2:$C$xxx=$A2), 6, 7)

だけを別セルに入れて、説明と結果の2列が出ているか目視で確認すると、事故が減ります。

同一ID+同一説明が複数行ある場合(更新で重複が出る)

要件が「先頭(元データ)だけ取れればOK」であれば、今回の構成は相性が良いです。なぜならVLOOKUPは一致候補が複数あっても先に見つかった1件を返すからです。

ただし、「先頭」がどれかは並び順に依存します。ERP出力が更新日時順で並んでいるのか、抽出条件で順序が変わるのか、は運用によって変わります。先頭の定義を安定させたい場合は、FILTERで抜いた後にSORT/SORTBYで並び替えてからLOOKUPするのが安全です。

やりたいこと考え方実装の方向性
最初(元)を取りたい古い日時が先になるように整列してから先頭を使うSORTBYで日時昇順 → VLOOKUP(先頭一致)
最新を取りたい新しい日時が先になるように整列してから先頭を使うSORTBYで日時降順 → VLOOKUP(先頭一致)

例として、更新日時がFILTER範囲内の「8列目」にあるなら、概念的には次のように組み立てます(列番号は実データに合わせて調整してください)。

=LET(
  id, $A2,
  sub, FILTER(Query1!$C$2:$L$xxx, Query1!$C$2:$C$xxx=id),
  sorted, SORTBY(sub, CHOOSECOLS(sub, 8), -1),
  IFERROR(VLOOKUP(D$1, CHOOSECOLS(sorted, 6, 7), 2, 0), "")
)

LETを使うと「FILTERした結果を何度も計算し直す」無駄を減らせるため、データが多い場合ほど効果が出やすいです(Excel 365/2021以降が前提)。

実運用で重くなりやすい理由と、まず効く対策

この手の横展開を数式だけでやると、データ規模によっては計算量が爆発します。とくに「行数が多い」「説明の種類が多い(Colour/Haze/Density…が200種類など)」「Sheet1側のセル数が膨大(ID数×説明数)」の3点が揃うと、再計算が極端に遅くなったり、ファイルを開くだけで固まったりします。

まず効きやすい対策を、現実的な順に並べます。

対策効果具体例
全列参照(A:Aなど)をやめる計算範囲を減らして劇的に軽くなるQuery1!H:HではなくQuery1!H2:Hxxx
Query1をExcelテーブル化する最終行xxx管理から解放され、参照も安定Ctrl+Tでテーブル化し、tQuery[TEST RESULT]のように参照
説明の種類を絞る/分割する列数が減り、セル総数が減るITEM TYPE別にシートを分ける、必要項目だけヘッダーに採用
計算方法を見直す再計算タイミングを制御できる手動計算、Power Pivot/Power BIに寄せる

テーブル参照に置き換えると、式が読みやすく壊れにくい

xxx行の管理に悩まされる場合は、Query1の範囲をテーブル化し、テーブル名を(例)tERPとして、列名参照に置き換えるのがおすすめです。列名は環境に合わせて読み替えてください。

=TRANSPOSE(SORT(UNIQUE(tERP[CHARACTERISTIC DESCRIPTION])))
=UNIQUE(tERP[個体ID])
=IFERROR(
  VLOOKUP(D$1,
    CHOOSECOLS(
      FILTER(tERP, tERP[個体ID]=$A2),
      1, 2
    ),
  2, 0),
"")

この場合、FILTERにテーブルそのものを渡し、CHOOSECOLSで「説明列」「結果列」を抜くイメージです。列番号は「FILTER後のテーブル配列の中で何列目か」で数えるため、テーブルの列順を固定しておくとより安全です。

大量データならPower Queryでピボットする方が安定しやすい

数式での横展開は便利ですが、数十万行規模になると限界が来ることがあります。そういうときは、ExcelのPower Query(データの取得と変換)で「縦持ち→横持ち」を作ってしまう方が、結果的に安定します。

Power Queryでの基本手順(概要)

  • Query1の範囲をテーブル化(Ctrl+T)
  • データタブ → 「テーブルまたは範囲から」
  • 不要列を削除(最初はID・説明・結果・更新日時だけ残すのが安全)
  • 重複がある場合は、更新日時で並べ替えてから「重複の削除」またはグループ化で先頭行を残す
  • 変換タブ → 「列のピボット」:ピボットする列=説明、値の列=結果
  • 読み込み先をSheet1やデータモデルに指定して完了
アプローチ向いているケース注意点
数式(FILTER+LOOKUP)行数が少ない〜中規模/手早く作りたい/説明が頻繁に変わるセル数が増えると再計算が重くなる
Power Query(ピボット)行数が多い/更新頻度が高い/安定運用したい最初の設定に少し慣れが必要(更新はワンクリック)

よくあるつまずきとチェックリスト

最後に、同じ構成でハマりやすいポイントをまとめます。エラーが出たときは、上から順に確認すると復旧が早いです。

症状原因として多いもの対処
#N/A が多発する説明名が一致していない(スペース、表記ゆれ)/その個体に項目が存在しない説明列をTRIMで正規化/IFERRORで空欄化/ヘッダー側のUNIQUE元を見直す
全て同じ値が入るLOOKUPの検索キーがIDだけになっている/D$1参照がずれているFILTERでID絞り込み→説明で引く形になっているか確認/$の位置を確認
別の列の値が返るCHOOSECOLSの列番号がズレているFILTER範囲の左端を1として列番号を再計算/CHOOSECOLSだけ単体で出力して確認
ファイルが重い・固まる全列参照/xxxが過大/ID×説明のセル数が多すぎる参照範囲を実データに限定/テーブル化/Power Queryへ切替/項目を分割

まとめ

ERP(TROPOS/Epicor)から出力された「説明列+結果列」の縦持ちデータは、Excel側で横展開できると分析が一気に楽になります。XLOOKUPが先頭値しか返らないときは、IDでFILTERしたサブ配列を作ってから、説明名をキーに結果を引くのが最短ルートです。

小〜中規模なら数式で十分、データが大きくなったらPower Queryを選ぶ、という住み分けにすると、保守性とパフォーマンスのバランスが取りやすくなります。まずは範囲(xxx)と列番号(CHOOSECOLS)を正しく合わせるところから始めてみてください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次