【不規則明細・完結編】行数がバラバラなデータの「正規化展開」
エクセルでCOBOL帳票や固定長データを整形したい方向けに、Excel関数・Power Query・MIDBなどを使って列分割、不要行除去、帳票データ変換を進める実務手順を扱います。
この記事の内容
💡 伝票ごとに明細行数が違う帳票の攻略
前回の超絶技巧編では、「ヘッダー行(親情報)を明細行に紐付けるフィルダウン」と「フラグ+抽出+MIDB分解」のパイプラインを学びました。
あの記事で紹介したデータは、各伝票の明細行数がたまたま揃っていました。では伝票ごとに明細の件数がバラバラだったら? ― 結論から言えば、超絶技巧編と全く同じパイプラインがそのまま機能します。
・明細行数がバラバラでもパイプラインは一切変更不要であることを確認する。
・本当に難易度が跳ね上がる「マルチラインレコード」について、攻略の考え方を押さえる。
【2】今回の帳票データ
以下のようなCOBOL帳票を想定します。第一商事は3件、第二物産は2件、第三工業は4件と、伝票ごとに明細行の件数がバラバラです。超絶技巧編と同じフォーマット・同じバイト位置ですが、件数だけが異なります。
ヘッダー行は「■」で始まり、明細行は先頭付近に「A」があります。区切り線(---)やその他の行はゴミ行です。この判定条件は超絶技巧編と全く同じです。
【3】超絶技巧編と同じ3ステップで正規化する
超絶技巧編で構築したパイプラインをそのまま適用します。流れを改めて確認しましょう。
Step 1 ― 貼付シート:フラグ列とフィルダウン列を作る
貼付シートのB列にデータを貼り付け、A列(フラグ列)とC列(フィルダウン列)に数式を入れます。
A列(フラグ列)の数式 ― A2に入れて下方コピー
明細行の判定位置(3バイト目)に「A」があればROW番号を返し、それ以外は空白にします。
C列(フィルダウン列)の数式 ― C2に入れて下方コピー
行の先頭が「■」(ヘッダー行)であればそのデータを取り込み、そうでなければ直上セルの値を引き継ぎます。
| A(フラグ) | B(元データ) | C(フィルダウン) | |
| 1 | フラグ | 元データ | 親情報 |
| 2 | ■伝票 9001 ㈱第一商事 | ■伝票 9001 ㈱第一商事 | |
| 3 | ------------------------------- | ■伝票 9001 ㈱第一商事 | |
| 4 | 4 | A 101 消しゴム 500 | ■伝票 9001 ㈱第一商事 |
| 5 | 5 | A 102 えんぴつ 300 | ■伝票 9001 ㈱第一商事 |
| 6 | 6 | A 103 ノート 800 | ■伝票 9001 ㈱第一商事 |
| 7 | ------------------------------- | ■伝票 9001 ㈱第一商事 | |
| 8 | ■伝票 9002 ㈱第二物産 | ■伝票 9002 ㈱第二物産 | |
| 9 | ------------------------------- | ■伝票 9002 ㈱第二物産 | |
| 10 | 10 | A 201 ボールペン 120 | ■伝票 9002 ㈱第二物産 |
| 11 | 11 | A 202 クリップ 60 | ■伝票 9002 ㈱第二物産 |
| 12 | ------------------------------- | ■伝票 9002 ㈱第二物産 | |
| 13 | ■伝票 9003 ㈱第三工業 | ■伝票 9003 ㈱第三工業 | |
| 14 | ------------------------------- | ■伝票 9003 ㈱第三工業 | |
| 15 | 15 | A 301 定規 150 | ■伝票 9003 ㈱第三工業 |
| 16 | 16 | A 302 ハサミ 400 | ■伝票 9003 ㈱第三工業 |
| 17 | 17 | A 303 テープ 90 | ■伝票 9003 ㈱第三工業 |
| 18 | 18 | A 304 のり 110 | ■伝票 9003 ㈱第三工業 |
フラグもフィルダウンも「今の行がヘッダーか明細かゴミか」を判定しているだけです。伝票ごとの明細が何件あるかという情報は一切参照していません。だから行数がバラバラでも数式は全く同じです。
Step 2 ― 抽出シート:明細行だけを取り出す
抽出シートでは、フラグ列に値がある行(=明細行)だけを取り出します。
Excel 2021 / 2024 / Microsoft 365 などの場合(FILTER関数)
全バージョン対応(INDEX + SMALL + IFERROR)
抽出シート!A2(元データ)
抽出シート!B2(親情報)
| A(元データ) | B(親情報) | |
| 1 | 元データ | 親情報 |
| 2 | A 101 消しゴム 500 | ■伝票 9001 ㈱第一商事 |
| 3 | A 102 えんぴつ 300 | ■伝票 9001 ㈱第一商事 |
| 4 | A 103 ノート 800 | ■伝票 9001 ㈱第一商事 |
| 5 | A 201 ボールペン 120 | ■伝票 9002 ㈱第二物産 |
| 6 | A 202 クリップ 60 | ■伝票 9002 ㈱第二物産 |
| 7 | A 301 定規 150 | ■伝票 9003 ㈱第三工業 |
| 8 | A 302 ハサミ 400 | ■伝票 9003 ㈱第三工業 |
| 9 | A 303 テープ 90 | ■伝票 9003 ㈱第三工業 |
| 10 | A 304 のり 110 | ■伝票 9003 ㈱第三工業 |
第一商事は3件、第二物産は2件、第三工業は4件 ― 件数がバラバラでも、明細行だけが正しく親情報と一緒に抽出されています。
Step 3 ― MIDB分解:固定長データを列に分ける
抽出シートのデータをMIDBで切り出して、最終的な正規化テーブルを作ります。ここも超絶技巧編と同じ手法です。
C列:取引先
D列:商品コード
E列:商品名
F列:金額
最終的な正規化テーブル
| 取引先 | 商品コード | 商品名 | 金額 |
|---|---|---|---|
| ㈱第一商事 | 101 | 消しゴム | 500 |
| ㈱第一商事 | 102 | えんぴつ | 300 |
| ㈱第一商事 | 103 | ノート | 800 |
| ㈱第二物産 | 201 | ボールペン | 120 |
| ㈱第二物産 | 202 | クリップ | 60 |
| ㈱第三工業 | 301 | 定規 | 150 |
| ㈱第三工業 | 302 | ハサミ | 400 |
| ㈱第三工業 | 303 | テープ | 90 |
| ㈱第三工業 | 304 | のり | 110 |
各ステップ(フラグ・フィルダウン・抽出・MIDB分解)は、すべて「今の行がヘッダーか明細かゴミか」という行種の判定だけで動いています。1伝票に明細が何行あるかという情報は一切必要としません。だから行数が固定でもバラバラでも、同じ数式がそのまま機能するのです。
【4】なぜ行数バラバラでも同じ数式で処理できるのか
改めて核心を整理します。パイプライン方式(フラグ+フィルダウン+抽出+MIDB分解)は「今の行がヘッダーか明細かゴミか」という行種の判定だけで動いています。1伝票に明細が何行あるかという情報は一切必要としません。
フラグ列は「3バイト目がAなら明細」と判定し、フィルダウン列は「先頭が■ならヘッダー」と判定する。この2つの判定は各行が自己完結しているため、前後の行数構成に一切影響されません。抽出シートもフラグが付いた行を拾うだけなので、3件でも2件でも4件でも正しく動きます。
パイプライン方式は行数の規則性に依存しない。行種の判定だけで動く汎用的な手法であり、あらゆる帳票構造に対応できます。
【5】速度面の注意
超絶技巧編で解説した速度面の注意はここでも同様に当てはまります。
COBOL帳票は貼付シートの行数が10万〜30万行になることがあります。MIDB分解のような重い計算を全行に適用すると処理が極端に遅くなるため、貼付シートではフラグとフィルダウンだけを行い、MIDB分解は抽出シート(明細行だけに絞った後)で実行するのが鉄則です。
例えば30万行の帳票で明細行が5,000行なら、MIDB分解の対象が60分の1に削減されます。この設計思想がパイプライン方式の速度上の利点です。
MATCH方式による高速参照や、対応環境でのSCAN+FILTERによるワンステップ処理については超絶技巧編を参照してください。
【6】本当に難易度が跳ね上がるのは「1明細が複数行に跨るケース」
ここまで見てきたように、伝票ごとの明細「件数」がバラバラなだけであれば、超絶技巧編のパイプラインをそのまま適用するだけで対処できます。
しかし実務では、さらにやっかいなケースが存在します。それは「1つの明細データ自体が2行以上に跨って記述されている」場合です。これが本当に厄介で、パイプラインをそのまま適用しただけでは解決しません。
COBOL帳票は印刷帳票のイメージをそのまま出力しているため、1つの明細の情報が人間が見やすいように複数行に分けて記述されることがよくあります。例えば以下のような形です。
このように1つの明細が2行・3行に分かれている「マルチラインレコード」は、印刷レイアウトの都合でごく当たり前に発生します。各行のMIDB位置(何バイト目に何がある)は固定ですが、1行目にはコードと商品名、2行目には数量と単価、3行目には納期…というように情報が行をまたいで分散しているのが特徴です。
攻略の考え方:貼付シートの作業列で「1行にまとめる」前処理を行う
マルチラインレコードに対処するための基本的な考え方は、貼付シートの作業列を増やして、各行からMIDBで必要な部分だけを切り出し、それらを1行に集約するというものです。
COBOL帳票は固定長データであるため、「明細の1行目は何バイト目にコードがある」「2行目は何バイト目に数量がある」「3行目は何バイト目に納期がある」という位置の規則性は必ず存在します。この規則性をまず目視で読み解くことが最初のステップです。
規則性を把握したら、貼付シートに作業列を追加して各行からMIDBでパーツを切り出します。そして明細の1行目の行に対して、直下の2行目・3行目の情報を作業列で横に集約すれば、「元は3行に分かれていたデータが、1行のレコードとして揃っている」状態を作ることができます。あとはその作業列に情報が揃った行だけをフラグで拾い、通常のパイプラインに乗せるだけです。
「明細が常に3行セット」なのか「2行目・3行目があったりなかったり」なのか、帳票によって構造が全く異なります。そのため本ページでは具体的な数式パターンを網羅することはせず、「まず規則性を目視で読み解き、作業列で1行にまとめてからパイプラインに乗せる」という考え方の原則だけをお伝えしています。
明細の1行目・2行目・3行目で「行の種類を区別する判定条件」を別々に用意した上で、それらを横に結合する仕組みが必要になります。フラグの種類が増え、抽出ロジックも複雑化するため、本シリーズで扱っている「1明細=1行」の帳票とは根本的に設計が変わります。
明細の「件数」がバラバラ(伝票ごとに明細行数が違う) → 超絶技巧編と同じ手法で対応可能
1明細が「複数行」に跨っている(マルチラインレコード) → 規則性の解析+作業列での結合が必要で、難易度が大きく上がる
📝 総まとめ
伝票ごとの明細行数がバラバラでも、超絶技巧編で学んだ「フラグ+フィルダウン+抽出+MIDB分解」のパイプラインは全く同じ数式でそのまま機能します。パイプラインは各行の「種類」だけを判定しており、行数の規則性には依存しないためです。
本当に難易度が上がるのは「1明細が複数行に跨るマルチラインレコード」のケースです。COBOL帳票は印刷レイアウトに合わせて1明細を複数行に分割することが珍しくなく、この場合は帳票の規則性を自分で読み解き、貼付シートの作業列で1行にまとめる前処理が必要になります。ただし、明細の件数が違うだけであれば恐れる必要はありません。
【基本編】MIDB切り出し・浄化・型変換 … 固定長データの基本的な切り出しと型変換のテンプレ。
【応用編】不要行の除外と横展開 … ROWフラグによる行フィルタリングと固定行数の横展開。
【超絶技巧編】ヘッダー紐付け・フィルダウン … 親情報のフィルダウンと抽出シートでのMIDB分解。速度チューニング。
【不規則明細・完結編】不規則明細の正規化(本ページ) … 行数バラバラでも同じパイプラインで正規化できることの確認。マルチラインレコードへの対処の考え方。
【補助解説】半角QRで別システムへ入力する実践編 … 整形済みのCOBOL帳票から対象者を抽出し、半角コード・数値だけをQR化して入力省力化につなげる橋渡し。