この特集のトップページへ
Chapter 7:プレゼンテーション層の構築

7.7.8 明細処理
●明細の印刷

○全伝票の明細を印刷できるようにする
 以上で,ユーザーがFormSlipDetailフォーム(Fig.7-92)で[印刷]ボタンを押したとき,FormPrintPreviewフォーム(Fig.7-45)が表示され,明細一覧をプレビュー表示したり印刷したりすることができるようになった。

 ではこれだけで十分かといえば,伝票の場合にはそうではない。というのは,ユーザーが伝票の明細を印刷したいときには,常に次の一連の手順をとる必要があるためである。

  1. FormSlipフォーム(Fig.7-86)で印刷したい明細を選択し,[明細]ボタンを押してFormSlipDetailフォーム(Fig.7-92)を表示させる

  2. FormSlipDetailフォームで[印刷]ボタンを押す

  3. FormPrintPreviewフォームでプレビュー表示されるので,さらにFormPrintPreviewフォームの[印刷]ボタンを押す

  4. 印刷ページ範囲を選択するウィンドウ(Fig.7-58)が表示されるので,そこでまた[印刷]ボタンを押す

 1枚の伝票明細を印刷するのに,これだけの手間がかかるのでは,作業効率が落ちることになるだろう。そこで,FormSlipフォーム(Fig.7-86)で選択した伝票の明細を,一気に印刷してしまう機能を実装することにしよう。具体的にどのようにするかというと,FormSlipフォームで[印刷]ボタンを押したときには,伝票の一覧(DGrid_Slipデータグリッドに表示されているデータ)を一覧形式で印刷するのではなく,Fig.7-101に示すウィンドウを表示し,どのような方法で印刷するのかを尋ねるようにするのである。

Fig.7-101 印刷方法を尋ねるウィンドウ
fig7_101

 Fig.7-101でユーザーが[表示されている表を印刷ならびにプレビュー]を選択したときには,すでにList 7-142BTN_PRINT_Clickプロシージャで実装したのと同じく,伝票の一覧を印刷する。そうではなく,[表内のすべての項目の明細を一括印刷]や[表内の選択されている項目の明細を一括印刷]を選択したならば,表示されている全伝票の明細を印刷するか,もしくは選択されている伝票の明細をまとめて印刷する。このとき,プレビュー画面は表示せず,いきなりプリンタへと出力させる。また,ページ範囲を尋ねるウィンドウも表示せず,全ページを印刷する。そのような実装をすれば,ユーザーはFormSlipフォームから[印刷]ボタンを押したあと,[表内のすべての項目の明細を一括印刷]か[表内の選択されている項目の明細を一括印刷]を選択するだけで,指定した伝票の全明細をプリンタに出力できるようになる。

 そのためにまず,Fig.7-101のようなウィンドウを実装しよう。ここでは,Fig.7-102に示すFormPrintSelectというフォームとして実装する。FormPrintSelectフォームは,MDIの子ウィンドウではなく,モーダルウィンドウとして表示させる。

Fig.7-102 FormPrintSelectフォーム
fig7_102

 FormPrintSelectフォームには,[OK]ボタン(BTN_OKボタン)や[キャンセル]ボタン(BTN_CANCELボタン)を押したときの処理を,List 7-176のように実装する。

 List 7-176では,グローバル変数Selectedを用意し,ユーザーがどのラジオボタンを選択したのかをこのグローバル変数で保持するようにした。9〜21行目で実装されている[OK]ボタン(BTN_OKボタン)が押されたときの処理を見るとわかるように,ラジオボタンの上から順に,値1,2,3と順に対応させている。また,3〜7行目で実装されている[キャンセル]ボタン(BTN_CANCELボタン)が押されたときの処理や,23〜25行目で実装されているフォームが表示(アクティブ化)されたときの処理を参照するとわかるように,ユーザーが[キャンセル]ボタンを押したり,右上の[×]ボタンを押してウィンドウを閉じたりしたときには,グローバル変数Selectedに-1を格納するようにしてある。

 List 7-176の実装により,FormPrintSelectフォームをShowメソッドを使ってモーダル表示したあと,FormPrintSelectフォームのグローバル変数Selectedを参照すれば,ユーザーがどの項目を選択したのかを判定できるようになる。

 さて,ユーザーがFormSlipフォーム(Fig.7-86)の[印刷]ボタン(BTN_PRINTボタン)を押したときに,FormPrintSelectフォーム(Fig.7-102)をモーダル表示させれば,ユーザーに印刷方法を選択させることができるようになる。

 FormPrintSelectフォームで,ユーザーが[表示されている表を印刷ならびにプレビュー]を選択した(FormPrintSelectフォームのグローバル変数Selectedが1であった)場合であれば,すでにList 7-142で示した処理を実行すればよい。これに対して,[表内のすべての項目の明細を一括印刷]を選択した(グローバル変数Selectedが2であった)場合や[表内の選択されている項目の明細を一括印刷]を選択した(グローバル変数Selectedが3であった)場合には,どのような処理をすればよいのだろうか。

 この処理は少々複雑そうだが,何のことはない。DGrid_Slipデータグリッドに表示されているすべての伝票をループ処理し,FormPrintPreviewフォームに配置されている[印刷]ボタン(BTN_PRTボタン)を押したときと同じような処理を実装すればよい。FormPrintPreviewフォームに配置されている[印刷]ボタンを押したときの処理は,すでにList 7-47のように実装してある。List 7-47を参照するとわかるように,ここでは主に次の処理を実行している。

  1. FormPageSettingフォーム(Fig.7-59)のGetPageプロシージャを呼び出し,印刷するページ数を入力させる

  2. PrinterオブジェクトのScaleModeプロパティをvbTwipsにする

  3. FormPrintingフォームのbCancelFlagプロパティをFalseにする

  4. FormPrintingフォームをモードレスウィンドウとして表示する

  5. DrawPreviewプロシージャ(List 7-173)の引数にPrinterオブジェクトを指定することで,プリンタに対して描画する

  6. FormPrintingフォームを閉じる

 ここではすべてのページを印刷したいので,上記のうち1.の処理は不要である。よって,ユーザーが[表内のすべての項目の明細を一括印刷]や[表内の選択されている項目の明細を一括印刷]を選択したときには,上記の2.〜6.の処理を実行すればよいことになる。ただし,5.で示したDrawPreviewプロシージャの呼び出しには注意が必要となる。本項中で説明したとおり,DrawPreviewプロシージャ(List 7-173)はPrivate宣言されているため,このプロシージャをFormPrintPreviewプロシージャ以外から呼び出すことはできない。そこで,DrawPreviewプロシージャを次のようにPublic宣言に変更する。

