帳票作成のテンプレートエンジン（いろいろ）

# テンプレートエンジン（いろいろ）

**KOMAINU - FastAPI Repot Engine**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/3b996214-9563-d421-f172-70e0a4b707b3.png)


## odt系

**py3o.template - odoo向けに開発**

py3o.formatsのソースコードは、py3o.formats-0.3-py2-none-any.whl等から入手可能

https://github.com/faide/py3o.template

<details><summary>py3o.formats</summary>

```py: main.py
# -*- coding: utf-8 -*-

DEFAULT_MIMETYPE = "application/octet-stream"

FORMAT_WORD97 = "doc"
FORMAT_WORD2003 = "docx"
FORMAT_PDF = "pdf"
FORMAT_DOCBOOK = "docbook"
FORMAT_HTML = "html"
FORMAT_ODT = "odt"
FORMAT_ODS = "ods"
FORMAT_XLS = "xls"


class UnkownFormatException(Exception):
    pass


class Format(object):

    def __init__(self, name, odfname, mimetype=DEFAULT_MIMETYPE, native=False):
        self.name = name
        self.odfname = odfname
        self.mimetype = mimetype
        self.native = native


class Formats(object):

    def __init__(self):

        self._formats = {
            FORMAT_WORD97: Format(
                FORMAT_WORD97, "MS Word 97", "application/msword"
            ),
            FORMAT_WORD2003: Format(
                FORMAT_WORD2003, "MS Word 2003 XML",
                "application/vnd.openxmlformats-officedocument"
                ".wordprocessingml.document"
            ),
            FORMAT_PDF: Format(
                FORMAT_PDF, "writer_pdf_Export", "application/pdf"
            ),
            FORMAT_DOCBOOK: Format(
                FORMAT_DOCBOOK, "DocBook File", "application/xml"
            ),
            FORMAT_HTML: Format(FORMAT_HTML, "HTML", "text/html"),
            FORMAT_ODT: Format(
                FORMAT_ODT, "writer8",
                "application/vnd.oasis.opendocument.text",
                native=True,
            ),
            FORMAT_ODS: Format(
                FORMAT_ODS, "calc8",
                "application/vnd.oasis.opendocument.spreadsheet",
                native=True,
            ),
            FORMAT_XLS: Format(
                FORMAT_XLS, "MS Excel 97", "application/msexcel"
            ),
        }

    def get_format(self, name):
        f = self._formats.get(name)

        if not f:
            raise UnkownFormatException("Format {} is unkown".format(name))

        return f

    def get_known_format_names(self, nativeonly=False):
        """return the a list of names that can be used as format names in
        py3o.template.

        :param nativeonly: a boolean flag. If set to True will only return
        native formats.
        :type nativeonly: bool

        :return: list of chars
        :returntype: list

        :raises: nothing
        """
        if nativeonly:
            return [
                f for f in self._formats if self.get_format(f).native
            ]
        else:
            return [f for f in self._formats]

```

```py: __init__.py
from py3o.formats.main import UnkownFormatException
from py3o.formats.main import Formats
from py3o.formats.main import Format
from py3o.formats.main import FORMAT_DOCBOOK
from py3o.formats.main import FORMAT_HTML
from py3o.formats.main import FORMAT_ODT
from py3o.formats.main import FORMAT_PDF
from py3o.formats.main import FORMAT_WORD2003
from py3o.formats.main import FORMAT_WORD97

```

</details>



**secretary - odtを変換(jinja2)**

https://github.com/christopher-ramirez/secretary

**python-odt-template - secretaryを元に開発**

https://github.com/Tobi-De/python-odt-template

## docx系

docxtpl

fastapi-report-engine

## xlsx系


https://github.com/OCA/reporting-engine/tree/18.0/report_xlsx

# odoo

**alnas-docx**

https://github.com/alienyst/alnas-docx

**py3o - server連携版**

https://github.com/OCA/reporting-engine/tree/16.0/report_py3o_fusion_server

# 帳票サーバー

**py3o - odoo向けのapiサーバー**

https://github.com/jp-one/py3o-whl

**javaベースの帳票生成API**

https://github.com/opensagres/xdocreport


# odoo帳票のしくみ - report_xlsx

### `report_xlsx\__manifest__.py`

| 分類 | 項目 | 内容 | 備考 |
|:----|:-----|:-----|:-----|
| 外部依存 | Python | xlsxwriter | external_dependencies に記述 |
|         |        | xlrd       |   |
| 依存  | (odoo) | base  |   |
|       |        | web   |   |
| assets | web.assets_backend | action_manager_report.esm.js |   |

