Java 如何在ApachePOI表的不同行中设置特定的单元格宽度?

Java 如何在ApachePOI表的不同行中设置特定的单元格宽度?,java,apache-poi,Java,Apache Poi,我想在ApachePOI表的不同行中设置特定的单元格宽度 我使用下面的代码设置单元格宽度,但它会更改整个列宽。我有办法解决这个问题吗 CTTblWidth width = cell1.getCTTc().addNewTcPr().addNewTcW(); width.setType(STTblWidth.DXA); width.setW(BigInteger.valueOf(500)); 我想要这种款式: 在Word文档中生成这样一个复杂的表需要了解Word表的内部结构 首先确定网格中所需列的

我想在ApachePOI表的不同行中设置特定的单元格宽度

我使用下面的代码设置单元格宽度,但它会更改整个列宽。我有办法解决这个问题吗

CTTblWidth width = cell1.getCTTc().addNewTcPr().addNewTcW();
width.setType(STTblWidth.DXA);
width.setW(BigInteger.valueOf(500));
我想要这种款式:


Word
文档中生成这样一个复杂的表需要了解
Word
表的内部结构


首先确定网格中所需列的总数。为此,在整个表格中绘制所有垂直线。对于示例表,您需要8列

在第一行中,第一个单元格跨越前三列,第二个单元格跨越下一个4列,第三个单元格是第八列

在第二行中,第一个单元格跨越7列,第二个单元格是第八列

在第三行和第四行中,第一个单元格是第一列,第二个单元格跨越第二列到第四列,第三个单元格是第五列,第四个单元格是第六列,第五个单元格是第七列,第六个单元格是第八列

在第五行中,合并所有单元格

一旦知道每行中的单个单元格需要如何跨越网格,就可以确定网格列的列宽。在下面的示例中,默认网格列的宽度为6/8英寸。因此,8列适合6英寸的页面宽度

现在,您可以使用给定的示例设置柱跨距

在执行此操作时,您需要注意,每次合并都会删除不再需要的列。在多次合并一行中的列时,必须在删除后重新计算新的列索引

合并后,需要设置结果列的列宽

