これから帳票開発をする方へおくる、「帳票開発の何がツライか」

マシュマロでExcel帳票についての質問が飛んできたのですが、ちゃんと話すと100字では到底収まらないので記事にしてみました。なお、同様の主旨のことを書いたコンテンツが近々公開されるので、同じことをブログで書くのはどうかな…と思いましたし、そうでなくても最近Excelの似たような話を書いたばっかりなので微妙だなーと思ったのですが、とりあえず書いてみます。

元の私の発言

内容

これに対する質問が以下です。

オフィスのツイートの件ですが、結局interopのイケてないところってcomオブジェクトの解放のみみたいな感じなんでしょうかね?それだとアスペクト志向とかusingとかで解決できるのでは?と思うのですがいかがでしょうね。あとcomオブジェクト解放不要なnetofficeというものもありまして、実務で使ってるのですが…書き方はVBAとほぼかわらないです。
ちなみにセル番地指定地獄は名前つきセル採用でかなりマシになると思うのですが、使ったことありますか?
自分はエクセル帳票開発ばかりやってる子持ちSEで、c# コードでぐぐって貴blogにたどり着いてから読者してます。
興味のある分野なので反応してみました。

元のマシュマロ

interopのイケてないところ

というあたりは、私がTwitterで言及したこの記事の中でMicrosoft.Office.Interop.ExcelあたりにあるCOMオブジェクトへの橋渡しをするAPIを利用して帳票を作成することはリソースの開放漏れ等々を引き起こすのでやりたくないよね、的な記述に対する問いかけということですね。

質問に対する簡単な回答

上に上げたツイートは、interopの是非ではなくてそもそも帳票開発の規模がある程度以上になるとコードを書いて帳票を開発すること自体がしんどい(と確信している)ということを言いたかったです。

質問に対する詳細な回答

ここからはご質問への回答も含みますが、せっかくなのでより広範に世間一般のこれから帳票開発に携わる方、あるいは携わって日の浅い方をターゲットに書いて記事にしたいと思います。(そのため、質問された方には既にご存知の内容も含まれているかと思いますがご容赦ください)

また、あくまでも私の経験上での感想の範疇を過ぎないので、下記に書いてあることが絶対ではないことを強く念頭に置いといてもらえると助かります。

概要

「帳票開発」とは一般に、納品書や明細書、その他事務的なフォームをPDFやExcel、プリンタ出力するためのシステムの開発一般のことを指します。日本人は罫線が入り組んだ帳票が大好きなので、単純な書式付きテキストの出力機能では要求仕様を満足できないことがほとんどです。

このため、帳票開発では何らかのツールを使用することがほとんどです。

開発方法

開発に使用するソフトウェアや方法は色々ありますが、ここでは大きく3つに分類してみます。

専用の帳票開発フレームワーク

  • SVF(シェア1位)
  • Create!Form
  • ActiveReports
  • JasperReports
  • その他山ほど

クラウドサービス

  • MFクラウド請求書
  • Misoca
  • その他山ほど

検索すると山ほど出てくる。とりあえず有名そうな二つを挙げてみた。

任意の帳票を作ると言うよりは、請求書などビジネスでよく必要となる帳票の出力と簡易カスタマイズ機能を提供するサービスがほとんどな印象。

自力で頑張る

  • Excelにデータをはめ込んで出力(POI/NPOI/OpenXMLSDK/.NET interop/Aspose Cells/他)
  • HTMLで帳票を作成し何らかの方法でそれをレンダリングしてPDF/プリンタ出力
  • InkscapeとPythonスクリプトでなんとかする
  • SVGで頑張る

前の記事でも「Excelは表計算ソフトなのでそれ以外の用途に使うな」という意見は現実的ではないのではないか、という趣旨のことを書きましたが、ともかく、Excelで帳票をデザインして出力するという行為は色んな所で普通に行われているのが現状で、かつ、私はその事自体に特に問題はないと考えています。

