January 26, 2016

HugoでCSVからデータを読み込んでテーブルを作成するには

Notice: Hugoを使用していて思ったのですが、CSVをドキュメント内に埋め込むという目的では以下の方法よりも、shortcodeを用いる方がより優れた方法かもしれません。

Hugoには外部データを読み込んでページを作成する方法が主に4つあります。
  1. config.tomlで定義したサイト変数(.Site.Params.variablename)を使う
  2. frontmatterで定義したページ変数(.Params.variablename)を使う
  3. データフォルダを使う(\data以下に保存して、.Site.Data.variablenameで参照)
  4. 外部データファイルをgetJSON, getCSVで読み込む

今回は4つ目にあたる外部データファイルの読み込みとその応用についてメモします。 また、ファイル形式としてはCSV形式を対象に説明していきます。

まず、読み込む対象となるCSV形式のデータを用意しましょう。エクセルやテキストエディタなど適当なソフトで作成してください。その際、文字コードはUTF-8を指定するようにしてください。間違ってShift-JIS等で保存すると文字化けの原因となります。保存先は、hugoから参照できるならばどこでも良いのですが、今回はローカルに保存することにします。
product, price, quantity
X001, 2, 30
X203, 3, 10
(staticフォルダ内に分かりやすくするため、csvフォルダを作成し、その中にdata.csvを保存する例)
次に、csvを出力する先のページコンテンツを作成します。
+++
type = "csv-table"
datafilename = "\static\csv\data.csv"
+++
この文章のあとにcsvから生成されたテーブルが表示されます。 そして、コンテンツ内でtypeで指定したレイアウトを作成します。
datafilenameのように.Paramsではすべて小文字の変数名しか使えない点に注意しましょう。getCSVは変数を二つ取る関数で、デリミタと読み込むファイル名を指定します。細かな話ですが、デリミタは1文字のみ指定が可能なのでミスタイプで余計なスペースが入らないように注意してください。getCSVで読み込んだデータを行数$iと$i行目のデータ$rに展開し、rangeで繰り返し各行について処理していきます。各行の内容は$rは配列なので、さらにrangeを使って各要素(テーブルのセル)ごとに処理を繰り返すことでテーブルを出力できます。なお、現在処理中の行数$iを使ってifで条件判断することで、行数に応じて処理を変えることができ、ここでは、1行目はthタグをそれ以降はtdタグを出力させました。


{{.Content}}


{{ range $i, $r := getCSV "," .Params.datafilename}}

{{ if eq $i 0}}
 {{range $r}}
  
 {{ end }}
{{ else }}
 {{range $r}}
  
 {{ end }}
 {{ end }}

{{ end }}
{{ . }} {{ . }}
これで、hugoを実行すれば、data.csvの内容が\public\dynamic-document\index.htmlにレンダリングされます。


この文章のあとにcsvから生成されたテーブルが表示されます。
productpricequantity
X001230
X203310
この手法の便利な点は既存のCSVデータを手軽にhtmlに変換できる、ということだけではなく、一度ウェブサイトを構築した後であってもdata.csvを更新し再度レンダリングすれば自由にテーブルの中身を変化させられるところにあります。
さらに、テンプレートをtypeとして定義したので、別のCSVファイルを別のコンテンツに出力することもできます。例えば、data2.csvとcsv-table-content.mdを作成しとします。
Hello, World
2, 1
+++
type = "csv-table"
datafilename = "\static\csv\data2.csv"
+++

今度は別のデータを別のファイルからレンダリングした結果が以下に現れます。
上記の2ファイルを作成し、hugoを実行すると、新たにcsv-table-contentが先ほどと同じcsv-tableレイアウトを使ってレンダリングされます。


今度は別のデータを別のファイルからレンダリングした結果が以下に現れます。
HelloWorld
21
なかなか便利な仕組みですよね!

No comments :

Post a Comment