例如:

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

 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(9,8);

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

  //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/8; // 8 columns fits to 6 inches 
  int[] colunmWidths = new int[] {
   defaultColWidth*5/4, defaultColWidth*3/4, defaultColWidth*1/4, defaultColWidth*1/4, 
   defaultColWidth*3/2, defaultColWidth, defaultColWidth, defaultColWidth*2
  };

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

  //using the merge methods and setting the column widths
  mergeCellHorizontally(table, 0, 0, 2); 
  setColumnWidth(table, 0, 0, colunmWidths[0]+colunmWidths[1]+colunmWidths[2]);
  mergeCellHorizontally(table, 0, (3-2), (6-2)); // merge grid cols 3 to 6 but 2 cols are removed already 
  setColumnWidth(table, 0, 1, colunmWidths[3]+colunmWidths[4]+colunmWidths[5]+colunmWidths[6]);
  setColumnWidth(table, 0, 2, colunmWidths[7]);

  mergeCellHorizontally(table, 1, 0, 6); 
  setColumnWidth(table, 1, 0, colunmWidths[0]+colunmWidths[1]+colunmWidths[2]+colunmWidths[3]
                              +colunmWidths[4]+colunmWidths[5]+colunmWidths[6]);
  setColumnWidth(table, 1, 1, colunmWidths[7]);

  mergeCellHorizontally(table, 2, 1, 3); 
  setColumnWidth(table, 2, 0, colunmWidths[0]);
  setColumnWidth(table, 2, 1, colunmWidths[1]+colunmWidths[2]+colunmWidths[3]);
  setColumnWidth(table, 2, 2, colunmWidths[4]);
  setColumnWidth(table, 2, 3, colunmWidths[5]);
  setColumnWidth(table, 2, 4, colunmWidths[6]);
  setColumnWidth(table, 2, 5, colunmWidths[7]);

  mergeCellHorizontally(table, 3, 1, 3); 
  setColumnWidth(table, 3, 0, colunmWidths[0]);
  setColumnWidth(table, 3, 1, colunmWidths[1]+colunmWidths[2]+colunmWidths[3]);
  setColumnWidth(table, 3, 2, colunmWidths[4]);
  setColumnWidth(table, 3, 3, colunmWidths[5]);
  setColumnWidth(table, 3, 4, colunmWidths[6]);
  setColumnWidth(table, 3, 5, colunmWidths[7]);

  mergeCellHorizontally(table, 4, 0, 7); 
  setColumnWidth(table, 4, 0, colunmWidths[0]+colunmWidths[1]+colunmWidths[2]+colunmWidths[3]
                              +colunmWidths[4]+colunmWidths[5]+colunmWidths[6]+colunmWidths[7]);

  mergeCellHorizontally(table, 5, 0, 4); 
  mergeCellHorizontally(table, 5, (5-4), (7-4)); // merge grid cols 5 to 7 but 4 cols are removed already 
  setColumnWidth(table, 5, 0, colunmWidths[0]+colunmWidths[1]+colunmWidths[2]+colunmWidths[3]+colunmWidths[4]);
  setColumnWidth(table, 5, 1, colunmWidths[5]+colunmWidths[6]+colunmWidths[7]);

  mergeCellHorizontally(table, 6, 0, 1); 
  mergeCellHorizontally(table, 6, (2-1), (4-1)); // merge grid cols 2 to 4 but 1 cols are removed already 
  mergeCellHorizontally(table, 6, (5-3), (6-3)); // merge grid cols 5 to 6 but 3 cols are removed already 
  setColumnWidth(table, 6, 0, colunmWidths[0]+colunmWidths[1]);
  setColumnWidth(table, 6, 1, colunmWidths[2]+colunmWidths[3]+colunmWidths[4]);
  setColumnWidth(table, 6, 2, colunmWidths[5]+colunmWidths[6]);
  setColumnWidth(table, 6, 3, colunmWidths[7]);

  mergeCellHorizontally(table, 7, 0, 1); 
  mergeCellHorizontally(table, 7, (2-1), (4-1)); 
  mergeCellHorizontally(table, 7, (5-3), (6-3)); 
  setColumnWidth(table, 7, 0, colunmWidths[0]+colunmWidths[1]);
  setColumnWidth(table, 7, 1, colunmWidths[2]+colunmWidths[3]+colunmWidths[4]);
  setColumnWidth(table, 7, 2, colunmWidths[5]+colunmWidths[6]);
  setColumnWidth(table, 7, 3, colunmWidths[7]);

  mergeCellHorizontally(table, 8, 0, 7); 
  setColumnWidth(table, 8, 0, colunmWidths[0]+colunmWidths[1]+colunmWidths[2]+colunmWidths[3]
                              +colunmWidths[4]+colunmWidths[5]+colunmWidths[6]+colunmWidths[7]);

  paragraph = document.createParagraph();

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

 }
}
导入java.io.File;
导入java.io.FileOutputStream;
导入java.math.biginger;
导入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{
静态空合并单元格垂直(XWPFTable表,int列,int fromRow,int toRow){
对于(int rowIndex=fromRow;rowIndex 0;i--){
删除第(0)段中的单元格;
}
单元格。添加段落();
}
//尝试获取TcPr,而不是每次都设置一个新的TcPr。
CTTcPr tcPr=cell.getCTTc().getcpr();
如果(tcPr==null)tcPr=cell.getCTTc().addNewTcPr();
tcPr.setVMerge(vmerge);
}
}
//通过设置栅格跨度而不是使用CTHMerge进行水平合并
静态空合并单元格(XWPFTable表格、int行、int fromCol、int toCol){
XWPFTableCell=table.getRow(row).getCell(fromCol);
//尝试获取TcPr,而不是每次都设置一个新的TcPr。
CTTcPr tcPr=cell.getCTTc().getcpr();
如果(tcPr==null)tcPr=cell.getCTTc().addNewTcPr();
//第一个合并的单元已设置“栅格跨度”属性
if(tcPr.isSetGridSpan()){
tcPr.getGridSpan().setVal(biginger.valueOf(toCol fromCol+1));
}否则{
tcPr.addNewGridSpan().setVal(biginger.valueOf(toCol fromCol+1));
}
//必须删除连接(合并)第一个单元格的单元格
对于(int colIndex=toCol;colIndex>fromCol;colIndex--){
table.getRow(row.getCtRow().removeTc(colIndex);
表.getRow(row).removeCell(colIndex);
}
}
静态void setColumnWidth(XWPFTable表格、int行、int列、int宽度){
CTTblWidth tblWidth=CTTblWidth.Factory.newInstance();
tblWidth.setW(biginger.valueOf(width));
设置类型(STTblWidth.DXA);
CTTcPr tcPr=table.getRow(row).getCell(col.getCTTc().getcpr();
如果(tcPr!=null){
tcPr.setTcW(tblWidth);
}否则{
tcPr=CTTcPr.Factory.newInstance();
tcPr.setTcW(tblWidth);
table.getRow(row).getCell(col).getCTTc().setTcPr(tcPr);
}
}
公共静态void main(字符串[]args)引发异常{
XWPFDocument document=新的XWPFDocument();
XWPFParagraph paragraph paragraph=document.createParagraph();
XWPFRun=段落.createRun();
run.setText(“表:”);
//创建表
XWPFTable table=document.createTable(9,8);
对于(int行=0;行<9;行++){
for(int col=0;col<8;col++){
table.getRow(行).getCell(列).setText(“行”+row+”,列“+col”);
}
}
//定义网格的列宽
//列宽值以点的二十分之一为单位(1/1440英寸)
int defaultColWidth=1*1440*6/8;//8列适合6英寸
int[]colunmWidths=新int[]{
defaultColWidth*5/4、defaultColWidth*3/4、defaultColWidth*1/4、defaultColWidth*1/4、,
defaultColWidth*3/2,defaultColWidth,defaultColWidth,defaultColWidth*2
};
//为此表创建宽度为8列的CTTblGrid。
//Libreoffice/Openoffice需要接受列宽。
//第一列
table.getCTTbl();
//其他栏目
for(int col=1;col