本記事ではこの「自力で頑張る」を以降「自前実装」と呼ぶことにします。

帳票開発のしんどいところ

  • グラフィカルな帳票を作ることの技術的困難さ
  • 現場サイドにシステム開発側が振り回されて対応に釘付けされる
  • 帳票作成ツール自体の習得が難しかったりする
  • 結局コーディングが必要になる場面が多々あり保守性が悪くなる
  • 出力したい帳票にマッチした帳票を出力できるツールが意外と無い
  • スケールしにくい
  • テストしにくい

あたりではと思います。それぞれ説明します。

  • グラフィカルな帳票を作ることの技術的困難さ

そもそも、罫線が入り組んだり時にグラフやバーコードが入ったり、データによってグループ分けしたりページ送りしたりヘッダフッタを付けたりといったことをしてそれをPDFやプリンタで出力するということが本質的に難しいです。難しいので大体、開発は大変です。大変な上、位置のズレや罫線の位置調整など地味な作業をやっていかなくてはならないので精神的にキツイです。

  • 現場サイドにシステム開発側が振り回されて対応に釘付けされる

帳票フォーマットは利用するエンドユーザーの都合で振り回されます。作ってみてやっぱりこうして欲しい、使ってみてやっぱり戻して欲しい、とかいう要望はたくさん出てくるでしょう。その都度、前述のような精神的にキツイ作業をしなければならないのがキツイです。キツイことが何度も続くのがキツイ。それに加え、頼んだ側はエクセルで行追加する程度の作業量を想定していることが多いので「なんで行一つ追加するのにこんなに時間がかかるんだ」などと不満がたまります。それを説明するのもまたしんどい。

  • 帳票作成ツール自体の習得が難しかったりする

しんどいので、人はネットで良い方法が無いか検索し、「簡単に帳票が作れます!」という触れ込みの商品を買います。でもこういう商品の多くはそもそもそのツールを使いこなせるようになるまで時間がかかります。時間がかかるということは、専門の人(専門の人を確保する時間)を確保しなければなりません。さらに、概してこういうツールは使いにくいです。日本人好みの複雑な表をサクッと作ってくれるツールは少なくとも私は見たことが無く、罫線を一つずつ配置し時に繰り返し処理を組んでいかなくてはなりません。

結局、帳票の分野でも銀の弾丸は無いのです。

  • 結局コーディングが必要になる場面が多々あり保守性が悪くなる

帳票作成ツールの類を利用しても、コーディングが必要になる場面はどうしてもあります。例えば私の経験では、複雑な条件分岐や描画処理を行う際はGUIエディタだけでは済まず、結局コーディングを行って表示位置を調整したり、表示コントロールを差し替えて描画するなどと言った小手先のテクニックが必要になるケースが何度も何度もありました。

そしてこういう小手先のテクニックはそのとおり、小手先なので何故それが必要なのか、何故そんな実装になったのかをコードから読み取るのがすごく難しいです。するとそれを後任者に伝えるための詳細なドキュメントかなにかを整備する必要があり、どんどん保守コストが高くなっていきます。

帳票作成ツールの類を使わずに何らかの方法で自前実装する時もこれは大体同じです。

  • 出力したい帳票にマッチした帳票を出力できるツールが意外と無い

特にクラウドサービスに多いのですが、前述した通り帳票を作ること自体が難しいので、帳票を自由に定義して出力できますよ、というサービスを作ることはさらに難しくなります。

なので、殆どのサービスでは決められた幾つかの帳票(たとえば請求書とか納品書とか)を多少カスタマイズ出来る、という程度の機能しか無かったりします。従って、例えば専門的な機械設備の点検レポートとかいう全然一般的でない帳票を開発したいという場合はそれだけで利用できるツール・サービスが限定されます。

  • スケールしにくい

帳票出力は重い処理になりがちです。パフォーマンスに問題があった場合は、札束でぶっ叩いて良いハードウェアを導入するくらいしか方法が無いです。しかもこれはサーバサイドで帳票を生成する場合は有効なものの、クライアントサイドで動作するソフトウェアだった場合は、従業員全員のマシンを帳票のためにアップグレードすることは現実的にはほぼ不可能なので我慢して待つ、くらいしか策が無いです。

また、たとえサーバサイドで生成していた場合であっても、特にパフォーマンスがスケールするか否か、まで気を配った製品というのは少ないです。もっとも、そこまでパフォーマンスがクリティカルになることもあまり無いからだと思いますが。

  • テストしにくい

「保守しにくい」とも若干共通する話ですが。

帳票の出力結果はPDFやExcelなのでテストコードがすごく書きにくいです。Excelに期待した値がはめ込まれているかどうかくらいなら何とかなりそうですが、PDFデータは扱いもだいぶ面倒ですし、Excelであってもグラフや罫線までテスト対象に含めるとコードで検証するのは現実的ではないでしょう。なので基本的には人の目で確認しながら開発を進めることになります。

これは自前で実装する際に特に問題になります。もし、すべての種類の帳票の出力結果に影響するような変更を行い、さらに帳票の種類が数十以上もあるとしたらどうでしょうか。それら全部を人間系に頼るのはこれまたしんどいです。見落としも絶対発生するでしょうし。少なくともテストパターンは少なくせざるを得ないでしょう。

何らかの帳票ツールを使うならば、少なくともその製品自体が担当する部分は通常テストする必要は無いですが、先に説明したようにコーディングした箇所についてはテストは必要になります。帳票ではフォントなど環境依存・データ依存する部分が多いですので、特に文字のはみ出しや、改行が組み合わされたテキストなどで目で見て調整が必要になる場面が多々あります。

ちなみに、出力した帳票のテストまで気を配ったサービスや開発フレームワークは私が知る限りは存在しないです。

テストに関しては、私はいい案は思いつかないですし、人力でやるか多少のデグレは許してもらうかしか無いと思ってます。テストを多少なりともマシにするなら、自分で作る部分を極力少なくして(つまり帳票作成ツールやサービスをなるべく利用して)テスト自体を少なくすることくらいしか出来ないのではないでしょうか。

また、何れの場合においても、開発するときは少しでもデバッグ・テストしやすくするために帳票テンプレートと差し込むデータをシステムから切り離して単体で動作できるようになっているべきであると思いますし、それらのデータは人間の目でみて容易に全体が確認できるような状態になっているべきです。

帳票作成ツールの中には、SQLを書いておけばデータベースから勝手にデータを取ってくれますよ、あなたはSQLのパラメータだけ指定すればOKですよ、みたいな仕組みを用意しているものもありますが、テスタビリティを考えるならばむしろJSONとかCSVとか単純なデータを食わせてあげてできるだけ内部状態を持たない方がいいのでは、という気もします。SQLのクエリまで表現機能に取り込まれてしまうと、SQLが正しいかというデバッグと帳票テンプレートが正しいかというデバッグを両方いっぺんにしないといけないのでややこしくなります。

それぞれの方法について

以上を、それぞれの開発方法の視点でも簡単にまとめてみます。

  • 専門の帳票開発ツール

これらは大体GUIで作業でき、グラフ、バーコード、複雑な罫線などが含まれた複雑な書式であってもひとまず作れてしまいます。プリンター出力が容易に出来たり、クライアントサイドで動作するアプリケーションで帳票を作成したり印刷したりするためのGUIパーツまで提供されることもあったりするのでそういう要求がある場面ではとても便利です。

しかし、それは使用する帳票作成ツール(フレームワーク)に熟練した開発者が居れば、という話です。GUIツールの使い方の習得は大変なことが多いです。私は3つほど帳票開発ツールを使用しましたが、どれもしんどかったです。完全に使いこなせるまで1ヶ月以上は確実にかかったと思います。

