我知道如何用Apache POI Word垂直合并单元格。但似乎如果创建了新行,合并就不会生效。
下面是输入表:
我希望在旧行2
和旧行3
之间添加一个新行,并将新行的第一列单元格合并到C2,如下所示:
public class POIWordAddSubRowQuestionDemo{
public static void main(String[] args) throws IOException, XmlException{
ClassLoader classLoader = POIWordAddSubRowQuestionDemo.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("input.docx");
String outputDocxPath = "F:/TEMP/output.docx";
assert inputStream != null;
XWPFDocument doc = new XWPFDocument(inputStream);
XWPFTable table = doc.getTables().get(0);
//this is 'old row 2'
XWPFTableRow secondRow = table.getRows().get(1);
//create a new row that is based on 'old row 2'
CTRow ctrow = CTRow.Factory.parse(secondRow.getCtRow().newInputStream());
XWPFTableRow newRow = new XWPFTableRow(ctrow, table);
XWPFRun xwpfRun = newRow.getCell(1).getParagraphs().get(0).getRuns().get(0);
//set row text
xwpfRun.setText("new row", 0);
// add new row below 'old row 2'
table.addRow(newRow, 2);
//merge cells at first column of 'old row 2', 'new row', and 'old row 3'
mergeCellVertically(doc.getTables().get(0), 0, 1, 3);
FileOutputStream fos = new FileOutputStream(outputDocxPath);
doc.write(fos);
fos.close();
}
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);
}
}
}
那么有没有合并新创建行的解决方案呢?我真的不想这样拆分这个操作:添加行>将docx保存到磁盘>从磁盘读取docx>合并行。
问题不在于MergeCellVertily
方法,而在于复制表行的方法。当复制基础ctrow
并使用xwpftable.addrow
将其插入ctbl.trarray
时,必须完全完成。以后的更改不是用XML
编写的。在我的回答中,java Apache POI Word现有的表,插入行的单元格样式和格式已经告诉了这一点。我在回答中提供了一个方法committableRows
不能更改。docx文件中的行文本,一旦行添加到table。在写出文档之前需要调用此方法,因此后面的更改将写入XML
。
因此,因为您正在复制第二行,这是合并的开始,所以该设置也会被复制。后面称为MergeCellVertily
的命令不生效。因此,newrow
仍然是合并的新起点。这就是你得到的。
因此,在所有更改之后,在写出之前,调用committableRows
。
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
public class WordInsertTableRowAndMerge {
static XWPFTableRow insertNewTableRow(XWPFTableRow sourceTableRow, int pos) throws Exception {
XWPFTable table = sourceTableRow.getTable();
CTRow newCTRrow = CTRow.Factory.parse(sourceTableRow.getCtRow().newInputStream());
XWPFTableRow tableRow = new XWPFTableRow(newCTRrow, table);
table.addRow(tableRow, pos);
return tableRow;
}
static void commitTableRows(XWPFTable table) {
int rowNr = 0;
for (XWPFTableRow tableRow : table.getRows()) {
table.getCTTbl().setTrArray(rowNr++, tableRow.getCtRow());
}
}
static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
for(int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
System.out.println("rowIndex: " + 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);
}
}
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument(new FileInputStream("./source.docx"));
XWPFTable table = doc.getTables().get(0);
XWPFTableRow row = table.getRow(1);
XWPFTableRow newRow = insertNewTableRow(row, 2);
XWPFTableCell cell = newRow.getCell(0); if (cell == null) cell = newRow.addNewTableCell();
// not needed because merged to cell above
cell = newRow.getCell(1); if (cell == null) cell = newRow.addNewTableCell();
for (XWPFParagraph paragraph : cell.getParagraphs()) { // only use first text runs in paragraphs
for (int r = paragraph.getRuns().size()-1; r >= 0; r--) {
XWPFRun run = paragraph.getRuns().get(r);
if (r == 0) {
run.setText("new row 1", 0);
} else {
paragraph.removeRun(r);
}
}
}
mergeCellVertically(table, 0, 1, 3);
commitTableRows(table);
FileOutputStream out = new FileOutputStream("./result.docx");
doc.write(out);
out.close();
doc.close();
}
}
谁能解释一下如何使用Apache POI为合并的单元格创建边框吗? 我使用的代码只影响一个单元格。
我想数一下一行中有多少单元格被合并了?我在Excel中合并(缩放)它,在Java中我想显示例如:“合并的单元格:4”(A1,B1,C1,D1)?
在旧版本中,您可以键入以下内容: 这会产生外部边框--即使是在合并的单元格周围,也会使用选定的颜色。不幸的是,在POI的新版本中,我似乎不能使用索引颜色,因为获得自定义RGB颜色索引的方法不起作用,并且被降级或标记为仅供测试。
我正在使用Apache POI将数据导出到一个.xlsx文件,我想对文件中包含的一些行和单元格设置样式。 我使用XSSF,因为该文件将在Excel2007+中读取。
我做了一个从Java到xls的导出,我使用POI库。 我的createCell方法: 我在一个For中调用这个方法,我有这样的消息错误: Echec de l'export:超出了单元格样式的最大数目。在.xls工作簿中最多可以定义4000个样式 如何重用我的单元格而不必重新创建每个迭代? THX
无法建立垂直。云环境中垂直柱之间的x群集 我在配置vert时遇到问题。x eventbus群集在私有云环境中。 在实验室测试中,我尝试使用Hazelcast集群管理器制作两个垂直点来建立一个集群,每个垂直点都在您自己的容器中运行。 问题很可能是由于配置错误引起的,但我无法找到它。在这个云上,不可能进行多播调用,那么我使用的是TCP IP发现策略。 最初的计划是制作一个“labatf api”垂直链