原文标题:Creating Word documents with Docx4j

原文链接:http://blog.iprofs.nl/2012/09/06/creating-word-documents-with-docx4j/

原文作者:lvdpal

发表时间:2012年9月6日

注:第一次翻译博客;由于个人水平不高,而且英语仅有四级水平,所以错误很多,请大家见谅!!!只是国内关于docx4j的博客极少,感觉这篇入门博客挺不错,勉强翻译过来,希望对大家有所帮助。


一段时间之前,我为一个想要在word和excel中作报表的客户提供服务。我以前的项目中生成过PDF文件和CSV文件,但从来没有处理过docx和xlsx文件。这些天了解到MS Office是基于XML的。我不禁想知道是否有一些库来帮助我生成这些文件。经过一番在线搜索,结果表明确实有:Docx4j。我开始去试用这个新库看它能做些什么。

在官方网站上你可以了解到docx4j可以读取、更新、创建docx、xlsx和pptx文档。我只需要生成文档,所以我没有尝试读取和更新文档,但原理是一样的。Docx4j已经自带了不少示例程序,但我发现其中的一些例子同时展示了多样东西或者没有完全展示我需要了解的。所以有不少东西我不得不自己解决。幸运的是docx4j严格遵循Office Open XML标准,所以还不算太难。总而言这,我对这个库所提供的功能非常满意。

在这个博客中我会展示一些我试用docx4j生成docx文档时创建的例子:

一些提示

在真正示例开始之前有几处提示。首先,在使用docx创建文档的时候,看看你使用word软件创建文档时生成的xml。当你使用一个ZIP压缩工具(例如7zip)打开一个docx文件时会找到这些XML文件。看一下都是些什么样的文件以及它们包含了哪些信息。通常情况下,如果你想得到什么东西,可以通过查看Word软件自己生成了什么而从中得到很多帮助。

其次,去看一下 the Office Open Specification

现在让我们来看一些代码。

用一些文本创建文档

最简单的例子就是创建一个新word文档并向其中添加一些文本内容。

运行下面代码:

  1. WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
  2. wordMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!");
  3. wordMLPackage.save(new java.io.File("src/main/files/HelloWord1.docx"));

结果生成一个如下所示的文件:

这里发生的就是一个word文档由一个带有文档部件的包组成。Docx4j提供一个创建包的工具方法(第1行);然后你可以从这个包中获取主文档部件并向其中添加一个文本段落(第2行);最后将这个包保存(第3行)。就这么简单,当然,如果你想做不仅仅是向文档中添加一些文本内容,那么你需要做更多的工作。

添加带样式的文本

然而即使添加带样式的文本也并不需要做过多的工作,不是向文档添加一个普通的文本段落,而是只需要添加一个带样式的段落。

 
  1. WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
  2. wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title", "Hello Word!");
  3. wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Subtitle","This is a subtitle!");
  4. wordMLPackage.save(new java.io.File("src/main/files/HelloWord2.docx"));

添加表格

当我们想添加一个表格时,情况开始变得复杂一些。直到现在我们的代码都如此简单以至于不需要拆分到多个方法中,所以我仅仅只展示了代码中相关的数行。但这个示例我们需要第二个方法,所以我会展示整个类。

 
  1. public class AddingATable {
  2. private static WordprocessingMLPackage  wordMLPackage;
  3. private static ObjectFactory factory;
  4. public static void main (String[] args) throws Docx4JException {
  5. wordMLPackage = WordprocessingMLPackage.createPackage();
  6. factory = Context.getWmlObjectFactory();
  7. Tbl table = factory.createTbl();
  8. Tr tableRow = factory.createTr();
  9. addTableCell(tableRow, "Field 1");
  10. addTableCell(tableRow, "Field 2");
  11. table.getContent().add(tableRow);
  12. wordMLPackage.getMainDocumentPart().addObject(table);
  13. wordMLPackage.save(new java.io.File("src/main/files/HelloWord4.docx"));
  14. }
  15. private static void addTableCell(Tr tableRow, String content) {
  16. Tc tableCell = factory.createTc();
  17. tableCell.getContent().add(
  18. wordMLPackage.getMainDocumentPart().createParagraphOfText(content));
  19. tableRow.getContent().add(tableCell);
  20. }
  21. }

