Docurain Labo

Docurainサービス開発日記

複雑な集約条件においても数式自動シフトが使えるようになりました

明細のある見積書や請求書のような帳票では、ページごとの合計金額、全ページの総合計金額のような項目がよくあります。

1ページ目 2ページ目
f:id:yutay:20210729172942p:plain:w300 f:id:yutay:20210729172947p:plain:w300

その際にDourainでは簡単にページごと、グループごと、全ページの各単位で金額を計算することが可能です。

作成するテンプレートで範囲の定義を行い、その範囲ごとに計算を行うようにすることで実現させます。

早速やってみましょう!

上に載せたような見積書を作成します。

サンプルのテンプレートとデータ(JSON)です。
サンプルダウンロード

範囲について

範囲は#scopeを使用して定義します。

今回、範囲は以下の「全て」・「顧客」・「ページ」の3つの範囲を定義します。

f:id:yutay:20210729164123p:plain

範囲の定義は以下のように書きます。それぞれの範囲を#scope - #endで囲みます。

#scopeの構文は次の通りです。

#scope([範囲の名称] as [変数名])

f:id:yutay:20210729192410p:plain

「全て」の範囲定義の通り、as [変数名] は省略可能です。範囲の名称を変数として使用する必要がない場合(範囲の名称が固定で良い場合)は、as [変数名] を省略します。

これで範囲の定義は完了です。

範囲を使用した計算について

範囲ごとに計算を行うにはDR.SHIFT_FORMULA()を使用します。

DR.SHIFT_FORMULA()は数式の自動シフトを適応可能にしてくれる機能です。*1

依然として Excelの数式そのまま であるため、Excelがもつ数式記述支援機能(構文チェック、引数チェックなど)を全て活用することができます!!

DR.SHIFT_FORMULA()の構文は次の通りです。

=DR.SHIFT_FORMULA(値or式,"scope=[#scope()で代入している変数], target=all")

scopetargetは指定せず=DR.SHIFT_FORMULA(値or式)でも可能です。scopetargetを指定しない場合は、「最も近いセル範囲」を指します。

先ほど#scopeにて定義した範囲をDR.SHIFT_FORMULA()から参照して計算を行います。

サンプルを確認しつつ以下をご覧ください。

  • 全ページの合計金額

    f:id:yutay:20210730095220p:plain =DR.SHIFT_FORMULA(SUM(D20),"scope=全て, target=all")とすることで、範囲名称が「全て」の範囲の合計金額セル(D20)を参照しSUMにて合計を算出します。それにより総合計金額を出力します。

  • 顧客ごとの合計金額

    f:id:yutay:20210730100414p:plain =DR.SHIFT_FORMULA(SUM(J31),"scope=$outerScope, target=all")とすることで、範囲名称が$outerScope(顧客ごと)の範囲のページ合計セル(J31)を参照しSUMにて合計を算出します。それにより顧客ごとの合計金額を出力します。

  • ページごとの合計金額

    f:id:yutay:20210730100428p:plain =DR.SHIFT_FORMULA(SUM(J29:J29),"scope=$innerScope, target=all")とすることで、範囲名称が$innerScope(ページごと)の範囲の明細金額セル(J29)を参照しSUMにて合計を算出します。それによりページごとの合計金額を出力します。

  • 明細ごとの金額 f:id:yutay:20210729194310p:plain =DR.SHIFT_FORMULA(G29*I29)とすることで、数量(G29)*単価(I29)を算出します。それにより明細ごとの合計金額を出力します。 DR.SHIFT_FORMULAを使うことで明細行が複数になってもG29・I29のセル範囲は自動シフトするため、何も意識せずテンプレート上で該当のセルを指定すれば良いです。

データを準備して出力

今回使用するデータは以下です。

{
  "顧客リスト": [
    {
      "顧客名": "株式会社 顧客1",
      "見積No": 1127,
      "見積日": "2021-07-29",
      "明細": [
                { "名称": "項目1-1", "数量": 1, "単位": "", "単価": 10000 },
                { "名称": "項目1-2", "数量": 2, "単位": "", "単価": 10000 },
               ...中略...
                { "名称": "項目1-17", "数量": 17, "単位": "", "単価": 10000 }
      ]
    },
    {
      "顧客名": "株式会社 顧客2",
      "見積No": 1128,
      "見積日": "2021-07-29",
      "明細": [
                { "名称": "項目2-1", "数量": 1, "単位": "", "単価": 20000 },
                { "名称": "項目2-2", "数量": 2, "単位": "", "単価": 20000 },
               ...中略...
                { "名称": "項目2-20", "数量": 20, "単位": "", "単価": 20000 }
      ]
    }
  ]
}

