如何在Java中使用POI水平合并XWPFTable [英] How to horizontally merge XWPFTable using POI in Java
问题描述
我想在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 mergeCellHorizontally(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);mergeCellHorizontally(table,1,2,3);mergeCellHorizontally(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屋!