我们再一次创建了word包,只是这一次我们将其保存为一个属性,从而我们可以在第二个方法中访问它。然后我们同样创建了一个对象工厂(ObjectFactory),这是一个帮助我们创建本例中所需要的具体对象的工具类,例如表格、表格行及表格列等具体对象。

然后我们创建了表格,创建了行并且在行中添加了两个单元格。最后我们将行添加到表格中,将表格添加到主文档部件并且将包保存。

给表格添加边框

现在我们拥有了一个表格,让我们给它添加一些边框。这需要深入研究一下表格的结构。

 
  1. public class TableWithBorders {
  2. private static WordprocessingMLPackage  wordMLPackage;
  3. private static ObjectFactory factory;
  4. public static void main (String[] args) throws Docx4JException {
  5. wordMLPackage = WordprocessingMLPackage.createPackage();
  6. factory = Context.getWmlObjectFactory();
  7. Tbl table = createTableWithContent();
  8. addBorders(table);
  9. wordMLPackage.getMainDocumentPart().addObject(table);
  10. wordMLPackage.save(new java.io.File(
  11. "src/main/files/HelloWord5.docx") );
  12. }
  13. private static void addBorders(Tbl table) {
  14. table.setTblPr(new TblPr());
  15. CTBorder border = new CTBorder();
  16. border.setColor("auto");
  17. tborder.setSz(new BigInteger("4"));
  18. border.setSpace(new BigInteger("0"));
  19. border.setVal(STBorder.SINGLE);
  20. TblBorders borders = new TblBorders();
  21. borders.setBottom(border);
  22. borders.setLeft(border);
  23. borders.setRight(border);
  24. borders.setTop(border);
  25. borders.setInsideH(border);
  26. borders.setInsideV(border);
  27. table.getTblPr().setTblBorders(borders);
  28. }
  29. private static Tbl createTableWithContent() {
  30. Tbl table = factory.createTbl();
  31. Tr tableRow = factory.createTr();
  32. addTableCell(tableRow, "Field 1");
  33. addTableCell(tableRow, "Field 2");
  34. table.getContent().add(tableRow);
  35. return table;
  36. }
  37. private static void addTableCell(Tr tableRow, String content) {
  38. Tc tableCell = factory.createTc();
  39. tableCell.getContent().add(
  40. wordMLPackage.getMainDocumentPart().
  41. createParagraphOfText(content));
  42. tableRow.getContent().add(tableCell);
  43. }
  44. }

首先我们创建了一个默认颜色(黑色)、粗细尺寸为4、间距为0的单线边框的边框组件(Border component),然后边框被应用到表格的四周以及表格内部水平和垂直的边框。随后我们将边框应用到表格;所有其它的代码与前面的示例一样。

给表格添加样式

接下来的问题--给表格添加样式让我忙活了一阵子,我们的客户想要在表格中使用粗体文本并且需要多种大小的字体。