出力結果です。

(サンプルテンプレートのA9セルにて明細15行ごとに分割して改ページするようにしています)

1ページ目(総合計)
f:id:yutay:20210729195227p:plain:w300
2ページ目(顧客1の1ページ目) 3ページ目(顧客1の2ページ目)
f:id:yutay:20210729195256p:plain:w300 f:id:yutay:20210729195303p:plain:w300
4ページ目(顧客2の1ページ目) 5ページ目(顧客2の2ページ目)
f:id:yutay:20210729195308p:plain:w300 f:id:yutay:20210729195319p:plain:w300

それぞれの範囲で計算され、「ページ合計金額」、「顧客ごとの合計金額」、「全ての合計金額」が正しく計算されてますね。

今回作成したサンプルは、無料トライアルページからも登録不要で試すことが出来ます。

他にも様々な機能がありますので、ぜひアカウント無料登録してマニュアルを参照しお試しください。

*1:数式の自動シフト:DocurainにてExcel/PDF出力後に命令行が削除されることを意識せずに、Docurainテンプレート上でExcelのセル範囲をそのまま使えることを指します。Docurainテンプレートにて、とあるセルを参照している数式がある場合、命令行が削除された後の行番号を考慮した数式でなければなりませんが、その命令行が削除された後の行番号に自動に適応します。

Unicode絵文字に対応済みです

以前、Docurainが「外字」または異体字セレクタ(IVS)に対応済みであることお知らせしましたが、 Unicode絵文字の出力と絵文字に対しての文字列操作も対応しています。

ja.wikipedia.org

早速、絵文字を出力してみよう

テンプレート・JSONは以下のように作成しています。

テンプレート

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/02/スクリーンショット-2021-02-26-14.32.12.png

JSON

{
    "農家": "👩‍🌾",
    "家族": "👨‍👩‍👧",
    "One": "1️⃣",
    "自転車": "🚵‍♀️",
    "国旗": "🇯🇵🇯🇵🇯🇵",
    "農家_es": "\ud83d\udc69\u200d\ud83c\udf3e",
    "家族_es": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67",
    "One_es": "1\ufe0f\u20e3",
    "自転車_es": "\ud83d\udeb5\u200d\u2640\ufe0f",
    "国旗_es": "\ud83c\uddef\ud83c\uddf5\ud83c\uddef\ud83c\uddf5\ud83c\uddef\ud83c\uddf5",
    "農家_ucd": "\\U+D83D\\U+DC69\\U+200D\\U+D83C\\U+DF3E",
    "家族_ucd": "\\U+D83D\\U+DC68\\U+200D\\U+D83D\\U+DC69\\U+200D\\U+D83D\\U+DC67",
    "One_ucd": "\\U+0031\\U+FE0F\\U+20E3",
    "自転車_ucd": "\\U+D83D\\U+DEB5\\U+200D\\U+2640\\U+FE0F",
    "国旗_ucd": "\\U+D83C\\U+DDEF\\U+D83C\\U+DDF5\\U+D83C\\U+DDEF\\U+D83C\\U+DDF5\\U+D83C\\U+DDEF\\U+D83C\\U+DDF5"
}

JSONはこのようになります。 以下のそれぞれで設定が可能です。

  • 絵文字
  • Unicodeエスケープシーケンス
  • Unicode(UTF-16)

上記テンプレート・JSONで出力してみましょう。

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/02/スクリーンショット-2021-02-26-14.39.34.png

問題なく絵文字が出力されています。(macOS上のExcel)

ただし、Windows版のExcelやPDFでは以下のように表示されます。

Windows Excel PDF
https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/02/スクリーンショット-2021-02-26-14.41.47.png https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/02/スクリーンショット-2021-02-26-14.42.42.png

このように、Docurainとしては絵文字の出力に対応していますが、 表示する側がまだ対応できていないことがあります。

絵文字の文字列操作

次にこの絵文字に対しての文字列操作です。

例えば

"🍣と🍺".length

とJavascriptで実行すると、3ではなく5が返ってきます。

これは↓の以前のブログでもご紹介している通り、🍣や🍺はサロゲートペアであるためです。 blog.docurain.jp

