合并单元格时出现 XmlValueDisconnectedException

XmlValueDisconnectedException when merging cells

在 XWPFDocument 的 XWPFTable 中两次合并一行的单元格时出现 XmlValueDisconnectedException。

我正在尝试合并一行的单元格两次。 该行有 10 列跨度。 首先,我试图合并第 0 列到第 4 列。现在该行只有 6 列。然后我试图合并第 3 列到第 5 列。 第一次合并正确完成。再次尝试合并时 XmlValueDisconnectedException 发生在 CTTcPr tcPr = cell.getCTTc().getTcPr();.

public void mergeCellHorizontally(XWPFTable table, int row, int fromCol,
        int toCol) {

        XWPFTableCell cell = table.getRow(row).getCell(fromCol);

        // Try getting the TcPr. Not simply setting an new one every time.
        CTTcPr tcPr = cell.getCTTc().getTcPr();

        UpdateExtTab.LogMsg("tcPr.." + tcPr);
        if (tcPr == null)
            tcPr = cell.getCTTc().addNewTcPr();
        // The first merged cell has grid span property set
        UpdateExtTab.LogMsg("tcPr1.." + tcPr);
        if (tcPr.isSetGridSpan()) {
            tcPr.getGridSpan().setVal(
                    BigInteger.valueOf(toCol - fromCol + 1));
        } else {
            tcPr.addNewGridSpan().setVal(
                    BigInteger.valueOf(toCol - fromCol + 1));
        }
        // Cells which join (merge) the first one, must be removed
        for (int colIndex = toCol; colIndex > fromCol; colIndex--) {
            table.getRow(row).getCtRow().removeTc(colIndex);
        }
        tcPr = null;
    }
}

mergeCellHorizontally(1,1,0,4);

mergeCellHorizontally(1,1,3,5);

mergeCellHorizontally:org 异常。apache.xmlbeans.impl.values.XmlValueDisconnectedException

mergeCellHorizontally:org 异常。apache.xmlbeans.impl.values.XmlValueDisconnectedException 在 org.apache.xmlbeans.impl.values.XmlObjectBase.check_orphaned(XmlObjectBase.java:1213) 在 org.openxmlformats.schemas.wordprocessingml.x2006.main.impl.CTTcImpl.getTcPr(未知来源)

您需要删除除低级别 CTTc 之外的 XWPFTableCell

...
  // Cells which join (merge) the first one, must be removed
  for(int colIndex = toCol; colIndex > fromCol; colIndex--) {
   table.getRow(row).getCtRow().removeTc(colIndex);
   table.getRow(row).removeCell(colIndex);
  }
...

完整示例:

import java.io.File;
import java.io.FileOutputStream;

import java.math.BigInteger;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;

public class CreateWordTableMerge2 {

 //merging horizontally by setting grid span instead of using CTHMerge
 static void mergeCellHorizontally(XWPFTable table, int row, int fromCol, int toCol) {
  XWPFTableCell cell = table.getRow(row).getCell(fromCol);
  // Try getting the TcPr. Not simply setting an new one every time.
  CTTcPr tcPr = cell.getCTTc().getTcPr();
  if (tcPr == null) tcPr = cell.getCTTc().addNewTcPr();
  // The first merged cell has grid span property set
  if (tcPr.isSetGridSpan()) {
   tcPr.getGridSpan().setVal(BigInteger.valueOf(toCol-fromCol+1));
  } else {
   tcPr.addNewGridSpan().setVal(BigInteger.valueOf(toCol-fromCol+1));
  }
  // Cells which join (merge) the first one, must be removed
  for(int colIndex = toCol; colIndex > fromCol; colIndex--) {
   table.getRow(row).getCtRow().removeTc(colIndex);
   table.getRow(row).removeCell(colIndex);
  }
 }

 static void setColumnWidth(XWPFTable table, int row, int col, int width) {
  CTTblWidth tblWidth = CTTblWidth.Factory.newInstance();
  tblWidth.setW(BigInteger.valueOf(width));
  tblWidth.setType(STTblWidth.DXA);
  CTTcPr tcPr = table.getRow(row).getCell(col).getCTTc().getTcPr();
  if (tcPr != null) {
   tcPr.setTcW(tblWidth);
  } else {
   tcPr = CTTcPr.Factory.newInstance();
   tcPr.setTcW(tblWidth);
   table.getRow(row).getCell(col).getCTTc().setTcPr(tcPr);
  }
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument document= new XWPFDocument();

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run=paragraph.createRun();  
  run.setText("The table:");

  //create table
  XWPFTable table = document.createTable(3, 10);

  //defining the column widths for the grid
  //column width values are in unit twentieths of a point (1/1440 of an inch)
  int defaultColWidth = 1*1440*6/10; // 10 columns fits to 6 inches 

  //create CTTblGrid for this table with widths of the 10 columns. 
  //necessary for Libreoffice/Openoffice to accept the column widths.
  //first column
  table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(defaultColWidth));
  setColumnWidth(table, 0, 0, defaultColWidth);
  //other columns
  for (int col = 1; col < 10; col++) {
   table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(defaultColWidth));
   setColumnWidth(table, 0, col, defaultColWidth);
  }

  //using the merge method

  mergeCellHorizontally(table, 1, 0, 4);
  mergeCellHorizontally(table, 1, 3, 5);

  paragraph = document.createParagraph();

  FileOutputStream out = new FileOutputStream("create_table.docx"); 
  document.write(out);
  out.close();

 }
}

结果: