MS-Accessでサブレポート無しで分割レポートを出力する方法

先日、今更ながらAccess推しをしているという話を書きました。

推す理由は上記エントリに書いているので、詳細は省きますが、帳票デザインの柔軟性も大きな理由になっていることも挙げています。

今回はそんな帳票デザインの技を一つ紹介します。今回紹介するような要件は、WEBアプリで実装するのは結構しんどいような気がしています。

内容としてはかなりマニアックな話になりますので、Accessをゴリゴリ使うような方向けの記事となります。

帳票の要件 3分割用紙に出力する

お客様の業務で、従来、手書きの3枚複写の納品伝票を利用されているものがありました。

一枚は「会社控え」、一枚は「お客様控え」、もう一枚は「配送担当者控え」という用途です。よくあるパターンです。

業務の電子化に伴い、従来の手書き伝票は使わないということになり、システムからそれらの伝票を出力出来るようにするのは必須要件でした。複写伝票フォームのコスト削減も目的の一つなので、ドットインパクトプリンタの導入はナシです。

単純にA4用紙を3枚印刷しても良いのですが、それだと印刷コストが3倍(用紙、カウンター)になってしまいますし、余白も多くなり無駄も出てしまいます。

そこで登場したのが、下記のような3分割の印刷用紙です。ミシン目が入っているので、印刷したものをちぎって使えば印刷コストも1枚分で済みます。

印刷内容には、伝票番号や配送先のお取引先情報などの「ヘッダ情報」のほか、配送商品の「明細情報」が含まれます。

ヘッダ情報だけであれば分割するのも簡単なのですが、明細情報をどう入れ込むのかの実装面で悩みました。

サブレポートを使っても良いのですが、明細行が増えた場合の改ページの扱いも難しくなりますし、サブレポートを使うことでレポートオブジェクトが増えてしまうのも避けたかったというのもあります。

実装方法について

実装に当たっては、下記記事が大変参考になりました。2013年の記事ですが、Access2019でも正常に動作しました。

正攻法であれば、先に述べたようにサブレポートを使うのが王道のような気もしますが、「こういうやり方もあるのか!」と目から鱗のエレガントな方法だったので、このやり方での実装を採用することにしました。

MoveLayoutプロパティを上手く活用する

AccessのレポートオブジェクトにはMoveLayoutというプロパティがあります。

聞きなれないプロパティですが(私は今回初めて知りました)、このプロパティは、各セクションのフォーマットイベント時に設定できるもので、何もしなければTrueになります。

このプロパティの意味は、次セクションの印字位置をどうするか?ということになります。通常(True)であれば次の印字位置に移動します。

例えば、ヘッダセクションのフォーマット時に、この値をFalseに設定すると、詳細セクションがヘッダセクションに上書きされて印字されてしまいます。通常の帳票でこれをやると、表示がごちゃごちゃになって訳が分からなくなります。

しかし、これを逆手に取って、ヘッダセクションに全ての枠組みを記載し、位置を上手く調整しながら明細レコードを詳細セクションに記載するというやり方にすれば、サブレポートを使わずに上手く3分割帳票が実装出来ます。

具体的なやり方

何はともあれ、具体的なやり方を紹介します。

  1. まず、ヘッダセクションにA4全体の印刷イメージを書いてしまいます(図表の①)。
  2. 次にヘッダセクションに含まれる項目のグループヘッダを挿入し、明細行の高さに設定します(図表の②)。明細開始位置はこのグループヘッダが担う形になります。
  3. さらに明細行に含まれる項目でグループヘッダを挿入し、明細行の1行分の高さに設定します(図表の③)。明細行の印字位置はこのグループヘッダが担う形になります。
  4. 最後に詳細セクションで、明細行の項目を設定します(図表の④)。詳細セクションのMoveLayoutはFalseとします(3のグループヘッダが改行してくれるため)。

レポートのデザインビューのイメージとしては下記の図のようになります。どうしてもデザインビューが縦長になってしまうのが珠に傷ですが。

レポートに読み込ませるクエリのイメージ

このレポートに読み込ませるクエリですが、ヘッダ情報テーブルと明細情報テーブルを結合し、ヘッダ情報テーブルを冗長に出力するような形で作成すればよいでしょう。

サンプルでは、T_OrderとT_OrderDetailというヘッダ情報テーブルと明細情報テーブルを、OrderNoというキーで結合させて、必要な列を出力する形を採っています。

注意点

②の「セクション繰り返しプロパティ」は、「はい」に設定します(初期値は「いいえ」)。これがないと、改ページされたときに明細行が所定の位置から開始されません。

改ページの方法

ただし、このままだと明細行が増えていくと、5行の枠を超えて下に印字されていきます。

そこで、改ページの指示をしてあげる必要があります。詳細セクションのフォーマットイベントに以下の改ページ用のコードを追加します(コードハイライタが見づらくてすみません)。

Option Compare Database
Option Explicit
Dim lRow As Long

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)
    Me.MoveLayout = False
    lRow = 0
    
End Sub

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    Me.MoveLayout = False
    
    '改ページの設定
    lRow = lRow + 1
    If lRow >= 5 Then   '1ページ当たり明細5件
        Me.詳細.ForceNewPage = 2  'カレントセクションの後で改ページ
    Else
        Me.詳細.ForceNewPage = 0  'カレントセクションの前で改ページ
    End If
    
End Sub

レコードカウント変数は、モジュール内のプライベート変数として定義しておき、ヘッダフォーマット時にリセットしてあげます。

この設定をしておけば、明細行が何行になっても改ページされていくので大丈夫です。

まとめ

多分、この記事が役に立つという人は殆ど居ないような気もしますが、折角苦労して実装したので、記録しておくことにしました。もしどなたかの役に立てたとしたら幸いです(シェア頂ければもっと幸いです)。

これを応用すれば、当然2分割や4分割の用紙にも使えます。

ITと経営に関するお悩みはありませんか?

ITに関連する経営課題についてどんな内容でもアドバイス可能です。
お一人で悩まれずに、些細なことだと思われることであっても、お気軽にご相談ください。
もちろん、お問い合わせメールへは無料で対応いたします。