这个示例程序有点复杂,注释和代码交织在一起。

 
  1. public class TableWithStyledContent {
  2. private static WordprocessingMLPackage  wordMLPackage;
  3. private static ObjectFactory factory;
  4. /**
  5. *  跟前面的做的一样, 我们再一次创建了一个表格, 并添加了三个单元格, 其中有两个
  6. *  单元带有样式. 在新方法中我们传进表格行, 单元格内容, 是否为粗体及字体大小作
  7. *  为参数. 你需要注意, 因为the Office Open specification规范定义这个属性是半个
  8. *  点(half-point)大小, 因此字体大小需要是你想在Word中显示大小的两倍,
  9. */
  10. public static void main (String[] args) throws Docx4JException {
  11. wordMLPackage = WordprocessingMLPackage.createPackage();
  12. factory = Context.getWmlObjectFactory();
  13. Tbl table = factory.createTbl();
  14. Tr tableRow = factory.createTr();
  15. addRegularTableCell(tableRow, "Normal text");
  16. addStyledTableCell(tableRow, "Bold text", true, null);
  17. addStyledTableCell(tableRow, "Bold large text", true, "40");
  18. table.getContent().add(tableRow);
  19. addBorders(table);
  20. wordMLPackage.getMainDocumentPart().addObject(table);
  21. wordMLPackage.save(new java.io.File("src/main/files/HelloWord6.docx") );
  22. }
  23. /**
  24. *  本方法创建单元格, 添加样式后添加到表格行中
  25. */
  26. private static void addStyledTableCell(Tr tableRow, String content,
  27. boolean bold, String fontSize) {
  28. Tc tableCell = factory.createTc();
  29. addStyling(tableCell, content, bold, fontSize);
  30. tableRow.getContent().add(tableCell);
  31. }
  32. /**
  33. *  这里我们添加实际的样式信息, 首先创建一个段落, 然后创建以单元格内容作为值的文本对象;
  34. *  第三步, 创建一个被称为运行块的对象, 它是一块或多块拥有共同属性的文本的容器, 并将文本对象添加
  35. *  到其中. 随后我们将运行块R添加到段落内容中.
  36. *  直到现在我们所做的还没有添加任何样式, 为了达到目标, 我们创建运行块属性对象并给它添加各种样式.
  37. *  这些运行块的属性随后被添加到运行块. 最后段落被添加到表格的单元格中.
  38. */
  39. private static void addStyling(Tc tableCell, String content, boolean bold, String fontSize) {
  40. P paragraph = factory.createP();
  41. Text text = factory.createText();
  42. text.setValue(content);
  43. R run = factory.createR();
  44. run.getContent().add(text);
  45. paragraph.getContent().add(run);
  46. RPr runProperties = factory.createRPr();
  47. if (bold) {
  48. addBoldStyle(runProperties);
  49. }
  50. if (fontSize != null && !fontSize.isEmpty()) {
  51. setFontSize(runProperties, fontSize);
  52. }
  53. run.setRPr(runProperties);
  54. tableCell.getContent().add(paragraph);
  55. }
  56. /**
  57. *  本方法为可运行块添加字体大小信息. 首先创建一个"半点"尺码对象, 然后设置fontSize
  58. *  参数作为该对象的值, 最后我们分别设置sz和szCs的字体大小.
  59. *  Finally we'll set the non-complex and complex script font sizes, sz and szCs respectively.
  60. */
  61. private static void setFontSize(RPr runProperties, String fontSize) {
  62. HpsMeasure size = new HpsMeasure();
  63. size.setVal(new BigInteger(fontSize));
  64. runProperties.setSz(size);
  65. runProperties.setSzCs(size);
  66. }
  67. /**
  68. *  本方法给可运行块属性添加粗体属性. BooleanDefaultTrue是设置b属性的Docx4j对象, 严格
  69. *  来说我们不需要将值设置为true, 因为这是它的默认值.
  70. */
  71. private static void addBoldStyle(RPr runProperties) {
  72. BooleanDefaultTrue b = new BooleanDefaultTrue();
  73. b.setVal(true);
  74. runProperties.setB(b);
  75. }
  76. /**
  77. *  本方法像前面例子中一样再一次创建了普通的单元格
  78. */
  79. private static void addRegularTableCell(Tr tableRow, String content) {
  80. Tc tableCell = factory.createTc();
  81. tableCell.getContent().add(
  82. wordMLPackage.getMainDocumentPart().createParagraphOfText(
  83. content));
  84. tableRow.getContent().add(tableCell);
  85. }
  86. /**
  87. *  本方法给表格添加边框
  88. */
  89. private static void addBorders(Tbl table) {
  90. table.setTblPr(new TblPr());
  91. CTBorder border = new CTBorder();
  92. border.setColor("auto");
  93. border.setSz(new BigInteger("4"));
  94. border.setSpace(new BigInteger("0"));
  95. border.setVal(STBorder.SINGLE);
  96. TblBorders borders = new TblBorders();
  97. borders.setBottom(border);
  98. borders.setLeft(border);
  99. borders.setRight(border);
  100. borders.setTop(border);
  101. borders.setInsideH(border);
  102. borders.setInsideV(border);
  103. table.getTblPr().setTblBorders(borders);
  104. }
  105. }

纵向合并单元格

