SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Javaの標準機能だけで実現する帳票印刷

Javaの標準機能だけで印刷する際の用紙のサイズや向き、余白の指定

Javaの標準機能だけで実現する帳票印刷 第2回


  • このエントリーをはてなブックマークに追加

 本稿では、Java SEの標準機能だけを使った帳票印刷の方法を解説します。今回は、用紙のサイズや向き、余白の指定について説明します。また実際に印刷する時には、PrinterJobを使う方法もDocPrintJobを使う方法も同じように使えることを、拡張の歴史を踏まえて説明します。

  • このエントリーをはてなブックマークに追加

はじめに

 第1回でJavaの基本機能だけで文字と罫線を0.1mm単位で位置指定して印刷する方法を紹介しました。0.1mmと書いたのは、72dpiだから解像度が不足するという誤解を解くためです。内部的にはマイクロメートル(µm)単位で扱われているようですので解像度は十分です。

 今回は、用紙のサイズや向き、余白の指定について説明します。プリンタは、あらかじめデフォルトのプリンタとして登録されているものを使用することを想定します。もちろん印刷ダイアログでデフォルト以外のプリンタに変更することは可能です。帳票印刷の用途では対象のプリンタはあらかじめ決まっている場合が多いでしょうからプリンタ選択はこの範囲で十分だと思います。

 Javaには指定した用紙が使えるプリンタを探し出して選択する方法が備わっていることになっていますが、WindowsでA3を印刷できるプリンタを探すとA4プリンタもリストに含まれてしまいます。他にも一般的に解説されていない不具合と思われるものや謎の仕様があるようですので、プリンタの検索と選択については次回に回します。

 Oracle社のサイトにあるドキュメントの中で、印刷についてまとめて書いてある一番新しいものは、「Java印刷サービスAPIユーザー・ガイド」です。これはJavaに印刷サービスが追加されたバージョン1.4の時に書かれたものです。まだSun Microsystems社の時代であったころの機能追加ですからかなり昔ですが、Javaの印刷はその時からほとんど変わっていません。最新のJava 12も全部を確認したわけではありませんが変わっていないようです。手直しをしたほうが良い部分もあるように感じられますが、変更がないということは同じ手法を使い続けられるということでもあり、これはこれで喜ばしいことでもあります。

 Oracle社のJava印刷サービスAPIユーザー・ガイドへのリンクを示しておきます。このリンクはJava 8の日本語版です。今回の連載のプログラムはJava 8で検証していますが12でも問題なくコンパイルできるはずです。Java 8での検証にした理由は仕様が変わっていないことに加え、LinuxのOpenJDKの多くが現在は8であることと、WindowsにおいてもJRE(実行環境)は8であることが多いことからです。

帳票印刷に使える2つの方法

 「Java印刷サービスAPIユーザー・ガイド」では「2Dグラフィックスを印刷する」として書かれているものが、これからやろうとする帳票印刷に相当します。PrinterJobを使う方法とDocPrintJobを使う方法が説明されています。2つの方法を大雑把に表にしてみます。

帳票印刷に使える2つの方法
  方法1 方法2
直接印刷に使うクラス PrinterJob DocPrintJob
正式らしい名称 Java 2D印刷API Java印刷サービスAPI
組み合わされる機能

PageFormat
Paper
(AttributeSet)
(PrintServiceLookup)
(ServiceUI)

AttributeSet
DocFlavor
PrintServiceLookup
ServiceUI
導入年とVer. 1998年 J2SE1.2 2002年 J2SE1.4

 PrinterJobとDocPrintJobは、名前にDocがついているか否かが大きな違いですが、PrinterとPrintの違いもあります。この解説では触れませんが、さらに古い方法でPrintJobというクラスが残っていますので注意が必要です。

 この2つは、Javaの印刷に関する2回の仕様拡張により、それぞれ導入されたものなのですが、拡張の目的が異なります。PreinterJobが導入された時の目玉はグラフィックの解像度の向上でした。そこで'2D'がつきました。DocPrintJobの目玉は必要な機能を持ったプリンタ(印刷サービス)を見つけ出して印刷する機能です。そのためにどんなものを印刷するのか(Doc)とどんな要求をするのか(Request)を伝える方法が必要になりました。これが、DocFlavorとAttributeSetです。

 このようにAttributeSetは、DocPrintJobで印刷するために導入された仕組みですが、同時にPreinterJobも拡張されて、こちらでも使えるようになりました。表に(AttributeSet)と括弧づきなのはこれを表現したつもりです。PrinterJobに組み合わせるAttributeSetは、中心的な役割をしているPrintRequestAttributeSetですが、これによって用紙の指定や余白の指定にPaperやPageFormatを使う必要がなくなり、とても簡単になっています。

 プリンタの検索と選択はPrintServiceLookupとServiceUIというクラスで行います。これもDocPrintJobで印刷するために導入された仕組みですが、PrintreJobにも後からServiceを結びつけるメソッドを追加しているので、PrintreJobとPrintServiceLookup、ServiceUIを組み合わせて利用できるようになっています。

 という事情で、PrinterJobを使う方法もDocPrintJobを使う方法も、帳票印刷の場合はどちらでも同じように使えます。

 プリンタの選択を次回に回した関係で、今回は、PrinterJobを使う方法で説明します。DocPrintJobは選択したServiceから生成するものだからです。しかし、PrintRequestAttributeSetについては使い方が同じですから、後からDocPrintJobに替えることは簡単です。

 DocPrintJobには、2Dグラフィックスを印刷する他に、画像ファイルやPDFファイルのデータを直接印刷する機能があります。「Java印刷サービスAPIユーザー・ガイド」では、これを新機能として強調して解説していますが、この連載でやろうとしているのは2Dグラフィックスによる帳票印刷の方です。

