天天看點

docx4j

docx4j

docx4j介紹

官方網站:http://www.docx4java.org/trac/docx4j

下載下傳位址:http://www.docx4java.org/downloads.html

入門指南:Getting Started guide(PDF)(HTML)

得益于天朝偉大的GFW,docx4j的官方站點有時可能需要挂代理才能通路。

官方介紹:

docx4j is a Java library for creating and manipulating Microsoft Open XML (Word docx, Powerpoint pptx, and Excel xlsx) files. 
It is similar to Microsoft's OpenXML SDK, but for Java. 
docx4j uses JAXB to create the in-memory object representation. 
It is available under the Apache License (v2). 
docx4j was created by Plutext Pty Ltd in 2008 - using OpenXML4J for the OPC piece. Plutext still drives the project, but since then docx4j has benefited from contributions from many individuals. The contributors are listed in docx4j's pom.xml.      

docx4j能做什麼

  1. 打開已存在docx(從檔案系統、SMB/CIFS、使用VFS的WebDAV),pptx,xlsx
  2. 建立新的docx、pptx、xlsx
  3. 程式設計式地操作上面打開的文檔(很顯示)

docx4j特殊的功能支援:

  1. 模版替換;CustomXML綁定
  2. 生産/消費Word2007的xmlPackage(pkg)格式
  3. 作為docx儲存docx到檔案系統(zipped)或者儲存到JCR(unzipped)
  4. 應用轉換,包括常見過濾器
  5. 作為HTML或者PDF導出
  6. 比較文檔、段落或者sdt(内容控件)之間的差異
  7. 字型支援(字型替換及使用任何文檔中嵌入的字型)

具體的使用技巧請看前面提到的幾篇部落格以及docx4j的入門指南,這裡僅列出幾個自己了解而前面部落格沒有提到的使用技巧:合并docx文檔和轉換PDF。

合并多個docx文檔

現在所做的項目中,需要合并多個docx文檔,這讓我糾結了很長一段時間;其實在docx4j的基礎上,作者還提供了合并多個docx文檔的lib,但那是需要商業授權的,是以沒法使用,但後來在docx4j的forum中看到了其他人提供的解決方案,詳情如下:

public InputStream mergeDocx(final List<InputStream> streams)
      throws Docx4JException, IOException {
 
  WordprocessingMLPackage target = null;
  final File generated = File.createTempFile("generated", ".docx");
 
  int chunkId = 0;
  Iterator<InputStream> it = streams.iterator();
  while (it.hasNext()) {
    InputStream is = it.next();
    if (is != null) {
      if (target == null) {
        // Copy first (master) document
        OutputStream os = new FileOutputStream(generated);
        os.write(IOUtils.toByteArray(is));
        os.close();
 
        target = WordprocessingMLPackage.load(generated);
      } else {
        // Attach the others (Alternative input parts)
        insertDocx(target.getMainDocumentPart(),
            IOUtils.toByteArray(is), chunkId++);
      }
    }
  }
 
  if (target != null) {
    target.save(generated);
    return new FileInputStream(generated);
  } else {
    return null;
  }
}
 
// 插入文檔
private void insertDocx(MainDocumentPart main, byte[] bytes, int chunkId) {
  try {
    AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart(
        new PartName("/part" + chunkId + ".docx"));
    afiPart.setContentType(new ContentType(CONTENT_TYPE));
    afiPart.setBinaryData(bytes);
    Relationship altChunkRel = main.addTargetPart(afiPart);
 
    CTAltChunk chunk = Context.getWmlObjectFactory().createCTAltChunk();
    chunk.setId(altChunkRel.getId());
 
    main.addObject(chunk);
  } catch (Exception e) {
    e.printStackTrace();
  }
}      

docx文檔轉換為PDF

在做docx轉換PDF時讓我為難了好長一陣子,因為中文導緻亂碼,官方示例中是有這一部分内容的,但由于注釋太少,是以一直沒有注意到,後來才發現示例的作者将字型相關的兩句代碼注釋掉了:

//  Set up font mapper
//  Mapper fontMapper = new BestMatchingMapper();
//  wordMLPackage.setFontMapper(fontMapper);      

在将這段代碼加上之後,中文亂碼沒有了,但是好像除了“宋體”以外的其它字型還會亂碼,比如:華文行楷、隸書之類的,要解決這些問題,需要多做點工作:

Mapper fontMapper = new IdentityPlusMapper();
fontMapper.getFontMappings().put("華文行楷", PhysicalFonts.getPhysicalFonts().get("STXingkai"));
// 其它中文字型
mlPackage.setFontMapper(fontMapper);
 
// 然後再建立轉換器
PdfConversion conversion = new Conversion(mlPackage);      

完整方法代碼:

/**
 * docx文檔轉換為PDF
 * @param docx docx文檔
 * @param pdfPath PDF文檔存儲路徑
 * @throws Exception 可能為Docx4JException, FileNotFoundException, IOException等
 */
public void convertDocxToPDF(File docx, String pdfPath) throws Exception {
  OutputStream os = null;
  try {
    WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(docx);
//      Mapper fontMapper = new BestMatchingMapper();
    Mapper fontMapper = new IdentityPlusMapper();
    fontMapper.getFontMappings().put("華文行楷", PhysicalFonts.getPhysicalFonts().get("STXingkai"));
    fontMapper.getFontMappings().put("華文仿宋", PhysicalFonts.getPhysicalFonts().get("STFangsong"));
    fontMapper.getFontMappings().put("隸書", PhysicalFonts.getPhysicalFonts().get("LiSu"));
    mlPackage.setFontMapper(fontMapper);
 
    PdfConversion conversion = new org.docx4j.convert.out.pdf.viaXSLFO.Conversion(mlPackage);
    os = new FileOutputStream(pdfPath);
    
    conversion.output(os, new PdfSettings());
  } finally {
    IOUtils.closeQuietly(os);
  }
}      

另外,docx4j還支援通過iTtext将docx文檔轉換為PDF,不過好像隻能支援iText2.X版本,新版本不能用!

其實這樣轉換好像還不夠完美,比如頁眉頁腳、目錄什麼的,都會出亂子;由于項目中word文檔較為複雜,最終沒有采用docx4j做PDF轉換,換成了jacob......

------------------- 消息中間件Rabbitmq ----------------------------------

消息中間件Rabbitmq(01)

消息中間件Rabbitmq(02)

消息中間件Rabbitmq(03)

消息中間件Rabbitmq(04)

消息中間件Rabbitmq(05)

消息中間件Rabbitmq(06)

消息中間件Rabbitmq(07)

------------------- ---------- 雲計算  -------------------------------------

雲計算(1)——docker的前世今生

雲計算(2)—— 體系結構

雲計算(3)—— 容器應用

雲計算(4)—— LAMP

雲計算(5)—— Dockerfile雲計算(6)—— harbor

雲計算(7)—— 網絡

雲計算(8)—— jekins(1)

雲計算(9)—— jekins(2)

關注公衆号 soft張三豐 

繼續閱讀