ゴールのイメージをそろえる
今回のテーマは「フォルダ内の複数ファイルを一括取込するときに、“中身が空のファイル”だけを自動で除外する実務テンプレ」です。
現場だと、こんなことがよく起きます。
フォルダに「まだ中身が入っていないテンプレファイル」も置かれている。
システムが“中身ゼロのCSV”を出力してくることがある。
これらをそのまま読み込むと、列だけあって行がゼロのテーブルが混ざったり、ヘッダーすら無くてエラーになったりします。
それを Power Query 側で「空ならスキップする」という型にしておく、というのが今回のゴールです。
まず「空ファイル」をどう定義するか
実務でよく使う二つの定義
空ファイルの定義は、ざっくり次のどちらかになります。
ファイルサイズがほぼゼロ(バイト数で判定)。
中身をテーブルにしたときに、データ行が1行もない(行数で判定)。
一番軽いのは「ファイルサイズで弾く」やり方です。
ただし、「ヘッダーだけあるけどデータがない」ファイルはサイズがそこそこあるので、
それも除外したい場合は「行数で判定する」方が確実です。
この二つを、CSV と Excel のフォルダ一括取込の流れに組み込んでいきます。
パターン1:CSV の空ファイルを自動除外するテンプレ
例題の前提
C:\Data\DailyCsv フォルダに、毎日こんなファイルが溜まっていくとします。
sales_2024-10-01.csv
sales_2024-10-02.csv
…
ところが、たまに「中身が空のファイル」や「ヘッダーだけでデータ行ゼロのファイル」が混ざる。
これらを自動で除外して、データがあるファイルだけを結合したい、という状況です。
ファイルサイズでざっくり除外するテンプレ
まずは一番軽い「サイズ判定」から。
let
Source = Folder.Files("C:\Data\DailyCsv"),
OnlyCsv =
Table.SelectRows(
Source,
each Text.Lower([Extension]) = ".csv"
),
// 1KB 未満のファイルを「空」とみなして除外する例
NonEmptySize =
Table.SelectRows(
OnlyCsv,
each [Size] > 0
),
AddedCsvTable =
Table.AddColumn(
NonEmptySize,
"CsvTable",
each
Csv.Document(
[Content],
[
Delimiter = ",",
Encoding = 65001,
QuoteStyle = QuoteStyle.Csv
]
),
type table
)
in
AddedCsvTable
Power Queryここでのポイントは [Size] > 0 の部分です。
Size はバイト数なので、0 のファイルは完全に空です。
「ヘッダーだけあるファイル」も除外したいなら、サイズの閾値をもう少し大きくしても構いません。
ただし、サイズ判定だけだと「ヘッダーだけのファイル」は残ってしまうことがあります。
そこで、より確実な「行数判定」のパターンも押さえておきます。
行数で「中身ゼロ」を判定して除外するテンプレ
CSV をテーブル化したあとで、「データ行が1行もないテーブル」を除外するパターンです。
let
Source = Folder.Files("C:\Data\DailyCsv"),
OnlyCsv =
Table.SelectRows(
Source,
each Text.Lower([Extension]) = ".csv"
),
// 各ファイルをテーブル化
AddedCsvTable =
Table.AddColumn(
OnlyCsv,
"CsvTableRaw",
each
Csv.Document(
[Content],
[
Delimiter = ",",
Encoding = 65001,
QuoteStyle = QuoteStyle.Csv
]
),
type table
),
// 先頭行をヘッダーに昇格
WithHeader =
Table.TransformColumns(
AddedCsvTable,
{
"CsvTableRaw",
each
Table.PromoteHeaders(
_,
[PromoteAllScalars = true]
),
type table
}
),
// 行数を数える列を追加
WithRowCount =
Table.AddColumn(
WithHeader,
"行数",
each Table.RowCount([CsvTableRaw]),
Int64.Type
),
// 行数が 0 のファイル(完全に空)を除外
NonEmptyOnly =
Table.SelectRows(
WithRowCount,
each [行数] > 0
)
in
NonEmptyOnly
Power Queryこの時点で、CsvTableRaw 列には「1行以上データがあるテーブル」だけが残っています。
あとは、いつも通り列名を取得して展開すれば、空ファイルを自動除外した結合テーブルが作れます。
ここでの重要ポイントは「Table.RowCount を使って、テーブルの行数で判定している」ことです。
これなら、サイズが小さくても中身があれば残るし、ヘッダーだけでデータ行ゼロならきちんと除外できます。
パターン2:Excel の空ブック/空シートを自動除外するテンプレ
例題の前提
C:\Data\MonthlyBooks に、毎月の売上ブックが溜まっているとします。
どのブックも「1枚目のシートに売上明細が入る」想定ですが、
たまに「テンプレだけでまだ入力されていないブック」や「シートはあるけどデータ行ゼロ」のものが混ざる。
これらを自動でスキップして、データがあるブックだけを結合したい、という状況です。
1枚目シートの行数で判定して除外するテンプレ
let
Source = Folder.Files("C:\Data\MonthlyBooks"),
OnlyXlsx =
Table.SelectRows(
Source,
each Text.Lower([Extension]) = ".xlsx"
),
// 各ブックの 1 枚目シートを読み込む
WithSheetTable =
Table.AddColumn(
OnlyXlsx,
"SheetTableRaw",
each
let
wb = Excel.Workbook([Content], true, true),
firstSheetRow =
Table.SelectRows(wb, each [Kind] = "Sheet"){0},
firstSheetTable = firstSheetRow[Data]
in
firstSheetTable,
type table
),
// 行数を数える列を追加
WithRowCount =
Table.AddColumn(
WithSheetTable,
"行数",
each Table.RowCount([SheetTableRaw]),
Int64.Type
),
// 行数が 0 のブック(完全に空)を除外
NonEmptyOnly =
Table.SelectRows(
WithRowCount,
each [行数] > 0
),
// 先頭行をヘッダーに昇格
WithHeader =
Table.TransformColumns(
NonEmptyOnly,
{
"SheetTableRaw",
each
Table.PromoteHeaders(
_,
[PromoteAllScalars = true]
),
type table
}
)
in
WithHeader
Power Queryこのテンプレでは、「1枚目シートの行数が 0 のブック」を空とみなして除外しています。
もし「ヘッダーだけあってデータ行がない」ブックも除外したいなら、
ヘッダー昇格後に「行数 > 0」ではなく「行数 > 1」などに変える、という考え方もできます。
ここでの重要ポイントは、「Excel.Workbook → Kind = ‘Sheet’ でシートを特定 → Data を取り出す → Table.RowCount で行数判定」という流れを型として覚えることです。
どこで「空判定」するのが一番ラクか
ファイル一覧の段階で判定するか、中身をテーブルにしてから判定するか
ざっくり分けると、空判定のタイミングは二つあります。
フォルダからファイル一覧を取った直後に、Size や Date modified などで判定する。
Content をテーブル化したあとで、Table.RowCount で判定する。
前者(サイズ判定)は軽くて速いですが、「ヘッダーだけあるファイル」を除外しにくい。
後者(行数判定)は少し重くなりますが、「本当にデータがあるかどうか」で判定できるので確実です。
実務テンプレとしては、
まずサイズで明らかに空なものを落とす(Size = 0)。
そのうえで、必要なら行数判定も入れる。
という二段構えにしておくと、パフォーマンスと確実性のバランスが取りやすくなります。
実務テンプレとしてのまとめイメージ
空ファイル自動除外の型は、こう整理できます。
フォルダ一括取込の流れの中で、「空判定用の列(行数やサイズ)」を一度追加する。
その列を使って「行数 > 0」「Size > 0」のようにフィルタし、空ファイル由来の行を丸ごと落とす。
一度この型を作っておけば、CSV でも Excel でも、
「Table.RowCount の対象」と「どの段階で判定するか」だけ変えれば、ほぼ同じノリで使い回せます。