それに、帳票開発ツールが基本的には想定していないような仕様を実装しなければならないとき(経験上、絶対でてきます)は結局コードを書いてゴニョゴニョやる必要があります。すると、結局GUIだけでは完結しなくなります。しかもこのゴニョゴニョは本来そのツールやライブラリの使い方で想定していないことを何とかするためのコードなので、そのツールの熟知していないと意図がコードからは読み取りにいです。また、どうしてもシステムと密結合になる部分も発生してしまうこともあります。そういう諸々がジワジワと保守コストを押し上げていきます。

また、帳票開発ツールは結構導入コストが高い製品が多かったりします。年間数十万円〜数百万円かかるという製品は珍しくはないです。独自の帳票を作りたいが、何十万円も帳票出力にかけてられない、という組織は結構多いと思うのですがどうでしょうか。

  • クラウドサービス

使い方が容易で、殆どすべてのサービスで完全プログラミングレスで帳票を作成できます。イニシャルコストやランニングコストも小さくて済むことがほとんどです。しかし、何の帳票でも出力できますよ、というものは少なく、請求書なら請求書と決められた帳票の出力に特化し、カスタマイズは最小限の機能でしか提供されていないとか、SalesforceやKintoneなどの外部サービスとの連携を前提にしているものが殆どです。

あらゆるフォーマット、データの帳票の出力が可能なクラウドサービスは、ざっとググった感じで名前だけ挙げると

  • SVF Cloud
  • Fleekform
  • Documentizer

という感じでしょうか。

  • 自前実装

OSS資産を活用するなら、イニシャルコストもランニングコストもゼロです。色んなOSS資産を組み合わせれば、バーコードやグラフも含んだ複雑な帳票も作成できてしまうでしょう。ですが、当然ながらそれを本気でやろうとすると帳票出力エンジンの開発と同じくらいのコストがかかります。帳票出力エンジンを開発してその開発・保守コストがペイできるほど大量の帳票を出力する会社ってそうは無いでしょうし、その規模になると第一の選択肢はおそらくSVFとかになるはずです。

したがって、ExcelやHTMLを利用して帳票を描画させるのが向いているのは、

  • 幾つかの固定の値を当てはめて完結する程度の簡単な帳票が殆ど
  • 出力する帳票の種類がそこまで多くない
  • そんなに帳票の保守作業(フォーマットの変更)も発生しない

という、せいぜい数人の担当者で乗り切れるような規模ということになります。

それ以上のことを自前実装な帳票でやろうとすると、前述したとおり人員を投入して真っ当な帳票出力エンジンを開発するのと大差無くなりますし、そうでないならば、帳票ごとに出力処理をハードコーディングして保守のしににくさを帳票に特化したエンジニアを張り付かせることで解決するという方法くらいしか無いと思います。

また、開発範囲がでかいのでテストも必然的に一番大変になります。テストが大変ということは、帳票が改定されるような場合はその都度保守コストもでかくなるということです。

例外的に、Inkscape + PythonやSVGをどうにかして出力するという方式ではテストも比較的行いやすいのですが、これらを使用する場合はそもそも帳票作成に向いた機能がほとんど無く、罫線の一本一本を座標指定で作るというあたりからの作業になるので実装量もかなり増え、テスタビリティが多少良くなったところで根本的な解決にならないです。

ご質問の内容そのものについて詳しく

というわけで、頂いたマシュマロのご質問そのものにももう少し詳しく回答してみます。
繰り返しになってしまう部分も多々あると思いますがご容赦ください。

オフィスのツイートの件ですが、結局interopのイケてないところってcomオブジェクトの解放のみみたいな感じなんでしょうかね?
それだとアスペクト志向とかusingとかで解決できるのでは?と思うのですがいかがでしょうね。あとcomオブジェクト解放不要なnetofficeというものもありまして、実務で使ってるのですが…書き方はVBAとほぼかわらないです。

