« 2025年6月 | トップページ | 2025年8月 »

2025年7月

EPP飛行機のヒンジテープ

固定翼と動翼がヒンジ部分も含めて一体成型されているEPP機の動翼が引きちぎれたので、3Mのプラスチック用強力接着剤の代替品であるボンドGクリヤーで接着し、補強の為ヒンジテープを購入しました。

1. OK模型(PILOT)ヒンジテープ(12mm)幅
柔軟性が高いテープです。以前使用していたものですが、生産終了なので入手できなくなりました。

2. コスモテック(3M)ヒンジテープ
収縮性が無い3Mの超透明テープSというものでした。材質は不明ですが、ポロリプロピレンのように見えます。貼ってみたところ、収縮性が無いので可動しにくく、EPPの凸凹にも馴染みにくいので動翼を動かすと剥がれてきます。EPPのヒンジテープとしては、使いにくいです。固定翼と分離した動翼なら使えるのかも知れません。

3. OK模型ライトヒンジテープ
1.と2.の中間くらいの柔軟性と厚みのような感じがします。使用していませんが、EPPのヒンジテープとしても使えそうな気がします。もう少し幅が欲しいです。

4. HSGPヒンジテープ(25mm幅)(ROBIN電動機用ヒンジテープ25mmx4.75mと同じものだと思われます。)
3Mブレンダームテープという医療用防水テープらしいです。
生産終了したOK模型のヒンジテープ(12mm)幅の幅違いのようです。
カッターで半分の幅に切って使用しました。
250726tape 250726tape2 250726tape3

| | コメント (0)

横に2種類の項目が種類順に繰り返し並んだ表をExcelで整形(Power Query, ワークシート関数)

まえがき

Yahoo!知恵袋では、様々な横に値項目が繰り返し並んだ表をリスト形式にする質問があります。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12317522767

Visual Basicカテゴリーの質問なので、VBAや人気があるワークシート関数の回答が付いていますが、Power Query Mのコードの回答も付いていました。Power Queryとワークシート関数式の意味が分からなかったのでChatGPTで調べて見ました。

回答にはありませんが、クリック操作のみで作るPower Queryも付け加えました。
この方法は各ステップ毎の表の変化を確認することにより動作を理解しやすいので、速度は遅いですが属人性は低いです。
なので、データが大きくなければお勧めです。

Power Queryだと、セルアドレス依存が少なくなるので、ワークシート関数やVBAの回答に比べて変更に影響されにくいというメリットがあります。

1. 入力表
2. 出力表
3. Power Query Mのコードを記述する方法
4. ワークシート関数による方法
5. Power Queryのクリック操作による方法

1. 入力表

本例ではCSVファイルです。パスは次の通りです。
"C:\Users\Public\Documents\250716pqyoko.csv"

品番 品名 店舗NO. 納期1 納期2 納期3 数量1 数量2 数量3 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 2025/1/4 2025/1/20 35 200 1 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/3 2025/1/4   13 20   2024/12/1

特徴

🔹納期と数量の組合せが隣接してなく、まず納期が横に展開され、次に数量が横に展開されています。

ヒント

本記事ではCSVファイルを取り込んでいますが、実務ではフォルダから取り込む方が良いです。そうすれば、新しいCSVファイルをフォルダに格納して、集計ファイルを更新するだけで、新しいファイルを取り込むことができます。

2. 出力表

リスト形式に整形します。

品番 品名 店舗NO. 納期 数量 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 35 2024/12/1
ABCD-123 ゴミ袋 ○○○ 2025/1/4 200 2024/12/1
ABCD-123 ゴミ袋 ○○○ 2025/1/20 1 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/3 13 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/4   2024/12/1

本記事では省略しますが、これをピボットテーブルなどに展開して利用します。

3. Power Query Mのコードを記述する方法

コード全体

let
    ソース = Csv.Document(File.Contents("C:\Users\Public\Documents\250716pqyoko.csv"),[Delimiter=",", Columns=10, Encoding=65001, QuoteStyle=QuoteStyle.None]),
    昇格されたヘッダー数 = Table.PromoteHeaders(ソース, [PromoteAllScalars=true]),
    納期数量列の追加 = Table.AddColumn(昇格されたヘッダー数, "納期数量", each
        let
            除外リスト = {"品番", "品名", "店舗NO.", "受信日"},
            必要リスト = List.Difference(Table.ColumnNames(昇格されたヘッダー数), 除外リスト),
            納期数量リスト = List.Transform(必要リスト, (x)=> Record.Field(_, x)),
            リスト分割 = List.Split(納期数量リスト, List.Count(納期数量リスト)/2),
            リスト入替 = List.Zip(リスト分割),
            レコード変換 = List.Transform(リスト入替, (x)=> [納期=x{0}, 数量=x{1}])
        in
            レコード変換),
    列の選択 = Table.SelectColumns(納期数量列の追加, {"品番", "品名", "店舗NO.", "納期数量", "受信日"}),
    列の展開1 = Table.ExpandListColumn(列の選択, "納期数量"),
    列の展開2 = Table.ExpandRecordColumn(列の展開1, "納期数量", {"納期", "数量"}),
    フィルターされた行 = Table.SelectRows(列の展開2, each [数量] <> null and [数量] <> ""),
    変更された型 = Table.TransformColumnTypes(フィルターされた行,{{"納期", type datetime}, {"数量", Int64.Type}, {"受信日", type datetime}})
in
    変更された型

Yahoo!知恵袋の回答では"納期数量列の追加"は次のような記述になっています。


    納期数量列の追加 = Table.AddColumn(昇格されたヘッダー数, "納期数量", each
        [
            除外リスト = {"品番", "品名", "店舗NO.", "受信日"},
            必要リスト = List.Difference(Table.ColumnNames(昇格されたヘッダー数), 除外リスト),
            納期数量リスト = List.Transform(必要リスト, (x)=> Record.Field(_, x)),
            リスト分割 = List.Split(納期数量リスト, List.Count(納期数量リスト)/2),
            リスト入替 = List.Zip(リスト分割),
            レコード変換 = List.Transform(リスト入替, (x)=> [納期=x{0}, 数量=x{1}])
        ][レコード変換]),

この each は "レコード変換" というフィールドを持つレコードを作り、その中から レコード変換 を返します。

クリックで生成できないコードは、Power Queryエディタの[ホーム]-[詳細エディタ]に直接記述します。具体的には、"納期数量列の追加"から"列の展開2"までのコードを直接記述します。

Power Query Mのコードの各行の解説

1) ソース

= Csv.Document(File.Contents("C:\Users\Public\Documents\250716pqyoko.csv"),[Delimiter=",", Columns=10, Encoding=65001, QuoteStyle=QuoteStyle.None]),

[データ]-[データの取得v]-[ファイルから]-[テキストまたhCSVファイルから]でCSVファイルを選択し、[データの変換]で生成されるコードです。

目的:CSVファイルを読み込みます。

  • File.Contents:指定したパスのファイルを読み込み。
  • Csv.Document:CSV形式で読み取り、10列、UTF-8エンコードで区切り文字はカンマ。
  • QuoteStyle.None:引用符で囲まれた値の扱いなし(標準的なCSV)。

2) 昇格されたヘッダー数

= Table.PromoteHeaders(ソース, [PromoteAllScalars=true]),

1)の操作で自動生成されます。1行目をヘッダにします。

目的:1行目を列ヘッダーとして使用する。

  • PromoteHeaders:1行目の値を列名として昇格。
  • PromoteAllScalars=true:全ての値がスカラーである前提で処理。

3) 納期数量列の追加