<details><summary>code - __manifest__.py</summary>

```py: report_xlsx/__manifest__.py
# Copyright 2015 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
    "name": "Base report xlsx",
    "summary": "Base module to create xlsx report",
    "author": "ACSONE SA/NV," "Creu Blanca," "Odoo Community Association (OCA)",
    "website": "https://github.com/OCA/reporting-engine",
    "category": "Reporting",
    "version": "18.0.1.0.0",
    "development_status": "Mature",
    "license": "AGPL-3",
    "external_dependencies": {"python": ["xlsxwriter", "xlrd"]},
    "depends": ["base", "web"],
    "demo": ["demo/report.xml"],
    "installable": True,
    "assets": {
        "web.assets_backend": [
            "report_xlsx/static/src/js/report/action_manager_report.esm.js",
        ],
    },
}

```

</details>


### `report_xlsx/__init__.py`

| 分類 | モジュール | 説明 | 備考 |
|:----|:----------|:-----|:-----|
| controllers  | main.py | ReportController | 継承  |
| models  | ir_report.py  | ReportActionモデル | "ir.actions.report"の継承|
| report  | report_abstract_xlsx.py | XLSX生成モジュール  | 各帳票で継承される |
|         | report_partner_xlsx.py |  Partner一覧作成 | report.report_xlsx.abstract"の継承  |

<details><summary>__init__.py</summary>

```py: report_xlsx/__init__.py
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from . import controllers
from . import models
from . import report

```

</details>

## XLSX帳票生成のシーケンス図

```plantuml
@startuml

actor odoo
Control ReportController
Control ReportAction
participant ReportXlsxAbstract
participant PartnerXlsx

odoo -> ReportController: report_download()
activate ReportController

ReportController -> ReportController: report_routes()
activate ReportController

ReportController -> ReportAction: _get_report_from_name()
activate ReportAction
deactivate ReportAction

ReportController -> ReportAction: _render_xlsx()
activate ReportAction

ReportAction -> ReportXlsxAbstract : create_xlsx_report()
activate ReportXlsxAbstract

ReportXlsxAbstract -> ReportXlsxAbstract : _get_objs_for_report()
ReportXlsxAbstract -> PartnerXlsx : get_workbook_options()
ReportXlsxAbstract -> PartnerXlsx : generate_xlsx_report()

deactivate ReportXlsxAbstract

ReportAction -> ReportAction: save_xlsx_report_attachment()
activate ReportAction
ReportAction --> ReportController: (response)
deactivate ReportAction

deactivate ReportAction

deactivate ReportController

ReportController -> ReportAction: _get_report_from_name()
ReportController --> odoo: (response:with "Content-Disposition")
deactivate ReportAction

@enduml

```

```plantuml
@startuml
participant Participant as Foo
actor       Actor       as Foo1
boundary    Boundary    as Foo2
control     Control     as Foo3
entity      Entity      as Foo4
database    Database    as Foo5
collections Collections as Foo6
queue       Queue       as Foo7
Foo -> Foo1 : To actor 
Foo -> Foo2 : To boundary
Foo -> Foo3 : To control
Foo -> Foo4 : To entity
Foo -> Foo5 : To database
Foo -> Foo6 : To collections
Foo -> Foo7: To queue
@enduml

```

# odoo帳票エンジン - docxをまねしてodtへ

**alnas-docx**
docxtplとdocxcomposeとで、レポートを生成している。
HtmlToDocxは、docxファイル内にhtmlを埋め込むために使用している。

https://github.com/alienyst/alnas-docx

docxtplでレンダリングしているので、これをodtテンプレートエンジンに変更する。

テンプレートでは、"docs"でデータにできる。


# pdf変換

**unoserver - libreofficeのサービス化**

https://github.com/unoconv/unoserver

```bash
pip install unoserver
```

LibreOffceのpython3環境で実行する必要がある

```bash
wget -O find_uno.py https://gist.githubusercontent.com/regebro/036da022dc7d5241a0ee97efdf1458eb/raw/find_uno.py
python find_uno.py

wget https://bootstrap.pypa.io/get-pip.py
/usr/bin/python3 get-pip.py
/usr/bin/python3 -m pip install unoserver -U

```

**unoserverの起動**

```bash
unoserver
```

**pdf変換**

```bash
unoconvert sampleja.odt sampleja.pdf
```

https://github.com/unoconv/unoserver/blob/master/tests/test_server.py

```py
from unoserver import server
```

# 関連記事

https://qiita.com/jp-96/items/4ff9a04c704d9366dba6

https://qiita.com/jp-96/items/2acd34f5783e12747b72