有时你想要一个三列的表格,其中第一列将多行组合在一起。

 
  1. package com.zyh.sample.docx4j;
  2. public class TableWithMergedCells {
  3. private static WordprocessingMLPackage  wordMLPackage;
  4. private static ObjectFactory factory;
  5. /**
  6. *  创建一个带边框的表格并添加四个带内容的行, 然后将表格添加到文档并保存
  7. */
  8. public static void main (String[] args) throws Docx4JException {
  9. wordMLPackage = WordprocessingMLPackage.createPackage();
  10. factory = Context.getWmlObjectFactory();
  11. Tbl table = factory.createTbl();
  12. addBorders(table);
  13. addTableRowWithMergedCells("Heading 1", "Heading 1.1",
  14. "Field 1", table);
  15. addTableRowWithMergedCells(null, "Heading 1.2", "Field 2", table);
  16. addTableRowWithMergedCells("Heading 2", "Heading 2.1",
  17. "Field 3", table);
  18. addTableRowWithMergedCells(null, "Heading 2.2", "Field 4", table);
  19. wordMLPackage.getMainDocumentPart().addObject(table);
  20. wordMLPackage.save(new java.io.File(
  21. "src/main/files/HelloWord9.docx") );
  22. }
  23. /**
  24. *  本方法创建一行, 并向其中添加合并列, 然后添加再两个普通的单元格. 随后将该行添加到表格
  25. */
  26. private static void addTableRowWithMergedCells(String mergedContent,
  27. String field1Content, String field2Content, Tbl table) {
  28. Tr tableRow1 = factory.createTr();
  29. addMergedColumn(tableRow1, mergedContent);
  30. addTableCell(tableRow1, field1Content);
  31. addTableCell(tableRow1, field2Content);
  32. table.getContent().add(tableRow1);
  33. }
  34. /**
  35. *  本方法添加一个合并了其它行单元格的列单元格. 如果传进来的内容是null, 传空字符串和一个为null的合并值.
  36. */
  37. private static void addMergedColumn(Tr row, String content) {
  38. if (content == null) {
  39. addMergedCell(row, "", null);
  40. } else {
  41. addMergedCell(row, content, "restart");
  42. }
  43. }
  44. /**
  45. *  我们创建一个单元格和单元格属性对象.
  46. *  也创建了一个纵向合并对象. 如果合并值不为null, 将它设置到合并对象中. 然后将该对象添加到
  47. *  单元格属性并将属性添加到单元格中. 最后设置单元格内容并将单元格添加到行中.
  48. *
  49. *  如果合并值为'restart', 表明要开始一个新行. 如果为null, 继续按前面的行处理, 也就是合并单元格.
  50. */
  51. private static void addMergedCell(Tr row, String content, String vMergeVal) {
  52. Tc tableCell = factory.createTc();
  53. TcPr tableCellProperties = new TcPr();
  54. VMerge merge = new VMerge();
  55. if(vMergeVal != null){
  56. merge.setVal(vMergeVal);
  57. }
  58. tableCellProperties.setVMerge(merge);
  59. tableCell.setTcPr(tableCellProperties);
  60. if(content != null) {
  61. tableCell.getContent().add(
  62. wordMLPackage.getMainDocumentPart().
  63. createParagraphOfText(content));
  64. }
  65. row.getContent().add(tableCell);
  66. }
  67. /**
  68. *  本方法为给定的行添加一个单元格, 并以给定的段落作为内容
  69. */
  70. private static void addTableCell(Tr tr, String content) {
  71. Tc tc1 = factory.createTc();
  72. tc1.getContent().add(
  73. wordMLPackage.getMainDocumentPart().createParagraphOfText(content));
  74. tr.getContent().add(tc1);
  75. }
  76. /**
  77. *  本方法为表格添加边框
  78. */
  79. private static void addBorders(Tbl table) {
  80. table.setTblPr(new TblPr());
  81. CTBorder border = new CTBorder();
  82. border.setColor("auto");
  83. border.setSz(new BigInteger("4"));
  84. border.setSpace(new BigInteger("0"));
  85. border.setVal(STBorder.SINGLE);
  86. TblBorders borders = new TblBorders();
  87. borders.setBottom(border);
  88. borders.setLeft(border);
  89. borders.setRight(border);
  90. borders.setTop(border);
  91. borders.setInsideH(border);
  92. borders.setInsideV(border);
  93. table.getTblPr().setTblBorders(borders);
  94. }
  95. }

