Excel方眼紙というものありけり
日本の企業では帳票というものが多く存在します。帳票の特徴は、外枠があり、その中が記入する情報量に応じて枠線でコマ割りされている点です。元々が記入項目名や枠線、そして注意事項のみが印刷されて、あとは手書きで記入するものでしたから、入力欄の大きさも場合によっては適切ではなく、記入する文字を小さくしたり1枠の中に2段で書いたりして人間系により柔軟に運用するものでした。
次のステップは、帳票デザインを印刷してある紙に、後からデータ部分だけ印字するというシステム化でした。ここで重要なのは印字時の位置合わせとなります。
そして最終的に紙ベースが終わって電子化したときにも、こだわったのが元の紙ベースの帳票のデザインを踏襲することであり、要は、いかに元のデザインと一緒に文字を印字するかという難題でした。
このような過程の中で、Wordのさまざまな便利機能ではどうしても元のデザインを再現できず、Excelを使って一つひとつのセルを正方形にしたExcel方眼紙という手法が生まれてきました。
Excel方眼紙の問題点
Excel方眼紙では、文章の折り返しなども既定の文字数まで入れ、次の行の所定のセルから文章を続けるような手作業制御が可能です。意図しない折り返しや字下げ設定など何も考えずに済みます。では、何がいけないのでしょうか。
図2の例にあるように「・・・元々が記入項目名や・・・」の途中で折り返しが入ったとき、文字列としてはどうなるでしょうか。「・・・元々が記入項」下のセルに移動して「目名や・・・」と入力した場合、後から「記入項目」で検索したとしても検索にヒットしませんし、もちろん一括置換の対象にもなりません。
また、文章に追加があったときも、後ろにはみ出したものをカットして下の行の先頭にペーストするということを延々と繰り返さなければなりません。
これは、非常に非効率的な作業です。
ActiveReportsによる帳票作成
このExcel方眼紙で作った帳票を、ActiveReportsに取り込んでいきたいと思います。今回使用する「ActiveReports for .NET 11.0J」は、以下のリンクよりトライアル版を入手できます。
ActiveReportsのレポート形式の種類と特徴
ActiveReportsのレポート形式には、セクションレポート、ページレポート、RDLレポートがあります。
形式 | レイアウト方式 | 用途 | 備考 |
---|---|---|---|
セクションレポート | セクションベース(ヘッダ、詳細、フッタで構成)のレイアウト方式。データ量に応じてセクションが繰り返されるため、デザイナ画面と実際の印刷結果は一致しない | 大量データの一覧として出力する帳票、データを繰り返し表示する帳票に最適。開発者が使い慣れているVB.NETやC#で帳票を柔軟に設計できる | ActiveReports for .NET発売当初からのレポート形式 |
ページレポート | ページイメージをそのままデザインできるページベースのレイアウト方式。データの繰り返しはデータ領域コントロールで定義する | 項目の配置が複雑な帳票に最適。WYSIWYGデザイナにより直感的にデザインできる | ActiveReports for .NET 7.0Jから採用された形式 |
RDLレポート | フリーレイアウト方式。ページレポートと同様のコントロールを使うが、データの表示領域はあらかじめ定義せず、セクションレポートのようにデータ量に応じて表示領域が伸長する |
データソースの異なるテーブルやグラフを自由に配置するレポートに最適。セクションの出力位置やページの用紙サイズといったレイアウト上の制約を意識することなく、レポートコントロールをレイアウトできる
|
ActiveReports for .NET 9.0Jから採用された形式 |
用途に応じて3つの形式を使い分けることができます。今回の記事ではRDLレポートを採用してみます。
RDLレポートプロジェクトを作成
Visual Studioの新規作成で「ActiveReports 11.0J RDLレポートアプリケーション」テンプレートを選択して新規にプロジェクトを作成します。
ActiveReportsでExcel方眼紙を取り込もう
ExcelファイルからActiveReports形式への変換は「ActiveReportsインポートウィザード」を使います。インポートウィザードは、[スタート]メニューから選択、あるいは「..\ActiveReportsNET11\Tools\Import」から「GrapeCity.ActiveReports.Imports.Win.exe」を実行することで起動できます。
ウィザードに従い、取り込むExcelファイルを選択し、出力先のフォルダやレポート形式(ページレポート/RDLレポート)を選択します。今回はRDLレポートにしてみます。
変換が完了すると、ウィザードで指定したフォルダにrdlxファイルが作成されます。
作成されたrdlxファイルをActiveReportsのデザイナで開いて結果を確認してみましょう。
Visual Studioでも確認できますが、ActiveReportsにはレポートファイルの作成・編集に使用できるデザイナプリケーションが付属しているのでそちらを使います。
[スタート]メニューから選択、あるいは「..\ActiveReportsNET11\Tools\Designer」から「GrapeCity.ActiveReports.Designer.exe」を実行することで起動できます。
先ほどのrdlxファイルを開き、プレビューすると以下のようになります。
一部タイトルが消えていますが、なぜ消えているのかの理由はデザイナタブに切り替えて見てみるとわかります。タイトルが書かれていたテキストボックスの横幅が足りていないのと、最前面ではなかったために後ろに隠れてしまっています。オブジェクトの横幅を広げ、右クリックして[最前面へ移動]メニューを選択すれば、隠れていた文字列が表示されます。
CSVファイルから報告書テキストを読み込もう(1)
ファイルをプロジェクトに追加
Visual Studioのソリューションエクスプローラでプロジェクト名を選択してから右クリックで[追加]-[既存の項目]メニューで先ほど作成したrdlxファイルをプロジェクトに読み込みます。
データエリアの追加
Excelからデザインを取り込めたら、動的に値を設定するデータエリアを追加します。帳票の罫線から少しだけ離れてTextBoxを配置します。
CSVファイルから報告書テキストを読み込もう(2)
CSVファイルを設定する
ActiveReportsへのデータソース(データの供給元)の指定は、「ActiveReports レポートエクスプローラ」で行います。
[ActiveReportsレポートエクスプローラ]ウィンドウが開いたら、[データソース]を右クリックして追加を選びます。
今回はCSVファイルからデータを読み込むので、CSVデータソースを選択して、ファイルパスにCSVファイルを指定してあげるとファイルの内容がすぐにプレビューで確認できます。ヘッダの有無や、デリミタなどの設定もダイアログから選ぶだけで変更できるので、簡単にさまざまな形式のCSVに対応できます。
設定が正しければデータソースの中にデータセットが自動的に追加されて、CSVの項目名も自動設定されます。
CSVの項目と帳票定義項目を紐付ける
CSVファイルの内容を読み込めるようになったら、帳票定義体上の項目とCSVの項目を結びつけます。印字領域に合わせてTextBoxを配置して、Valueプロパティにドロップダウンリストから項目を選択します。ここで式を指定してファイル内容を変換して印字することも可能です。
印字プレビューの確認
ActiveReportsは、プログラムを実行しなくてもデザイナのプレビュー機能により、実際にCSVファイルの値を読み込んで印字イメージを確認できます。
プログラムコードの作成
開発環境での動作であれば、「ActiveReports 11.0J RDLレポートアプリケーション」より新規プロジェクトを作った場合は、自動生成されたコードのrdlxファイル名の修正だけで動作させることができます。
private void Form1_Load(object sender, EventArgs e) { viewer1.LoadDocument(Application.StartupPath + @".\Sheet2.rdlx"); }
しかし、このままでは帳票定義体の中に絶対パスでCSVファイル名が定義されているため、実行時もCSVファイルが開発環境で指定した場所と同じ場所になければなりません。
そこでアプリからCSVファイルの場所を指定できるようにします。
このサンプルではApplication.StartupPathにCSVファイルを配置する前提でコードを作成します。まず、ソリューションエクスプローラでCSVファイルをプロジェクトに追加し、そのプロパティで「常にコピーする」にしておきます。
準備が整ったら次のようにコードを修正します。
private void Form1_Load(object sender, EventArgs e) { var rptPath = new System.IO.FileInfo(Application.StartupPath + @".\Sheet2.rdlx"); var rpt = new GrapeCity.ActiveReports.PageReport(rptPath); rpt.Report.DataSources[0].ConnectionProperties.ConnectString = "Path=" + Application.StartupPath + ".\\\\Data.csv;Encoding=shift_jis;Locale=ja-JP;TextQualifier=\";ColumnsSeparator=,;RowsSeparator=\\r\\n;HasHeaders=True"; var runtime = new GrapeCity.ActiveReports.Document.PageDocument(rpt); viewer1.LoadDocument(runtime); }
このようにデータソースの中のConnectionStringの内容を変更することで読み込むCSVファイルを変更できます。
アプリの実行
コードが完成したらさっそく実行して確認してみます。ここまでの手順が正しければ、プレビューと同じ内容が画面に表示されます。
そもそもExcel方眼紙でつくられた帳票ファイルがなかったら?
例えば、Excel方眼紙もなく帳票原紙と呼ばれる紙でしか存在せず、使用するときはそれを物理的なファイルから取り出してコピーして使うような状態からActiveReports化するにはどうしたらいいでしょうか。
このような場合は最初からActiveReportsデザイナで帳票をデザインしてしまうのがいいでしょう。ActiveReportsデザイナをつかえば、まるで紙に定規で線を引きながら帳票をつくっていくような感覚で帳票が作成できます。
RDLレポートプロジェクトを作成
Visual Studioの新規作成で「ActiveReports 11.0J RDLレポートアプリケーション」テンプレートを選択して新規にプロジェクトを作成します。
Visual Studioでレポートをデザイン
Visual Studioのソリューションウィンドウで「RdlReport1.rdlx」を選択すれば、ActiveReportsデザイナが開いてデザイン画面が表示されます。ツールボックスもRDLレポートで利用できるコントロールが表示されているので、必要なコントロールをActiveReportsデザイナにドラッグアンドドロップしてデザインしてきます。
まずは、ツールボックスから「Shape」をドラッグアンドドロップして外枠を設定してみましょう。初期設定で2.5cmのマージン(余白)が設定されているのでA4サイズ(横21.0cm×縦29.7cm)の用紙の外枠を設定するにはそれぞれ次のようにプロパティを設定します。
Location.Left | Location.Top | Size.Width | Size.Height | |
---|---|---|---|---|
Shape1 | 0 | 0 | 16 | 24.7 |
ActiveReportsデザイナのプレビュー機能で確認してみます。
レイヤーを追加する
[表示]-[その他のウィンドウ]-[ActiveReports 11.0J レイヤー一覧]メニューをクリックして[レイヤー一覧]ウィンドウを表示したら、左上の緑の十字アイコンをクリックしてレイヤーを追加します。
ついでに、「Layer1」を選択した状態で、「レイヤー一覧」ウィンドウ上部の最右端にある「最背面へ移動」アイコンをクリックして最背面にレイヤーを配置します。
紙の帳票原紙を元に帳票デザインを行う
紙帳票をデザインテンプレートとして使う
Excelファイルのような電子媒体として帳票原紙が存在しない場合でも、紙の帳票原紙をテンプレートとしてActiveReportsの帳票デザインを行う方法があります。
次のような手順で作業してActiveReportsデザイナに紙の帳票原紙を取り込んでみましょう。
- 紙の帳票原紙をスキャナーでスキャンしてPNGファイルとして保存します。
- Imageコントロールを配置し、全体を覆うようにLocationプロパティとSizeプロパティを設定します。
- Valueプロパティに保存したPNGファイルを指定します。
プレビューで確認すると先ほど設定した外枠とずれています。これは紙の帳票原紙には周りのマージン(余白)も設定されているためActiveReportsで設定した余白と二重に余白がとられてしまうからです。ActiveReportsの余白を0cmにすれば期待したプレビューとなります。
今度は、2.5cmのマージンを前提とした外枠がずれてしまうので、帳票原紙に合わせて位置を修正します。
このあとは、帳票原紙に合わせてShapeやLineを上にのせていく作業をしていきます。このとき、Layer1のプロパティ([レイヤー一覧]ウィンドウで「Layer1」を選択したときに[プロパティ]ウィンドウに表示される)のDesinerTransparentプロパティを「0.8」にしておくとデザイナ上でだけ帳票原紙が薄く表示されるようになるので配置しやすくなります。
しかし、ちょっと待ってください。帳票原紙のイメージがすでにActiveReportsに入っているのですから、データ印字領域だけ確保したらどうでしょうか。
紙帳票にデータを上乗せする
既存紙帳票をスキャンしたり、Excelから画像ファイルに変換したりして、配置したImageコントロールに既存帳票を貼り付けたら、ActiveReportsレポートエクスプローラを使ってデータソースを指定しておきます。
データソースが指定できたら、データを上乗せするところにTextBoxコントロールを貼り付けていきます。プロパティウィンドウのValueプロパティをクリックすれば、そこからデータソースに指定した項目を選択すれば自動的にデータと印字フィールドが紐付きます。
データを整形する
TextBoxコントロールを貼り付けてValueプロパティを指定すればデータの内容を上乗せ印字することができます。しかしここまでの手順では2つのポイントで不具合が生じていることがわかります。
- 年月日部分で帳票に「 年 月 日」の印字があるため上乗せしたデータと重なってしまう。
- 年月日印字が「〇年〇月〇日」ではなく「〇/〇/〇」となってしまっている。
この2つの問題をそれぞれ解決してみましょう。
1. 元のデザインを消して印字したい
このためには、TextBoxのBackgroundColorプロパティを「Transparent」から「White」に変更すれば解決します。つまり、TextBoxの背景色を白色にしてしまって隠してしまうのです。
2. 日付の印字フォーマットを指定したい
このためにはTextBoxのFormatプロパティを指定します。「業務報告書」の前は「〇年〇月」ですからFormatプロパティには「y」、右上の年月日にはFormatプロパティとして「D」を指定します。この指定文字列を何にするかはいつも迷うところですが、ActiveReportsのFormatプロパティではプレビュー機能があるので安心して設定できます。
しかし、今回のケースでは、このFormatプロパティを指定してもその通りに整形されません。
式を活用する
Formatプロパティの日付関係の整形は、データの型が日付である必要があります。今回のCSVファイルでは文字列になっているためFormatプロパティが正しく機能しませんでした。そこで、Valueプロパティに対して次のように式を適用して文字列を日付型に変換してから、Formatプロパティでの日付型整形を有効にします。
Value | Format | |
---|---|---|
TextBox7 | =DateValue(First(Fields!年月.Value, "DataSet1")) | y |
TextBox8 | =DateValue(First(Fields!日付.Value, "DataSet1")) | D |
これで期待した通りの印字ができるようになります。
なお、すでに罫線やタイトルが印刷された用紙に対して印字するのであれば、先ほどのBackgroundColorプロパティを「White」にして、データを重ね合わせた部分も年月日の3つの部分を別々にとりだして印字するようにしてから背景に設定した帳票原稿を削除してあげると、きれいに位置合わせしたように印字できるのでお勧めです。
帳票原紙をすべてActiveReports化する
最後に、帳票原紙を背景にはめ込むこともやめて、罫線や帳票タイトルなどもすべてActiveReportsのコントロールで定義してみましょう。
すべてActiveReportsのコントロールで定義する場合も、元の帳票のフォーマットをできるだけ踏襲しましょう。ActiveReportsならば0.01cmくらいの指定でも再現性は高いので、帳票原紙のサイズを物差しで測って枠の大きさを求めるなり、先ほどのように別レイヤーでDesignerTransparentを0.8にして薄く表示しながらその上にコントロールを合わせるなりして作成(作成後はレイヤーごと削除)していきます。
ヘッダ部分については、TextBoxコントールでBorderStyleプロパティをSolidにして作成しています。それ以外についてはShapeコントロールを貼り付けた後にその中にBorderStyleプロパティがnoneのTextBoxコントロールを貼り付けています。
これでLayer1レイヤーに配置したコントロールは常にdefaultレイヤーの背面に表示することができます。ここに帳票原紙のイメージを配置しておきます。
なぜ、別レイヤーにしておくかといえば、Layer1のDesignerTransparentプロパティに「0.8」を設定してみるとわかります。デザイナ画面ではLayer1に配置した画像がうっすらと表示されるので帳票原紙に印字されている項目がどれなのかの区別が容易になります。
まとめ
今回試したようにExcel方眼紙のように本来のExcel的な使い方ではないシートでもActiveReportsで正しく読み取ることができました。また、データ印字範囲というExcelにはない概念を入れることで、帳票枠内での文字の折り返しなどもスムーズに設定ができました。
このようにActiveReports化することで帳票定義とデータ部分が分離できるので、データだけを使って2次加工や集計することもしやすくなります。
また、Excel方眼紙から自動生成した定義ではなく、ActiveReportsのコントロールを使った帳票定義をすることで、あとで帳票定義を変更する必要があったときも直しやすくなります。また、データもそのままではなく印字時加工も多彩なものがありますので、ノンプログラミングでも非常に柔軟に印字結果を制御できるのがお分かりいただけたのではないでしょうか。
印刷出力というのは、システム開発においても利用者が気にする部分ですので、痒いところに手が届くActiveReportsで細かな仕様を実現する道を確保しておくのが良いでしょう。