ゴールのイメージを先にそろえる
今回のテーマは「Excelブックの中から、特定のシート名だけを Power Query で安定して取り込む実務テンプレ」です。
たとえば「毎月『集計』シートだけを読みたい」「別ブックの『SheetSales』だけをデータソースにしたい」といった場面を想定します。
キーワードは Excel.Workbook と「Name(または Item)+ Kind でシートを特定する」という考え方です。ここを押さえれば、あとはパターン化できます。
基本の仕組み:Excel.Workbook で「カタログ化」してから選ぶ
ブック全体を一覧にしてから、目的のシートを1行だけ抜き出す
Power Query は、Excel ブックを読むときに Excel.Workbook という関数を使います。
let
Source = Excel.Workbook(
File.Contents("C:\Data\SalesData.xlsx"),
true,
true
)
in
Source
Excel.Workbook は、そのブックに含まれる「シート」「テーブル」「名前付き範囲」などを、1行ずつ並べた“カタログ表”を返します。 適材適所
この表には、少なくとも次のような列があります。
Name(または Item)…シート名やテーブル名
Kind …「Sheet」「Table」などの種類
Data …そのシートやテーブルの中身(テーブル型)
特定シート名を指定する、というのは「このカタログ表の中から、Name=“欲しいシート名” かつ Kind=“Sheet” の行を1つだけ選び、その行の Data を取り出す」という操作に言い換えられます。
単一ブックから「特定シート名」だけを取るテンプレ
一番ストレートな M コード
たとえば、C:\Data\SalesData.xlsx の中の「SheetSales」というシートだけを取り込みたいとします。
その場合の M コードは、次のような形になります。
let
// 1) ブック全体を読み込む
XlFile = File.Contents("C:\Data\SalesData.xlsx"),
Source = Excel.Workbook(XlFile, true, true),
// 2) Name と Kind で「SheetSales」シートを特定
SheetSalesRow = Source{[Name = "SheetSales", Kind = "Sheet"]},
// 3) その行の Data 列(中身のテーブル)を取り出す
SheetSalesTable = SheetSalesRow[Data],
// 4) 必要なら先頭行をヘッダーに昇格
Promoted = Table.PromoteHeaders(
SheetSalesTable,
[PromoteAllScalars = true]
)
in
Promoted
ここで一番大事なのは、この1行です。
SheetSalesRow = Source{[Name = "SheetSales", Kind = "Sheet"]},
これは「Source テーブルの中から、Name が ‘SheetSales’ で Kind が ‘Sheet’ の行を1つだけ取り出す」という意味です。{…} の中に「行を特定する条件レコード」を書くことで、その行を直接インデックス指定できます。
その行の Data 列を取り出したものが、シートの中身そのもの(テーブル)です。
フォルダ内の複数ブックから「同じシート名」だけをまとめて取る
実務でよくあるシナリオ
現場でよくあるのは、「毎月のブックがフォルダにたまっていて、その中の『集計』シートだけを全部縦に結合したい」というパターンです。
どのブックにも「集計」というシートがあり、列構成も同じ、という前提です。
フォルダ+特定シート名の実務テンプレ
次のコードは、C:\Data\MonthlyBooks フォルダ内のすべての .xlsx について、「SheetSales」シートだけを読み込み、最後に全部まとめて1つのテーブルにするテンプレです。
let
// 1) フォルダ内のファイル一覧を取得
Source = Folder.Files("C:\Data\MonthlyBooks"),
// 2) .xlsx だけに絞り込む
Filtered = Table.SelectRows(
Source,
each [Extension] = ".xlsx"
),
// 3) 各ファイルから「SheetSales」シートを読み込むカスタム列を追加
AddedTables = Table.AddColumn(
Filtered,
"SheetSales",
each
let
XlFile = [Content],
WB = Excel.Workbook(XlFile, true, true),
TargetRow = WB{[Name = "SheetSales", Kind = "Sheet"]},
TargetTable = TargetRow[Data],
Promoted = Table.PromoteHeaders(
TargetTable,
[PromoteAllScalars = true]
)
in
Promoted
),
// 4) そのカスタム列を展開して、全ブック分を縦に結合
SampleTable = AddedTables[SheetSales]{0},
ColumnNames = Table.ColumnNames(SampleTable),
Expanded = Table.ExpandTableColumn(
AddedTables,
"SheetSales",
ColumnNames,
ColumnNames
)
in
Expanded
やっていることを言葉で整理すると、こうなります。
フォルダからファイル一覧を取る。
各行(各ファイル)について、「Excel.Workbook → Name/Kind でシートを特定 → Data を取り出す → ヘッダー昇格」という処理を実行し、その結果を SheetSales 列に入れる。
最後に SheetSales 列を展開して、全ブック分を縦に結合する。
ポイントは、「特定シート名を指定するロジックを、Table.AddColumn の中に閉じ込めている」ことです。これにより、フォルダにファイルを追加するだけで、同じ処理が自動で全ファイルに適用されます。
重要ポイントの深掘り
Name / Item と Kind をセットで使う理由
Excel.Workbook の結果には、シートだけでなくテーブルや名前付き範囲も含まれます。
同じ Name を持つ別種のオブジェクトが存在する可能性もあるため、「Name だけ」で行を特定するのは少し危険です。
そこで、実務テンプレとしては
Name(または Item)=「欲しいシート名」
Kind = “Sheet”
という2条件で行を特定するのが定番パターンになります。
これなら、「同名のテーブル」などに引っかかるリスクを避けられます。
シート名をセルやパラメータで可変にする発展形
もう一歩進めると、「シート名を固定文字列ではなく、セルに入力した値から取る」ということもできます。
たとえば、別クエリで「シート名」を1セルだけ持つテーブルを作り、それをドリルダウンしてテキスト値として取得しておきます(SheetNameParam など)。
あとは、先ほどの行特定部分をこう書き換えるだけです。
TargetRow = WB{[Name = SheetNameParam, Kind = "Sheet"]},
こうしておけば、「シート名が変わったらセルの値だけ変える」という運用にできます。
M コードを直接触る頻度を減らしたい現場では、かなり有効なパターンです。
実務での使い分けイメージ
特定シート名指定は、「シート名がきちんとルール化されている」現場で特に強いです。
たとえば、どのブックにも必ず「集計」「明細」「SheetSales」といった決まった名前のシートがあり、そこだけをデータソースにしたい場合です。
一方で、「シート名が人によってバラバラ」「でも1枚目にだけデータがある」という現場では、前に話した「1枚目固定取込」の方が壊れにくくなります。
つまり、「シート名が安定しているなら名前指定」「シート名が揺れるなら順番指定」という切り分けで考えると、設計がスッキリします。