为表格设置列宽

作为本博客的最后一个示例, 我会展示怎样为表格设置列宽。

 
  1. public class SettingColumnWidthForTable {
  2. private static WordprocessingMLPackage  wordMLPackage;
  3. private static ObjectFactory factory;
  4. /**
  5. *  创建一个带边框的表格并添加一行. 然后添加两个带内容的单元格并给定宽度.
  6. */
  7. public static void main (String[] args) throws Docx4JException {
  8. wordMLPackage = WordprocessingMLPackage.createPackage();
  9. factory = Context.getWmlObjectFactory();
  10. Tbl table = factory.createTbl();
  11. addBorders(table);
  12. Tr tr = factory.createTr();
  13. addTableCellWithWidth(tr, "Field 1", 2500);
  14. addTableCellWithWidth(tr, "Field 2", 0);
  15. table.getContent().add(tr);
  16. wordMLPackage.getMainDocumentPart().addObject(table);
  17. wordMLPackage.save(new java.io.File(
  18. "src/main/files/HelloWord13.docx") );
  19. }
  20. /**
  21. *  本方法创建一个单元格并将给定的内容添加进去.
  22. *  如果给定的宽度大于0, 将这个宽度设置到单元格.
  23. *  最后, 将单元格添加到行中.
  24. */
  25. private static void addTableCellWithWidth(Tr row, String content, int width){
  26. Tc tableCell = factory.createTc();
  27. tableCell.getContent().add(
  28. wordMLPackage.getMainDocumentPart().createParagraphOfText(
  29. content));
  30. if (width > 0) {
  31. setCellWidth(tableCell, width);
  32. }
  33. row.getContent().add(tableCell);
  34. }
  35. /**
  36. *  本方法创建一个单元格属性集对象和一个表格宽度对象. 将给定的宽度设置到宽度对象然后将其添加到
  37. *  属性集对象. 最后将属性集对象设置到单元格中.
  38. */
  39. private static void setCellWidth(Tc tableCell, int width) {
  40. TcPr tableCellProperties = new TcPr();
  41. TblWidth tableWidth = new TblWidth();
  42. tableWidth.setW(BigInteger.valueOf(width));
  43. tableCellProperties.setTcW(tableWidth);
  44. tableCell.setTcPr(tableCellProperties);
  45. }
  46. /**
  47. *  本方法为表格添加边框
  48. */
  49. private static void addBorders(Tbl table) {
  50. table.setTblPr(new TblPr());
  51. CTBorder border = new CTBorder();
  52. border.setColor("auto");
  53. border.setSz(new BigInteger("4"));
  54. border.setSpace(new BigInteger("0"));
  55. border.setVal(STBorder.SINGLE);
  56. TblBorders borders = new TblBorders();
  57. borders.setBottom(border);
  58. borders.setLeft(border);
  59. borders.setRight(border);
  60. borders.setTop(border);
  61. borders.setInsideH(border);
  62. borders.setInsideV(border);
  63. table.getTblPr().setTblBorders(borders);
  64. }
  65. }

总结

在这篇文章中,我展示了如何创建一个文档、如何为其应用样式以及添加带样式的表格。以后的文章我会展示更多的关于docx文档的示例(比如添加目录、添加图片、添加页眉和页脚等)以及一些关于xlsx文档的示例。

