XWPFTable 创建新行(循环)

XWPFTable create new row (looping)

我对如何使用 XWPFTable 循环数据有疑问? 我有一些问题;

  1. 我很困惑为什么 XWPFRun examRun = examInfoRowP.createRun(); (自动读取第 2 列,而不是第 1 列
  2. 我的编码结构,我觉得使用XWPFTable效率比较低,如何让代码更简洁

注: 列表 listLHA 是数据 我正在使用 apache-poi 3.8

XWPFTable Table = document.getTableArray(16);
            
            XWPFTableRow getRow1 = Table.getRow(1);
            
            
            XWPFTableRow getRow0 = Table.getRow(0);
            
            //baris 1
            for(int i = 0; i < listLHA.size(); i++) {
                getRow0.getCell(0).setText(listLHA.get(0).getKeyProsses()+ " KEY PROSES");
                break;
            }
            
            //baris 2
            
            for(int i = 0; i < listLHA.size(); i++) {
                getRow1.getCell(0).setText(listLHA.get(0).getRiskRating());
                getRow1.getCell(1).setText(listLHA.get(0).getAuditObservationTitle()+ " AO TITLE");
                break;
            }
            
            XWPFTableRow examInfoRow = Table.createRow();
            XWPFTableCell cellRowInfo = examInfoRow.addNewTableCell();

            XWPFParagraph examInfoRowP = cellRowInfo.getParagraphs().get(0);
            XWPFRun examRun = examInfoRowP.createRun(); //problem 1
            
            examInfoRowP.setAlignment(ParagraphAlignment.LEFT);
            //list Action plan
            examRun.setText("Action Plan:");
            examRun.addBreak();
            for (AuditEngagementLHA lha : listLHA) {
                int i = listLHA.indexOf(lha);
                examRun.setText(i+1 +"."+lha.getDescAP().replaceAll("\<[^>]*>",""));
                examRun.addBreak();
            }
            for(int i = 0; i < listLHA.size(); i++) {
                examRun.setText("Target Date: ");
                examRun.setText(listLHA.get(0).getTargetDateAP());
                examRun.addBreak();
                break;
            }
            
            examRun.addBreak();
            for(int i = 0; i < listLHA.size(); i++) {
                examInfoRow.getCell(0).setText(listLHA.get(0).getDescAO()+" Desc AO");
                examRun.addBreak();
                break;
            }
            //List penanggung jawab
            examRun.setText("Penanggung Jawab:");
            examRun.addBreak();
            for (AuditEngagementLHA lha : listLHA) {
                int i = listLHA.indexOf(lha);
                
                examRun.setText(i+1 +"."+lha.getPicAP()+" - ");
                examRun.setText(lha.getJabatanPicAP());
                examRun.addBreak();
            }

*我的word模板是这样的

*现在的结果是这样的

*结果应该是这样的,整洁

Apache POI 正在高度开发中。因此,版本很快就会过时。版本apache poi 3.8是2012年发布的,十年后的2022年用的太旧了

第一个问题:

根据文档XWPFTable.createRow 创建一个新的 XWPFTableRow 对象,其单元格数与当时定义的列数一样多。

所以在你的情况下 XWPFTableRow examInfoRow = Table.createRow(); 创建一个 examInfoRow 已经至少有两列,因为 table 已经包含至少两列来自上面的行。

然后 XWPFTableCell cellRowInfo = examInfoRow.addNewTableCell(); 通过向该行添加一个新的 table 单元格来添加一个额外的列。这就是 cellRowInfo 不会出现在第一列的原因。

你的第二个问题过于宽泛,无法在这里得到完整的回答。

我可以告诉你的是,Word table 是可怕的东西。它们有一个定义列的基础 table 网格。如果行需要不同的列大小,则设置列跨度是必要的,就像在 HTML table 中一样。 table,您显示为想要的结果,包含三列。在第一行中,第一列跨越其他列。在第二行中,第二列跨越第三列。在第三行中,第一列横跨第二列。这是为每一行生成不同列的唯一方法。

了解这一点应该避免插入 and/or 添加或创建 table 单元格。如果模板是可能的,那么该模板应该已经包含所有可能的行模板。然后只需要复制行而不是插入单元格。

完整示例:

模板:

代码:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;

import java.util.List; 
import java.util.ArrayList; 

public class WordInsertContentInTable {
    
 static void setText(XWPFTableCell cell, String text) {
  String[] lines = text.split("\n");
  List<XWPFParagraph> paragraphs = cell.getParagraphs();
  for (int i = 0; i < lines.length; i++) {
   String line = lines[i];
   XWPFParagraph paragraph = null;
   if (paragraphs.size() > i) paragraph = paragraphs.get(i);
   if (paragraph == null) paragraph = cell.addParagraph();
   XWPFRun run = null;
   if (paragraph.getRuns().size() > 0) run = paragraph.getRuns().get(0);
   if (run == null) run = paragraph.createRun();
   run.setText(line, 0);
  }
  for (int i = paragraphs.size()-1; i >= lines.length; i--) {
   cell.removeParagraph(i);
  }
 }
    
 static void insertContentInTable(XWPFTable table, List<POJO> listOfPOJOs) throws Exception {
  XWPFTableRow titleRowTemplate = table.getRow(0);
  if (titleRowTemplate == null) throw new Exception("Table template does not match: No title row.");
  if (titleRowTemplate.getTableCells().size() != 1) throw new Exception("Table template does not match: Wrong title row column count.");
  XWPFTableRow subTitleRowTemplate = table.getRow(1);
  if (subTitleRowTemplate == null) throw new Exception("Table template does not match: No sub title row.");
  if (subTitleRowTemplate.getTableCells().size() != 2) throw new Exception("Table template does not match: Wrong sub title row column count.");
  XWPFTableRow contentRowTemplate = table.getRow(2);
  if (contentRowTemplate == null) throw new Exception("Table template does not match: No content row.");
  if (contentRowTemplate.getTableCells().size() != 2) throw new Exception("Table template does not match: Wrong content row column count.");
  
  XWPFTableRow titleRow = titleRowTemplate;
  XWPFTableRow subTitleRow = subTitleRowTemplate;
  XWPFTableRow contentRow = contentRowTemplate;
  XWPFTableCell cell;
  for (int i = 0; i < listOfPOJOs.size(); i++) {
   POJO pojo = listOfPOJOs.get(i); 
   if (i > 0) {
    titleRow = new XWPFTableRow((CTRow)titleRowTemplate.getCtRow().copy(), table);
    subTitleRow = new XWPFTableRow((CTRow)subTitleRowTemplate.getCtRow().copy(), table);
    contentRow = new XWPFTableRow((CTRow)contentRowTemplate.getCtRow().copy(), table);
   }
   String titleRowText = pojo.getTitleRowText();
   cell = titleRow.getCell(0);
   setText(cell, titleRowText);   
   String subTitleRowLeftText = pojo.getSubTitleRowLeftText();   
   String subTitleRowLeftColor = pojo.getSubTitleRowLeftColor();   
   String subTitleRowRightText = pojo.getSubTitleRowRightText();   
   cell = subTitleRow.getCell(0);
   setText(cell,subTitleRowLeftText);   
   cell.setColor(subTitleRowLeftColor);   
   cell = subTitleRow.getCell(1);
   setText(cell,subTitleRowRightText);
   String contentRowLeftText = pojo.getContentRowLeftText();   
   String contentRowRightText = pojo.getContentRowRightText();   
   cell = contentRow.getCell(0);
   setText(cell, contentRowLeftText);   
   cell = contentRow.getCell(1);
   setText(cell, contentRowRightText);
   if (i > 0) {
    table.addRow(titleRow);
    table.addRow(subTitleRow);
    table.addRow(contentRow);
   }
  }     
 }

 public static void main(String[] args) throws Exception {
     
  List<POJO> listOfPOJOs = new ArrayList<POJO>();
  listOfPOJOs.add(new POJO("Title row text 1", 
                           "Sub title row left text 1", "FF0000", "Sub title row right text 1\nSub title row right text 1\nSub title row right text 1", 
                           "Content row left text 1\nContent row left text 1\nContent row left text 1", 
                           "Content row right text 1\nContent row right text 1\nContent row right text 1"));
  listOfPOJOs.add(new POJO("Title row text 2", 
                           "Sub title row left text 2", "00FF00", "Sub title row right text 2\nSub title row right text 2", 
                           "Content row left text 2\nContent row left text 2",
                           "Content row right text 2\nContent row right text 2"));
  listOfPOJOs.add(new POJO("Title row text 3", 
                           "Sub title row left text 3", "0000FF", "Sub title row right text 3", 
                           "Content row left text 3", 
                           "Content row right text 3"));

  XWPFDocument document = new XWPFDocument(new FileInputStream("./WordTenplate.docx"));

  XWPFTable table = document.getTableArray(0);
  
  insertContentInTable(table, listOfPOJOs);

  FileOutputStream out = new FileOutputStream("./WordResult.docx");
  document.write(out);
  out.close();
  document.close();
 }
 
 static class POJO {
  private String titleRowText;
  private String subTitleRowLeftText;
  private String subTitleRowLeftColor;
  private String subTitleRowRightText;
  private String contentRowLeftText;
  private String contentRowRightText;
  public POJO ( String titleRowText,
                String subTitleRowLeftText,
                String subTitleRowLeftColor,
                String subTitleRowRightText,
                String contentRowLeftText,
                String contentRowRightText ) {
   this.titleRowText = titleRowText;
   this.subTitleRowLeftText = subTitleRowLeftText;
   this.subTitleRowLeftColor = subTitleRowLeftColor;
   this.subTitleRowRightText = subTitleRowRightText;
   this.contentRowLeftText = contentRowLeftText;
   this.contentRowRightText = contentRowRightText;     
  }
  public String getTitleRowText() {
   return this.titleRowText;
  }
  public String getSubTitleRowLeftText() {
   return this.subTitleRowLeftText;
  }
  public String getSubTitleRowLeftColor() {
   return this.subTitleRowLeftColor;
  }
  public String getSubTitleRowRightText() {
   return this.subTitleRowRightText;
  }
  public String getContentRowLeftText() {
   return this.contentRowLeftText;
  }
  public String getContentRowRightText() {
   return this.contentRowRightText;
  }
 }
}

结果:

此代码已最小化以显示原理。如果需要文本格式,则需要扩展方法 setText(XWPFTableCell cell, String text)。 Word中的文本格式需要XWPFRuns,每个文本的格式应该不同。当然 POJO 也需要字段来确定所需的格式。