私のツイート(記事冒頭のもの)は、言語仕様や各種ライブラリのAPI仕様の使いやすさではなくて開発規模が大きくなるとコードで書くこと自体がしんどくなるのではないか、という主張です。ツイートで引用した記事が主張しているように、COMオブジェクト等のリソース開放漏れ等々が解消されたとしても(つまりDioDocsを使用したとしても)その他にも帳票開発には数々の大変さがあり、それらは解決できないのでは、ということを言いたかったです。

もちろん、細かいリソースの管理を簡単に出来る方法があるならそれを使ったほうが良いのはごもっともです。usingみたいな構文でも良いですし、DioDocsとかでも良いでしょう。

ただ、ツイートで言及した記事中でも指摘されていますが、interop(←正式名称が良く分からない)でやる方法はリソースの開放忘れ意外にもサーバサイドで動かすときには様々な問題があります。以下のMSが公開している記事が詳しいです。

Office のサーバーサイド オートメーションについて

簡単に要約すると、「サーバサイドで動かす用途で作ってないからサーバサイドで動かすと問題が出るだろうし、ライセンス的にも問題があったりするからなるべくやらないでね」という事です(私の読解が間違って無ければ)。

実際、前職でもサーバサイドでExcelシートを自動計算させて計算結果を返却する、みたいなことをやろうとしているチームがあり、私は止めたほうが良いですよと反対したのですが、案の定ずっと動かしているとExcelが反応しなくなるとか、たまに許容できないほどExcelの起動が遅くなるとかいう現象に悩んでいました。

質問者の方におかれましては、どちらで使用しておられるのか明記されていないのでよくわからないのですが、例えクライアントサイドでやる場合であっても、COMを使う場合はPCにインストールされているOfficeのバージョンによって動作が異なったりエラーが出たりというバージョン依存の問題が発生して私はだいぶ苦労させられた経験があるので、たとえクライアントサイドでのみ使う場合であっても個人的にはPOI/NPOI/Open XML SDKなど、自分で依存関係を完全に解決できる方法を好みます。

ちなみにセル番地指定地獄は名前つきセル採用でかなりマシになると思うのですが、使ったことありますか?

あります。名前付きセル以外の方法として、例えば特殊なプレースホルダを埋め込み、それを元にデータを挿入するような方式で実装する事は可能でしょう。

しかし、帳票開発という目的を念頭においた上で、私はそれくらいが自前で実装する場合の限界として認識すべきではないかと考えています。

具体的には、

  1. 自前実装で簡単な帳票をサクッとつくる
  2. 多少の便利メソッドやプレースホルダ的な仕組みを実装する
  3. 帳票に要求される事項が増えていく
  4. どんんどんコードが肥大化する
  5. コードでテストできない(しにくい)ので保守コストが肥大化する
  6. ならばコードを書かずに帳票を作れるようにすべき
  7. テンプレートエンジン的なものを実装し始める
  8. 実装が大変すぎることに気づいて諦めるか、コスト度外視で開発を続けるか、作った人しか理解できない負の遺産になるかの何れかに至る

という結果に至りやすいと考えています。この結末を回避するには、3.が訪れたあたりで何かを諦めるしかありません。具体的には、

  • 自前実装を諦める
  • 保守コストの抑制を諦める(専門のエンジニアを張り付けておくコストを許容する、人や時間をかけることを許容する、多少のデグレは笑って許すなど)
  • 複雑な帳票を作るのはターゲットにしない
  • システム自体の規模を限定する(せいぜい数種類の帳票だけ出せてればいいとする)

などです。軽い用途ではそもそも諦めるまでもなく、制約に引っかからないということももちろんあると思いますが。

私はExcel、HTML両方の方法でそのテンプレートエンジン的なものを実装しようと試みたことがあります。