= Table.AddColumn(昇格されたヘッダー数, "納期数量", each
    let
        除外リスト = {"品番", "品名", "店舗NO.", "受信日"},
        必要リスト = List.Difference(Table.ColumnNames(昇格されたヘッダー数), 除外リスト),
        納期数量リスト = List.Transform(必要リスト, (x)=> Record.Field(_, x)),
        リスト分割 = List.Split(納期数量リスト, List.Count(納期数量リスト)/2),
        リスト入替 = List.Zip(リスト分割),
        レコード変換 = List.Transform(リスト入替, (x)=> [納期=x{0}, 数量=x{1}])
    in
        レコード変換),

目的:各行に「納期と数量のペアのリスト(=納期数量)」を新しい列として追加。

納期数量列の追加(Table.AddColumn)の中の詳細:

🔢 対象の1行(例)

次のCSVの1行目のレコードの処理を例にして説明します。

品番, 品名, 店舗NO., 納期1, 納期2, 納期3, 数量1, 数量2, 数量3, 受信日
ABCD-123, ゴミ袋, ○○○, 2025/1/1, 2025/1/4, 2025/1/20, 35, 200, 1, 2024/12/1

🔁 ステップごとの変換詳細

🔹Step1:除外リスト:変換に不要な列(固定項目)を指定。

除外リスト = {"品番", "品名", "店舗NO.", "受信日"}

🔹Step2:必要リスト:変換対象(納期と数量)だけを抽出。列名リストから除外リストを除く。

必要リスト = List.Difference(Table.ColumnNames(昇格されたヘッダー数), 除外リスト)

🔹Table.ColumnNames : https://learn.microsoft.com/ja-jp/powerquery-m/table-columnnames
🔹List.Difference : https://learn.microsoft.com/ja-jp/powerquery-m/list-difference

📌 結果:

必要リスト = {"納期1", "納期2", "納期3", "数量1", "数量2", "数量3"}

🔹Step3:納期数量リスト:各列の値を行データから取得し、リスト化。

納期数量リスト = List.Transform(必要リスト, (x)=> Record.Field(_, x))

は、1行のレコードから「指定した列名」の値だけを取り出してリストにする処理です。

🔍 全体の構造(何をしているか)

🔹必要リスト:納期や数量の列名(文字列のリスト)です。
  例:{"納期1", "納期2", "納期3", "数量1", "数量2", "数量3"}
🔹List.Transform:この文字列リストの各列名に対して処理を行い、対応する値を取り出す。

🔧 構文の詳細

🔹List.Transform(list, transformFunction) : https://learn.microsoft.com/ja-jp/powerquery-m/list-transform

Power Query の標準関数で:

🔹list の各要素に transformFunction を適用して新しいリストを作ります。

ここでは:

🔹list:必要リスト{"納期1", "納期2", "納期3", "数量1", "数量2", "数量3"}
🔹transformFunction:(x) => Record.Field(_, x)

🔹 (x) => Record.Field(_, x) : Power Queryの関数を作成する:https://qiita.com/spumoni/items/6841aec922c02ee92a2f

これはラムダ関数(無名関数)で、次のように読めます:

パーツ 意味
x 必要リスト の各列名(たとえば "納期1")が順に入る変数
_ この Table.AddColumn で処理中の**行レコード(1行分)**を表す暗黙的な変数
Record.Field(_, x) x という名前のフィールド(列)を _ というレコードから取り出す :
https://learn.microsoft.com/ja-jp/powerquery-m/record-field

🧠 具体例

1行目のレコードは次のようになります。

_ = [
    品番 = "ABCD-123",
    品名 = "ゴミ袋",
    店舗NO. = "○○○",
    納期1 = "2025/1/1",
    納期2 = "2025/1/4",
    納期3 = "2025/1/20",
    数量1 = 35,
    数量2 = 200,
    数量3 = 1,
    受信日 = "2024/12/1"
]

このとき、必要リスト = {"納期1", "納期2", "納期3", "数量1", "数量2", "数量3"} に対して:

List.Transform(必要リスト, (x) => Record.Field(_, x))

は以下の生成します。

{
    Record.Field(_, "納期1") → 2025/1/1,
    Record.Field(_, "納期2") → 2025/1/4,
    Record.Field(_, "納期3") → 2025/1/20,
    Record.Field(_, "数量1") → 35,
    Record.Field(_, "数量2") → 200,
    Record.Field(_, "数量3") → 1
}

つまり

納期数量リスト = {
    "2025/1/1",
    "2025/1/4",
    "2025/1/20",
    35,
    200,
    1
}

📌 結果:

納期数量リスト = {2025/1/1, 2025/1/4, 2025/1/20, 35, 200, 1}

🔹Step4:リスト分割:納期と数量の2グループに分割(例:3納期+3数量 → 2つのリストに分かれる)。

リスト分割 = List.Split(納期数量リスト, List.Count(納期数量リスト)/2)

→ 要素数は3x2=6なので、2つに等分:
🔹List.Split : https://learn.microsoft.com/ja-jp/powerquery-m/list-split

📌 結果:

リスト分割 = {
    {2025/1/1, 2025/1/4, 2025/1/20}, // 納期リスト
    {35, 200, 1} // 数量リスト
}

🔹Step5:リスト入替(List.Zip):納期・数量をペアにして1行分のリストに変換。

リスト入替 = List.Zip(リスト分割)

納期と数量をペアに:
🔹List.Zip : https://learn.microsoft.com/ja-jp/powerquery-m/list-zip

📌 結果:

リスト入替 = {
    {2025/1/1, 35},
    {2025/1/4, 200},
    {2025/1/20, 1}
}

🔹Step6:レコード変換:それぞれを [納期=..., 数量=...] のレコードに変換。

レコード変換 = List.Transform(リスト入替, (x)=> [納期=x{0}, 数量=x{1}])

📌結果:

納期数量 = {
    [納期=2025/1/1, 数量=35],
    [納期=2025/1/4, 数量=200],
    [納期=2025/1/20, 数量=1]
}

このリストが新しく追加される "納期数量" 列の1セルに格納されます(リスト型)。

4) 列の選択

= Table.SelectColumns(納期数量列の追加, {"品番", "品名", "店舗NO.", "納期数量", "受信日"}),

目的:必要な列だけ残す。

5) 列の展開1

= Table.ExpandListColumn(列の選択, "納期数量"),

目的:「納期数量」列を行に展開(縦持ち化)。

6) 列の展開2

= Table.ExpandRecordColumn(列の展開1, "納期数量", {"納期", "数量"}),

目的:「納期数量」列のレコード(納期・数量)を列に展開。

品番 品名 店舗NO. 納期 数量 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 35 2024/12/1
ABCD-123 ゴミ袋 ○○○ 2025/1/4 200 2024/12/1
ABCD-123 ゴミ袋 ○○○ 2025/1/20 1 2024/12/1

7) フィルターされた行

= Table.SelectRows(列の展開2, each [数量] <> null and [数量] <> ""),

目的:数量が空の行(元データで数量未入力だったもの)を削除。

8) 変更された型

= Table.TransformColumnTypes(フィルターされた行,{{"納期", type datetime}, {"数量", Int64.Type}, {"受信日", type datetime}})

4. ワークシート関数による方法の解説

ワークシート関数を用いた回答もありましたが、これも理解ができなかったのでChatGPTに聞いてみました。

この式は、Excel の LET 関数と LAMBDA, TOCOL, HSTACK などの動的配列関数を組み合わせて、「横持ち(ワイド)表」を「縦持ち(ロング)表」に変換(アンピボット)しているものです。

🔍 入力データ

A1から次の表があります。

品番 品名 店舗NO. 納期1 納期2 納期3 数量1 数量2 数量3 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 2025/1/4 2025/1/20 35 200 1 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/3 2025/1/4   13 20   2024/12/1

🔍 出力領域

A5から次の表があります。

品番 品名 店舗NO. 納期 数量 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 35 2024/12/1
ABCD-123 ゴミ袋 ○○○ 2025/1/4 200 2024/12/1
ABCD-123 ゴミ袋 ○○○ 2025/1/20 1 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/3 13 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/4 20 2024/12/1

🔍 A6セルの式の目的

A6に次の式が入っています。この式は、Excel の LET 関数と LAMBDA, TOCOL, HSTACK などの動的配列関数を組み合わせて、「横持ち(ワイド)表」を「縦持ち(ロング)表」に変換(アンピボット)しているものです。

=LET(
  fx,
    LAMBDA(範囲,
      TOCOL(範囲 & IF(D2:F3 = "", 1/0, ""), 3)
    ),
  HSTACK(fx(A2:A3), fx(B2:B3), fx(C2:C3), TOCOL(D2:F3,1), TOCOL(G2:I3,1), fx(J2:J3)*1)
)

これは以下のような変換をしています:

  • 納期1~3, 数量1~3 を「行方向に展開」して、
  • 各「納期-数量」のペアを1行として出力。
  • 他の列(品番・品名・店舗NO・受信日)は繰り返して展開。
  • 受信日の「fx(J2:J3)*1」は、「*1」で数値化=シリアル値に変換。

🔍 fx 関数の意味

fx = LAMBDA(範囲, TOCOL(範囲 & IF(D2:F3 = "", 1/0, ""), 3))

この関数の役割は「空白行を除いて縦ベクトルに変換する」です。

  • 範囲 & IF(D2:F3 = "", 1/0, "")
    • D2:F3 のセルが空なら 1/0(エラー)となる。
    • 範囲 & エラー ⇒ そのセルが空ならエラーになり、TOCOL(...,3) によってその行が削除される。
  • TOCOL(..., 3) は「行方向に→列方向に変換+エラー削除」
    つまり、fx関数に渡した範囲のうち、対応する D2:F3 が空白の行は除外して、縦並びにしてくれるというわけです。

🔍 代表例で動作を確認

たとえば「品番列」だけ見ると:

fx(A2:A3)
→ ABCD-123
→ ABCD-123
→ ABCD-123
→ ABCE-456
→ ABCE-456

  • ABCD-123 → 納期3まである ⇒ 3行
  • ABCE-456 → 納期3が空白 ⇒ 2行(1行分カット)
    同様に fx(J2:J3) は「受信日」の展開:

fx(J2:J3)
→ 2024/12/1
→ 2024/12/1
→ 2024/12/1
→ 2024/12/1
→ 2024/12/1

🔍 全体の式構造(展開される列)

HSTACK(
  品番列, 品名列, 店舗NO列, 納期列, 数量列, 受信日列
)

すべて5行になるので、次のような結果になります:

品番 品名 店舗NO 納期 数量 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 0:00 35 2024/12/1 0:00
ABCD-123 ゴミ袋 ○○○ 2025/1/4 0:00 200 2024/12/1 0:00
ABCD-123 ゴミ袋 ○○○ 2025/1/20 0:00 1 2024/12/1 0:00
ABCE-456 ブラシ ○○○ 2025/1/3 0:00 13 2024/12/1 0:00
ABCE-456 ブラシ ○○○ 2025/1/4 0:00 20 2024/12/1 0:00

✅ まとめ:この式のポイント

  • TOCOL(..., 3) で行方向データを縦持ちに変換。
  • & IF(..., 1/0, "") で空白行を除外。
  • LET + fx + HSTACK で項目別に一括展開。
  • 結果として、横持ちの納期・数量データを「1納期1行」にアンピボット。

5. Power Queryのクリック操作による方法の解説

クリック操作で整形する方法です。
ステップ数が増え、マージもあるので遅くなりますが、ワークシート関数式やPower Query Mのプログラミングの知識が無い人でも、動作を理解しやすいというメリットがあります。

1) Click0:ソース

[ホーム]-[データの取得v]-[ファイルから]-[テクストまたはCSVファイルから]でCSVファイルを選択し[インポート]、文字コードなどが正しいことを確認して[データの変換]。
右のクエリの設定のプロパティの名前を"Click0"に変更。

2) 昇格されたヘッダ数

前記操作で自動生成されます。
変更された型は削除しても問題ありません。

品番 品名 店舗NO. 納期1 納期2 納期3 数量1 数量2 数量3 受信日
ABCD-123 ゴミ袋 ○○○ 2025/1/1 2025/1/4 2025/1/20 35 200 1 2024/12/1
ABCE-456 ブラシ ○○○ 2025/1/3 2025/1/4   13 20   2024/12/1

3) ピボット解除された他の列

Ctrtキーを押したまま"品番", "品名", "店舗NO.", "受信日"列を選択し、[変換]-[列のピボット解除v]-[その他の列のピボット解除]。
これで納期と数量が縦に並びます。

品番 品名 店舗NO. 受信日 属性 値
ABCD-123 ゴミ袋 ○○○ 2024/12/1 納期1 2025/1/1
ABCD-123 ゴミ袋 ○○○ 2024/12/1 納期2 2025/1/4
ABCD-123 ゴミ袋 ○○○ 2024/12/1 納期3 2025/1/20
ABCD-123 ゴミ袋 ○○○ 2024/12/1 数量1 35
途中省略          
ABCE-456 ブラシ ○○○ 2024/12/1 数量2 20
ABCE-456 ブラシ ○○○ 2024/12/1 数量3  

4) 文字の移行による列の分割

"属性"列を選択し[変換]-[列の分割v]-[数字以外から数字による分割]。
これで納期と数量の項目名を統一すると同時に、それらを識別するための後ろの数字の列が生成されます。この数字は、後で納期と数量をピボットで横に展開する時のエラーを回避するために使います。

品番 品名 店舗NO. 受信日 属性.1 属性.2 値
ABCD-123 ゴミ袋 ○○○ 2024/12/1 納期 1 2025/1/1
ABCD-123 ゴミ袋 ○○○ 2024/12/1 納期 2 2025/1/4
ABCD-123 ゴミ袋 ○○○ 2024/12/1 納期 3 2025/1/20
ABCD-123 ゴミ袋 ○○○ 2024/12/1 数量 1 35
途中省略            
ABCE-456 ブラシ ○○○ 2024/12/1 数量 2 20
ABCE-456 ブラシ ○○○ 2024/12/1 数量 3  

5) Click数量:ソース

左の"Click0"を右クリックし[参照]。
右のクエリの設定のプロパティの名前を"Click数量"に変更。

6) フィルターされた行

"属性.1"列のフィルタアイコンをクリックし、[指定の値で始まる]、"数量"を入力し[OK]。
これで数量行のみになります。

7) 削除された列

"属性.1"列を右クリックし[削除]。

8) 名前が変更された列

"値"列をWクリックし、名前を"数量"に変更。
これで"数量"が縦に並んだ表ができます。

品番 品名 店舗NO. 受信日 属性.2 数量
ABCD-123 ゴミ袋 ○○○ 2024/12/1 1 35
ABCD-123 ゴミ袋 ○○○ 2024/12/1 2 200
途中省略          
ABCE-456 ブラシ ○○○ 2024/12/1 2 20
ABCE-456 ブラシ ○○○ 2024/12/1 3  

9) Click:ソース

左の"Click0"を右クリックし[参照]。
右のクエリの設定のプロパティの名前を"Click"に変更。

6) フィルターされた行

"属性.1"列のフィルタアイコンをクリックし、[指定の値で始まる]、"納期"を入力し[OK]。
これで納期行のみになります。