また、"👨‍👩‍👧と🏖".length"👩‍❤️‍👨で🎡".length は どちらも11となります。

これは 👨‍👩‍👧 や 👩‍❤️‍👨 は

👨‍👨‍👦 = 👨 + 👧 + 👩

👩‍❤️‍👩 = 👩 + ❤️ + 👩

のようにできている絵文字だからです。

"🍣と🍺".length

"👨‍👨‍👦と🏖".length

"👩‍❤️‍👨で🎡".length

いずれも3が欲しいですよね...

対応してます!

Docurain独自の関数

Docurain独自の関数u_lengthを使えばOKです。

実際に確認してみましょう。

  • テンプレート

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/02/スクリーンショット-2021-02-26-18.13.00.png

  • JSON
{
    "arg1": "🍣と🍺",
    "arg2": "👨‍👩‍👧と🏖",
    "arg3": "👩‍❤️‍👨で🎡"
}
  • 出力結果

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/02/スクリーンショット-2021-02-26-18.13.26.png

それぞれ3となりましたね!見た目上の文字数でカウントすることができました。

Docurainでは、以下のようなユニコード専用の文字列操作を用意しています。 JSONで送ったデータの文字列オブジェクトのメソッドとして呼び出すことができます。

関数名 説明
u_length ユニコードを考慮した文字列長を返す。サロゲートペアや異体字セレクタなどの 書記素クラスタ(grapheme cluster) の文字を全て1文字とカウントする。例えば"🍣と🍺と䄂\uDB40\uDD01"の長さは5とカウントする。
u_charAt(int index) ユニコードを考慮した文字取得メソッド。オリジナルのString#charAtとは異なり、このメソッドの戻り値は「1文字」を表す文字列になる。書記素クラスタの文字は1文字とカウントする
u_toCharArray() ユニコードを考慮して文字列を文字に分解する。オリジナルのString#toCharArrayとは異なり、このメソッドの戻り値は「1文字」を表す文字列の配列になる。書記素クラスタの文字は1文字とカウントする。
例えば`'🍣と䄂\uDB40\uDD01'`.u_toCharArray()の結果は["🍣","と","䄂\uDB40\uDD01"]になる
u_substring(int from), u_substring(int from, int to) ユニコードを考慮した部分文字列取得メソッド。書記素クラスタの文字は1文字とカウントする
u_hasIVS() 異体字セレクタを含む文字列か判定する
u_removeIVS() 異体字セレクタを除去して通常の字体のみにする

最低限必要なものは用意しましたが、不足がありましたら随時追加していきます。

絵文字やを扱う帳票作成が必要な際はぜひ試してみてください!

他にも様々な機能がありますので、ぜひアカウント無料登録してマニュアルを参照しお試しください。

Windowsの「外字」とは?基礎から解説 & Docurainでの対応

この度、Docurainにて、純粋な意味の外字対応が可能かどうかの検証が必要になり、詳細を調べてみましたのでそれをまとめます。

「外字」とは

「外字」とは、本来システムに登録されていない文字のことを指します。よくある例としては、漢字の異体字などです。これをシステムから利用できるようにするための機能が各種OSには備わっていたりします。これが本来の意味ですが、私の経験上では単に「マイナーな異体字」を「外字」と表現する人も多々見かけてきました。

異体字の多くはUnicodeでもすでに定義されていますので、「外字でなくてUnicodeを使いましょう」という運動が昨今進んでいます。以下はMicrosoft ブログから引用です:

Windows と日本語のテキストについて - Windows Blog for Japan

Unicode を使用することにより、人名地名に使用される漢字等を正確に表現するニーズにも対応することができます。従来、このような用途では外字を使用するケースが多くありましたが、現在「外字でなければ表示できない文字」をお使いのお客様は限定的です。Unicode に定義されており、Windows に同梱のフォントを使用して標準の状態でも表示可能な文字を、外字にいわば「再定義」してお使いのお客様が非常に多くいらっしゃいます。

(中略) 現在外字を使用している国としては日本が突出しており、外字が既にレガシーな機能であることもお伝えしなければなりません。

(中略) 外字を使用していることや、テキストを Shift-JIS で保存していることがクラウド移行の大きな障壁となるケースが急増しています。

ということです。つまり、

  • 外字はレガシーな機能であり、移行が必要
  • 異体字はUnicodeで表現可能なことがほとんど