Public Function DrawPreview( _
  ByRef objPic As Object, _
  ByRef StartPage As Long, _
  ByRef EndPage As Long) As Long

 それでは,ユーザーがFormSlipフォーム(Fig.7-86)の[印刷]ボタン(BTN_PRINTボタン)を押したら,FormPrintSelectフォーム(Fig.7-102)が表示され,ユーザーに印刷方法の指定を求めるように実装してみよう。FormPrintSelectフォームで[表内のすべての項目の明細を一括印刷]や[表内の選択されている項目の明細を一括印刷]を選択したときには,各伝票に対して,上記の2.〜6.の処理を実行すればよい。そのためには,すでに実装してあるFormSlipフォームのBTN_PRINT_Clickプロシージャ(List 7-142)を,List 7-177のように書き換える。

 List 7-177の10行目では,FormPrintSelectフォーム(Fig.7-102)をモーダルウィンドウとして表示し,ユーザーに印刷方法を選択させている。そしてそのあと,12行目のSelect Case文によって,FormPrintSelectフォームのグローバル変数Selectedの値に応じて場合分けし,指定された印刷方法に従って印刷処理を実行するようになっている。

[表示されている表を印刷ならびにプレビュー]の場合
 この場合,13〜16行目が実行される。この処理は,DGrid_Slipデータグリッドをそのまま表形式で印刷しているだけであり,変更まえのList 7-142と同じ処理である。
 
[表内のすべての項目の明細を一括印刷]の場合
 この場合,17〜36行目が実行される。ここでは,DGrid_Slipデータグリッドに割り当てられているADODB.Recordsetオブジェクトを保持するグローバル変数g_objRecに対してループ処理を実行し,個々の伝票について明細を印刷している。なお,細かいことだが,ループ処理する以上,グローバル変数g_objRecが指すADODB.Recordsetオブジェクトを先頭から末尾に向かってカレント行を変更しながら処理することになる。そこで,23行目と36行目にあるように,印刷まえのカレント行の位置を示すブックマークを保存しておいて,印刷後はそのブックマークを再設定することで,印刷まえと印刷後とでカレント行の位置が変わらないようにしてある。この処理がないと,印刷終了後にカレント行は必ずEOFを指すようになってしまう。
 
[表内の選択されている項目の明細を一括印刷]の場合
 この場合,38〜57行目が実行される。この処理は,前述した[表内のすべての項目の明細を一括印刷]と似ているが,ユーザーが選択した伝票のみを処理対象とするため,ブックマークを利用しているという点が異なる。データグリッドコントロールでユーザーが複数の行を選択すると([SHIFT]キーを押しながら選択すると複数行の選択ができる),選択されたすべての行を指すブックマークの値がSelBookmarksコレクションに格納される。45〜53行目では,SelBookMarksコレクションに対してFor EachNextによるループ処理をすることで,選択された伝票すべての明細を印刷するという処理をしている。
  COLUMN    印刷ジョブ

 List 7-177の処理で伝票の明細を一括印刷するときには,確かにDGrid_Slipデータグリッドに表示されているすべての伝票もしくは選択した伝票の明細が一括して印刷される。しかしこの実装では,すべてが1つの印刷ジョブに収まるわけではなく,1つの伝票ごとに1つのジョブにまとまる。つまり,たとえば各伝票の明細がそれぞれ1ページだとした場合,100個の伝票明細を印刷するためには,1つのジョブで100ページ印刷されるのではなく,1ページの印刷ジョブが100個できることになる。これは,DrawPreviewプロシージャ(List 7-173)ならびにDrawPreview2プロシージャ(List 7-175)の処理において,1つの明細を印刷したあとでPrinterオブジェクトのEndDocメソッドを呼び出しているためである。

 Visual Basicでは,EndDocメソッドを呼び出すと,印刷ジョブがその時点で終了する。よって,このままの実装だと明細を印刷する伝票の数だけ印刷ジョブが作成されるということになる。一般に,多数のジョブができるのと,1つのジョブで多数のページを印刷するのとでは結果は同じだから,この処理で問題になることはない。しかし,たとえばホチキス止めできるプリンタを使う場合やソーターをサポートするプリンタなどを利用する場合,ジョブ単位でホチキス止めや排紙の仕分けをひとまとめにすることが多いから問題になることもある。その場合には,DrawPreviewプロシージャ(List 7-173)やDrawPreview2プロシージャ(List 7-175)のうち,EndDocメソッドを呼び出している箇所をNewPageメソッドに置き換えて改ページのみ実行するようにし,全印刷が終わった時点でEndDocメソッドを呼び出す,という処理に変更する必要がある。

Prev 119/134 Next