トップ回答者
複数の印刷を同時に行う方法について

質問
-
こんにちは。
VB2005Express+SQLServerExpressにて開発を行っています。
ボタンをクリックすることにより、DBから取得したデータを印刷することができるようになったのですが、
いくつかの印刷を同時に行う方法を考えています。
イメージとしては、印刷物の一覧をチェックボックスで用意をして、印刷したいものにチェックを入れ、
印刷ボタンをクリックすることで、それらすべてを印刷する。ということをしたいと考えています。
まずは、そもそもこのようなことはしないほうがよいというのであれば、現時点であきらめます。
現在、実現できたことは、ボタンのクリックイベントに印刷を行うプロシージャを関連付けて、
ボタンをクリックすることで印刷を実現できています。
しかし、イベントの関連付けは一つしかできないため、複数の印刷をここに関連付けることは
できないと思います。
そこで、チェックボックスのチェックのアル分だけ、印刷する内容ごとにクリックイベントに関連付け、
印刷、ないしはプレビューの表示ということを繰り返しても問題はないのでしょうか。
印刷の勉強を始めて、間もないので、基本というものがよくわかっていません。
(参考書なども単一内容の印刷はのっているのですが、複数の内容を一度に印刷するということは
のっていませんでした。)
また、複数の印刷を一度に行う場合、データを取得するDataTableなどはひとつだけ宣言をしておき、
汎用的に使用することができるのか、印刷ごとにそれぞれ宣言をしなければならないものなのでしょうか。
漠然とした質問で申し訳ありませんが、どうかお知恵を貸してください。
よろしくお願いいたします。
回答
-
PrintPageイベントハンドラで処理するのでしたね。すみません。わたしもうっかりしていました。イベントハンドラで処理しますので、印刷プロシージャ(メソッド)内にプライベートでDataTableを持つことができません。
なので、DataTableや行カウンタも含めて保持するクラスを帳票毎に用意されると良いと思います。
(参考)
ReportDocument
http://yan-note.blogspot.com/2007/06/blog-post_5424.html
#ReportDocumentと記載されていますが、PrintDocumentoの間違いだと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク TI-cb400 2009年9月24日 21:54
-
ということを繰り返しても良いかなとも考えたのですが、その場合に一回のボタンのクリックで、帳票の数だけボタンのクリックイベントを
クリックイベントを呼び出す必要はなく、印刷処理を実行すれば良いので、クリックイベントハンドラから印刷処理部分をメソッドとして抜き出し、それを実行すれば良いと思います。
呼び出せるのか?という疑問に突き当たりました。
ちなみにボタンのクリックイベントを発生させるのであれば、Button1.PerformClick()のようにしてできますが、前述したように印刷処理部分をメソッドとして切り出した方が良いでしょう。
浅はかな知識で申し訳ないのですが、クラスというのは汎用的な機能を持つものというイメージがあるので、単一の目的のために
クラスに汎用的かどうかは関係ありません。サブルーチンとそれに付随する値をくくるための入れ物と考えても良いと思います。今回はプリントに関するメソッドやイベントハンドラ、それに付随するデータテーブルやカレント行を覚えておくためのindexなどを一まとめにすると管理しやすくなります。そこでクラスという入れ物でくくるのです。もし汎用的ということであれば、そのクラスを抽象化して作成した継承元のクラスがそのように言えるかもしれません。
作るというものに違和感を感じてしまいます。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク TI-cb400 2009年9月24日 21:54
すべての返信
-
イメージとしては、印刷物の一覧をチェックボックスで用意をして、印刷したいものにチェックを入れ、
印刷ボタンをクリックすることで、それらすべてを印刷する。ということをしたいと考えています。
まずは、そもそもこのようなことはしないほうがよいというのであれば、現時点であきらめます。ユーザが指定する内容をまとめて印刷するという考え方自体はよくある話なので、問題ないと思います。
そこで、チェックボックスのチェックのアル分だけ、印刷する内容ごとにクリックイベントに関連付け、
印刷、ないしはプレビューの表示ということを繰り返しても問題はないのでしょうか。ユーザが許すのであれば良いかもしれませんが、私がユーザなら許しません。
組み方次第ですが、今の様子だと、複数の項目の印刷プレビューを要求したとき、印刷プレビューが数回開くということになりませんか?
ユーザから見ると、1回の印刷でまとめて印刷することを期待しているのに、印刷プレビューが複数回開くのは納得ができません。印刷の勉強を始めて、間もないので、基本というものがよくわかっていません。
(参考書なども単一内容の印刷はのっているのですが、複数の内容を一度に印刷するということは
のっていませんでした。)PrintPage イベントの中で「今印刷しているものはページが残っているか」「今印刷しているものが印刷終了の場合、次に印刷するべきものがあるか」等の判断を加えて、連続して印刷できるようにしたら良さそうに思えます。(試していません)
なお、今回のように、応用例は参考書やサイト等に載っていないことも多いと思います。
基礎として学んだことをどのように組み合わせれば実現できるかを考えていく力が今後求められるでしょう。また、複数の印刷を一度に行う場合、データを取得するDataTableなどはひとつだけ宣言をしておき、
汎用的に使用することができるのか、印刷ごとにそれぞれ宣言をしなければならないものなのでしょうか。印刷内容や今後の組み方次第だと思います。
同じデータを異なる様式で印刷するだけであれば、1つのインスタンスを使い回すこともできるでしょう。
解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。 -
ご回答ありがとうございます。
現在、以下のように印刷を記述しています。
Dim DT as DataTable
Private Sub btn_Test_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_Test.Click
'PrintDocumentの宣言、DataTableへデータの取得 ←ここ
End sub
Private Sub pd_test(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
'DTを参照して、その内容の印字処理
End Sub
といった処理をしています。
そこで、矢印の部分を
Private Sub TestPrint
'PrintDocumentの宣言、DataTableへデータの取得
End Sub
を呼び出す形に変更しようと考えています。
ただ、DataTableへのデータの取得の際に
DT = New DataTable
DT=データ取得
とした場合、2つ以上の印刷処理を矢印の部分で呼び出しをした際に、どのデータを参照にするのだろうと考えてしまいます。
Newにより新しいインスタンスを作成するので、データ自体はそれぞれの処理の内容を取得できるとは思うのですが、
どのDataTableにそれぞれの印刷処理に必要なデータが入っているかの判断ができないように思えます。
ということから、一番最初のDataTableの宣言の時点で、必要な数のDataTableの宣言が必要になると思えます。
同時に、異なる内容にデータを印刷する場合は上記のように行うしかないのでしょうか。
今、試す環境が手元にないのですが、どうしても気になってしまったので、質問をさせていただきました。
どうか、アドバイスお願いいたします。 -
とした場合、2つ以上の印刷処理を矢印の部分で呼び出しをした際に、どのデータを参照にするのだろうと考えてしまいます。
メンバー変数 DT を配列やリストにすれば良いのでは?
そして、今処理しているのは何番目かを覚える変数も追加して、必要な位置に DataTable を作って代入していけば良いでしょう。
そして、印刷する際も配列の何番目のものを参照するべきか判断して利用すると良いでしょう。
配列だと最初の時点で数が決定している必要があります。ただ、今回の要求では印刷開始時点で最大数を決定できるので特に支障はないように思えます。
リスト = List(Of T) の場合は最初に数を決めなくても良いです。
解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。 -
しかし、イベントの関連付けは一つしかできないため、複数の印刷をここに関連付けることは
ここの意味がよくわからなかったのですが、ボタンのクリックイベントに複数のイベントハンドラをセットできないということでしょうか? であれば、それは可能です。
できないと思います。
そこで、チェックボックスのチェックのアル分だけ、印刷する内容ごとにクリックイベントに関連付け、
私は良いと思いますよ。ただ、ロジックとしては、それぞれの帳票の印刷プロシージャがあって、それがクリックイベントに結びついているのが基本だと思います。例えば、
印刷、ないしはプレビューの表示ということを繰り返しても問題はないのでしょうか。
'TestA印刷プロシージャ
Private Sub TestAPrint
End Sub
'TestB印刷プロシージャ
Private Sub TestBPrint
End Sub
Private Sub btn_TestA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_TestA.Click
TestAPrint()
End sub
Private Sub btn_TestB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_TestB.Click
TestBPrint()
End sub
複数同時に印刷指示したい場合は、
Private Sub btn_TestOnce_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_TestOnce.Click
If TestAチェックボックスがチェックされていれば、 Then TestAprint()
If TestBチェックボックスがチェックされていれば、 Then TestBprint()
End sub
帳票によって用意するDataTableの構造は違うのが普通ですから、それぞれの印刷プロシージャでプライベートで用意してしまえば良いと思います。
また、ユーザーは印刷指示を何度も行うのが面倒で一度に行いたいだけであり、帳票毎に印刷プレビューが開くのは問題ないと思います。むしろ一つの印刷プレビューでつながっているのであれば、目的の帳票を画面で確認したい場合に探しにくいのではないでしょうか? 私が知る範囲では、一度に印刷指示したい場合は大抵が定型業務になっており、どの帳票を選択したかという情報も記憶できるようになっています。そして大抵は印刷プレビューを行いません。複数帳票を一度に指示したい場合は大抵がプレビューで確認したいわけではなく、一度に印刷したいからだからです。
もちろん上記は私の個人的な思いであり、実際にどのような動作を求めているのかはユーザーに確認する以外はないというのは言うまでもありません。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/ -
ご回答ありがとうございます。
私の説明に一部不足が間違いがありました。
Private Sub pd_test(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
'DTを参照して、その内容の印字処理
End Sub
上記の部分で印刷を行っていると書きましたが、その前のボタンのクリックイベントにおいて、PrintDocumentの宣言を
行い、そのPrintDocumentのPrintPageイベントに追加をしておりました。
'PrintDocumentオブジェクトの作成
PD = New System.Drawing.Printing.PrintDocument'Printpageイベントハンドラの追加
AddHandler PD.PrintPage, AddressOf pd_Test
最初の私の質問はAddressOfのあとに、複数のイベントをセットできるのかどうかということでした。
これはできるということなのですね。勝手に思い込んでおりました。
Azulean様
DataTableなども配列にできるのですね。このようなことはまったく考えておりませんでした。一度試してみたいと思います。
trapemiya様
印刷プロシージャにDataTableをプライベートで用意するというのはどのようなことをさすのでしょうか。
現時点での私の理解としては、PrintPage内でデータの取得処理をすると複数舞の印刷にわたる場合、その都度データ取得
処理が入るので非効率となる。
そこで、どこからでも参照ができる形で、DataTableを宣言しておき、ボタンのクリック時にDataTableにデータを取得。
その内容を持って、PrintDocumentのPrintPageに関連付けしたイベント内で印刷処理を行う。
というもので、そのために最初に質問に記述してあるような書き方をしております。
自分でこのような方法をとろうと思うといっておきながら、実は下記の方法だとどこで、PrintDocumentの宣言を行うかや
DataTableの宣言、データの取得タイミングがわからず悩んでおります。
'TestA印刷プロシージャ
Private Sub TestAPrint
End Sub
もしよろしければ、その部分だけでも教えていただけませんでしょうか。
どうか、よろしくお願いします。 -
PrintPageイベントハンドラで処理するのでしたね。すみません。わたしもうっかりしていました。イベントハンドラで処理しますので、印刷プロシージャ(メソッド)内にプライベートでDataTableを持つことができません。
なので、DataTableや行カウンタも含めて保持するクラスを帳票毎に用意されると良いと思います。
(参考)
ReportDocument
http://yan-note.blogspot.com/2007/06/blog-post_5424.html
#ReportDocumentと記載されていますが、PrintDocumentoの間違いだと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク TI-cb400 2009年9月24日 21:54
-
ご回答ありがとうございます。
私の現状の知識ではPrintPageイベントハンドラ内での処理しか思いつかないのですが、何か他に印刷を行う方法があるのでしょうか。
参考の部分も拝見させていただきました。
内容を見ると、trapemiya様がおっしゃっているように帳票の数だけクラスを作る必要がありそうですね
自分が現在行っている方法で、取得するデータごとに別名のDataTableを宣言しておき、それぞれ印刷のプロシージャを用意して
イベントハンドラにセット → 印刷
ということを繰り返しても良いかなとも考えたのですが、その場合に一回のボタンのクリックで、帳票の数だけボタンのクリックイベントを
呼び出せるのか?という疑問に突き当たりました。
となると、クラスを複数作るほうが現実的かなとも思えます。
浅はかな知識で申し訳ないのですが、クラスというのは汎用的な機能を持つものというイメージがあるので、単一の目的のために
作るというものに違和感を感じてしまいます。
このように感じるのはやはり、私の知識のなさのためなのでしょうか。 -
ということを繰り返しても良いかなとも考えたのですが、その場合に一回のボタンのクリックで、帳票の数だけボタンのクリックイベントを
クリックイベントを呼び出す必要はなく、印刷処理を実行すれば良いので、クリックイベントハンドラから印刷処理部分をメソッドとして抜き出し、それを実行すれば良いと思います。
呼び出せるのか?という疑問に突き当たりました。
ちなみにボタンのクリックイベントを発生させるのであれば、Button1.PerformClick()のようにしてできますが、前述したように印刷処理部分をメソッドとして切り出した方が良いでしょう。
浅はかな知識で申し訳ないのですが、クラスというのは汎用的な機能を持つものというイメージがあるので、単一の目的のために
クラスに汎用的かどうかは関係ありません。サブルーチンとそれに付随する値をくくるための入れ物と考えても良いと思います。今回はプリントに関するメソッドやイベントハンドラ、それに付随するデータテーブルやカレント行を覚えておくためのindexなどを一まとめにすると管理しやすくなります。そこでクラスという入れ物でくくるのです。もし汎用的ということであれば、そのクラスを抽象化して作成した継承元のクラスがそのように言えるかもしれません。
作るというものに違和感を感じてしまいます。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク TI-cb400 2009年9月24日 21:54
-
おはようございます。
思い切り勘違いをしていたことに気付きました。
ボタンをクリックすることで、PrindDocumentを作成し、PrintDocumentのPrintPageイベントに何を印刷するかということを
関連付けていたのであり、ボタンのクリックイベントに関連をつけているわけではありませんでした。
となると、印刷をする都度だけ、PrintDocumentのPrintPageイベントに関連付けをして印刷を実行することということも
実現できそうです。
ただ、クラスにしたほうがひとつの処理を一塊と見ることができるので、わかりやすくはなりそうです。
まずは、クラスを利用する方法で検討してみたいと思います。
共通のプロパティ(DataTableなど)を持つクラスをBaseクラスとして作っておき、個別の処理をそれぞれの印刷物ごとに
行うという形をとりたいと思います。
ありがとうございました。