Javaでプリンター名を指定して印刷する方法【ライブラリなし】


Posted on 2021/8/21 at 1:58

Update on 2022/1/24 at 0:58


Javaから帳票データを作成し印刷する際、ある帳票はA4で、もう一方の帳票はB5で印刷したいという事があります。 プリンターが1台しかなくてもトレーが複数ある機種であれば、それぞれの用紙サイズや向きを設定したプリンターをあらかじめ登録しておき、 プログラムからプリンター名を指定して印刷するという方法があります。プリンターのドライバーをインストールしておけばいくらでもプリンターの追加が 可能なので便利でおすすめです。

2つの印刷方法について

Javaの標準機能で印刷を行うにはPrinterJobを使う方法とDocPrintJobを使う方法があります。

後者のDocPrintJobの方が後から追加されたクラスで、用紙の指定や余白の指定をPrintRequestAttributeSetで簡単に行うことができるようになりました。 しかし、PrinterJobクラスも拡張されて、AttributeSetを利用できるようになっているため、PrinterJobとDocPrintJobどちらも同じ様に利用できます。

単一の画像ファイルを印刷する場合は、DocPrintJobを利用すると簡単に実装することができますが、それ以外ではDocPrintJobを利用するメリットはあまりないと思います。

今回はPrinterJobを利用した方法を実装してみます。

サンプルコード

縦向きのA4用紙の中央に文字列を描画し、印刷を行います。 サンプルコードではプリンター名を「Microsoft Print to PDF」という仮想プリンター名を指定しPDFに保存していますが、 印刷したい物理プリンター名に変更すればダイレクトに印刷することができます。

  
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.Locale;

import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrinterName;

public class JPrint {

	private final PrinterJob job;
	private final PrintRequestAttributeSet attrs;
	private final MediaSize mediaSize;

	public static void main(String[] args) {
		try {
			new JPrint().print("Microsoft Print to PDF");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public JPrint() {
		job = PrinterJob.getPrinterJob();
		mediaSize = MediaSize.ISO.A4;
		attrs = new HashPrintRequestAttributeSet();
		attrs.add(mediaSize.getMediaSizeName());
		attrs.add(OrientationRequested.PORTRAIT);
		setMargin(5f, 5f, 5f, 5f);
	}
	private void print(String printerName) throws PrintException, PrinterException {
		PrintService service = lookupPrintService(printerName);
		if (service == null)
			if (printerName == null)
				throw new PrintException("Not Found Default Printer");
			else
				throw new PrintException("Not Found Printer [" +printerName+ "]");
		job.setPrintService(service);
		TestPrintable printable = new TestPrintable();
		job.setPrintable(printable);
		job.print(attrs);
	}
	// 余白(mm)の指定
	private void setMargin(float marginTop, float marginRight, float marginBottom, float marginLeft) {
		float mediaW = mediaSize.getX(Size2DSyntax.MM);
		float mediaH = mediaSize.getY(Size2DSyntax.MM);
		MediaPrintableArea area = new MediaPrintableArea(
	            marginLeft, marginTop, mediaW-marginLeft-marginRight, mediaH-marginTop-marginBottom,
	            MediaPrintableArea.MM);
		attrs.add(area);
	}
	// プリンター名からPrintServiceを検索
	private PrintService lookupPrintService(String printerName) throws PrintException {
		if (printerName == null) {
			// プリンター名を指定しない場合はデフォルトのプリンターを使用
			return PrintServiceLookup.lookupDefaultPrintService();
		}
		PrintServiceAttributeSet printAttrSet = new HashPrintServiceAttributeSet();
		printAttrSet.add(new PrinterName(printerName, Locale.getDefault()));
	    PrintService[] services 
	    		= PrintServiceLookup.lookupPrintServices(null, printAttrSet);
	    if (services.length == 0)
	    	return null;
	    return services[0];
	}
	
	class TestPrintable implements Printable {
		public int getNumberOfPages() {
			return 1;
		}
		@Override
		public int print(Graphics g, PageFormat pf, int pageindex) throws PrinterException {
			if (pageindex == getNumberOfPages())
				return Printable.NO_SUCH_PAGE;
			Graphics2D g2 = (Graphics2D)g;
			g2.setColor(Color.WHITE);
			g2.fillRect(0, 0, (int)pf.getWidth(), (int)pf.getHeight());
			g2.translate(pf.getImageableX(), pf.getImageableY());
			g2.setRenderingHint(
					RenderingHints.KEY_TEXT_ANTIALIASING, 
					RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			Font font = new Font("MS ゴシック", Font.PLAIN , 20);
			g2.setFont(font);
			g2.setColor(Color.LIGHT_GRAY);
			g2.drawLine(
					0, 
					(int) pf.getImageableHeight()/2, 
					(int) pf.getImageableWidth(), 
					(int) pf.getImageableHeight()/2);
			g2.drawLine(
					(int) pf.getImageableWidth()/2, 
					(int) 0, 
					(int) pf.getImageableWidth()/2, 
					(int) pf.getImageableHeight());
			FontMetrics fm = g2.getFontMetrics(font);
			String str = "プリンターを指定して印刷";
			int strW = fm.stringWidth(str);
			int strH = fm.getHeight();
			int x = (int)pf.getImageableWidth()/2 - strW/2;
			int y = (int)pf.getImageableHeight()/2  - strH/2 + fm.getMaxAscent();
			g2.setColor(Color.RED);
			g2.drawString(str, x, y);
			return Printable.PAGE_EXISTS;
		}
	}
}
  

プログラムの実行結果

プログラムの通り「プリンターを指定して印刷」という文字列を領域中央に描画することができました。

関連記事

Javaでプリンター名を指定して画像を印刷する【ライブラリなし】

Java標準機能でプリンター名を指定して画像を印刷する方法についての紹介です。

関連記事

Javaで印刷プレビューを表示する

Javaで印刷プレビューを表示するライブラリを作成しましたので、ご紹介です。

関連記事

Javaで文字列を描画する【Graphics】

Java(Graphics)で文字列を描画する際の描画位置の指定方法と、サンプルコードです。