Go言語によるExcelテンプレートエンジンを活用した高度なレポート出力

複雑な構造を持つExcelレポート(例えば、週単位、日単位、サービス単位でネストされたデータや、バージョンごとに分かれたシートなど)をプログラムで一から構築するのは、コードの可読性とメンテナンス性の観点から非常に困難です。このような場合、MustacheやHandlebars形式のプレースホルダを埋め込んだExcelファイルをテンプレートとして用意し、そこにデータを流し込む手法が効率的です。

テンプレートベースの生成アプローチ

Go言語において、テンプレートを用いたExcel操作を実現するために github.com/ivahaev/go-xlsx-templater というライブラリが有効です。このライブラリは、内部的にExcel操作用の tealeg/xlsx と、テンプレートエンジンの aymerick/raymond を組み合わせて動作します。

基本的なワークフローは以下の通りです。

import (
    "github.com/ivahaev/go-xlsx-templater"
)

func generateBasicReport() {
    // テンプレートの初期化
    report := xlst.New()
    err := report.ReadTemplate("./template.xlsx")
    if err != nil {
        panic(err)
    }

    // データの注入
    dataContext := map[string]interface{}{
        "Title": "月次業務報告書",
        "Items": []map[string]string{
            {"Name": "サーバー保守", "Status": "完了"},
            {"Name": "バックアップ確認", "Status": "進行中"},
        },
    }

    // レンダリングと保存
    report.Render(dataContext)
    report.Save("./output.xlsx")
}

複数シートの一括生成への拡張

標準的な機能では、テンプレート内のシートを個別に処理することは可能ですが、一つのデータ集合から動的に複数のシートを生成する場合にはカスタマイズが必要です。以下は、スライス形式のパラメータを受け取り、それぞれのデータに対して新しいシートを割り当ててレンダリングする拡張実装の例です。

type ReportConfig struct {
    SheetTitle string
    Data       interface{}
}

func (x *Xlst) ExportMultiSheetData(configs []ReportConfig, opts *Options) (*xlsx.File, error) {
    if opts == nil {
        opts = &Options{}
    }

    newFile := xlsx.NewFile()
    // テンプレートの最初のシートをベースに使用
    baseSheet := x.file.Sheets[0]

    for _, cfg := range configs {
        // 新規シートの作成
        targetSheet, err := newFile.AddSheet(cfg.SheetTitle)
        if err != nil {
            return nil, err
        }

        // シート構造のコピー
        replicateSheetStructure(baseSheet, targetSheet)

        // テンプレートエンジンのコンテキストにデータをバインド
        renderErr := processRows(targetSheet, baseSheet.Rows, cfg.Data, opts)
        if renderErr != nil {
            return nil, renderErr
        }

        // カラム設定の同期
        targetSheet.Cols = append(targetSheet.Cols, baseSheet.Cols...)
    }

    return newFile, nil
}

印刷設定とレイアウトの最適化

実用的なレポートでは、セルの折り返し設定による行高さの自動調整や、印刷時の改ページ挿入といった細かい制御が求められます。特に tealeg/xlsx を使用する場合、改ページ(Page Breaks)情報を保持するために構造体を拡張し、XML定義にマッピングする必要があります。

// xlsxライブラリのSheet構造体に改ページ情報を追加する定義
type CustomSheet struct {
    Name            string
    Rows            []*Row
    Cols            []*Col
    // 印刷制御用の改ページフィールド
    RowPageBreaks   *XlsxBreaks `xml:"rowBreaks"`
    ColPageBreaks   *XlsxBreaks `xml:"colBreaks"`
}

type XlsxBreaks struct {
    Count   int          `xml:"count,attr"`
    Manual  int          `xml:"manualCount,attr"`
    Brk     []XlsxBreak  `xml:"brk"`
}

type XlsxBreak struct {
    ID  int  `xml:"id,attr"`
    Max int  `xml:"max,attr"`
    Man bool `xml:"man,attr"`
}

このように、既存のライブラリが提供する機能が不足している場合は、基礎となるデータ構造(XMLマッピング層)に手を入れることで、Excel固有の高度な機能(改ページプレビューやオートフィルター設定など)をGoから操作できるようになります。テンプレート方式は、デザインとロジックを分離できるため、複雑な要件のビジネスレポート作成において非常に強力な武器となります。

タグ: Go Excel template xlsx Report-Generation

9月26日 23:12 投稿