3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Power Query workout - File.Contents

Last updated at Posted at 2022-04-05

どのように動作しているのか知らずとも多くの機会で利用する Power Query の関数。それが File.Contents。でも、想像より複雑にかつ合理的な動作をしているはずなのである。

Power Query でファイル( binary )を読み込むときの動作には、

  • 可能な限り少ない読み込みで完了すること
  • ソースデータのファイルフォーマットごとで適した動作をしていること

という特徴があって、

Csv.Document(
    File.Contents( ... )
)

のような利用であるけれども、File.Contents でファイルを取得し Csv.Document で解釈するという理解では Power Query の特徴を表しきれない。File.Contents で binary 読込完了 → 次の処理(ステップなど) ということではなく、次以降の処理を勘案し File.Contents での binary 読込 がコントロールされるのだ。

ウォームアップ

構文と例

File.Contents (Power Query)
File.Contents(
    path as text,
    optional options as nullable record
) as binary

Returns the contents of the file, path, as binary. The options parameter is currently intended for internal use only.

path 引数は絶対パスを表現する文字列でファイルシステムよりファイル (binary) を取得する動作をする。単独で利用することは少ない。

鍛錬

フラットファイル データソース がわかりやすい
改行文字を区切りとして テーブル でいうところの行として読み込むとき、可能な限り必要な部分を読み込む動作を観察。
テキストファイルや CSV ファイルなどは、4096 byte ごとで読み込むことがわかっているから、改行文字含め 4096 byte を 1 セット(1 行) 10 セット(10 行)の ソールファイル を読み込む経過を観察。

テーブルとして読み込み、行ごとの処理( Table.AddColumn ) を意図的に遅らせ( Function.InvokeAfter )、その時の時刻( DateTime.LocalNow )を記録。このとき、Process Monitor で ReadFile を記録。

SourceQuery (Power Query)
let
    Source = File.Contents(SourceFile),
    BinaryToLines = Lines.FromBinary(Source),
    ListToTable = Table.FromColumns({BinaryToLines}),
    AddedColumn2 = Table.AddColumn(
        ListToTable,
        "Column2",
        each Function.InvokeAfter(
            ()=>DateTime.ToText(
                {[Column1], DateTime.LocalNow()}{1},
                "hh:mm:ss.fffffff tt"
            ),
            #duration(0,0,0,1)
        ),
        Text.Type
    ),
    SelectColumn2 = Table.SelectColumns(
        AddedColumn2,
        {"Column2"}
    )
in
    SelectColumn2

image.png
意図的に遅延させた行ごとの処理( Table.AddColumn ) に一致するように ReadFile が行われる。

Query1 (Power Query)
// Query1
let
    Source = SourceQuery,
    First5Rows = Table.FirstN(Source,5)
in
    First5Rows

このクエリ(SourceQuery)の先頭 5 行だけ読み込む( Table.FirstN ) とすれば、ReadFile は 5件で済む。

Query2 (Power Query)
// Query2
let
    Source = SourceQuery,
    Last5Rows = Table.LastN(Source, 5)
in
    Last5Rows

最後 5 行だけ読み込む( Table.LastN ) とすると、ReadFile は 10 件。ただし、遅延させた行ごとの処理( Table.AddColumn ) 5 行分は ReadFile 10 件 すべて完了してからになる。

Query3 (Power Query)
// Query3
let
    Source = SourceQuery,
    Skip5Rows = Table.Skip(Source,5)
in
    Skip5Rows

先頭 5 行をスキップ( Table.Skip ) したとき、先頭 5 行分では 遅延させた行ごとの処理( Table.AddColumn ) は発生しない。スキップ完了以降の処理については、遅延させた行ごとの処理( Table.AddColumn ) 通りに ReadFile が発生する。

その他

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?