7) 削除された列

"属性.1"列を右クリックし[削除]。

8) 名前が変更された列

"値"列をWクリックし、名前を"納期"に変更。
これで"納期"が縦に並んだ表ができます。

品番 品名 店舗NO. 受信日 属性.2 納期
ABCD-123 ゴミ袋 ○○○ 2024/12/1 1 2025/1/1
ABCD-123 ゴミ袋 ○○○ 2024/12/1 2 2025/1/4
途中省略          
ABCE-456 ブラシ ○○○ 2024/12/1 2 2025/1/4
ABCE-456 ブラシ ○○○ 2024/12/1 3  

9) マージされたクエリ数

[ホーム]-[クエリのマージv]-[クエリのマージ]で次のように選択します。
2つ目の表に[Click数量]を選択。
Ctrlキーを押したまま上下の"品番", "品名", "店舗NO.", "受信日", "属性.2"列をクリックし[OK]。
250716pqyoko01

10) 展開されたClick数量

"Click数量"列の矢印展開アイコンをクリックし、"数量"のみチェックし、"元の列名をプレフィックスとして使用します"のチェックを外し[OK]。

品番 品名 店舗NO. 受信日 属性.2 納期 数量
ABCD-123 ゴミ袋 ○○○ 2024/12/1 1 2025/1/1 35
ABCD-123 ゴミ袋 ○○○ 2024/12/1 2 2025/1/4 200
途中省略            
ABCE-456 ブラシ ○○○ 2024/12/1 2 2025/1/4 20
ABCE-456 ブラシ ○○○ 2024/12/1 3    

11) 削除された列1

マージキーとして使用した"属性.2"列を右クリックして[削除]。

12) フィルタされた行1

"数量"列のフィルタアイコンをクリックし[空の削除]。

13) 並べ替えられた列

"受信日"列を選択し、[変換]-[移動v]-[末尾に移動]。

14) 変更された型

"納期"、"受信日"の型を[日付/時刻]、"数量"の型を[整数]に変更。

15) 閉じて読み込む

[ホーム]-[閉じて読み込むv]-[閉じて次に読み込む]で"接続の作成のみ"を選択し[OK]。

16) 読み込み先

[データ]-[クエリと接続]で右の"クエリと接続"から読み込みたいクエリを右クリックし[読み込み先]で、読み込み先を選び[OK]。

6. サンプル

ダウンロード - 250716pqyoko.zip

C:\Users\Public\Documents に展開してください。

7. その他

関連記事

Power Queryで表をリスト形式に整形する方法(まとめ)
https://bigarrow.tea-nifty.com/blog/2025/11/post-4925ca.html

月別に独立して横に展開されている項目の表の整形
https://bigarrow.tea-nifty.com/blog/2025/07/post-485823.html

項目が繰り返し横に伸びる、開始日と終了日のデータのみの表をモダンExcelで集計
https://bigarrow.tea-nifty.com/blog/2025/07/post-258734.html

Excel Power Queryで横項目3段のクロス表をリスト形式にする方法
https://app.cocolog-nifty.com/cms/blogs/632678/entries/95284684

| | コメント (0)

月別に独立して横に展開されている項目の表の整形

まえがき

Yahoo!知恵袋に次のような質問がありました。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14317423854 この表の特異なところは、各月間の行が無関係であることです。月別に2項目の表が横に並んでいる表です。
表の使い方を考えずに、Excelをメモ帳として使っているのだと思われます。

BAの回答の通り、元表自体をピボットテーブルが使用できるリスト形式に変えるべきなのですが、元表を変えずにPower Queryで整形をしてみました。また、前月差をメジャーで計算しました。

1. 入力

元データです。

25/04 25/05
取引先 売上 取引先 売上
a社 1,000,000 a社 500,000
b社 100,000 c社 1,000,000
    d社 500,000

特徴

25/04と25/05の表が横に並んでいますが、25/04と25/05の行に関係はありません。

2. 出力(リスト)

元データをデータべース(リスト)形式にしたものです。これをPower Queryで作成します。

年月 取引先 売上
25/04 a社 1,000,000
25/04 b社 100,000
25/05 a社 500,000
25/05 C社 1,000,000
25/05 d社 500,000

3. 出力(クロス表)

データべース形式からピボットテーブルで集計したものです。これをPower Pivotで作成します。

取引先 25/05 25/06 総計
a社 1,000,000 500,000 1,500,000
b社 100,000   100,000
c社   1,000,000 1,000,000
d社   500,000 500,000
総計 2,100,000 2,000,000 4,100,000

4. カレンダテーブル

元の質問に増減の確認要望があることと(時間軸の処理が必要)、ピボットテーブルの項目に書式設定ができないので年月をテキストにしたいことから、カレンダテーブルをExcelで作ります。

集計ブックに次の表を作成し、表を全選択して[挿入]-[テーブル]でテーブル化し、[デーブルデザイン]で名前を"カレンダ"に変更します。

日付 年月 月 四半期 期 年度
2025/4/1 25/04 4月 25/1Q 25/1H 25年度
2025/4/2 25/04 4月 25/1Q 25/1H 25年度
途中省略          
2026/3/31 26/03 3月 25/4Q 25/2H 25年度
2026/4/1 26/04 4月 26/1Q 26/1H 26年度

ワークシート式

セルA3が2025/4/1の場合のワークシート式は次のようになります。

  • A4(日付:2025/4/2):=A3 + 1 または =INDIRECT(ADDRESS(ROW() - 1, COLUMN())) + 1
  • B3(年月):=TEXT([@日付], "yy/mm")
  • C3(月):=TEXT([@日付], "m月")
  • D3(四半期):=LET(m, MONTH([@日付]), y, YEAR([@日付]), yy, VALUE(TEXT([@日付],"yy")), IFS(m<4, yy-1&"/4Q", m<7, yy&"/1Q", m<10, yy&"/2Q", TRUE, yy&"/3Q"))
  • E3(期):=LET(m, MONTH([@日付]), y, YEAR([@日付]), yy, VALUE(TEXT([@日付], "yy")), IFS(m<4, yy-1&"/2H", m<10, yy&"/1H", TRUE, yy&"/2H"))
  • F3(年度):=TEXT(EDATE([@日付], -3), "yy年度")

注意

元データの日付が変わった時は、カレンダーテーブルも元データの日付を含むように修正してください。
カレンダの範囲を自動的に変更する場合は、次の参考記事を見てください。

参考:Excel Power Query Mでカレンダを作成し、メジャーで前の値との差を計算
https://bigarrow.tea-nifty.com/blog/2025/06/post-b14054.html

参考:Excelでテーブルに数式をセットする際の注意点
https://neverendworks.com/news/notes-on-setting-formulas-in-the-table/

5. 処理の概要

  1. 行と列を入れ替えて日付をフィルで埋める。
  2. 次の3.でピボット解除して縦に並べる項目を結合する。
  3. 行と列を入れ替えて元に戻し、結合行をヘッダにしてピボット解除して縦に並べる。
  4. "集計なし"でピボットするために、ピボットする項目に識別番号を振り、ピボットして横に展開する。

6. 処理手順

1) カレンダの取得

集計ブックのカレンダを選択し[データ]-[テーブルまたは範囲から]でPower Queryエディタに取込み、右のプロパティのクエリ名を"カレンダ"にする。

2) 型の設定

"日付"列を選択し[変換]-[データ型]-[日付]。"月"列を選択し[変換]-[データ型]-[テキスト]。その他の列も、必要があれば適切な型に変更する。

3) カレンダをデータモデルに追加