最初はExcelでした。これはA列に条件分岐や繰り返し処理を制御する特殊なコードを埋め込んでおき、データに応じて動的にセルや行を追加して帳票をレンダリングするという代物でした。POIを使ったものと、Open XML SDKを使ったものと、二つも作りました。が、いずれもすぐに実装コストがめちゃ大きくなるので現実的でないと判断しました。適当にコードを組むとすぐにOutOfMemoryがスローされたり、出力するのにめちゃくちゃ時間がかかったり、Excelで開けないファイルが出力されたりということがたくさん発生したからです。原因はOpen XMLの仕様をちゃんと理解していないことに起因することが大きいです。

その時点で、私がやりたいのは帳票エンジンの開発やOpen XMLフォーマットの理解ではなくて帳票の出力なのだと思い直し、コーディングレスで出力するのは諦めて保守性に問題がある状態で妥協しました。多分、あの調子で帳票エンジンを作ったとしたら、保守性に問題があるどころか、誰も保守できない負の遺産になっていたでしょう。

次に取り組んだのはHTMLを利用した帳票開発でした。CSS3を駆使すればどんなデザインだろうとコーディングレスで正しく描画できるだろうという思いからこの方法でチャレンジしました。グラフ描画はそういうことが出来るJavaScriptライブラリに任せて、帳票の出力はHTMLをWebKitエンジンでJavaScriptの実行込みでレンダリングした結果をPDF化するというライブラリ(名前は忘れてしまった)を使って実装しました。

このアイディアは個人的には中々良いと思ったのですが、現場では「出力した帳票は編集できないようPDFで出力して欲しい」ということもあれば、「後で現場の人間が編集できるようExcelになっていて欲しい」という要求も根強く、後者にはどうやっても対応できないという問題がありました。

また、HTML/CSSはプログラミングほどに敷居は高くないですが、開発できる人員は限られます。これも問題の一つです。さらに、意図したとおりに表示させるためにCSSを書いてデバッグすることはコーディングと大差ないですし、それを容易にするためのCSSコンパイラの導入なども同様にコーディング環境の整備と言え、結局当初の目的である「コーディングレス」は達成できないということに気づいた時点でこれはダメだと諦めました。

自分はエクセル帳票開発ばかりやってる子持ちSEで、c# コードでぐぐって貴blogにたどり着いてから読者してます。
興味のある分野なので反応してみました。

私の想像なので間違っていたら恐縮ですが、質問者の方のバックグラウンドは、「エクセル帳票開発ばかりやってる」というあたりから、前述したような「数人の開発メンバーの体制で対処できる」または「専門のエンジニアを張り付けておくコストを許容できる」という感じの環境なのではと想像します。そういう場面で、特にExcelをinteropなりPOIなりNPOIなりで触っていく方法で現状問題が無いならば、そこから開発手法を変える必要も無いのでは、と思います。

いずれにせよ、質問者様の環境におかれましてはinteropであろうとなんだろうと、現状苦しんでなくて仕事が回ってるならその方法のままでよく、せっかく作った資産を捨てて変える必要も無いのでは、という感じです。(もっとも、変えたいという意思もご質問中には書かれていないですが)

ただしつこいですが、interopで苦しむ人もいれば、それ意外の部分で苦しむ人も居るということです。で、それを解決しようと帳票関連のパッケージ製品やクラウドサービスがたくさんありますが、すべての要望にフィットする銀の弾丸的な何かはまだ見つかってないので難しいよねーという感じです。

まとめ

帳票開発の苦しみについて解説してみたつもりです。「XXXを使えば簡単に出来るのでは?」というアイディアは結構出てくると思いますが、単純に思いつくものはおそらく色んな人が既にチャレンジして、多くが失敗している(少なくともうまく行っていないか、苦痛を感じたまま開発が続いている)と思います。

今回は私も個人的に色々と思うところがあります。詳細は大人の事情で言及は避けます。ともかく、何か参考になれば幸いです。