java - 合并单元格时出现 XmlValueDisconnectedException

标签 java apache-poi xwpf

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

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

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);

mergeCellHorizo​​ntally 中的异常:org.apache.xmlbeans.impl.values.XmlValueDisconnectedException

mergeCellHorizo​​ntally 中的异常: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();

 }
}

结果:

enter image description here

关于java - 合并单元格时出现 XmlValueDisconnectedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56245697/

相关文章:

java - 将 Java Web Start 应用程序转换为 Applet

java - 如何检查excel列标题在apache poi中是否按特定顺序排列

java - poi XWPF 双空格

java - Apache POI : ${my_placeholder} is treated as three different runs

java - Java 中的 IIFE/自动方法?

java - WebSocket session 之间共享的所有成员是否应该同步?

java - 使用输入 Excel 中的更新更新 Jar 文件

java - 有没有办法读取oracle中的RAW和TIMESTAMP数据类型并使用JAVA代码导出到Excel

java - 使用 Apache POI 读取 .docx 文件

java - 如何在 Selenium 中找到这个元素(页面上的按钮)?