[ホーム]-[閉じて読み込むv]-[閉じて次に読み込む]で"データの接続のみ"と"このデータをデータモデルに追加する"を選択し[OK]で、Excelに戻る。

4) 元データを取得

集計ブックで[データ]-[データの取得]-[ファイルから]-[Excelブックから]で元データのファイルを選択し[インポート]、元データのシートを選択し[データの変換]でPower Queryエディタに取込み、右のプロパティのクエリの名前を"売上"に変更。

5) 自動生成された不要なステップを削除

右のステップの"ソース"と"ナビゲーション"以外のステップの右の×アイコンをクリックし、ステップを削除する。

6) 不要な行を削除

[ホーム]-[行の削除v]-[上位の行の削除]で"1"を入力し[OK]。不要な行が削除される。

Column1 Column2 Column3 Column4
2025/5/1   2025/6/1  
取引先 売上 取引先 売上
a社 1000000 a社 500000
b社 100000 c社 1000000
    d社 500000

7) [変換]-[入れ替え]。

行と列が入れ替えられる。日付を埋める下準備。

8) 日付のnullを埋める

"Column1"を選択し[変換]-[フィル]-[下へ]。日付が埋まる。

Column1 Column2 Column3 Column4 Column5
2025/5/1 取引先 a社 b社  
2025/5/1 売上 1000000 100000  
2025/6/1 取引先 a社 c社 d社
2025/6/1 売上 500000 1000000 500000

9) 日付と項目を結合

Ctrlを押しながら"Column1"と"Column2"をクリックして選択し[変換]-[列のマージ]で区切り記号を[セミコロン]にし[OK]。日付と項目をピボット解除する下準備。

10) [変換]-[入れ替え]。行と列を元に戻す。

11) 日付と項目の結合項目をヘッダに昇格

[変換]-[1行目をヘッダとして使用v]-[1行目をヘッダとして使用]。

2025/5/1;取引先 2025/5/1;売上 2025/6/1;取引先 2025/6/1;売上
a社 1000000 a社 500000
b社 100000 c社 1000000
    d社 500000

12) 日付と項目の組合せ列をピボット解除

適当な列をクリックし、Ctrl+aで全列を選択し、[変換]-[列のピボット解除v]-[列のピボット解除]。日付と項目と値が縦に並ぶ。

属性 値
2025/5/1;取引先 a社
2025/5/1;売上 1000000
2025/6/1;取引先 a社
2025/6/1;売上 500000
2025/5/1;取引先 b社
2025/5/1;売上 100000
2025/6/1;取引先 c社
2025/6/1;売上 1000000
2025/6/1;取引先 d社
2025/6/1;売上 500000

13) 日付と項目を分離

"属性"列を選択し[列の分割v]で区切り記号に[セミコロン]、分割を[機切り記号の出現ごと]、引用符文字を[なし]にし[OK]。日付と項目が分離する。そして、数式バーを次のように変更する。

= Table.SplitColumn(ピボット解除された列, "属性", Splitter.SplitTextByDelimiter(";", QuoteStyle.None), {"日付", "属性.2"})

14) インデックス列を追加

[列の追加]-[インデックス列v]-[0から]。

15) 項目の識別列を追加

[列の追加]-[標準v]-[除算(整数)]。これで項目に重複しない番号が付く。これにより、後で行う項目のピボットでエラーが発生しなくなる。

16) 不要になった作業列を削除

"インデックス"列を選択し[ホーム]-[列の削除v]-[列の削除]。作業列を削除。

日付 属性.2 値 整数除算
2025/5/1 取引先 a社 0
2025/5/1 売上 1000000 0
2025/6/1 取引先 a社 1
2025/6/1 売上 500000 1
2025/5/1 取引先 b社 2
2025/5/1 売上 100000 2
2025/6/1 取引先 c社 3
2025/6/1 売上 1000000 3
2025/6/1 取引先 d社 4
2025/6/1 売上 500000 4

17) 項目をピボット

"属性.2"列を選択し[変換]-[列のピボット]で、値列に[値]、詳細設定オプションの値の集計関数を[集計しない]にして[OK]。

日付 整数除算 取引先 売上
2025/5/1 0 a社 1000000
2025/5/1 2 b社 100000
2025/6/1 1 a社 500000
2025/6/1 3 c社 1000000
2025/6/1 4 d社 500000

参考:ピボット解除する項目のフィールド値(項目名)が重複している場合、それらを区別する列が無いとエラーになる。このエラーを回避するため、"整数除算"列を付けている。

18) 不要になった作業列を削除

"整数除算"列を選択し[ホーム]-[列の削除v]-[列の削除]。作業列が削除されます。

日付 取引先 売上
2025/5/1 a社 1000000
2025/5/1 b社 100000
2025/6/1 a社 500000
2025/6/1 c社 1000000
2025/6/1 d社 500000

19) 型の設定

全ての列の型を確認し、[変換]-[データ型]で適切な型を設定する。

参考:ここで型を設定するので、途中で自動追加された"変更された型"のステップは都度削除して良い。

20) ピボットテーブル化

[ホーム]-[閉じて読み込むv]-[閉じて次に読み込む]で"ピボットテーブル"と"このデータをデータモデルに追加する"を選択し[OK]で、Excelに戻る。

21) リレーション

[データ]-[データモデル(緑のアイコン)v]-[リレーションシップ]-[新規作成]で次のように入力し[OK]。
テーブル:売上、列:日付、関連テーブル:カレンダ、関連列:日付

[Power Pivot]-[管理]-[ダイアグラムビュー]で、'売上'[日付]を'カレンダ'[日付]にドラッグしても良い。

22) メジャー

ピボットテーブルを選択し"ピボットテーブルのフィールド"の"売上"を右クリックし[メジャーの追加]で次のように入力。
名前:M増減
数式:

=VAR IsMonthLevel = HASONEVALUE('カレンダ'[年月]) // コンテキストフィルタのレベル
VAR IsQuarterLevel = HASONEVALUE('カレンダ'[四半期])
VAR IsHalfYearLevel = HASONEVALUE('カレンダ'[期])
VAR IsYearLevel = HASONEVALUE('カレンダ'[年度])
// 共通の現在値とデータの有無
VAR CurrentSales = SUM('売上'[売上])
VAR HasCurrentSales = NOT ISBLANK(CurrentSales)
// 前月の売上
VAR PrevMonthSales =
  CALCULATE(
    SUM('売上'[売上]),
    PREVIOUSMONTH('カレンダ'[日付])
  )
// 前四半期の売上
VAR PrevQuarterSales =
  CALCULATE(
    SUM('売上'[売上]),
    PREVIOUSQUARTER('カレンダ'[日付])
  )
// 前半期の売上(≒2四半期前)
VAR PrevHalfYearSales =
  CALCULATE(
    SUM('売上'[売上]),
    DATESINPERIOD('カレンダ'[日付], MIN('カレンダ'[日付]) - 1, -6, MONTH)
  )
// 前年度の売上
VAR PrevYearSales =
  CALCULATE(
    SUM('売上'[売上]),
    SAMEPERIODLASTYEAR('カレンダ'[日付])
  )
// 前期間または今期間のデータの存在チェック
VAR HasMonth =
  OR(NOT ISBLANK(PrevMonthSales), HasCurrentSales)
VAR HasQuarter =
  OR(NOT ISBLANK(PrevQuarterSales), HasCurrentSales)
VAR HasHalfYear =
  OR(NOT ISBLANK(PrevHalfYearSales), HasCurrentSales)
VAR HasYear =
  OR(NOT ISBLANK(PrevYearSales), HasCurrentSales)
