(2)JISの封筒を指定する方法
定形郵便の最大サイズである長形3号、A4を折らずに入れる角形2号などの封筒は、MediaSizeにサイズが登録されているのにMediaSizeNameには登録されていないので使うことができません。これは謎な仕様です。
ところが、プリンタダイアログの「ページ設定」のページでメディアサイズを選択すると、候補に「長形3号」を見つけることができます。OSとプリンタの機種によりこの候補は変わりますから、この情報はJavaの中ではなくプリンタドライバの中にあると考えられます。例えば、Windows 10上のCanon MP493では次のようになります。
Linux上では名前が「Japanese long envelope #3」となりますが、これが長形3号です。同じプリンタでも内容に差があるのはドライバの設計者が異なるからでしょう。長形3号というJIS規格(読み方は「なががた」)ですが、プリンタやそのドライバで名前が異なるのは困ったことです。
Javaからlookupメソッドで使えるプリンタを探すという機能があるわけですから、プリンタドライバからの情報を得る方法はあるはずと考えて、改めてAPIマニュアルからメソッドを探しました。どうやらPrinterServiceインターフェースのgetSupportedAttributeValues()メソッドが使えそうです。
使える用紙の情報をプリンタから取得する
getSupportedAttributeValues()メソッドはjavax.printパッケージのPrintServiceにあるメソッドです。PrintRequestAttributeSetに指定するような属性のうち、指定したプリンタがサポートしているものを列挙してくれます。長形3号が使えるようになるだけではなく、A3が印刷できるプリンタを特定することもできるかもしれません。
getSupportedAttributeValues
Object getSupportedAttributeValues(Class<? extends Attribute> category,
DocFlavor flavor,
AttributeSet attributes)
第一引数はAttributeインターフェースを持ったクラス。今回はMedia.classにします。
第二引数はDocFlavor。今回はnullにします。
第三引数はAttributeSet。今回はこれもnullにします。MediaSizeNameに登録されていないので長形3号と指定できずに苦労しているのです。
戻値はObjectです。調べる印刷属性が異なると戻値の型も変わるからですが、あまりスマートでない使い方になります。
具体的にはこういうことです。svをPrintServiceのインスタンスとして、次のようにします。
Media[] meds = (Media[])sv.getSupportedAttributeValues(Media.class, null, null);
引数をMedia.classにすると、プリンタがサポートする属性のうち、Media.classな要素が格納されたObjectの配列が戻ってきます。それをMediaクラスの配列にキャストしてMediaクラスの配列に代入します。
Mediaクラスにはさらにサブクラスがあります。このMedia[]の要素は、MediaSizeNameかMediaNameかMediaTrayかのどれかです。実際にはほとんどがMediaSizeNameです。全部の要素を調べて、それがMediaSizeNameだった時に、さらにMediaSizeを求めます。
for (Media med : meds) {
if(med instanceof MediaSizeName){
MediaSizeName msn = (MediaSizeName)med;
MediaSize ms = MediaSize.getMediaSizeForName(msn);
MediaSizeが分かれば、これからgetX()とgetY()で、次のように用紙の縦横の長さがmm単位で分かるということです。
float msx = ms.getX(MediaSize.MM); float msy = ms.getY(MediaSize.MM);
このようにして、それぞれのPrintServiceから使用できるすべての用紙の縦横の長さと、そのMediaSizeNameを取得できます。縦横の長さで比較して、一致したらそのMediaSizeNameを使うという段取りになります。
このMediaSizeNameにはjavax.print.attribute.standardにないものも含まれています。toString()メソッドで文字列表現を得ることができます。しかし、長形3号の場合、MediaSizeNameは「長形3号」であったり、「Japanese long envelope #3」であったりと、プリンタに依存しますから、名前で特定することができません。
getSupportedAttributeValues()メソッドを使うプログラム
どのようにデータが得られるかテストプログラムを書いてみます。これは、OSやプリンタ、プリンタドライバ、あるいはJavaのバージョンが変わった時に再検証するためでもあります。
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
/**
SupportedValuesTest.java
すべてのプリンタについて.getSupportedAttributeValues()から
MediaSizeNameの一覧を取得。
MediaSizeを経由して用紙のX,Yを取得し、
指定の大きさに近い用紙名を書き出す。
起動時引数により、長形3号,葉書,A3,A4に切り替える。
2019-07-18
Adachi
*/
public class SupportedValuesTest {
public static void main(String[] args) {
float x = 0;
float y = 0;
int job = 1;
if (args.length==0) {
System.out.println("1:chou_3 2:postcard 3:A3 4:A4");
}
if (args.length>0) job = Integer.parseInt(args[0]);
if(job==1) {x=120f; y=235f;} //chou_3
if(job==2) {x=100f; y=148f;} //hagaki
if(job==3) {x=297f; y=420f;} //A3
if(job==4) {x=210f; y=297f;} //A4
PrintRequestAttributeSet rqset = new HashPrintRequestAttributeSet();
DocFlavor flv = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintService[] svs = PrintServiceLookup.lookupPrintServices(flv,rqset);
for(PrintService sv:svs){
System.out.println(sv.getName());
printerSupportedAtrributes(sv,x,y);
}
}
public static void printerSupportedAtrributes(PrintService sv,float x,float y){
MediaSizeName retmsn = null;
Media[] meds = (Media[])sv.getSupportedAttributeValues(Media.class, null, null);
for (Media med : meds) {
if(med instanceof MediaSizeName){
MediaSizeName msn = (MediaSizeName)med;
MediaSize ms = MediaSize.getMediaSizeForName(msn);
if(ms!=null){
float msx = ms.getX(MediaSize.MM);
float msy = ms.getY(MediaSize.MM);
if(2>=Math.abs(msx-x) && 2>=Math.abs(msy-y)){
System.out.print(" "+msx+" "+msy+" : ");
System.out.println(msn.toString()+"("+msn.getValue()+")");
}
}
}
}
}
}
実行結果(Windows 10)
起動時の引数を1として幅と高さが120mmと235mmつまり長形3号を探しています。
PS Z:\java\print01> java SupportedValuesTest 1 OneNote Microsoft XPS Document Writer 120.0 235.0 : 封筒 長形 3 号(20) Microsoft Print to PDF Fax 120.0 235.0 : 封筒 長形 3 号(20) EPSON PX-1700F 120.0 235.0 : 長形3号封筒 120 x 235 mm(101) Canon MP493 series Printer 120.0 235.0 : 長形3号(112) Canon Inkjet iP9910 120.0 235.0 : 長形3号(112)
OneNoteからFaxまでは仮想的なプリンタで、OneNoteと"Microsoft Print to PDF"には合致したものがなかったということです。
PX-1700Fで、見つかったのは1つで、幅、高さが120.0,235.0、NediaSizeNameを文字列化すると「長形3号封筒 120 x 235 mm」です。
MP493 series Printerでは、見つかったのはやはり1つで、幅、高さが120.0,235.0、NediaSizeNameを文字列化すると「長形3号」です。
実行結果(Linux)
Linuxでは接続されている物理的なプリンタの2台のみ表示されます。
縦横の長さが、きりの良い数値でありません。
adachi@debian64:~$ java SupportedValuesTest 1 Canon_MP493_series 119.944 234.95 : Japanese long envelope #3(83) EPSON_EPSON_PX-1700F 120.015 234.985 : Envelope 120 x 235 mm(887)
WindowsでもLinuxでも
(101)などのカッコ内の数値はgetValue()で調べた整数値で、この整数値がMediaSizeNameからMediaSizeを得る時のキーになっているようです。この整数値はJavaの標準にあるMediaSizeNameではプリンタが異なっても同一ですが、ないものはプリンタごとに異なります。また、OSが再起動されるなどで異なる値が割り当てられます。
どちらにしても、印刷時には見つかったMediaSizeNameと、MediaSizeから計算したMediaPrintableAreaをPrintRequestAttributeSetに加えたものを指定して印刷すればうまく行きます。
葉書、A3、A4に適用してみる
葉書、A3、A4については、getSupportedAttributeValues()メソッドを使わなくてもMediaSizeNameを指定できるのですが、上記の「SupportedValuesTest.java」を使って調べてみます。1つのプリンタに対してサイズが合致するMediaSizeNmaeが複数になる場合があるので、MediaSizeNmaeのリストとして表を作っています。仮想プリンタは省いてあります。getSupportedAttributeValues()を使うにあたって考慮すべき点が見えてきます。
葉書
Windows 10の場合です。PX-1700Fは葉書の100x148に近い用紙が2つ合致します。98mmは2mm以内なので「洋形3号封筒 98 x 148 mm」も合致と判断されました。
| PrinterService | MediaSizeNmaeのリスト |
|---|---|
| EPSON PX-1700F |
100.0 148.0 : japanese-postcard(48) 98.0 148.0 : 洋形3号封筒 98 x 148 mm(104) |
| Canon MP493 series Printer | 100.0 148.0 : japanese-postcard(48) |
| Canon Inkjet iP9910 | 100.0 148.0 : japanese-postcard(48) |
Linuxの場合です。どういうわけかMP493に同じものが3つ出てきます。
| PrinterService | MediaSizeNmaeのリスト |
|---|---|
| Canon_MP493_series |
100.0 148.0 : japanese-postcard(48) 100.0 148.0 : japanese-postcard(48) 100.0 148.0 : japanese-postcard(48) |
| EPSON_EPSON_PX-1700F |
100.0 148.0 : japanese-postcard(48) 98.002 147.99 : Envelope 98 x 148 mm(891) |
japanese-postcardはもともとのMediaSizeNameに名前も値も定義されているので、OSやプリンタが異なってもgetValue()の値は(48)と同一になると考えられます。
A3の場合
Windows 10です。Canon MP493 はA4までのプリンタですが、A3に名乗りを上げています。これではA3非対応とできません。
| PrinterService | MediaSizeNmaeのリスト |
|---|---|
| EPSON PX-1700F | 297.0 420.0 : iso-a3(3) |
| Canon MP493 series Printer | 297.0 420.0 : iso-a3(3) |
| Canon Inkjet iP9910 |
297.0 420.0 : iso-a3(3) 297.0 420.0 : ファインアート A3(128) |
Linuxの場合です。MP493は対応しないと分かります。
| PrinterService | MediaSizeNmaeのリスト |
|---|---|
| Canon_MP493_series | |
| EPSON_EPSON_PX-1700F | 297.0 420.0 : iso-a3(3) |
A4の場合
Windows 10です。ユーザー定義というのは、A4にしておいて、余白を大きくとって調整するという作戦なのかもしれません。
| PrinterService | MediaSizeNmaeのリスト |
|---|---|
| EPSON PX-1700F |
210.0 297.0 : iso-a4(4) 210.0 297.0 : ユーザー定義サイズ(67) |
| Canon MP493 series Printer |
210.0 297.0 : iso-a4(4) 210.0 297.0 : ユーザー定義用紙...(122) |
| Canon Inkjet iP9910 |
210.0 297.0 : iso-a4(4) 210.0 297.0 : ファインアート A4(127) 210.0 297.0 : ユーザー定義用紙...(122) |
Linuxです。単純に1つずつです。
| PrinterService | MediaSizeNmaeのリスト |
|---|---|
| Canon_MP493_series | 210.0 297.0 : iso-a4(4) |
| EPSON_EPSON_PX-1700F | 210.0 297.0 : iso-a4(4) |
困った。印刷できる封筒は意外に少ない
さらに長形3号以外のJIS封筒についてもMediaSizeNameを取得できるか「SupportedValuesTest.java」を使って確認してみました。ところが、多くの封筒でうまく行きませんでした。そこで、JavaのMediaSizeに登録されたJIS封筒24種について、getSupportedAttributeValues()メソッドでMediaSizeNameが得られるかを調べて表にしました。
長形、角形、洋形に分けてまとめています。Win/Linの欄にP,M,Iなどが書かれているものが、幅×高からMediaSizeNameが取得できたものです。
表の詳しい説明は以下のとおりです。
-
名前:
JIS,旧JIS,および類する封筒の名前。 -
幅×高:
用紙のサイズ。単位はmm。Javaの仕様に従い短辺を幅にしてあります。 -
投入書類・用途:
どのような大きさかの目安にするため投入できる用紙を折り方と共に紹介します。
ISO A3 297×420(mm)、ISO A4 210×297(mm)、ISO A5 148×210(mm)、
JIS B4 257×364(mm)、JIS B5 182×257(mm)、JIS B6 128×182(mm)。 -
規格:
"JIS"が現行JIS(JIS S 5502:2014)に規定されているもの。
現在のJISにあるのは18種だけです。旧JISについては一次情報を調べていないので改定の時期は正確ではありません。 -
登録MS:
JavaのMediaSizeに登録されている名前。 -
Win/Lin:
幅×高からMediaSizeNameを取得できるかどうか。WinはWindows 10上、LinはLinux上。
取得できたプリンタをP,M,Iの英字一文字で表してあります。
P:PX-1700F、M:MP-493、I:iP9900(Winのみ)、-:対応しない。 -
登録MSN:
MediaSizeNameに定数フィールド値が用意されているものの名前です。
プリンタから得られるMediaSizeNameではなくjavax.print.attribute.standardにある近いサイズのMediaSizeNameです(≒は近い、=は同等)。
ここに名前が入っていても「Win/Lin」の欄にPMIのどれかがない場合は、印刷に指定できません。
そもそも、封筒への印刷が必要かどうかや、OSやプリンタのドライバの違いもあり個別に対応すべき事態になるので、調査の方法も書いておきます。封筒への印刷が必要な場合に参考になるように願っています。
長形
長形は幅に対して2倍以上の高さがある封筒とされています。
| 名前 | 幅×高 |
投入書類 |
規格 | 登録MS | Win | Lix | 登録MSN |
|---|---|---|---|---|---|---|---|
| 長形 1号 | 142×332 | A3横3折 |
旧JIS |
CHOU_1 | --- | -- | |
| 長形 2号 | 119×277 |
B4横4折・ |
JIS | CHOU_2 | --- | -- | ≒NA_NUMBER_12_ENVELOPE(2.4) |
| 長形 3号 | 120×235 |
A4横3折・ |
JIS | CHOU_3 | PMI | PM | |
| 長形 30号 | 92×235 | A4横4折 | CHOU_30 | --- | -- | ||
| 長形 4号 | 90×205 | B5横4折 | JIS | CHOU_4 | PMI | PM | |
| 長形 40号 | 90×225 | A4横4折 | JIS | CHOU_40 | --- | -- | |
| 長形 5号 | 90×185 | B5横4折 |
旧JIS |
--- | -- | ||
| 長形 6号 | 110×220 |
A4横3折・ |
JIS |
-MI | -M | =ISO_DESIGNATED_LONG |
getSupportedAttributeValues()メソッドでMediaSizeNameが得られるものはWin/Linの欄にP,M,Iなどが書かれているものです。
角形
角形は幅に対して2倍以下の高さの(細長くない)封筒とされています。
| 名前 | 幅×高 |
投入書類 |
規格 | 登録MS | Win | Lix | 登録MSN |
|---|---|---|---|---|---|---|---|
| 角形 0号 | *287×382 | B4判 | JIS | KAKU_0 | --- | -- | |
| 角形 1号 | *270×382 | B4判 |
旧JIS(〜 |
KAKU_1 | --- | -- | |
| 角形 2号 | *240×332 | A4判 | JIS | KAKU_2 | P-- | P- | |
| 角形20号 | *229×324 | A4判 | JIS | KAKU_20 | --- | -- | =ISO_C4 |
| 角形 3号 | *216×277 |
B5判・ |
JIS | KAKU_3 | --- | -- | |
| 角形 4号 | 197×267 | B5判 | JIS | KAKU_4 | --- | -- | |
| 角形 5号 | 190×240 |
A5判・ |
JIS | KAKU_5 | --- | -- | |
| 角形 6号 | 162×229 | A5判 | JIS | KAKU_6 | --- | -M | =ISO_C5 |
| 角形 7号 | 142×205 |
B6判・ |
JIS | KAKU_7 | --- | -- | |
| 角形 8号 | 119×197 | 給料 | JIS | KAKU_8 | --- | -- | |
| 角形A4号 | *228×312 | A4判 | KAKU_A4 | --- | -- |
getSupportedAttributeValues()メソッドでMediaSizeNameが得られるものはWin/Linの欄にP,M,Iなどが書かれているものです。極めて少なくなっています。
幅×高の幅に*印がついて太字になっているのは、A4プリンタでは入らないものです。
洋形
洋形は長辺側に開口部がある封筒とされています。
| 名前 | 幅×高 |
投入書類 |
規格 | 登録MS | Win | Lix | 登録MSN |
|---|---|---|---|---|---|---|---|
| 洋形 1号 | 120×176 |
カード, |
JIS | YOU_1 | P-- | PM | |
| 洋形 2号 | 114×162 |
A4縦横4折 |
JIS | YOU_2 | P-- | PM | =ISO_C6 |
| 洋形 3号 | 98×148 | B5縦横4折 |
旧JIS(〜 |
YOU_3 | P-- | P- | |
| 洋形 4号 | 105×235 |
A4横3折, |
JIS | YOU_4 | PMI | PM | |
| 洋形 5号 | 95×217 | A5縦2折 |
旧JIS(〜 |
YOU_5 | --- | -- | |
| 洋形 6号 | 98× 190 | B5横3折 | JIS | YOU_6 | -MI | -M | ≒MONARCH_ENVELOPE(0.5) |
| 洋形 7号 | 92×165 | A5横3折 |
旧JIS(〜 |
YOU_7 | --- | -- | ≒PERSONAL_ENVELOPE(0.1) |
getSupportedAttributeValues()メソッドでMediaSizeNameが得られるものはWin/Linの欄にP,M,Iなどが書かれているものです。P:PX-1700F、M:MP-493、I:iP9900(Winのみ)ですが、洋形はプリンタにより対応に差がある封筒です。
