使用Docx4j操作PPT指南系列(五)

                                                     —— 向PPT中插入表格

本章是系列中最后一部分内容,将会介绍如何向PPT中插入一个表格。表格操作可以说是Docx4j中最复杂的部分,由于数据、样式存在多变性,直接导致了表格很难使用XML Schema直接生成,当然如果想硬拼接XML字符串也可以,但会严重降低代码的可读性。因此,本章以使用代码生成表格为主。

看一下效果图:

上图中,PPT包含了一个 4 x 4(行数由代码控制,不局限于给定行数)的表格,下面我们就来介绍如何在PPT中使用Docx4j来生成这种表格。 

// 预先定义表头与列宽度  

private final String[] totalAyTitle = new String[] { "Column1", "Column2",
   "Column3", "Column4" };
 private final int[] totalAyColWidth = new int[] { 792088, 792088, 792088,
   792088};

// 定义表格的位置
 private final int AyX = 467544;
 private final int AyY = 1544824;

 

/**
  * 创建表格
  */
 private void createStTableSlide(
   PresentationMLPackage presentationMLPackage) {

  String partTitle ="";
  String partName = "/ppt/slides/" + getRandomID() + ".xml";

// 创建空白页  

SlidePart slidePart = createCommonSlide(presentationMLPackage,
    partTitle, partName);

  String[][] rowDatas = new String[3][4];

   rowDatas [0] = new String[]{"A","B","C","D"};

   rowDatas [1] = new String[]{"E","F","G","H"};

   rowDatas [2] = new String[]{"I","J","K","L"};

  createTable(slidePart, totalAyTitle, totalAyColWidth, rowDatas, AyX,
    AyY);

 }

/**
  * @param slidePart
  * @param colNames
  * @param colWidths
  * @param rowDatas
  * @param x
  * @param y
  */
 private void createTable(SlidePart slidePart, String[] colNames,
   int[] colWidths, String[][] rowDatas, int x, int y) {

  CTGraphicalObjectFrame graphicFrame = graphicObjectFactory
    .createCTGraphicalObjectFrame();

  org.pptx4j.pml.CTGraphicalObjectFrameNonVisual nvGraphicFramePr = graphicObjectFactory
    .createCTGraphicalObjectFrameNonVisual();
  org.docx4j.dml.CTNonVisualDrawingProps cNvPr = objectFactory
    .createCTNonVisualDrawingProps();

  org.docx4j.dml.CTNonVisualGraphicFrameProperties cNvGraphicFramePr = objectFactory
    .createCTNonVisualGraphicFrameProperties();

  org.docx4j.dml.CTGraphicalObjectFrameLocking graphicFrameLocks = objectFactory
    .createCTGraphicalObjectFrameLocking();

  org.docx4j.dml.CTTransform2D xfrm = objectFactory.createCTTransform2D();

  // 设置表格的位置
  CTPoint2D ctPoint = objectFactory.createCTPoint2D();
  ctPoint.setX(x);
  ctPoint.setY(y);
  xfrm.setOff(ctPoint);

  Graphic graphic = objectFactory.createGraphic();
  GraphicData graphicData = objectFactory.createGraphicData();

  // 设置表格样式
  CTTable ctTable = objectFactory.createCTTable();
  CTTableProperties ctTablePr = objectFactory.createCTTableProperties();
  ctTablePr.setFirstRow(true);
  ctTablePr.setBandRow(true);
  ctTable.setTblPr(ctTablePr);
  ctTablePr.setTableStyleId("{21E4AEA4-8DFA-4A89-87EB-49C32662AFE0}");

  JAXBElement<CTTable> tbl = objectFactory.createTbl(ctTable);
  CTTableGrid ctTableGrid = objectFactory.createCTTableGrid();

  graphicFrame.setNvGraphicFramePr(nvGraphicFramePr);
  nvGraphicFramePr.setCNvPr(cNvPr);
  cNvPr.setName("1");
  nvGraphicFramePr.setCNvGraphicFramePr(cNvGraphicFramePr);
  cNvGraphicFramePr.setGraphicFrameLocks(graphicFrameLocks);
  graphicFrameLocks.setNoGrp(true);
  nvGraphicFramePr.setNvPr(graphicObjectFactory.createNvPr());
  graphicFrame.setXfrm(xfrm);

  xfrm.setExt(objectFactory.createCTPositiveSize2D());

  graphicFrame.setGraphic(graphic);
  graphic.setGraphicData(graphicData);
  graphicData
    .setUri("http://schemas.openxmlformats.org/drawingml/2006/table");
  graphicData.getAny().add(tbl);
  ctTable.setTblGrid(ctTableGrid);

  int length = colWidths.length;

  for (int i = 0; i < length; i++) {
   ctTableGrid.getGridCol().add(createCol(colWidths[i]));
  }

  ctTable.getTr().add(createRow(colNames));

  if (rowDatas != null) {

   for (int j = 0; j < rowDatas.length ; j++) {
    ctTable.getTr().add(createRow(rowDatas[j]));
   }
  }

  slidePart.getJaxbElement().getCSld().getSpTree()
    .getSpOrGrpSpOrGraphicFrame().add(graphicFrame);

 }