// 実行
RETURN
  SWITCH(
    TRUE(),
    IsMonthLevel, IF(HasMonth, CurrentSales - PrevMonthSales, BLANK()),
    IsQuarterLevel, IF(HasQuarter, CurrentSales - PrevQuarterSales, BLANK()),
    IsHalfYearLevel, IF(HasHalfYear, CurrentSales - PrevHalfYearSales, BLANK()),
    IsYearLevel, IF(HasYear, CurrentSales - PrevYearSales, BLANK()),
    BLANK()
  )

 

このメジャーは、前期間との差を計算するメジャーです。6月であれば6月-5月、25/1Qであれば、25/1Q-24/4Qを計算します。
今期間と全期間のどちらかのデータがあれば、値を返し、両方ともデータが無ければ値を返しません。

もし、前期間のデータが無い時に値を返さないようにするのであれば、次の記事のメジャーを使用してください。

23) ピボットテーブル

ピボットテーブルを選択し、ピボットテーブルのフィールドで次のように設定。
列:'カレンダ'[四半期]、'カレンダ'[年月]。行:Σ値、'売上'[取引先]。Σ値:合計 / '売上'[売上]、[M増減]。

24) ピボットテーブルのオプション

[ピボットテーブル分析]-[オプションv]-[オプション]の[レイアウトと書式]タブの"更新時に列幅を自動調整する"のチェックを外す、[表示]タブの"データが無いアイテムを行/列に表示する"のチェックを外す。

25) ピボットテーブルのデザイン

[デザイン]-[レポートのレイアウトv]-[表形式で表示]、[小計]/[総計]を好みの設定にする。

値 取引先 25/05 25/06 25/1Q
合計/売上 a社 1,000,000 500,000 1,500,000
b社 100,000   100,000
c社   1,000,000 1,000,000
d社   500,000 500,000
M増減 a社 +1,000,000 -500,000 +1,500,000
b社 +100,000 -100,000 +100,000
c社   +1,000,000 +1,000,000
d社   +500,000 +500,000
合計 1,100,000 2,000,000 3,100,000
M増減 +1,100,000 +900,000 +3,100,000

7. サンプル

ダウンロード - 250713para.xlsx

C:\Users\Public\Documents に入れてください。

8. その他

関連記事

Power Queryで表をリスト形式に整形する方法(まとめ)
https://bigarrow.tea-nifty.com/blog/2025/11/post-4925ca.html

横に値項目が繰り返し並んだ表をExcelで整形(Power Query, ワークシート関数)
https://bigarrow.tea-nifty.com/blog/2025/07/post-ccee90.html

項目が繰り返し横に伸びる、開始日と終了日のデータのみの表をモダンExcelで集計
https://bigarrow.tea-nifty.com/blog/2025/07/post-258734.html

Excel Power Queryで横項目3段のクロス表をリスト形式にする方法
https://app.cocolog-nifty.com/cms/blogs/632678/entries/95284684

| | コメント (0)

項目が繰り返し横に伸びる、開始日と終了日のデータのみの表をモダンExcelで集計

まえがき

Yahoo!知恵袋に次のような質問がありました。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10317033155

VBAの回答が付いています。
これをExcelのPower Queryでリスト形式に整形し、Power Pivot(メジャー/DAX)で集計してみました。

要旨

  1. Power Queryで、横に繰り返し項目が伸びる表をリスト形式に整形する方法
  2. メジャーDAX式で、開始と終了日のデータから、間の日も含めた集計月の日数をカウントする方法

1. 入力

記録
番号 氏名 入居日 退去日 部屋番 入居日 退去日 部屋番 入居日 退去日 部屋番
1 山口 2025/6/2 2025/6/5 103 2025/6/10 2025/6/12 105 2025/6/30 2025/7/10 203
2 田中 2025/5/3 2025/5/5 106 2025/5/10 2025/5/11 105 2025/6/3 2025/6/5 103
10 加藤 2025/7/1 2025/7/2 201            
15 広瀬 2025/8/3 2025/8/8 203 2025/9/10 2025/9/15 106      
5 長澤                  
23 深田 2025/4/3 2025/4/8 101 2025/7/12 2025/7/15 205      

特徴

  1. 左端の番号と氏名以外は入居日~部屋番の3列が任意の数だけ横に伸びる表です。
  2. 入居日と退去日のみデータがあり、その間のデータがありませんが、入居日と退去日の間は全て利用日となります。

2. 出力

抽出表です。例として2025年7月の利用者の情報と当月の利用日数を表示しています。

出力
番号 名前 入居日 退去日 部屋番 当月日数
1 山口 25/06/30 25/07/10 203 10
25/07/13 25/07/16 203 4
25/07/18 25/07/22 203 5
山口 集計     19
10 加藤 25/07/01 25/07/02 201 2
加藤 集計     2
2 田中 25/07/03 25/07/06 205 4
田中 集計     4
23 深田 25/07/12 25/07/15 205 4
深田 集計     4

月またぎの場合の課題

  1. 単純に入居日、退去日で集計月のフィルタを掛けることができません。
  2. 利用日数を「退去日-入居日」では計算できません。

3. 概要

  1. 横に展開された入力表をPower Queryでリスト形式に変換します。
    横に展開された繰り返し項目を縦に並べて繰り返し毎の番号を付けます。これをピボットして繰り返し列をまとめます。
  2. 抽出月は、月のカレンダテーブルをスライサーで絞り込むことにより指定します。
  3. 入居日と退去日の間の利用日のレコードが無いので、利用日の計算はメジャーを使用して行います。

4. 手順詳細

クリック操作が主な作業です。以下、操作手順の概要です。

1) 入力表

元データブックのシート名を"記録"とします。('記録'以外の名前を使用する場合は、後の説明の'記録'を使用する名前に変更してください。)

2) 集計月のテーブル

集計ブックを作り、集計月を記入するテーブルを作成します。次の表を作成して表の範囲を全選択し、[挿入]-[テーブル]でテーブル化し、[テーブルデザイン]でテーブル名を"集計月"とします。

集計月

年月日 年月
2025/04/01 25/04
2025/05/01 25/05
途中略  
2026/03/01 26/03

年月日:日付型です。メジャーで参照します。
年月:テキスト型です。集計月を選択するスライサーに使います。

3) 入力表の取込み

[データ]-[データの取得v]-[ファイルから]-[Excelブックから]で元データブックを選び[インポート]で"記録"シートを選択し、[データの変換]でPower Queryエディタに取込みます。
右のプロパティの名前を"記録"にします。
右のステップの内、"ソース"と"ナビゲーション"を除くステップを各ステップ名の左に現れる×アイコンをクリックして削除します。

Column1 Column2 Column3 Column4 Column5 Column6 Column7 Column8 Column9 Column10 Column11
番号 氏名 入居日 退去日 部屋番 入居日 退去日 部屋番 入居日 退去日 部屋番
1 山口 2025/6/2 2025/6/5 103 2025/6/10 2025/6/12 105 2025/6/30 2025/7/10 203
2 田中 2025/5/3 2025/5/5 106 2025/5/10 2025/5/11 105 2025/6/3 2025/6/5 103
10 加藤 2025/7/1 2025/7/2 201            
15 広瀬 2025/8/3 2025/8/8 203 2025/9/10 2025/9/15 106      
5 長澤                  
23 深田 2025/4/3 2025/4/8 101 2025/7/12 2025/7/15 205      

4) null値の穴埋め

中央の表をクリックし、Ctrl+aで全選択し、[変換]-[値の置換v]-[値の置換]で検索する値をnull、置換後を0にして[OK]。数式バーの式を次のように書き換えます。
= Table.ReplaceValue(記録_Sheet,null,0,Replacer.ReplaceValue,Table.ColumnNames(記録_Sheet))

※ Table.ColumnNames(記録_Sheet)の"記録_Sheet"は、= Table.ReplaceValue(記録_Sheet,の"記録_Sheet"に合わせてください。

解説

後のステップで横に繰り返し並ぶ"入居日","退去日","部屋番"に識別番号を付けます。この3つの組合せに欠けがあると剰余の計算で正しい番号が付けられないので、nullを0に置換することにより、欠けが出ないようにします。
横のColumn数は入力データによって変わるので、"Column1"等の名前を使用しない式に書き換えます。

5) 番号と氏名の連結

"Column1"と"Column2"列をCtrlを押しながら選択し、[変換]-[列のマージ]で区切り記号[セミコロン]、新しい列名"結合済み"で[OK]。
(後で番号と名前を一時的にヘッダに入れてピボット解除するためにまとめます。)

結合済み Column3 Column4 Column5 Column6 Column7 Column8 Column9 Column10 Column11
番号;氏名 入居日 退去日 部屋番 入居日 退去日 部屋番 入居日 退去日 部屋番
1;山口 2025/6/2 2025/6/5 103 2025/6/10 2025/6/12 105 2025/6/30 2025/7/10 203
2;田中 2025/5/3 2025/5/5 106 2025/5/10 2025/5/11 105 2025/6/3 2025/6/5 103
10;加藤 2025/7/1 2025/7/2 201            
15;広瀬 2025/8/3 2025/8/8 203 2025/9/10 2025/9/15 106      
5;長澤                  
23;深田 2025/4/3 2025/4/8 101 2025/7/12 2025/7/15 205      

6) 転置

[変換]-[入れ替え]で縦横を入れ替え。
(横に並んでいた"入居日","退去日","部屋番"が一時的に縦1列に並びます。これを後で横3列にピボットします。)

Column1 Column2 Column3 Column4 Column5 Column6 Column7
番号;氏名 1;山口 2;田中 10;加藤 15;広瀬 5;長澤 23;深田
入居日 2025/6/2 2025/5/3 2025/7/1 2025/8/3 0 2025/4/3
退去日 2025/6/5 2025/5/5 2025/7/2 2025/8/8 0 2025/8/4
部屋番 103 106 201 203 0 101
途中略            
入居日 2025/8/20 2025/10/3 0 0 0 0
退去日 2025/8/23 2025/10/8 0 0 0 0
部屋番 201 102 0 0 0 0

7) データが無い行を削除

"Column1"列の右のフィルタアイコンでnullと0のチェックを外し[OK]。(入力表の右の空列を削除する処理。)

8) "番号;氏名"をヘッダに昇格

[変換]-[1行目をヘッダとして使用v]-[1行目をヘッダとして使用]で結合した行をヘッダに昇格。
(一時的に番号;氏名がヘッダに並びます。これを後でピボット解除することで番号;氏名をリスト形式に変換します。)

9) 行番号を付ける

[列の追加]-[インテックス]-[0から]で開始インデックス0、増分1で[OK]。(作業列が追加される。)

10) 3行毎に番号を付ける

"インデックス"列を選択し、[列の追加]-[標準v]-[除算(整数)]で値を3で[OK]。
(入居日、退去日、部屋番行毎に番号が振られます。この整数除算列によって複数行ある1列目の"入居日","退去日","部屋番"の区別ができるようになります。)

番号;氏名 1;山口 2;田中 10;加藤 15;広瀬 5;長澤 23;深田 インテックス 整数除算
入居日 2025/6/2 2025/5/3 2025/7/1 2025/8/3 0 2025/4/3 1 0
退去日 2025/6/5 2025/5/5 2025/7/2 2025/8/8 0 2025/8/4 2 0
部屋番 103 106 201 203 0 101 3 0
途中略                
入居日 2025/8/20 2025/10/3 0 0 0 0 15 5
退去日 2025/8/23 2025/10/8 0 0 0 0 16 5
部屋番 201 102 0 0 0 0 17 5

11) 作業列を削除

"インデックス"列を右クリックし[削除]。(作業列が削除される。)

12) "番号;氏名"をピボット解除

"番号;氏名", "整数除算"をCtrlキーを押しながら選択し[変換]-[列のピボット解除v]-[他の列のピボット解除]。

(名前が縦に並びます。値を除く列の組合せには重複がありません。なので、後でピボットする時に、値の重複が無いので、集計しないでピボットすることができるようになりました。もし、整数除算列が無いと、値を除く列の組合せに重複が出るので、集計が必要になります。)

番号;氏名 整数除算 属性 値
入居日 0 1;山口 2025/6/2
入居日 0 2;田中 2025/5/3
入居日 0 10;加藤 2025/7/1
入居日 0 15;広瀬 2025/8/3
入居日 0 5;長澤 0
入居日 0 23;深田 2025/4/3
退去日 0 1;山口 2025/6/5
以下省略      

13) "番号;氏名"を分割

"属性"列を選択し、[列の分割v]で区切り記号をセミコロン、詳細設定オプションの引用符文字を[なし]にし[OK]。数式バーの式を次のように変更。
= Table.SplitColumn(ピボット解除された他の列, "属性", Splitter.SplitTextByDelimiter(";", QuoteStyle.None), {"番号", "名前"})

(6)で結合した番号と名前が分離されます。)

番号;氏名 整数除算 番号 名前 値
入居日 0 1 山口 2025/6/2
入居日 0 2 田中 2025/5/3
入居日 0 10 加藤 2025/7/1
入居日 0 15 広瀬 2025/8/3
入居日 0 5 長澤 0
入居日 0 23 深田 2025/4/3
退去日 0 1 山口 2025/6/5
以下省略        

14) "入居日,退去日,部屋番"の列を横にピボット

"番号;氏名"列を選択し[変換]-[列のピボット]で値列を[値]、詳細設定オプションの値の集計関数を[集計しない]で[OK]。("入居日","退去日","部屋番"が横項目になる。10~12)の作業は、エラーを回避するための処理。)

番号

整数除算 番号 氏名 入居日 退去日 部屋番
0 1 山口 2025/6/2 2025/6/5 103
0 10 加藤 2025/7/1 2025/7/2 201
0 15 広瀬 2025/8/3 2025/8/8 203
0 2 田中 2025/5/3 2025/5/5 106
      以下 省略  

[集計しない]オプションのエラー
https://support.microsoft.com/ja-jp/office/-abc9c8da-3be9-44c4-886e-0be331ab387a

15) "入居日"が無い行を削除

"入居日"列のフィルタアイコンで[日付フィルタ]-[カスタム]で次のように入力し[OK]。(データが無い行が削除される。)
指定の値と等しくない、0
および
指定の値と等しくない、(何も入力しない)

16) 型変更

各列を選択し[変換]-[データ型]で"入居日","退去日"の型を日付、"部屋番"の型をテキストに変更。

17) データモデルに追加

[ホーム]-[閉じて読み込むv]-[閉じて次に読み込む]で"データの接続のみ"と"データモデルに追加する"を選び、[OK]でExcelに戻る。

以上で'記録'データモデルが完成です。

18) '集計月'の取込み

集計月テーブルを選択し[データ]-[テーブルまたは範囲から]でPower Queryエディタに取込む。

19) 型の変更

"年月日"列を選択し、[変換]-[データ型]で[日付]を選択。

20) データモデルに追加

[ホーム]-[閉じて読み込むv]-[閉じて次に読み込む]で"データの接続のみ"と"データモデルに追加する"を選び、[OK]でExcelに戻る。

以上で'集計月'データモデルが完成です。

21) ピボットテーブルの作成

[挿入]-[ピボットテーブル]-[データモデルから]でピボットテーブルを追加。

22) メジャーの作成(退去日)

右のピボットテーブルのフィールドの"記録"を右クリックし、[メジャーの追加]で次のメジャーを追加

メジャーの名前:M退去日
数式:=IF(HASONEFILTER('記録'[入居日]), MAX('記録'[退去日]))

解説

メジャーでテーブルの値を返すときは、集計関数が必要になります。
ピボットテーブルがテーブルの1行を示す場合は、値が1つなので、1つの値のMAX値でその値を求めています。なので、集計関数はMINやその他の関数でもOKです。
ピボットテーブルが小計や総計では、複数行を示すので、複数の退去日があります。これのMAX値を返しても意味は無いので、HASONEFILTERでフィルタが掛かってる時のみ値を返すようにしています。

参考

メジャーの特性 や 見出しの階層に合わせて集計する には:https://qiita.com/PowerBIxyz/items/17d5d531ea074a43867b

ピボットテーブルでの応用

  • ISFILERED:総計、合計との区別をしたいとき
  • HASONEFILER:小計との区別をしたいとき
  • HASONEVALUE:値が1つかどうかを区別したいとき

23) メジャーの作成(部屋番、当月日数)

以下同様に次のメジャーを追加
メジャーの名前:M部屋番
数式:=IF(HASONEFILTER('記録'[入居日]), MAX('記録'[部屋番]))

メジャーの名前:M当月日数(利用日数が不要なら、このメジャーの代わりに日数列を使用)
数式:=VAR st = EOMONTH(MIN('集計月'[年月日]), -1) + 1 // 月初日
VAR et = EOMONTH(MAX('集計月'[年月日]), 0) // 月末日。集計月スライサーの値
RETURN
    SUMX(
        '記録', // ピボットテーブルは番号、名前、入居日を全て表示
        CALCULATE(
            VAR sd = MIN('記録'[入居日])
            VAR ed = MAX('記録'[退去日])
            VAR sc = MAX(st, sd) // 日数カウント開始日
            VAR ec =MIN(et, ed) // 日数カウント終了日
            RETURN
                IF(
                    ec >= sc, // 終了>=開始なら日数をカウント
                    DATEDIFF(sc, ec, DAY) + 1
                )
        )
    )

解説:カウント開始終了のsc、ecの求め方
   sd1  st  sd2         ed1  et  ed2
---+---|---+----------+---|---+---
sd1<stならsd1、sd2>stならst、ed1<etならed1、de2>etならetを採用する。

参考:以下は同じ結果を得られますが式が長いです。

メジャーの名前:M当月日数旧
数式:= SUMX('記録',
    CALCULATE(
        VAR st = EOMONTH(MIN('集計月'[年月日]), -1) + 1 // 月初日
        VAR et = EOMONTH(MAX('集計月'[年月日]), 0)      // 月末日
        VAR sd = MIN('記録'[入居日])
        VAR ed = MAX('記録'[退去日])
        RETURN
        SWITCH(
            TRUE,
            AND(AND(sd >= st, sd <= et), AND(ed >= st, ed <= et)), // 入居日=当月、退去日=当月
                DATEDIFF(sd, ed, DAY) + 1,         // 退去日-入居日+1
            AND(AND(sd >= st, sd <= et), ed > et), // 入居日=当月、退去日>当月
                DATEDIFF(sd, et, DAY) + 1,         // 月末-入居日+1
            AND(sd < st, AND(ed >= st, ed <= et)), // 入居日<当月、退去日=当月
                DATEDIFF(st, ed, DAY) + 1,         // 退去日-月初+1
            AND(sd <st, ed > et),                  // 入居日<当月、退去日>当月
                DATEDIFF(st, et, DAY) + 1          // 月末-月初+1
        )    // 上記以外はnull
    )
)

解説

「SUMX('記録', 第2引数)」で'記録'テーブルの1行毎に第2引数の処理を行ったものを合計します。
SUMX()の第2引数のCALCLATEで、CALCULATEの中が行コンテキストに対応するフィルタコンテキストに変わります。[氏名]と[入居日]は'記録'テーブルに重複が無いので、実質は1行の処理になります。
(もし、CALCULATEが無いと、MAX()等の対象範囲はピボットテーブルのフィルタコンテキストになり、1行毎の処理になりません。)
CALCULATEの中で、集計月の月初と月末日と入居日と退去日の関係をSWITCHで場合分けして、利用日数を計算します。

参考

24) ピボットテーブルを次のように展開

列:Σ値。行:番号、名前、入居日。Σ値」M退去日、M部屋番、M単月日数。

25) 絞り込みフィルタ

ピボットテーブルの入居日のフィルタアイコンから[値フィルタ]で[M当月日数]が0より大きいというフィルタを掛ける。
250703nyukyo01

解説

ピボットテーブルではΣ値にフィルタを掛けることができません。そこで、Σ値をキーに項目行にフィルタを掛けます。

別の方法としてΣ値をメジャーのみにし、メジャーの式でフィルタするものをnullにすることでも、値のフィルタができます。

26) 当月選択スライサー

ピボットテーブルのフィールドで[すべて]タブを表示し、"集計月"の"年月"を右クリックして[スライサーとして追加]。集計したいスライサーの年月をクリックして選択。これでスライサーが選択した年月日がメジャーM単月日数で処理され、27)のフィルタで絞り込まれます。

解説

'集計月'スライサーは、メジャーM当月日数が計算する範囲を選択するために使用します。
'集計月'スライサーは、'記録'から作成されたピボットテーブルの表示フィルタには使いません。
よって、'集計月'と'記録'をリレーションしてはいけません。リレーションすると、月またぎのレコードが表示されなくなります。
リレーションの警告表示は無視してください。

27) 表のレイアウト、構成の変更

[ピボットテーブル分析]-[オプション]-[レイアウトと書式]の"列幅の自動調整"や、[デザイン]-[レポートのレイアウト/小計/総計]などを好みに応じて変更。
250703nyukyo02 250703nyukyo03 250703nyukyo04 250703nyukyo05

28) 表のレイアウト、構成の変更

ピボットデーブル内の要素を右クリックし、小計のチェック他を好みに応じて変更。
250703nyukyo06

29) 更新手順

[データ]-[すべて更新v]-[すべて更新]でデータを更新する。

5. サンプルファイル

ダウンロード - 250703nyukyo.xlsx

C:\Users\Public\Documents\に保存してください。

6. 関連リンク

Power Queryで表をリスト形式に整形する方法(まとめ)
https://bigarrow.tea-nifty.com/blog/2025/11/post-4925ca.html

Excel/Power Queryでデータブロックが横に並んでいるデータを縦にまとめる方法
https://bigarrow.tea-nifty.com/blog/2025/06/post-80cc7d.html

日付範囲でVLOOKUPできないなら他の関数を使えばいいじゃない【Excel】
https://www.youtube.com/watch?v=95TfTNPQmeg


7. 余談

ココログで表を書くのが面倒なので、VS Codeにマークダウンで入力し、拡張機能 Markdown All in OneでHTMLに書き出したものをココログに貼ってみました。

ココログはHTMLのごく一部しか機能しないので、Markdown All in OneのHTMLを貼り付けると、かなり多くのコードが消えます。なので、最初の原稿をVS Codeで書きHTML化してココログに貼り付けた後に修正が必要になります。なので、貼付け後はココログで編集するしかないです。

<table>は使用できるパラメータが異なるので、ココログで<table>にスタイルなどを追加します。

<pre>の中でも<br />が自動的に入り改行が2重になるので、<pre>を<p>に変更します。

| | コメント (0)

« 2025年6月 | トップページ | 2025年8月 »