ということが言えると思います。

今日、システム上で異体字を扱わなければならないケースが生じた際には、

  • Unicodeに対応したシステムを構築する(UTF-8, サロゲートペア、Unicodeエスケープなどへの対応)
  • IPAmj明朝などの異体字が表現できるフォントを利用できるようなシステム設定を行う

という対応をすることが正攻法になるでしょう。なぜなら、これが将来的な技術的負債となる可能性が大きいからです。「外字」として独自の文字を定義するのは最後の手段と考えたほうが良さそうです。

なお、Docurainは既にIPAmj明朝には完全対応しています。

blog.docurain.jp

今回の検証は、何らかの理由によりIPAmj明朝が使えないケースのための予備調査となります。

Windowsにおける外字機能

Windowsにおける外字機能としては、古くから「外字エディタ」が提供されてきました。この機能は現在のWindows10からも利用可能です。試しに使ってみましょう。

使う場合は、Windowsメニューから「外字」で検索するか、Winキー+Rを押してから「eudcedit」と入力してEnterを押します。

f:id:withpop:20210426114421p:plain

すると、こういった画面が表示されます。

f:id:withpop:20210426114542p:plain

一度も使ったことがなければ、ここには灰色の空のマスが並んでいます。このE000というのはUnicodeです。E000〜F8FFまでは「私用領域」として定められており、通常ここに文字(グリフ)が割り当てられることはありません。名前の通り、グローバルに何かを定めるためのものではなく、ユーザーが定義して使うために領域を残しているわけです。

つまり、これは「外字」そのものですね。

f:id:withpop:20210426115135p:plain

特定のUnicode コードを選択すると文字のエディタが立ち上がります。ここで任意の文字を作成して定義できます。ここでは、ShiftJISでF042、UnicodeでE002の場所におにぎりを表す漢字を独自に定義しました。これ一文字で「おにぎり」と読みます。私が勝手に定義して私的に利用する漢字です。

続いて今回は「ドラえもん」「うずまき」という漢字を作ってみました。

では定義した文字はどのようにして利用すれば良いのでしょうか?この文字が「おにぎり」と読むことをシステムは知りません。なので、IMEから「おにぎり」と入力して変換してもこのおにぎり漢字が出てくることはありません。

Microsoft IMEの「IMEパッド」は任意の文字を入力できるのでこれを利用すると入力することが出来ます。

f:id:withpop:20210426115904p:plain

「Unicode(基本多言語面)」→「私用領域」とたどると今回定義した文字が出てくるので、ここをクリックするとその文字が入力できます。

f:id:withpop:20210426120235p:plain

「おにぎり」と入力したらこの文字が表示されるようにしたい場合は、IMEから単語登録すればよいでしょう。外字エディタではその文字の「読み」は気にしません。私用領域の特定のコードに編集した文字を割り当てる、それだけを外字エディタは行います。

では、Windowsではどのようにしてこの機能を実現できているのでしょうか。

実は、外字エディタで編集した文字は c:\windows\fonts\EUDC.TTE というファイルとして保存されます。これは拡張子がTTEとなっていますが、実態はTrueTypeフォントのようです。

Windowsでは、表示中のフォントで定義されていないおにぎりグリフ(E002)があった場合にEUDC.TTEで定義されている文字にフォールバックするように設定されているようです。

ここまでの話をまとめると、外字エディタとは

  • 独自のグリフをドットで作成し
  • 私的領域の任意のコードに割りあて
  • Windowsがそのコードの表示を行う時にEUDC.TTEをフォールバックフォントとして設定する

ような機能であると言えます。

もちろん、ここで定義した文字はいわゆる機種依存文字になりますから、他のコンピュータでは表示できません。機種依存どころか特定のマシン依存です。他のコンピュータで表示するためにはEUDC.TTEを表示するコンピュータにインストールする必要があります。

逆に言えば、EUDC.TTEを表示するコンピュータにインストールすればおにぎり漢字も表示できるはずですね。

EUDC.TTEを調査する

ではこのフォントを調査してみましょう。このフォントをファイルとして抽出するためにはコマンドプロンプトでコピーする必要があります。

f:id:withpop:20210426120918p:plain

エクスプローラで c:\windows\fonts\ を開くとフォントのリストを表示する特殊な表示となってしまい、EUDC.TTEが見つかりませんでした。

ここからはLinux(Ubuntu)で作業をします。まずはFontforge(フォント編集ソフト)でフォント情報を見てみましょう。

