Javaで帳票印刷してみた

　VisualBasicで帳票印刷を実装したことがあります。印刷プレビュー画面も１枚、２枚、４枚と切り替えることができ、結構使えてました。今時、ExcelやAccessで十分にできますが、私の業務ではどちらも帯に短し襷に長しだったので結局自作した訳です。Javaでも同様にできないかと考え、１枚プレビュー・印刷まではできてました。今回、複数枚の印刷つまり帳票印刷ができましたのでご紹介します。A4に印刷した結果が次です。スマホの写真で少し見辛いかも知れませんがご容赦を。
![JavaPrint1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/51b6a3e9-8b94-6d09-5b82-85398e50ba46.jpeg)
試しに１枚目のみLandscapeで印刷してみました。
![JavaPrint2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/390df0e2-2595-7e7d-a96d-68eba2843252.jpeg)
次がそのソースです。pleiades2022と我が家の〇〇sonプリンターで検証しました。
```
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import javax.swing.JPanel;

public class PrintBook2 {	
	public static void main(String[] args){
		PrinterJob job = PrinterJob.getPrinterJob();// 印刷をするクラスのインスタンス:jobを生成

		PageFormat pfl = job.defaultPage();
		pfl.setOrientation(PageFormat.LANDSCAPE);	// 横向き印刷をするページフォーマットを設定する

		PageFormat pfp = job.defaultPage();
		pfp.setOrientation(PageFormat.PORTRAIT); 	// 縦向き印刷をするページフォーマットを設定する

		Book bk = new Book();						// Bookクラスのインスタンスを作成
		bk.append(new PrintCover()  ,pfl,1);		// 表紙を1ページ追加
		bk.append(new PrintContent(),pfp,3);		// 本文を3ページ追加 defaultPage PORTRAIT
		job.setPageable(bk);						// Bookを印刷jobに渡す
		if (job.printDialog())						// 印刷ダイアログを表示、プリンタの設定可能
		{    
			try { job.print();}						// 印刷指示
			catch (Exception e){/* handle exception */ }
		}
		System.exit(0);
	}
}

// 表紙。landscapeで印刷する
class PrintCover extends JPanel implements Printable {
	//PrintCover(){}
	public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
		int pW = (int) pf.getWidth();    
		int pH = (int) pf.getHeight();
		int x0 = (int) pf.getImageableX();
		int y0 = (int) pf.getImageableY();

		g.setColor(Color.black);
		g.drawRect(x0, y0, pW-x0-75, pH-y0-75);

		Font fnt = new Font("Helvetica-Bold", Font.PLAIN, 12);
		g.setFont(fnt);				// pageIndex 0-3
		String strxy = "x0="+Integer.toString(x0)+"y0=" +Integer.toString(y0);
		g.drawString(strxy, x0, y0+10);

		fnt = new Font("Helvetica-Bold", Font.PLAIN, 24);
		g.setFont(fnt);				 // pageIndex 0-3
		String str0 = Integer.toString(pageIndex)+ "ページ";
		g.drawString(str0, x0, y0+30);

		fnt = new Font("Helvetica-Bold", Font.PLAIN, 36);	// 上下の中央部に36ポイントで表示
		g.setFont(fnt);
		String str1="JAVA 帳票印刷テスト 表紙";
		FontMetrics fm = g.getFontMetrics();
		g.drawString(str1, x0+140, (int) (pH/2 - fm.getHeight()/2));

		return Printable.PAGE_EXISTS;
	}
}

// 本文帳票。portraitで印刷する
class PrintContent extends JPanel implements Printable {
	//PrintContent(){}
	public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
		Font fnt = new Font("Helvetica-Bold", Font.PLAIN, 36);
		g.setFont(fnt);
		g.setColor(Color.black);
		int pW= (int) pf.getWidth();    
		int pH= (int) pf.getHeight();
		int x0 = (int) pf.getImageableX();
		int y0 = (int) pf.getImageableY();
		g.drawString("帳票 No."+Integer.toString(pageIndex), x0, y0+30);
		for(int k=1;k<7;k++)g.drawLine(x0, y0+30+95*k,pW-x0-2 , y0+30+95*k);
		g.drawRect(x0, y0+30, pW-x0-75, pH-y0-30-74);
		
		g.drawString("宛先："+Integer.toString(pageIndex)+"県", x0, y0+30+40);
		g.drawString("氏名："+Integer.toString(pageIndex)+"山"
							 +Integer.toString(pageIndex)+"郎", x0, y0+30+95+40);
		
		return Printable.PAGE_EXISTS;
	}
}
```
罫線などは共通に出来ます。CSVファイルにでも落としておいたデータを配列
    　a[0][0],a[0][1],・・・,a[0][i]
    　a[1][0],a[1][1],・・・,a[1][i]
        ・
        ・
    　a[n][0],a[n][1],・・・,a[n][i]
に読込み、所定の場所に書き出させれば帳票印刷、というか差し込み印刷完了ですかね。
　５万円、１０万円に事欠く職場でしたので、自分でできることは自分で何とかしたいという習慣が今もついている貧乏性の爺ちゃんです。ただ、printableな範囲はプリンターによっても違うでしょうし、その調整に何枚もの用紙とインクを無駄使いしましたよ。印刷プレビューができれば良いのですが。（実はプリンターのプロパティで見ることができました、後で分かりましたがね）
　どこかの誰かのお役に立ちますかね...