如何在Java中使用POI水平合并XWPFTable [英] How to horizontally merge XWPFTable using POI in Java

查看:232
本文介绍了如何在Java中使用POI水平合并XWPFTable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在XWPFTable中水平合并行的列.我尝试了此链接中的答案.

谢谢.

解决方案

有两种设置水平合并的方法.第一种是使用 CTHMerge ,这与使用 CTVMerge 的垂直合并相似,并且它不需要显式的表格网格.第二个是使用网格跨度属性.此方法需要一个表格网格,并且必须删除与第一个网格合并的单元格.

Microsoft Word 支持所有方法.

Libreoffice Writer 也支持 CTHMerge ,但是由于正确呈现了表格,因此必须设置表格网格.

WPS Writer 仅支持设置网格跨度.

因此,这应该是最兼容的解决方案:

  import java.io.File;导入java.io.FileOutputStream;导入java.math.BigInteger;导入org.apache.poi.xwpf.usermodel.XWPFDocument;导入org.apache.poi.xwpf.usermodel.XWPFTable;导入org.apache.poi.xwpf.usermodel.XWPFTableCell;导入org.apache.poi.xwpf.usermodel.XWPFParagraph;导入org.apache.poi.xwpf.usermodel.XWPFRun;导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;导入org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;导入org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;公共类CreateWordTableMerge {static void mergeCellVertically(XWPFTable table,int col,int fromRow,int toRow){for(int rowIndex = fromRow; rowIndex< = toRow; rowIndex ++){XWPFTableCell单元格= table.getRow(rowIndex).getCell(col);CTVMerge vmerge = CTVMerge.Factory.newInstance();if(rowIndex == fromRow){//第一个合并的单元格设置为RESTART合并值vmerge.setVal(STMerge.RESTART);} 别的 {//连接(合并)第一个单元格的单元格设置为CONTINUEvmerge.setVal(STMerge.CONTINUE);//并且应删除内容for(int i = cell.getParagraphs().size(); i> 0; i--){cell.removeParagraph(0);}cell.addParagraph();}//尝试获取TcPr.不只是每次都设置一个新的.CTTcPr tcPr = cell.getCTTc().getTcPr();如果(tcPr == null)tcPr = cell.getCTTc().addNewTcPr();tcPr.setVMerge(vmerge);}}//通过设置网格跨度而不是使用CTHMerge进行水平合并static void mergeCellHorizo​​ntally(XWPFTable表,int行,int fromCol,int toCol){XWPFTableCell单元格= table.getRow(row).getCell(fromCol);//尝试获取TcPr.不只是每次都设置一个新的.CTTcPr tcPr = cell.getCTTc().getTcPr();如果(tcPr == null)tcPr = cell.getCTTc().addNewTcPr();//第一个合并的单元格设置了网格跨度属性如果(tcPr.isSetGridSpan()){tcPr.getGridSpan().setVal(BigInteger.valueOf(toCol-fromCol + 1));} 别的 {tcPr.addNewGridSpan().setVal(BigInteger.valueOf(toCol-fromCol + 1));}//必须删除加入(合并)第一个单元格的单元格for(int colIndex = toCol; colIndex> fromCol; colIndex--){table.getRow(row).getCtRow().removeTc(colIndex);table.getRow(row).removeCell(colIndex);}}公共静态void main(String [] args)引发异常{XWPFDocument document = new XWPFDocument();XWPFParagraph段落= document.createParagraph();XWPFRun run = paragraph.createRun();run.setText("the table:");//创建表XWPFTable table = document.createTable(3,5);for(int row = 0; row< 3; row ++){for(int col = 0; col< 5; col ++){table.getRow(row).getCell(col).setText("row" + row +,col" + col);}}//为此表格创建5列宽度的CTTblGrid.//Libreoffice/Openoffice接受列宽所必需.//值的单位是点的二十分之一(1/1440英寸)//第一列= 1英寸宽table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(1 * 1440));//其他各列(本例中为2列)的宽度也均为1英寸for(int col = 1; col< 5; col ++){table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1 * 1440));}//为所有行中的所有列创建并设置列宽//大多数示例未设置CTTblWidth的类型,但这//对于在所有Office版本中工作都是必需的for(int col = 0; col< 5; col ++){CTTblWidth tblWidth = CTTblWidth.Factory.newInstance();tblWidth.setW(BigInteger.valueOf(1 * 1440));tblWidth.setType(STTblWidth.DXA);for(int row = 0; row< 3; row ++){CTTcPr tcPr = table.getRow(row).getCell(col).getCTTc().getTcPr();如果(tcPr!= null){tcPr.setTcW(tblWidth);} 别的 {tcPr = CTTcPr.Factory.newInstance();tcPr.setTcW(tblWidth);table.getRow(row).getCell(col).getCTTc().setTcPr(tcPr);}}}//使用合并方法mergeCellVertically(table,0,0,1);mergeCellHorizo​​ntally(table,1,2,3);mergeCellHorizo​​ntally(table,2,1,4);段落= document.createParagraph();FileOutputStream out =新的FileOutputStream("create_table.docx");document.write(out);out.close();System.out.println("create_table.docx成功写入");}} 

I want to horizontally merge columns of the row in a XWPFTable. I tried the answer in this link. How to merge cells (or apply colspan) using XWPFTable in POI in Java? and also of this link How to merge cells horizontally using apache-poi

It helped me to get cells merged vertically. But horizontal merge is not happening. I am attaching the sample screenshot of what I really wanted.

Thanks.

解决方案

There are two methods setting horizontally merging. The first is using CTHMerge which is similar to the vertically merging using CTVMerge and it does not explicitly need a table grid. The second is using grid span properties. This method needs a table grid and the cells which are merged with the first one must be removed.

Microsoft Word supports all methods.

Libreoffice Writer supports CTHMerge too but a table grid must be set because of the correct rendering the table.

WPS Writer supports only setting grid span.

So this should be the most compatible solution:

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;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;

public class CreateWordTableMerge {

 static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
  for(int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
   XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
   CTVMerge vmerge = CTVMerge.Factory.newInstance();
   if(rowIndex == fromRow){
    // The first merged cell is set with RESTART merge value
    vmerge.setVal(STMerge.RESTART);
   } else {
    // Cells which join (merge) the first one, are set with CONTINUE
    vmerge.setVal(STMerge.CONTINUE);
    // and the content should be removed
    for (int i = cell.getParagraphs().size(); i > 0; i--) {
     cell.removeParagraph(0);
    }
    cell.addParagraph();
   }
   // Try getting the TcPr. Not simply setting an new one every time.
   CTTcPr tcPr = cell.getCTTc().getTcPr();
   if (tcPr == null) tcPr = cell.getCTTc().addNewTcPr();
   tcPr.setVMerge(vmerge);
  }
 }

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

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

  for (int row = 0; row < 3; row++) {
   for (int col = 0; col < 5; col++) {
    table.getRow(row).getCell(col).setText("row " + row + ", col " + col);
   }
  }

  //create CTTblGrid for this table with widths of the 5 columns. 
  //necessary for Libreoffice/Openoffice to accept the column widths.
  //values are in unit twentieths of a point (1/1440 of an inch)
  //first column = 1 inches width
  table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(1*1440));
  //other columns (2 in this case) also each 1 inches width
  for (int col = 1 ; col < 5; col++) {
   table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1*1440));
  }

  //create and set column widths for all columns in all rows
  //most examples don't set the type of the CTTblWidth but this
  //is necessary for working in all office versions
  for (int col = 0; col < 5; col++) {
   CTTblWidth tblWidth = CTTblWidth.Factory.newInstance();
   tblWidth.setW(BigInteger.valueOf(1*1440));
   tblWidth.setType(STTblWidth.DXA);
   for (int row = 0; row < 3; row++) {
    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);
    }
   }
  }

  //using the merge methods
  mergeCellVertically(table, 0, 0, 1); 
  mergeCellHorizontally(table, 1, 2, 3); 
  mergeCellHorizontally(table, 2, 1, 4); 

  paragraph = document.createParagraph();

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

  System.out.println("create_table.docx written successully");
 }
}

这篇关于如何在Java中使用POI水平合并XWPFTable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