grunt-mustache-renderを使ってエクセルからhtmlを量産したい!


エクセルのデータからhtmlファイルを大量に作成する案件があったので、
その時のことをメモ兼ねて書いてみました。

はじめに

今回はGruntで作業を行ったので、Gruntでの方法になってます。
主なモジュールはコレ

・grunt-mustache-render
・xlsx

簡単な構成としては、下記な感じです。
(1) xlsxモジュールでデータを取り出し
(2) grunt-mustache-renderで使えるようにデータを整形
(3) grunt-mustache-renderでファイル生成

各種設定

エクセルファイルのフォーマット

1行目をヘッダー、
2行目以降が生成ファイルのデータ(1レコード1ファイル)
でエクセルを作成してます。

テンプレートの設定

template.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{タイトル}}</title>
    <link rel="stylesheet" href="/css/{{パラメータ1}}_{{パラメータ2}}_{{パラメータ3}}.css">
</head>
<body>
    <header>
        <h1>{{タイトル}}</h1>
    </header>
    <div>
        <img src="{{&画像}}" alt="{{タイトル}}">
    </div>
</body>
</html>

{{ }}で括ってる部分がエクセルからのデータを流し込む箇所になります。
{{ }}の中の名前はエクセルで作成したヘッダー名で指定しましょう。

Gruntの設定

Gruntfile.js
'use strict';
var XLSX = require('xlsx');
module.exports = function(grunt) {
  grunt.initConfig({
    clean: {
        run: ['./output']
    },
    mustache_render: {
        run: {
            files: (function() {
                // 設定
                var inpFile = 'サンプル.xlsx';
                var inpSheet = 'Sheet1';

                // ファイル読み込み
                var data = XLSX.readFile(inpFile);
                var sheet = data.Sheets[inpSheet];

                // ファイル内容整形
                var json = XLSX.utils.sheet_to_json(sheet);

                var files = [];
                for (var i=0, j=json.length; i<j; i++){
                    var pageData = json[i];

                    // files配列にオブジェクトを追加
                    files.push({
                        // ページデータ
                        data: pageData,
                        // テンプレートファイルを指定
                        template: './template.html',
                        // 生成するhtmlの場所と名前を設定
                        dest: './output/' + pageData.パラメータ1 + '_' + pageData.パラメータ2 + '_' + pageData.パラメータ3 + '.html'
                    });
                }
                // 配列を返却
                return files;
            }())
        }
    }
  });
  grunt.loadNpmTasks('grunt-mustache-render');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.registerTask('run', ['clean', 'mustache_render']);
};

cleanを導入してますけど、これは好みでどうぞ。
上記ではファイルを生成する前に一度ディレクトリの中を空にしてます。

Gruntfile.js(抜粋1)
// 設定
var inpFile = 'サンプル.xlsx';
var inpSheet = 'Sheet1';

上記の部分では、
inpFileでは読み込み対象のエクセルを指定し、
inpSheetでは上記ファイル内のシート名を指定しています。

ちなみに、今回は特に設定をしていないため、ルートのディレクトリはGruntfile.jsが置いてる階層となってます。

Gruntfile.js(抜粋2)
// files配列にオブジェクトを追加
files.push({
  // ページデータ
  data: pageData,
  // テンプレートファイルを指定
  template: './template.html',
  // 生成するhtmlの場所と名前を設定
  dest: './output/' + pageData.パラメータ1 + '_' + pageData.パラメータ2 + '_' + pageData.パラメータ3 + '.html'
});

こちらのブロックでは、
実際にファイルを出力する際のデータを整形しています。

なお、data: pageData,では読み込んだエクセルの1レコード分のデータが格納されてます。
各レコード内のパラメータへのアクセスは、
pageData.[パラメータ名]
で可能です。

パラメータを加工する必要がある場合は、
このブロックで行いましょう。
もちろんpageDataへのパラメータ追加も可能です。

いざ実行

上記の設定では

grunt run

でタスクが実行されます。

生成されたファイル

001_A01_BS000.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>サンプル1</title>
    <link rel="stylesheet" href="/css/001_A01_BS000.css">
</head>
<body>
    <header>
        <h1>サンプル1</h1>
    </header>
    <div>
        <img src="/img/sample01.png" alt="サンプル1">
    </div>
</body>
</html>

とりあえず、こんな方法もあるよということで〜

サンプル

今回作成したサンプルデータをgithubにアップしています。
https://github.com/kurokuma29/xlsx-render