/**
  * @param width
  * @return
  */
 private CTTableCol createCol(int width) {

  CTTableCol gridCol = objectFactory.createCTTableCol();

  gridCol.setW(width);

  return gridCol;
 }

 /**
  * @param datas
  * @return
  */
 private CTTableRow createRow(String[] datas) {

  CTTableRow ctTableRow = objectFactory.createCTTableRow();

  for (String data : datas) {

   ctTableRow.getTc().add(createCell(data));

  }

  return ctTableRow;
 }

 /**
  * @param value
  * @return
  */
 private CTTableCell createCell(String value) {

  CTTableCell ctTableCell = objectFactory.createCTTableCell();

  // 单元格文字
  CTTextBody ctTextBody = objectFactory.createCTTextBody();
  ctTextBody.setBodyPr(objectFactory.createCTTextBodyProperties());
  ctTextBody.setLstStyle(objectFactory.createCTTextListStyle());
  CTTextParagraph ctTextPr = objectFactory.createCTTextParagraph();

  CTRegularTextRun run = objectFactory.createCTRegularTextRun();

  CTTextCharacterProperties ctTpr = objectFactory
    .createCTTextCharacterProperties();

  // 14号字体
  ctTpr.setSz(1200);

  TextFont font = objectFactory.createTextFont();
  font.setTypeface("微软雅黑");

  ctTpr.setLatin(font);
  ctTpr.setEa(font);

  run.setRPr(ctTpr);

  // 设置内容,不能为null
  run.setT(value == null ? "" : value);

  ctTextPr.getEGTextRun().add(run);

  ctTextPr.setEndParaRPr(objectFactory.createCTTextCharacterProperties());
  ctTextBody.getP().add(ctTextPr);
  ctTableCell.setTxBody(ctTextBody);

  return ctTableCell;
 }

通过上面的代码,我们就可以在PPT中创建一个表格,需要注意的是在选择表格样式时需要了解当前PPT模板的表格样式ID,如上面的代码中就使用了如下的定义方式:

ctTablePr.setTableStyleId("{21E4AEA4-8DFA-4A89-87EB-49C32662AFE0}");

——完——

写在最后:

本系列的内容在这里就告一段落了,刚刚上手docx4j时感觉非常不适应(以前习惯了POI那种一切都采用自己对象封装的方式)docx4j本身的文档非常匮乏,很多内容都需要在项目论坛中慢慢寻找,算是运气比较好,很多问题在论坛上都能找到答案,于是就想把这些内容汇总整理起来,形成一系列的文档,算是早早的砸下了一块砖头。文笔不好,请看官见谅。

docx4j是一款非常强大的工具,在对office2007文档的操作支持方面几乎是无懈可击,用法虽然有些复杂,但是如果能充分的了解Microsoft的OOXML结构的话,这些就都不是困难了。以后我会整理一些使用过程中的技巧和注意事项供大家参考。