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

7.4.7 顧客情報の印刷処理
●プレビュー処理

・ページの表示/非表示の設定
 211〜220行目の処理は,描画の初期設定をするものである。ここで,以下の処理で使う変数の役割について説明しておく。

 211行目で設定しているnewPageFlag変数は,新しいページが始まったならばTrueを,そうでなければFalseを保持する変数である。この変数の内容は,291行目でページの先頭に列見出し(ヘッダ行)を描画するかどうかを判断するのに使われる。

 212行目で設定しているNowPage変数は,その時点で描画しているページ番号を保持する変数である。

 214〜219行目で設定しているdrawFlag変数は,その時点のページ(NowPage変数に保持されたページ番号のページ)を描画するならばTrueを,描画しないならばFalseを,それぞれ保持する変数である。214行目にもあるように,その時点で描画しようとしているページ番号がDrawPreviewプロシージャの第2引数と第3引数に渡されたページ描画範囲内であるならばdrawFlag変数をTrueに,そうでなければFalseに設定するという処理をしている。

 後続の処理では,drawFlag変数がTrueの場合には実際に描画せずに,描画位置だけを進めるようにする。そうすることによって,指定された範囲外のページの出力を抑制する。

 なぜこのような処理が必要なのだろうか。それは,たとえば2ページ目から出力する場合に,2ページ目の先頭がADODB.Recordsetオブジェクトの保持する第何番目のレコードから始まるのかを知るためには,1ページ目を描画しなければならないからである。今回のサンプルでは,1ページに出力するレコード数(行数)は可変である。可変というのは,フォントの大きさによっても出力できるレコード数が変わるということもあるが,それだけでなく,列幅よりも長い文字列であるときには折り返して複数行に展開するため,1レコードあたりの高さが不定となることを意味している。

 そこで,2ページ目から描画するときにも,まずは1ページから描画を始める。しかし,このときdrawFlag変数の値をFalseにしておき,実際には描画しないで,列の高さや文字列の高さなどを計算していくだけとする。そして,改ページした段階でdrawFlag変数の値をTrueにし,実際に描画すれば,2ページ目から描画できることになる。

 このように述べると,今回のサンプルでは,たとえば100ページ目から出力するときには1〜99ページ目を描画しないものの処理はすることになり,処理速度が低下するのではないかと思われるだろう。事実そのとおりである。すなわち,今回のサンプルの場合には,ページ数が多いものを後半から出力するようなケースでは,パフォーマンス面で問題が生じるおそれがある。この問題を回避するには,次の2つの方法が考えられる。

1ページあたり何レコード描画するかをあらかじめ決めてしまう方法
 たとえば1ページあたり50レコード描画すると決めてしまえば,100ページ目から出力する場合には,単純に50×100レコード分だけ進めてから描画を開始すればよいので,処理速度は向上する。
 
逐一ページを計算するのではなく,はじめに一度だけ全ページの描画を処理しておく方法
 はじめに一度だけ全ページの描画処理を実行し(実際に描画しなくても,ただ計算するだけでよい),各ページに収まるレコード数を配列などに保存しておく。たとえば,PageRecordのような配列を用意しておき,1ページ目に50レコード収まったならば,PageRecord(1)=50,2ページ目に40レコード収まったならばPageRecord(2)=40,といった具合に,ページごとのレコード数を格納しておく。そして,以降の処理において,たとえば100ページ目から印刷したいのであれば,PageRecord(1)からPageRecord(99)の総和を加えたものだけレコードを進め,そこから描画し始めることで,100ページ目から描画する処理でも高速化される。

 しかし,いずれの方法もやや処理が煩雑になるため,今回はこれらの方法はとらない。単純に1ページ目から描画処理を始め,描画ページ範囲外のときには,計算はするが描画はしないという処理で対応してゆくことにする。

・列幅の計算
 222〜253行目は,列の幅を計算している箇所である。Fig.7-41に示したとおり,描画する表の幅は用紙の幅に合わせる。具体的には,データグリッドコントロールに表示されている各列の幅の総和が用紙幅から余白(MLeft変数の内容+MRight変数の内容)を引いた分だけに収まるよう,適時拡大縮小して描画することになる。各列の幅はcolWidthという名前の配列に格納するものとする。また,各列の幅の総和はColWidthTotal変数に格納するものとする。

 ところで今回は,データグリッドコントロールに結び付けられているADODB.Recordsetオブジェクトの全フィールド(列)を描画するのではなく,そのうち表示されている列(列に対応するColumnオブジェクトのVisibleプロパティがTrueである列)のみを描画対象とする。そこで,データグリッドコントロールが保持しているフィールドのうち,表示されている列の総数をVisibleNumプロパティに格納することにする。そして,表の左から順に,対応するデータグリッドコントロールのColumnオブジェクトのインデックス番号をcolIndexという名前の配列に格納する。

 まず,240〜248行目では,データグリッドコントロールが保持する列数分だけループし,表示される列に対して(VisibleプロパティがTrueである列に対して),243〜246行目の処理を実行し,colWidth配列に列幅を,colIndex配列にそのColumnオブジェクトのインデックス番号を格納する。また,ColWidthTotal変数には,列幅の総和を格納する。

 250〜253行目では,求めた列幅を用紙サイズに合うように拡大縮小する。すでに左余白はMLeft変数に,右余白はMRight変数に格納してある。また,用紙幅(プレビュー画面幅)はobjPicオブジェクトのWidthプロパティから取得できる。用紙幅から左余白と右余白を減算したものが,表の幅となる。そこで,求めたcolWidth配列のそれぞれの要素に対して,用紙幅から左余白と右余白を減算したものを掛け,全体の列幅で割れば,用紙幅から左余白と右余白を減算したものと全列の総和とが一致するように,各列の幅が拡大縮小されることになる。少々わかりにくいが,この処理は比例配分的な処理であり,概念的に図示するとFig.7-53のような処理をしていることになる。

Fig.7-53 表の大きさを用紙サイズに合わせる
fig7_53

Prev 49/134 Next