PowerShellとLibreOffice Drawで請求書作成

[LibreOffice AdventCalendar 2018 25日目](https://adventar.org/calendars/3306)

請求書を作ります。
請求書は業務システムでは最も一般的な帳票です。

一番の難関はページングです。

以下の条件で作ります。

1. 6行明細の請求書に9行の売上。
2. 請求書は2枚出力。
3. 2枚目の最後の行には請求合計を出力

ソースは下記のGitHubにあります。

[invoice - GitHub](https://github.com/arachan/invoice)

## 環境

- Windows10 Pro
    - PowerShell
- LibreOffice Draw
    - Flat ODT(fodg)

##作成開始

では作成していきます。


### Templateを作成

1. LibreOffice Drawで下記のようなTemplateを作ります
    - 用紙サイズはA4縦
    -![invoice.png](https://qiita-image-store.s3.amazonaws.com/0/24550/88ee4256-8233-d53e-2861-099d49f185de.png)
2. Flat XML ODF 図形描画(.fodg)で保存します

### Dataを作成

1. data.csvを作成
2. headerは salesno,customer,supplier,item,subtotal
3. 売上の内容をゴリゴリ書いていきます。

下記な感じになります。

|salesno|customer|supplier|item|subtotal|
|:-:|:--|:--|:--|--:|
|1|You|Amazon|Nintendo Switch1|100|
|1|You|Amazon|Nintendo Switch2|200|
|1|You|Amazon|Nintendo Switch3|300|
|1|You|Amazon|Nintendo Switch4|400|
|1|You|Amazon|Nintendo Switch5|500|
|1|You|Amazon|Nintendo Switch6|600|
|1|You|Amazon|Nintendo Switch7|700|
|1|You|Amazon|Nintendo Switch8|800|
|1|You|Amazon|Nintendo Switch9|900|

### 帳票作成シェル

makeinvoice.ps1　を作成します。
詳しくはソースを見て下さい。
ざっくりした説明をすると

1. dataを読込
2. templateを読込
3. templateの{salesno}等を該当するデータに書換
4. 6行目になったら請求書を出力
5. 以下繰り返し
6. 最後のあまりを請求書に出力
7. 最後の請求書に合計を出力

となります。

```posh:makeinvoice.ps1
# load data
$data=Import-Csv -Path .\data.csv -Encoding UTF8

# load template
$temp=Get-Content .\invoice.fodg -Encoding UTF8

# cnt row in report
$i=1
# reportrows
$rprow=6
# total row count
$rc=0
# page
$p=0

# total page
$tp=$data.Count/$rprow
$tp=[Math]::Ceiling($tp)

# calcurate total
$sum=$data | Measure-Object 'subtotal' -sum

foreach($d in $data){     

    # merge template
    $temp=$temp -replace '{salesno}',$d.salesno
    $temp=$temp -replace '{customer}',$d.customer
    $temp=$temp -replace '{supplier}',$d.supplier
    $temp=$temp -replace "{item$i}",$d.item
    $temp=$temp -replace "{subtotal$i}",$d.subtotal
    
    # rowcount
    $rc=$rc+1

    # report end write build report
    if($i%$rprow -eq 0){
        # Write-Output "行"$rc
        # Write-Output "data数"$data.Count
        
        # Page Count
        $p=$p+1

        # write total
        if($rc -eq $data.Count){
            $temp=$temp -replace '{total}',$sum.Sum
        }

        # add Page No
        $temp=$temp -replace '{page}',"$p"
        # add Total Page
        $temp=$temp -replace '{total page}',"$tp"
        # delete {}
        $temp=$temp -replace "{(.*)}",""

        # output name 
        $date=Get-Date -Format yyyyMMddhhmmss
        $file="output\"+$date+$p

        # output newfile
        $temp | out-file -FilePath $file'.fodg' -Encoding utf8
        
        $i=$i-$rprow
        
        # load template
        $temp=Get-Content .\invoice.fodg -Encoding UTF8
    }
    
    # report in row
    $i=$i+1    
}

# output remainder data to report
if($data.Count%$rprow -ne 0){
    $p=$p+1
    $file="output\"+$date+$p

    # write total
    $temp=$temp -replace '{total}',$sum.Sum
    $temp=$temp -replace '{page}',"$p"
    $temp=$temp -replace '{total page}',"$tp"
    
    # delete {}
    $temp=$temp -replace "{(.*)}","" 
    
    #output report
    $temp | out-file -FilePath $file'.fodg' -Encoding utf8

}
```

### 印刷

print.ps1

下記の動作をしてくれます。

1. outputに出力された請求書を標準プリンターに印刷
2. 印刷後削除


```posh:print.ps1
# Get report list to print
$outputs=(Get-ChildItem output\*.fodg)

foreach($invoice in $outputs){

    # Print to Default Printer
    Start-Process $invoice -Verb Print | Stop-Process
    # After print and Delete
    Remove-Item $invoice

}
```

##最後に

夢のDrawで帳票ができてしまいました。

1. エンドユーザーが帳票を設計できる
2. OSSで導入が低コスト

結構いけるんじゃないでしょうか？

メリー、クリスマス！