使用Docx4j创建word文档的更多相关文章

  1. C#实现通过模板自动创建Word文档的方法

    原文地址:http://www.jb51.net/article/55332.htm   本文实例讲述了C#实现通过模板自动创建Word文档的方法,是非常实用的技巧.分享给大家供大家参考.具体实现方法 ...

  2. 在C#中创建word文档

    在下面文档中  首先引用word组件:Microsoft.Office.Interop.Word 在头文件中写上 using Word = Microsoft.Office.Interop.Word; ...

  3. Java 后台创建word 文档

    ---恢复内容开始--- Java 后台创建 word 文档 自己总结  网上查阅的文档 分享POI 教程地址:http://www.tuicool.com/articles/emqaEf6 方式一. ...

  4. [java,2017-05-04] 创建word文档

    package test; import java.text.SimpleDateFormat; import java.util.Date; import com.aspose.words.Data ...

  5. OpenXml SDK 2.0 创建Word文档 添加页、段落、页眉和页脚

    using (WordprocessingDocument objWordDocument = WordprocessingDocument.Create(@"C:\********.doc ...

  6. Python批量创建word文档(2)- 加图片和表格

    Python创建word文档,任务要求:小杨在一家公司上班,每天都需要给不同的客户发送word文档,以告知客户每日黄金价格.要求在文档开始处给出banner条,价格日期等用表格表示.最后贴上自己的联系 ...

  7. Python批量创建word文档(1)- 纯文字

    Python创建word文档,任务要求:小杨在一家公司上班,每天都需要给不同的客户发送word文档,以告知客户每日黄金价格.最后贴上自己的联系方式.代码如下: 1 ''' 2 #python根据需求新 ...

  8. C#程序通过模板自动创建Word文档

    引言:前段时间有项目要用c#生成Word格式的计算报告,通过网络查找到很多内容,但是都很凌乱,于是自己决定将具体的步骤总结整理出来,以便于更好的交流和以后相似问题可以迅速的解决! 现通过具体的示例演示 ...

  9. 使用Freemarker创建word文档

    最近做一个项目,本来是直接在网页上查看文本信息,然后给客户直接打印的,但是发现也许是浏览器还是打印机的原因,总之,有个客户打印出来的格式始终与其他的不同,没办法,最后想到了直接将数据库中的信息生成一个 ...

随机推荐

  1. SCRUM 12.09 软件工程第二周计划

    第二轮迭代的第二周开始了,上一周我们进行了对代码优化的探索与自我审查. 本周,我们有以下两点目标要实现: 1.对客户端进行优化. 2.网络爬虫爬取美团外卖. 客户端优化主要开发人员:高雅智.牛强.彭林 ...

  2. 基于Ryu的服务器实现及相关请求访问处理

    基于Ryu的服务器实现及相关请求访问处理 前言及问题描述 近期又遇到了一个非常棘手的问题,由于Ryu是通过Python语言开发的,通过Ryu的wsgi的方式建立服务器,无法解析PHP,通过多次方法解决 ...

  3. 基于Winform框架DataGridView控件的SqlServer数据库查询展示功能的实现

    关键词:Winform.DataGridView.SqlServer 一个基于winform框架的C/S软件,主要实现对SqlServer数据库数据表的实时查询. 一.为DataGridView添加数 ...

  4. Ubuntu安装eclipse,并创建桌面快捷方式

    系统:Ubuntu 16.04 JDK版本:1.8.0_121 Ubuntu下安装JDK配置环境变量可见我的这篇文章   http://www.cnblogs.com/AloneZ/p/Ubuntu1 ...

  5. Web网络服务介绍

    Web网络服务也叫WWW(World Wide Web),一般是指能够让用户通过浏览器访问到互联网中文档资源服务.目前提供WEB网络服务的程序有Apache .Nginx 和  IIS  等等,Web ...

  6. jdk命令行工具:jstat与jmap

    转自文章:http://blog.csdn.net/gzh0222/article/details/8538727 C:\Users\Administrator\Desktop>jstat -g ...

  7. Spring之事务操作(注解)

    事务操作步骤: <!-- 第一步.配置事务管理器 --> <bean id="transactionManager" class="org.spring ...

  8. 安装spring-tool-suite插件

    spring-tool-suite是一个非常好用的spring插件,由于eclipse是一个很简洁的IDE,因此许多插件,需要我们自己去手动下载.而Spring-tool-suite插件即是其中之一. ...

  9. js new关键字

    实现new 关键字只需4步 1. 声明一个对象: 2. 把这个对象的__proto__ 指向构造函数的 prototype; 3. 以构造函数为上下文执行这个对象: 4. 返回这个对象. 简洁的代码示 ...

  10. 【BZOJ3139】[HNOI2013]比赛(搜索)

    [BZOJ3139][HNOI2013]比赛(搜索) 题面 BZOJ 洛谷 题解 双倍经验