發表於 程式分享

使用word功能變數,convert word to pdf,並解決中文顯示問題

使用xdocreport套件:https://github.com/opensagres/xdocreport

1.word / Ctrl + F9 => 編輯功能變數 => 設定"Merge Field",欄位名稱請加$

1.PNG1.PNG

2.程式碼

import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
import fr.opensagres.xdocreport.converter.ConverterTypeTo;
import fr.opensagres.xdocreport.converter.ConverterTypeVia;
import fr.opensagres.xdocreport.converter.Options;
import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.itext.extension.font.ITextFontRegistry;
import fr.opensagres.xdocreport.samples.docxandvelocity.model.Project;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;

public class Convert2PDF {
    public static void main(String[] args) throws DocumentException {
        try {             
              InputStream in = new FileInputStream(new File("A.docx"));
              IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Velocity);
              IContext context = report.createContext();
              Project project = new Project("測試XDocReport");
              context.put("project", project);
              //功能變數替換
              context.put("fieldName1", "-1.FieldFirst中文");
              context.put("titleName2", "-2.中文MergeTitleTwo");
              context.put("parameter1", "-3.row1,value3");
              context.put("parameter2", "-4.row2,value1");
              context.put("parameter3", "-5.red,row3,value2");
             
              OutputStream out = new FileOutputStream(new File("A_Out.pdf"));
              PdfOptions pdfOptions = PdfOptions.create();
              pdfOptions.fontProvider( new ITextFontRegistry()
              {
                  public Font getFont( String familyName, String encoding, float size, int style, Color color )
                  {
                      try
                      {
                          BaseFont bfChinese =
                              BaseFont.createFont( "font/kaiu.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED );
                          Font fontChinese = new Font( bfChinese, size, style, color );
                          if ( familyName != null )
                              fontChinese.setFamily( familyName );
                          return fontChinese;
                      }
                      catch ( Throwable e )
                      {
                          e.printStackTrace();
                          // An error occurs, use the default font provider.
                          return ITextFontRegistry.getRegistry().getFont( familyName, encoding, size, style, color );
                      }
                  }
    
              } );
              
              Options options = Options.getTo(ConverterTypeTo.PDF).via(ConverterTypeVia.XWPF).subOptions(pdfOptions);
              report.convert(context, options, out);
             
              //加密            
              Document pdfDocument = new Document();
              PdfCopy pdfCopy = new PdfCopy(pdfDocument, new FileOutputStream("A_Out2.pdf"));
              String pwd = "testpwd";
              pdfCopy.setEncryption(pwd.getBytes(), pwd.getBytes(), 0,
                        PdfWriter.ENCRYPTION_AES_128);
              
              PdfReader pdfReader = new PdfReader("A_Out.pdf");
              int numberPage = pdfReader.getNumberOfPages();
              pdfDocument.open();
              for (int iPage = 1; iPage <= numberPage; iPage++) {
                  pdfCopy.addPage(pdfCopy.getImportedPage(pdfReader, iPage));
              }
              pdfDocument.close();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (XDocReportException e) {
             e.printStackTrace();
         }
    }
}

3.執行後結果:開啟"A_Out2.pdf"

1) 顯示輸入密碼

1.PNG

2) 顯示內容

1

補充:pdf檔案加密,需於執行此程式時,請下載 bcprov-jdk16-146.jar (http://www.java2s.com/Code/Jar/b/Downloadbcprovjdk16146jar.htm),
執行時classpath加上bcprov-jdk16-146.jar

補充說明:我使用的xdocReport是使用iText2,原本是要用iText7開發套表成pdf檔,但需購買pdf writer,且iText7/iText5應該需要購買商業版權,關於iText license說明如下-https://zh.wikipedia.org/wiki/IText說明請參考:

iTextSharp 4.1.6/iText 4.2.0之前的版本是在MPLLGPL許可證下分發的,
允許用戶在閉源軟體專案中使用。
2009年底,iText第5版發布,其許可證被更換為Affero通用公共許可證第3版。 
那些不願意提供其原始碼的專案,可以購買iText第5版的商業許可,
或沒有任何變化的繼續使用iText的以前版本(其許可證更寬鬆)。
然而,開發商Bruno Lowagie警告說,
第5版之前的版本可能包含非LGPL授權的代碼,
因而以前版本的閉源專案的用戶可能需要為侵犯版權負責。
雖然AGPL庫可以連結到GPL的程式,但AGPL許可證與GPL許可證不相容。

發表留言