💻 STEP 31: Mコードの基礎
Power Queryの裏側を覗く!M言語で自動化をマスター
📋 このステップで学ぶこと
- Mコード(M言語)とは何か
- 詳細エディタの使い方と画面構成
- M言語の基本構文(let…in、変数、演算子)
- よく使うM関数(テーブル操作、テキスト、日付)
- カスタム関数の作成方法
- Mコードのデバッグとエラー対処
ゴール:GUIで生成されたMコードを理解し、簡単な編集ができるようになる
🎯 1. Mコードとは
M言語の概要を理解しよう
Power QueryでGUI(ボタンやメニュー)を使って操作すると、裏ではMコード(M言語)というプログラムコードが自動生成されています。このコードを理解し、直接編集できるようになると、より高度なデータ変換が可能になります。
| GUI操作 | 裏で生成されるMコード | 意味 |
|---|---|---|
| 列を削除 | Table.RemoveColumns(…) | テーブルから列を削除する関数 |
| 列名を変更 | Table.RenameColumns(…) | 列の名前を変更する関数 |
| 行をフィルター | Table.SelectRows(…) | 条件に合う行だけを選択する関数 |
| データ型を変更 | Table.TransformColumnTypes(…) | 列のデータ型を変換する関数 |
なぜMコードを学ぶのか
GUIだけでも多くの操作は可能ですが、Mコードを理解すると、より効率的で高度なデータ処理ができるようになります。
| メリット | 説明 | 具体例 |
|---|---|---|
| GUIでできない操作が可能 | 複雑な条件分岐やループ処理が書ける | 複数条件での動的フィルター |
| 変換の再利用が簡単 | コピー&ペーストで他のクエリに適用できる | 同じ変換を別ファイルに適用 |
| バッチ処理が可能 | 複数ファイルを一度に処理できる | フォルダ内の全Excelを結合 |
| パフォーマンスの最適化 | 無駄なステップを削除・統合できる | 処理速度の向上 |
| トラブルシューティング | エラーの原因を特定しやすい | どのステップで問題が起きたか把握 |
| ポイント | 説明 |
|---|---|
| すべてを理解する必要はない | GUIで操作し、必要に応じてコードを少し編集する、というアプローチで十分 |
| プログラミング経験不要 | 最初はGUIで操作し、生成されたコードを眺めることから始める |
| 徐々にステップアップ | 簡単な編集(列名変更、条件追加)から始めて、徐々に複雑な処理へ |
📝 2. 詳細エディタの使い方
詳細エディタとは
詳細エディタは、Power Queryで自動生成されたMコードを表示・編集するための専用画面です。ここでコードを直接編集することで、GUIでは難しい高度な変換が可能になります。
| 方法 | 操作手順 | 表示される内容 |
|---|---|---|
| 方法1 | ホームタブ→「詳細エディタ」ボタン | クエリ全体のMコードが表示される |
| 方法2 | 表示タブ→「数式バー」にチェック | 現在選択中のステップのコードのみ表示 |
| 方法3 | ステップの⚙マークをクリック | そのステップの設定ダイアログが開く |
| 手順 | 操作 | 補足 |
|---|---|---|
| 1 | Power Queryエディタを開く | ホームタブ→「データの変換」 |
| 2 | ホームタブをクリック | リボンの「ホーム」タブを選択 |
| 3 | 「詳細エディタ」ボタンをクリック | 「クエリ」グループ内にある |
| 4 | Mコードが表示される | 編集可能なテキストエリアで表示 |
詳細エディタの画面構成
詳細エディタは非常にシンプルな構成です。中央にコード編集エリア、下部にボタンが配置されています。
| 要素 | 説明 | 使い方 |
|---|---|---|
| コード編集エリア | Mコードが表示される領域 | 直接編集可能。行番号も表示 |
| OKボタン | 変更を保存して閉じる | 編集完了後にクリック |
| キャンセルボタン | 変更を破棄して閉じる | 間違えた時にクリック |
| エラー表示 | 構文エラーがある場合に表示 | エラー内容を確認して修正 |
Mコードの基本構造
Mコードはlet…inという構造で書かれています。letの中でステップ(変数)を定義し、inの後で最終結果を指定します。
let
ソース = Excel.Workbook(File.Contents("C:\data.xlsx")),
Sheet1 = ソース{[Item="Sheet1"]}[Data],
昇格されたヘッダー = Table.PromoteHeaders(Sheet1),
変更された型 = Table.TransformColumnTypes(昇格されたヘッダー, ...)
in
変更された型
※モバイルでは横スクロールできます
| 要素 | 役割 | 具体例 |
|---|---|---|
| let | ステップの定義を開始 | let の後に各ステップを記述 |
| 各行(ステップ) | 変換処理を定義 | ソース = Excel.Workbook(…) |
| カンマ(,) | ステップの区切り | 各ステップの末尾に付ける(最後以外) |
| in | 最終結果を指定 | in の後に出力したいステップ名を書く |
📖 3. M言語の基本構文
変数とステップの書き方
Mコードでは、各操作を「変数名 = 式」という形で記述します。GUI操作で追加される「適用したステップ」は、すべてこの形式でMコードに変換されています。
| 可否 | ルール | 例 |
|---|---|---|
| ✅ OK | 日本語の変数名 | 売上データ = … |
| ✅ OK | 英数字の変数名 | SalesData = … |
| ✅ OK | スペースを含む名前(推奨しない) | #”売上 データ” = … |
| ⚠️ 注意 | 大文字小文字は区別される | Data と data は別の変数 |
| ❌ NG | 予約語は使えない | let, in, if, then, else など |
データ型
Mコードでは様々なデータ型を扱います。テキスト、数値、日付などの基本的な型に加え、リスト、レコード、テーブルといった複合的な型もあります。
| データ型 | 書き方 | 具体例 |
|---|---|---|
| テキスト | ダブルクォートで囲む | “こんにちは”、”東京都” |
| 数値 | そのまま記述 | 123、123.45、-50 |
| 日付 | #date(年, 月, 日) | #date(2024, 1, 15) |
| 日付時刻 | #datetime(年, 月, 日, 時, 分, 秒) | #datetime(2024, 1, 15, 14, 30, 0) |
| 論理値 | true または false | true、false |
| null | null | 値がないことを表す |
| リスト | { } で囲む | {1, 2, 3, 4, 5} |
| レコード | [ ] で囲む | [名前=”山田”, 年齢=25] |
演算子
Mコードで計算や比較を行うための演算子を覚えましょう。特に比較演算子はフィルター条件で頻繁に使用します。
| 演算子 | 意味 | 例 |
|---|---|---|
| + | 加算(足し算) | 10 + 5 → 15 |
| – | 減算(引き算) | 10 – 5 → 5 |
| * | 乗算(掛け算) | 10 * 5 → 50 |
| / | 除算(割り算) | 10 / 5 → 2 |
| & | 文字列連結 | “山田” & “太郎” → “山田太郎” |
| 演算子 | 意味 | 例 |
|---|---|---|
| = | 等しい | [地域] = “東京” |
| <> | 等しくない | [状態] <> “削除” |
| > | より大きい | [売上] > 100000 |
| >= | 以上 | [売上] >= 100000 |
| < | より小さい | [年齢] < 20 |
| <= | 以下 | [年齢] <= 65 |
| 演算子 | 意味 | 例 |
|---|---|---|
| and | かつ(両方満たす) | [売上] > 100000 and [地域] = “東京” |
| or | または(どちらか満たす) | [地域] = “東京” or [地域] = “大阪” |
| not | 否定(反転) | not [削除フラグ] |
🔧 4. よく使うM関数
テーブル操作関数
Power Queryでデータを変換する際、最も頻繁に使用するのがTable.で始まる関数です。これらの関数でテーブルの行や列を操作します。
| 関数名 | 機能 | GUIでの操作 |
|---|---|---|
| Table.SelectRows | 条件に合う行だけを抽出 | フィルター |
| Table.SelectColumns | 指定した列だけを残す | 他の列の削除 |
| Table.RemoveColumns | 指定した列を削除 | 列の削除 |
| Table.RenameColumns | 列名を変更 | 列名の変更 |
| Table.TransformColumnTypes | データ型を変更 | データ型の変更 |
| Table.AddColumn | 新しい列を追加 | カスタム列の追加 |
// 基本構文 Table.SelectRows(テーブル, each 条件) // 例1: 売上が100万円以上の行を抽出 Table.SelectRows(元データ, each [売上] >= 1000000) // 例2: 東京都のデータだけを抽出 Table.SelectRows(元データ, each [地域] = "東京都") // 例3: 複数条件(売上100万円以上かつ東京都) Table.SelectRows(元データ, each [売上] >= 1000000 and [地域] = "東京都")
※モバイルでは横スクロールできます
| 項目 | 説明 |
|---|---|
| each とは | 「各行に対して」という意味。テーブルの1行1行に処理を適用する |
| [列名] の意味 | 現在処理中の行の、指定した列の値を取得する |
| 使用例 | each [売上] > 100000 は「各行の売上が10万円より大きい場合」 |
テキスト関数
文字列の加工にはText.で始まる関数を使用します。大文字変換、空白除去、文字列結合など、様々な処理ができます。
| 関数名 | 機能 | 例 |
|---|---|---|
| Text.Upper | 大文字に変換 | Text.Upper(“hello”) → “HELLO” |
| Text.Lower | 小文字に変換 | Text.Lower(“HELLO”) → “hello” |
| Text.Trim | 前後の空白を削除 | Text.Trim(” 山田 “) → “山田” |
| Text.Length | 文字数を取得 | Text.Length(“こんにちは”) → 5 |
| Text.Start | 先頭からN文字を取得 | Text.Start(“こんにちは”, 2) → “こん” |
| Text.End | 末尾からN文字を取得 | Text.End(“こんにちは”, 2) → “ちは” |
| Text.Contains | 文字列を含むか判定 | Text.Contains(“東京都”, “東京”) → true |
| Text.Replace | 文字列を置換 | Text.Replace(“A-001”, “-“, “”) → “A001” |
| Text.Combine | リストを結合 | Text.Combine({“山田”,”太郎”}, ” “) → “山田 太郎” |
日付関数
日付データの操作にはDate.で始まる関数を使用します。年月日の取得、日付の加算、曜日の取得などが可能です。
| 関数名 | 機能 | 例(2024/1/15の場合) |
|---|---|---|
| Date.Year | 年を取得 | Date.Year(日付) → 2024 |
| Date.Month | 月を取得 | Date.Month(日付) → 1 |
| Date.Day | 日を取得 | Date.Day(日付) → 15 |
| Date.AddDays | 日を加算 | Date.AddDays(日付, 7) → 2024/1/22 |
| Date.AddMonths | 月を加算 | Date.AddMonths(日付, 1) → 2024/2/15 |
| Date.DayOfWeek | 曜日を取得 | Date.DayOfWeek(日付) → 0〜6(日曜=0) |
| Date.ToText | 日付を文字列に変換 | Date.ToText(日付, “yyyy/MM/dd”) |
条件分岐(if文)
条件によって処理を変えたい場合は、if…then…else構文を使用します。カスタム列でのランク付けなどでよく使われます。
| 構文 | 説明 |
|---|---|
| 基本形 | if 条件 then 真の場合 else 偽の場合 |
| 複数条件 | if 条件1 then 値1 else if 条件2 then 値2 else 値3 |
// 例1: 単純な条件分岐 if [売上] >= 1000000 then "達成" else "未達成" // 例2: 複数条件でのランク付け if [売上] >= 1000000 then "A" else if [売上] >= 500000 then "B" else if [売上] >= 100000 then "C" else "D" // 例3: 複数条件の組み合わせ(andを使用) if [売上] >= 1000000 and [地域] = "東京" then "最重要" else if [売上] >= 500000 then "重要" else "通常" // 例4: null判定 if [列名] = null then "未設定" else [列名] // 例4の代替(?? 演算子を使用) [列名] ?? "未設定"
※モバイルでは横スクロールできます
⚙️ 5. カスタム関数の作成
関数を自分で作る
同じ処理を何度も使う場合、カスタム関数として定義しておくと便利です。一度定義すれば、様々な場所で再利用できます。
| メリット | 説明 |
|---|---|
| ロジックの一元管理 | 同じ計算ロジックを1箇所で管理。変更が必要な時も1箇所直すだけ |
| 再利用が簡単 | 複数の列や複数のクエリで同じ関数を使い回せる |
| 可読性の向上 | 関数名で処理内容がわかり、コードが読みやすくなる |
// 基本構文
(引数) => 処理
// 例1: 消費税を計算する関数
(税抜金額) => 税抜金額 * 1.1
// 例2: 複数の引数を取る関数
(引数1, 引数2) => 処理
// 例3: 範囲チェック関数
(値, 最小, 最大) =>
if 値 >= 最小 and 値 <= 最大
then "範囲内"
else "範囲外"
※モバイルでは横スクロールできます
実践例:売上ランク判定関数を作成する
売上金額に応じてA/B/Cのランクを付ける関数を作成し、複数の列で再利用する方法を学びます。
| 手順 | 操作 | 補足 |
|---|---|---|
| 1 | Power Queryエディタを開く | ホーム→データの変換 |
| 2 | ホーム→新しいソース→空のクエリ | 新しいクエリを作成 |
| 3 | ホーム→詳細エディタを開く | Mコードを直接入力 |
| 4 | 関数コードを入力(下記参照) | let...in構造で記述 |
| 5 | OKをクリック | 関数として保存される |
| 6 | クエリ名を「売上ランク」に変更 | わかりやすい名前に |
let
売上ランク = (金額) =>
if 金額 >= 1000000 then "A"
else if 金額 >= 500000 then "B"
else "C"
in
売上ランク
※モバイルでは横スクロールできます
| 手順 | 操作 | 補足 |
|---|---|---|
| 1 | データのクエリを選択 | 関数を適用したいテーブル |
| 2 | 列の追加タブ→カスタム列 | 新しい列を追加 |
| 3 | 列名「今月ランク」、式に 売上ランク([今月売上]) と入力 | 関数名(列名)の形式で呼び出す |
| 4 | OKをクリック | 新しい列が追加される |
再利用例:売上ランク([前月売上])、売上ランク([累計売上]) など、同じ関数を別の列にも適用できます。
🐛 6. Mコードのデバッグ
エラーの種類と対処法
Mコードを編集する際、エラーが発生することがあります。エラーの種類を理解し、適切に対処しましょう。
| エラーの種類 | 原因 | 対処法 |
|---|---|---|
| 構文エラー | カンマの位置、括弧の不一致 | エラーメッセージの行番号を確認 |
| 名前が見つからない | 変数名や列名のスペルミス | 正確な名前を確認して修正 |
| 型の不一致 | 数値と文字列の比較など | 適切な型変換を追加 |
| 列が見つからない | 参照している列が削除された | ステップの順序を確認 |
| 手順 | 操作 | 目的 |
|---|---|---|
| 1 | 各ステップをクリックして確認 | どのステップで問題が起きたか特定 |
| 2 | 問題のステップを特定 | エラー(!マーク)が表示されるステップを見つける |
| 3 | 詳細エディタで該当行を確認 | コードの問題箇所を特定 |
| 4 | 修正してOK | エラーが解消されたか確認 |
途中結果を確認するテクニック
Mコードでは、一時的にinの後を変更することで、途中のステップの結果を確認できます。デバッグに非常に便利です。
let
ソース = ...,
ステップ1 = ...,
ステップ2 = ..., // ← ここまでの結果を確認したい
ステップ3 = ...
in
ステップ2 // ← 一時的にステップ2に変更
// 確認後、元に戻す
in
ステップ3
※モバイルでは横スクロールできます
コメントの活用
Mコードにコメントを書いておくと、後で見返した時に処理内容がわかりやすくなります。チームでの共有にも役立ちます。
| 種類 | 書き方 | 使用場面 |
|---|---|---|
| 単一行コメント | // コメント | 各行の説明 |
| 複数行コメント | /* コメント */ | 長い説明や一時的なコード無効化 |
let
// ソースデータの読み込み
ソース = Excel.Workbook(File.Contents("C:\data.xlsx")),
/*
不要な行を削除
ヘッダー行が3行あるため、最初の2行を削除
*/
行削除 = Table.Skip(ソース, 2),
// 1行目を列名として昇格
ヘッダー = Table.PromoteHeaders(行削除)
in
ヘッダー
※モバイルでは横スクロールできます
💡 7. 実践的なMコードパターン
エラーハンドリング
データ変換中にエラーが発生しても処理を続行させたい場合、try...otherwise構文を使用します。
| 構文 | 説明 |
|---|---|
| 基本形 | try 処理 otherwise デフォルト値 |
| 意味 | 処理を試みて、エラーが発生したらデフォルト値を返す |
// 例1: 型変換でエラーが出る可能性がある場合
// 変換できない値は0にする
Table.AddColumn(元データ, "数値",
each try Number.From([テキスト列]) otherwise 0)
// 例2: 文字列から日付への変換
// 変換できない場合はnullにする
Table.AddColumn(元データ, "日付",
each try Date.From([日付文字列]) otherwise null)
// 例3: エラー行を除外
Table.SelectRows(元データ,
each try [列名] <> null otherwise false)
※モバイルでは横スクロールできます
📝 STEP 31 のまとめ
- Mコード:Power QueryのGUI操作の裏で自動生成されるコード
- 詳細エディタ:Mコードを直接確認・編集できる画面
- 基本構文:let...in構造、変数、演算子
- M関数:Table、Text、Date関数で様々な処理
- カスタム関数:再利用可能なロジックを作成
- デバッグ:ステップ確認、コメントでエラー対処
Mコードは完璧に理解する必要はありません。
まずはGUIで操作し、生成されたコードを眺めることから始めましょう。
徐々に簡単な編集(列名変更、条件追加など)ができるようになれば十分です。
Mコードの真価は複雑な自動化やバッチ処理で発揮されます!
📝 実践演習
GUIで簡単な操作(列の削除、列名変更)を行い、詳細エディタでMコードを確認してください。どの行がどの操作に対応しているか理解してください。
| 1 | データを読み込む(Excel等) |
| 2 | 列を1つ削除(右クリック→削除) |
| 3 | 別の列の名前を変更(ダブルクリック) |
| 4 | ホームタブ→詳細エディタ |
| 5 | Mコードを確認 |
確認ポイント:
- let...in構文になっている
- Table.RemoveColumns(...) が列の削除
- Table.RenameColumns(...) が列名変更
- 各行が「適用したステップ」と対応している
カスタム列を追加し、以下の条件でランク付けしてください。Mコードの条件文(if...then...else)を詳細エディタで確認してください。
①100万円以上:A、②50万円以上:B、③それ以外:C
| 1 | 列の追加タブ→カスタム列 |
| 2 | 新しい列名:「ランク」 |
| 3 | 式を入力(下記参照) |
| 4 | OK→詳細エディタで確認 |
カスタム列の式で入力:
if [売上] >= 1000000 then "A" else if [売上] >= 500000 then "B" else "C"
詳細エディタで直接Mコードを編集して、以下を実現してください:①姓と名を結合して氏名列を作成、②郵便番号に「-」を追加(1500043→150-0043)、③コメントを追加して処理内容を説明
let
// データソースの読み込み
ソース = Excel.Workbook(File.Contents("C:\data.xlsx")),
Sheet1 = ソース{[Item="Sheet1"]}[Data],
// ヘッダーの昇格
ヘッダー = Table.PromoteHeaders(Sheet1),
// ①姓と名を結合して氏名を作成
氏名追加 = Table.AddColumn(ヘッダー, "氏名",
each [姓] & " " & [名], type text),
// ②郵便番号に「-」を追加(例: 1500043 → 150-0043)
郵便番号整形 = Table.AddColumn(氏名追加, "郵便番号(整形)",
each Text.Start([郵便番号], 3) & "-" &
Text.End([郵便番号], 4), type text)
in
郵便番号整形
ポイント:
- // でコメントを追加
- & で文字列を結合
- Text.Start() で先頭3文字を取得
- Text.End() で末尾4文字を取得
❓ よくある質問
基本的な分析ならMコードを書く必要はありません。ただし、複雑な自動化やバッチ処理をしたい場合、Mコードの知識があると非常に便利です。
まずはGUIから始めて、必要に応じて少しずつ学習しましょう。
Mコードの編集は慎重に行いましょう。特によくあるエラーの原因は:
- カンマの位置ミス(最後の行にはカンマ不要)
- 括弧の対応が合っていない
- スペルミス
詳細エディタからコード全体をコピーし、別のクエリに貼り付けることができます。
ただし、ファイルパスや列名などは環境に合わせて修正が必要です。
| 項目 | Mコード | DAX |
|---|---|---|
| 使用場所 | Power Query(データ変換) | Power BI本体(分析) |
| 用途 | データの読み込み・整形 | 集計・計算・メジャー作成 |
| 実行タイミング | データ読み込み時 | レポート表示時 |
両方を学ぶ必要がありますが、まずはMコードから始めましょう。
テーブルの各行に対して処理を適用する際に使用します。
例えば
each [売上] > 100000 は「各行の売上列の値が10万より大きいかどうか」をチェックします。eachの後の [列名] は、現在処理中の行の該当列の値を参照しています。
学習メモ
BIツール入門 - Step 31