PrintDocumentクラスを使って帳票を印刷します。
印刷するデータとしてテキストファイルを作成して、その内容を印刷します。
テキストファイル作成
100行のテキストデータを作成します。
void TextWrite() { string FilePath = @"C:/TESTDATE.txt"; // ファイルが存在しなかったら作る if( File.Exists(FilePath) == false ) { StreamWriter StrWtr = File.CreateText(FilePath); StrWtr.Close(); } // ストリームライターオープン using (StreamWriter StrWtr = new StreamWriter(FilePath, false, Encoding.UTF8)) { // 100行書き込む for(int i = 0; i < 100; i++) StrWtr.WriteLine("テキストファイルの" + (i+1).ToString() + "行目です"); }; }
ファイルが存在しなかったらファイルを作成してから使って100行書き込みます。
File.CreateTextをつかってファイルを作成すると、そのファイルをオープンした状態になるので1度クローズしています。
印刷の準備をするコード
void TextPrintMain() { // プリンタードキュメントインスタンス using (PrintDocument PrtDoc = new PrintDocument()) { }; }
PrintDocumentをインスタンスします。
印刷用紙の設定
void TextPrintMain() { // プリンタードキュメントインスタンス using (PrintDocument PrtDoc = new PrintDocument()) { // 用紙設定 A4 foreach (PaperSize ps in PrtDoc.PrinterSettings.PaperSizes) { if (ps.Kind == PaperKind.A4) { PrtDoc.DefaultPageSettings.PaperSize = ps; break; } } // 用紙の向き 縦 PrtDoc.DefaultPageSettings.Landscape = false; // true:横 false:縦 }; }
4A縦に設定します。
印刷対象のプリンターの用紙にA4が存在するか調べて設定します。
用紙の向きはDefaultPageSettings.Landscapeをtrueにすると横向き、falseで縦向きになります。
ここでは縦向きfalseにします。
印刷イメージ作成
PrintPageEventHandlerで印刷するイメージを書き込みます。
void TextPrintMain() { // プリンタードキュメントインスタンス using (PrintDocument PrtDoc = new PrintDocument()) { // 用紙設定 A4 foreach (PaperSize ps in PrtDoc.PrinterSettings.PaperSizes) { if (ps.Kind == PaperKind.A4) { PrtDoc.DefaultPageSettings.PaperSize = ps; break; } } // 用紙の向き 縦 PrtDoc.DefaultPageSettings.Landscape = false; // true:横 false:縦 // PrintPageイベント・ハンドラ PrtDoc.PrintPage += new PrintPageEventHandler(this.DocWtr); }; } private void DocWtr(object sender, PrintPageEventArgs e) { ここにページイメージを書き込むコードを書く }
ページイメージを書き込むのにはページの座標(x,y)が必要になります。
座標は1/100インチの単位で指定するのですが、分かりにくいのでmmから1/100インチに変換する処理を作ります。
mmから1/100インチに変換
int MmToInch(decimal Mm) { decimal a = (decimal)(Mm / (decimal)25.4); int b = (int)(a * 100); return b; }
もっと簡素化できるコードですが、分かりやすくしました。
テキストファイルを読み込んでページイメージに書き込む
フォントサイズは10ptで1行5mmの高さで書き込みます。
void TextPrintMain() { // プリンタードキュメントインスタンス using (PrintDocument PrtDoc = new PrintDocument()) { // 用紙設定 A4 foreach (PaperSize ps in PrtDoc.PrinterSettings.PaperSizes) { if (ps.Kind == PaperKind.A4) { PrtDoc.DefaultPageSettings.PaperSize = ps; break; } } // 用紙の向き 縦 PrtDoc.DefaultPageSettings.Landscape = false; // true:横 false:縦 // PrintPageイベント・ハンドラ PrtDoc.PrintPage += new PrintPageEventHandler(this.DocWtr); // プレビュー表示 PrintPreviewDialog Pd = new PrintPreviewDialog(); Pd.PrintPreviewControl.Zoom = 0.75; Pd.Document = PrtDoc; Pd.ShowDialog(); }; } private void DocWtr(object sender, PrintPageEventArgs e) { string FilePath = @"C:/TESTDATE.txt"; // フォントサイズと色 Font DefFont = new Font("メイリオ", 10f); Brush DefBrush = new SolidBrush(Color.Black); // StreamReaderオブジェクトのインスタンスを生成 using (StreamReader Sr = new StreamReader(FilePath)) { int i = 0; while ( Sr.Peek() >= 0 ) { string Rec = Sr.ReadLine(); e.Graphics.DrawString(Rec, DefFont, DefBrush, new PointF(MmToInch(1),MmToInch(1 + (5 * i)))); i++; } } }
テキストファイルを読み込んで印刷プレビューを表示しましたが、余白も無し、最悪なのは1ページしか印刷されません。
ページ書式を設定
今回は4A縦の設定ですので、印刷範囲は横は210mm、縦は297mmに範囲になります。
上下左右の余白を15mmにします。
1行の高さを5mmにして上下に0.5mmのマージンを設けます。
とりあえず、書式を設定して印刷するコードを作ります。
1ページしか印刷されない対策はその後にします。
private void DocWtr(object sender, PrintPageEventArgs e) { // テキストファイルのパス string FilePath = @"C:/Users/ks420/Desktop/Projects/PrintTest/TESTDATE.txt"; // 書式・書き込み座標等 int PageMarginTop = MmToInch(15); // 上余白15mm int PageMarginLeft = MmToInch(15); // 左余白15mm int TextHight = MmToInch(5); // テキストの高さ5mm int TextMarginTop = MmToInch((decimal)0.5); // テキスト上の余白0.5mm int TextMarginBottom = MmToInch((decimal)0.5); // テキスト下の余白0.5mm int NowPositionY = PageMarginTop; // 印刷するY座標 // フォントサイズと色 Font DefFont = new Font("メイリオ", 10f); Brush DefBrush = new SolidBrush(Color.Black); // StreamReaderオブジェクトのインスタンスを生成 using (StreamReader Sr = new StreamReader(FilePath)) { int i = 0; while ( Sr.Peek() >= 0 ) { string Rec = Sr.ReadLine(); e.Graphics.DrawString(Rec, DefFont, DefBrush, new PointF(PageMarginLeft,NowPositionY + TextMarginTop)); NowPositionY = NowPositionY + TextMarginTop + TextHight + TextMarginBottom; } } }
先ほどのコードを少しいじって書式に対応しました。
これでプレビューを表示すると上、左に余白があり、行もスッキリした感じで表示されます。
では改ページの対策をします。
用紙に対応した改ページ
改ページ(複数ページ)に対応するにはHasMorePagesプロパティを使います。
単一ページ又は最後のページならHasMorePagesにfalseを代入、それ以外、改ページの必要があればtrueを代入します。
このプロパティだけの設定であれば簡単なことなのですが、HasMorePagesをtrueに設定すると、印刷イメージを書き込むメソッド(ここではDocWtr)がってもう一度実行されるのです。
なので、このコードでは2回目以降に呼び出された時にはストリーマーのインスタンスをしないようにします。
完成したコード
不具合の対策と保守性を対策したコードです。
上位スコープ
namespace PrintTest { public partial class Form1 : Form { // 用紙 const string Page_Kind = "A4"; const string Page_Landscape = "TATE"; // 1インチ:25.4mm const decimal Inch = (decimal)25.4; // テキストファイルパス const string FilePath = @"C:/TESTDATE.txt"; // 書式・書き込み座標等 int PageMarginTop; int PageMarginBottm; int PageMarginLeft; int PageBottomPositionY; int TextHight; int TextMarginTop; int TextMarginBottom; // ストリーマー StreamReader StrmRdr; // フォントサイズと色 Font FontDef = new Font("メイリオ", 10f); Brush BrushDef = new SolidBrush(Color.Black);
保守性を高めるために定数をスコープ上位で設定します。
注目は改ページ対策のためにする時に、StreamReaderを宣言することです。
インストラクタ
public Form1() { InitializeComponent(); // 書式の設定 PageMarginTop = MmToInch(15); // 上余白15mm PageMarginBottm = MmToInch(15); // 下余白15mm PageMarginLeft = MmToInch(15); // 左余白15mm PageBottomPositionY = MmToInch(297) - PageMarginBottm; // 印刷範囲外となるY座標 TextHight = MmToInch(5); // テキストの高さ5mm TextMarginTop = MmToInch((decimal)0.5); // テキスト上の余白0.5mm TextMarginBottom = MmToInch((decimal)0.5); // テキスト下の余白0.5mm }
余白等の書式を設定します。
ミリメートルを1/100インチに変換
int MmToInch(decimal Mm) { decimal a = (decimal)(Mm / Inch); int b = (int)(a * 100); return b; }
ミリメートルをdecimal で引数で受け取り1/100インチをintで返します。
テスト用テキストファイル作成
void TextWrite() { // ファイルが存在しなかったら作る if( File.Exists(FilePath) == false ) { StreamWriter StrWtr = File.CreateText(FilePath); StrWtr.Close(); } // ストリームライターオープン using (StreamWriter StrWtr = new StreamWriter(FilePath, false, Encoding.UTF8)) { // 100行書き込む for(int i = 0; i < 100; i++) StrWtr.WriteLine("テキストファイルの" + (i+1).ToString() + "行目です"); }; }
テスト用テキストデータを100行、作ります。
ファイルが無かったら作成します。
印刷処理
void TextPrintMain() { // プリンタードキュメントインスタンス using (PrintDocument PrtDoc = new PrintDocument()) { // 用紙設定 A4 foreach (PaperSize ps in PrtDoc.PrinterSettings.PaperSizes) { if ( Page_Kind == "A4") { if (ps.Kind == PaperKind.A4) { PrtDoc.DefaultPageSettings.PaperSize = ps; break; } } } // 用紙の向き 縦 if( Page_Landscape == "TATE") PrtDoc.DefaultPageSettings.Landscape = false; else PrtDoc.DefaultPageSettings.Landscape = true; // ストリームリーダーオープン StrmRdr = new StreamReader(FilePath); // PrintPageイベント・ハンドラ PrtDoc.PrintPage += new PrintPageEventHandler(this.DocWtr); // プレビュー表示 PrintPreviewDialog Pd = new PrintPreviewDialog(); Pd.PrintPreviewControl.Zoom = 0.75; Pd.Document = PrtDoc; Pd.ShowDialog(); // ストリームリーダークローズ StrmRdr.Close(); } }
プリンタードキュメントクラスをインスタンスして用紙や用紙の向きを指定します。
ストリームリーダーをオープン、プリントページイベントを利用しています。
プリントイメージをプレビューします。
プリントイメージ作成
private void DocWtr(object sender, PrintPageEventArgs e) { // 書き込み座標 int NowPositionY = PageMarginTop; // 印刷するY座標 while ( StrmRdr.Peek() >= 0 ) { // ストリーマー読み込み string Rec = StrmRdr.ReadLine(); // 印刷イメージ書き込み e.Graphics.DrawString(Rec, FontDef, BrushDef, new PointF(PageMarginLeft,NowPositionY + TextMarginTop)); // 次の行を準備 NowPositionY = NowPositionY + TextMarginTop + TextHight + TextMarginBottom; // 改ページ判定 if( NowPositionY >= PageBottomPositionY ) { e.HasMorePages = true; break; } else e.HasMorePages = false; } }
ストリームリーダーを読み込みプリントイメージに書き込みます
プリントイメージに書き込む時は書式に沿った座標に書き込みます。
印刷範囲を超える場合はHasMorePagesの設定で複数ページに対応しています。
まとめ
印刷ツールを使わなくても意外と簡単に印刷するプログラムは作成できます。
又、ブレイク処理やデータソースも自由にできるので利用範囲も広がると思います。
応用して利用できるので、今後も活用します。
PrintPageEventHandlerの使い方。
HasMorePagesプロパティで複数ページに対応した時の動作。
(HasMorePagesにtrueを代入して複数ページに対応すると、プリントページイベントが再度呼び出されるのでその対応をロジックて対策が必要になる。)
コメント