f:id:withpop:20210426121039p:plain

フォントファミリーは「EUDC」、スタイルは「Regular」であることが分かります。ベンダIDには「RICO」(ママ)の文字が入っていました。この機能はリコー(RICOH)が開発に携わっているのでしょうか?

f:id:withpop:20210426121403p:plain

定義されているグリフを見ると、確かに私的領域に今回作成した3文字が入っています。その他は全部空欄でした。

f:id:withpop:20210426121545p:plain

ちなみに、ここまでのスクリーンショットをご覧になったところでお気づきの方も多いと思われますが、編集はドットで行った(つまりラスタ画像)のに、フォントはそれを平滑にしたようなベクタ画像になっています。もともと外字エディタってこの仕様だったのでしょうか?中々すごい機能が備わっていますね。

Docurainの外字対応

ここまででWindowsの外字とは何か?ということを説明しました。

冒頭に説明したとおり、外字はレガシーな機能で使うのを避けてUnicodeと対応フォントに移行すべきではありますが、「ではそうしましょう!」で何も問題なくプロジェクトは実際少ないだろうことは皆さんお察しのとおりです。

というわけで今回、Docurainでも外字対応が可能かどうかを検証しました。と、言えどもここまでに調べた仕様から察するに特に問題なく表示できるでしょう。

どのような設定を行ったかはDocurain内部システムの構成の話になるので省きます。

今回は以下のようなテンプレートを作成しました。

f:id:withpop:20210426122216p:plain

text1〜3に任意の文字を入力して表示するだけです。ただ、任意のフォントからフォールバック可能であることを検証するためにそれぞれ違うフォントを設定しています。

使用するエンティティデータは以下のようになります。

f:id:withpop:20210426122340p:plain

外字は対応するコードのUnicodeエスケープで記述します。必ずUnicodeエスケープで記述しなければならないというわけではありませんが、開発ツールやIDEなどの親和性を考えると楽なのはUnicodeエスケープで記述する方法です。

f:id:withpop:20210426122622p:plain

出力したPDFファイルです。フォント埋め込みなので、ここで出力したファイルはあらゆるデバイスで同じように表示できます。

こちらからダウンロードして皆さんの環境でも同様に表示できることを確かめてみて下さい。

まとめ

今回はWindowsの外字機能の概要をまとめた上で、DocurainからもWindows外字エディタで作成した文字が利用可能であることを確かめました。

もし、帳票開発をもっとモダンなものに置き換えたいが外字対応がネックになっている…という方はぜひご相談下さい。

1セル内の複数フォントスタイル設定が可能になりました

Docurainではこれまで一つのセル内で複数のフォントスタイルを設定できない制限事項がありましたが、それが可能になりました!

これまでは...?

例えば以下のように文字の部分は明朝体、数字部分はゴシック体にしたい場合にこれまではセルを分ける必要がありました。

  • 想定出力結果

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/01/スクリーンショット-2021-01-14-14.29.35.png

  • テンプレート(これまで)

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/01/スクリーンショット-2021-01-14-14.31.23.png

はい、面倒ですね!

これが今回の対応により、一つセル内でそれぞれフォント設定を行えば良いことになります。

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/01/スクリーンショット-2021-01-14-15.10.49.png

いくつかのフォントスタイルで確認

これまでは一つのセル内では先頭行のスタイルがセル内のすべてのテキストに適用される仕様でしたが、上記の通りテンプレートで設定したように出力されますので、いくつかのフォントスタイルで確認してみます。

  • テンプレート

https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/01/スクリーンショット-2021-01-14-15.06.34.png

  • JSON
{
    "font1": "IPA ゴシックフォント",
    "font2": "IPA P ゴシック フォント",
    "font3": "IPAex 明朝 フォント",
    "font4": "IPAmj明朝 フォント",
    "font5": "Rounded M+ フォント",
    "font6": "Noto Sans CJK JP フォント",
    "font7": "刻明朝 フォント"
}
  • 出力結果
https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/01/スクリーンショット-2021-01-14-15.06.54.png https://s3.ap-northeast-1.amazonaws.com/site.docurain.jp/blog/2021/01/スクリーンショット-2021-01-14-15.07.00.png

このようにテンプレートの設定のまま出力されるようになりました。

他にも様々な機能がありますので、ぜひアカウント無料登録してマニュアルを参照のうえ、お試しください。