PrinterJobでの印刷

 第1回で紹介したPrinterJobでの印刷はデフォルトプリンタにデフォルトな用紙設定で印刷するものでした。これに、用紙サイズや余白の指定を加えます。

 「SomethingPrintable00.java」で用いた方法はこうでした。

Printable pable = new SomethingPrintable00();
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(pable);
if (pj.printDialog()) {
    try { pj.print(); }
    catch (PrinterException e) {
        System.err.println(e);
    }
}

 これにPrintRequestAttributeSetを使って用紙サイズや余白を指定するには、次のようにします。

Printable pable = new SomethingPrintable00();
//用紙サイズなどの指定をrqsetに集約
PrintRequestAttributeSet rqset = new HashPrintRequestAttributeSet();
rqset.add(new Copies(3)); //3部印刷 
rqset.add(MediaSizeName.ISO_A3); //A3用紙
rqset.add(new MediaPrintableArea(
   10.1f, 10.3f, 276.7f, 399.3f,
   MediaPrintableArea.MM)); //左余白,上余白,描画幅,描画高,単位
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(pable);
//rqsetを指定してダイアログ提示と印刷
if (pj.printDialog(rqset)) {
    try { pj.print(rqset); }
    catch (PrinterException e) {
        System.err.println(e);
    }
}

 これだけで、デフォルトプリンタまたはダイアログで変更するプリンタが、A3用紙で印刷できるなら指示通り印刷されます。

 指示はA3の用紙に左余白10.1mm、上余白10.3mm、印刷幅276.7mm、印刷高399.3mmで同じものを3枚印刷するというものです。このような解説に同じものを複数枚という指定はよく目にします。最も説明することが少なく確実に反映される例だからでしょう。

指定が反映された印刷ダイアログ/印刷部数が3になっている(Windows 10)
指定が反映された印刷ダイアログ/印刷部数が3になっている(Windows 10)

 printDialog()をPrintRequestAttributeSetを引数にして使うと、「ページ設定」のタブが使えます。このタブで用紙サイズと余白(マージン)が伝わっていることを確認できます。

指定が反映された印刷ダイアログ/ページ設定のタブでサイズと余白を確認(Windows 10)
指定が反映された印刷ダイアログ/ページ設定のタブでサイズと余白を確認(Windows 10)

 プログラム中では印刷幅276.7mmとしていましたが、これはA3の短辺が297.0mmなので、297.0-10.1-10.2=276.8として計算して指定したものです。Javaはここから297.0-10.1-276.7=10.2と逆算して右マージンを計算しています。

 環境によってはプリンタがA3に対応しない場合にマージンを少なく調整して印刷領域を確保しようとするかもしれません。そのときはデフォルトのプリンタをA3に対応したものにしておくことで問題を回避できます。

 PrintRequestAttributeSetの指定内容については後でもう少し解説します。

 ちなみに上記のプログラムの例は、前回の「SomethingPrintable00.java」を変更することを想定していますが、実際には下記のimport文の追加が必要になります。

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSizeName;

 面倒なら次のようにしてもいいでしょう。

import javax.print.attribute.*;
import javax.print.attribute.standard.*;

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
用紙サイズや余白を指定する方法の詳細

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
Javaの標準機能だけで実現する帳票印刷連載記事一覧

もっと読む

この記事の著者

安達 順一(アダチ ジュンイチ)

私立高校に理科・情報の教員として勤めていました。Linuxサーバー/クライアントの授業システムを作り、移動プロファイルで運用していました。教員用にもLinuxサーバーを用意し成績処理プログラムを書きました。情報の学校設定科目ではウェブページ制作とjavaのプログラミングの初歩の授業を作りました。情報...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/11670 2019/10/24 21:58

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング