2010年9月20日月曜日

用紙定義を使ってPDF文書を作成する:(2)

PDFファイルの作成
iText による PDF 作成の基本的なステップは次のようなものです。
    public void createPdf(String filename) throws IOException, DocumentException {
       // step 1 Document を作成
       Document document = new Document();
       // step 2 PdfWriter を取得
       PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));

       // step 3 Document をオープン
       document.open();
       PdfContentByte cb = writer.getDirectContent();
      
       // step 4 コンテンツを出力
       ...

       // step 5 Document をクローズ
       document.close();
   }


宛名印刷クラスを作成して、上記の手順で実際に宛名PDFを作成します。
/**
* 宛名PDF作成クラス.
*/
public class AtenaPDF {

   //縦書き時に見栄えをよくするため住所の数字を漢数字に変換するのに使用.
   private static Map<String, BaseFont> baseFontMap = new HashMap<String, BaseFont>();
  
   private static final String YOKO_SUUJI = "12345678901234567890";
   private static final String TATE_SUUJI = "一二三四五六七八九〇一二三四五六七八九〇";
  
   private static final String ITEM_ZIP = "1";
   private static final String ITEM_JUSYO1 = "2";
   private static final String ITEM_JUSYO2 = "3";
   private static final String ITEM_JUSYO3 = "4";
   private static final String ITEM_SIMEI = "5";

   ...

   /**
    * 宛名PDFの作成.
    * 選択された連絡先ごとの宛名を、用紙定義情報で指定された用紙に出力する.
    *
    * @param outputName 出力する PDFファイル(絶対パス)
    * @param w      用紙の幅
    * @param h      用紙の高さ
    * @param pageDef  用紙定義
    * @param selection      選択された連絡先
    * @param monitor  進捗モニタ
    */
   public static void createPdf(String outputName, PageDef pageDef,
            IStructuredSelection selection, String type, IProgressMonitor monitor)
               throws CoreException, DocumentException, IOException {

       //スキャン画像のイメージと DPI から用紙サイズを求める
       ImageData imageData = new ImageData(pageDef.getImageFileName());
       float width = imageData.width * 72 / pageDef.getScanDPI();
       float height = imageData.height * 72 / pageDef.getScanDPI();
       Document document = new Document(new Rectangle(width, height), 0, 0, 0, 0);

       PdfWriter writer = PdfWriter.getInstance(document,  new FileOutputStream(outputName));
       writer.setViewerPreferences(PdfWriter.PageLayoutSinglePage);
       document.open();
      
       PdfContentByte cb = writer.getDirectContent();

       //先頭のページだけ背景画像を追加
       Image jpg = Image.getInstance(pageDef.getImageFileName());
       jpg.scaleAbsolute(document.getPageSize().getWidth(), document.getPageSize().getHeight());
       jpg.setAbsolutePosition(0,0);
       document.add(jpg);

       //先頭ページを作成
       createPage(pageDef, height, (Contact)selection.getFirstElement(), cb, type);
       document.newPage();

       //選択された連絡先の数だけページを作成
       for (Object obj : selection.toArray()) {
           Contact contact = (Contact) obj;
           createPage(pageDef, height, contact, cb, type);
           document.newPage();
       }
       document.close();
   }
  
   private static void createPage(PageDef pageDef, float height, Contact contact,
                       PdfContentByte cb, String type) throws DocumentException, IOException {
       BaseFont bfHifun = BaseFont.createFont("KozMinPro-Regular", "Identity-V", false);
       for (ItemDef item : pageDef.getItemList()) {
           String[] fontdt = item.getFontElement();
           String fontName = fontdt[ItemDef.E_NAME];
           float size = Integer.parseInt(fontdt[ItemDef.E_SIZE]);
           float x = item.getX();
           float y = height - item.getY();
           String text = "";
           if (item.getOkikae().equals("有")) {
               text = getText(contact, item.getId(), type);
           } else {
               text = item.getName();
           }
           if (item.getHoko().equals("縦")) {
               Font fontTate = new Font(getBaseFont(fontName, BaseFont.IDENTITY_V), size);
               VerticalText vt = new VerticalText(cb);
               //縦の場合X座標は中央基準の補正を追加
               vt.setVerticalLayout(x + size/2, y, height, 2, size);
               vt.setAlignment(Element.ALIGN_LEFT); //上詰めにする
               //--- 数字を漢数字に置き換えるバージョン ---
               char[] ch = text.toCharArray();
               for (int i=0; i<ch.length; i++) {
                   String s = new String(ch, i, 1);
                   int n =YOKO_SUUJI.indexOf(s);
                   if (n >=0) {
                       vt.addText(new Chunk(TATE_SUUJI.substring(n,n+1), fontTate));
                   } else    if (s.equals("-") || s.equals("-")) {
                       vt.addText(createHifunChunk(bfHifun, size));
                   } else {
                       vt.addText(new Chunk(s, fontTate));
                   }
               }
               int status = vt.go();
           } else {
               float sp = cb.getCharacterSpacing();
               cb.setFontAndSize(getBaseFont(fontName, BaseFont.IDENTITY_H), size);
               cb.setCharacterSpacing(item.getPitch());
               cb.beginText();
               //横の場合Y座標は下基準の補正を追加
               cb.setTextMatrix(x, y - size / 1.2f);
               cb.showText(text);
               cb.endText();
               cb.setCharacterSpacing(sp);
           }
       }
   }
  
   ...

   private static BaseFont getBaseFont(String fontName, String type) throws DocumentException, IOException {
       //このアプリケーションで可能なフォント名かチェックしてベースフォントを作成
       BaseFont bf = baseFontMap.get(fontName + type);
       if (bf==null) {
           //簡単にするため今は1つのフォント名しかサポートしない
           if (fontName.equals("HG祥南行書体")) {
               bf = BaseFont.createFont("c:\\windows\\fonts\\HGRSNG.TTC,0", type, BaseFont.EMBEDDED);
               baseFontMap.put(fontName + type, bf);
           } else {
               //デフォルトフォント
               bf = BaseFont.createFont("KozMinPro-Regular", "Identity-V", false);
           }
       }
       return bf;
   }
  
   /**
    * @param text
    * @return converted text
    */
   private static Chunk createHifunChunk(BaseFont bf, float fontSize) {
       char[] cc = new char[1];   
       cc[0] = (char)('-' - ' ' + 8720);
       return new Chunk(new String(cc), new Font(bf, fontSize));
   }

  
}


上記の createPage() メソッド内の getText(contact, item.getId(), type) は、項目定義の ID (ITEM_ZIP, ITEM_JUSYO1, ...) に応じて連絡先オブジェクトから住所情報を取得します。 type により、自宅住所と会社住所を識別します。

ポップアップメニューから「宛名印刷(会社)」を実行すると、AtenaPDF.createPdf()を呼んで、指定した場所に会社住所の宛名PDFファイルを作成します。

0 件のコメント: