скопировать таблицу из шаблонов с фиксированным местом, используя Apache Poi - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть таблица в шаблоне docx.В зависимости от количества объектов мне приходится дублировать таблицу столько раз, сколько у меня есть объектов.Дубликаты таблиц должны быть после таблицы из шаблона.У меня есть несколько таблиц в шаблоне, которые должны вести себя следующим образом.

XmlCursor занимает место первой таблицы из шаблона и помещает туда следующую.Я хочу вставить следующую таблицу после предыдущей, которую я добавил сам, но xmlcursor не возвращает добавленный элемент таблицы, но возвращает «STARTDOC»

XmlCursor cursor = docx.getTables().get(pointer).getCTTbl().newCursor();
cursor.toEndToken();

while (cursor.toNextToken() != XmlCursor.TokenType.START) ;

XWPFParagraph newParagraph = docx.insertNewParagraph(cursor);
newParagraph.createRun().setText("", 0);
cursor.toParent();
cursor.toEndToken();
while (cursor.toNextToken() != XmlCursor.TokenType.START) ;
docx.insertNewTbl(cursor);

CTTbl ctTbl = CTTbl.Factory.newInstance();
ctTbl.set(docx.getTables().get(numberTableFromTemplate).getCTTbl());
XWPFTable tableCopy = new XWPFTable(ctTbl, docx);
docx.setTable(index + 1, tableCopy);

1 Ответ

0 голосов
/ 20 сентября 2019

Непонятно, к чему вы стремитесь с cursor.toParent();.И я также не могу воспроизвести проблему, имеющую только небольшой фрагмент кода.Но вам может помочь полный рабочий пример.

Предполагается, что у нас есть следующий шаблон:

enter image description here

Затем следующий код:

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

import org.apache.poi.xwpf.usermodel.*;

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;

public class WordCopyTableAfterTable {

 static XmlCursor setCursorToNextStartToken(XmlObject object) {
  XmlCursor cursor = object.newCursor();
  cursor.toEndToken(); //Now we are at end of the XmlObject.
  //There always must be a next start token.
  while(cursor.hasNextToken() && cursor.toNextToken() != org.apache.xmlbeans.XmlCursor.TokenType.START);
  //Now we are at the next start token and can insert new things here.
  return cursor;
 }

 static void removeCellValues(XWPFTableCell cell) {
  for (XWPFParagraph paragraph : cell.getParagraphs()) {
   for (int i = paragraph.getRuns().size()-1; i >= 0; i--) {
    paragraph.removeRun(i);
   }  
  }
 }

 public static void main(String[] args) throws Exception {

  //The data. Each row a new table.
  String[][] data= new String[][] {
   new String[] {"John Doe", "5/23/2019", "1234.56"},
   new String[] {"Jane Doe", "12/2/2019", "34.56"},
   new String[] {"Marie Template", "9/20/2019", "4.56"},
   new String[] {"Hans Template", "10/2/2019", "4567.89"}
  };

  String value;
  XWPFDocument document = new XWPFDocument(new FileInputStream("WordTemplate.docx"));
  XWPFTable tableTemplate;
  CTTbl cTTblTemplate;
  XWPFTable tableCopy;
  XWPFTable table;
  XWPFTableRow row;
  XWPFTableCell cell;
  XmlCursor cursor;
  XWPFParagraph paragraph;
  XWPFRun run;

  //get first table (the template)
  tableTemplate = document.getTableArray(0);
  cTTblTemplate = tableTemplate.getCTTbl();
  cursor = setCursorToNextStartToken(cTTblTemplate);

  //fill in first data in first table (the template)
  for (int c = 0; c < data[0].length; c++) {
   value = data[0][c];
   row = tableTemplate.getRow(1);
   cell = row.getCell(c);
   removeCellValues(cell);
   cell.setText(value);
  }

  paragraph = document.insertNewParagraph(cursor); //insert new empty paragraph
  cursor = setCursorToNextStartToken(paragraph.getCTP());

  //fill in next data, each data row in one table
  for (int t = 1; t < data.length; t++) {
   table = document.insertNewTbl(cursor); //insert new empty table at position t
   cursor = setCursorToNextStartToken(table.getCTTbl());

   tableCopy = new XWPFTable((CTTbl)cTTblTemplate.copy(), document); //copy the template table

   //fill in data in tableCopy
   for (int c = 0; c < data[t].length; c++) {
    value = data[t][c];
    row = tableCopy.getRow(1);
    cell = row.getCell(c);
    removeCellValues(cell);
    cell.setText(value);
   }
   document.setTable(t, tableCopy); //set tableCopy at position t instead of table

   paragraph = document.insertNewParagraph(cursor); //insert new empty paragraph
   cursor = setCursorToNextStartToken(paragraph.getCTP());
  }

  paragraph = document.insertNewParagraph(cursor);
  run = paragraph.createRun(); 
  run.setText("Inserted new text below last table.");
  cursor = setCursorToNextStartToken(paragraph.getCTP());

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

приводит к следующему результату:

enter image description here

Это то, чего вы хотели достичь?

Обратите вниманиекак я вставляю дополнительные таблицы.

Используя table = document.insertNewTbl(cursor);, новая пустая таблица вставляется в позицию t.Эта таблица помещается в тело документа.Таким образом, эта таблица должна быть использована для настройки курсора.

Затем tableCopy = new XWPFTable((CTTbl)cTTblTemplate.copy(), document); копирует таблицу шаблонов.Затем эта копия заполняется данными.И затем он устанавливается в документ в позиции t, используя document.setTable(t, tableCopy);.

К сожалению, apache poi здесь неполный.XWPFDocument.setTable устанавливает только внутренние ArrayList с, но не базовые XML.XWPFDocument.insertNewTbl устанавливает базовый XML, но только с использованием пустой таблицы.Поэтому мы должны сделать это ужасно сложным способом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...