diff --git a/clearing-parent/reports-service/pom.xml b/clearing-parent/reports-service/pom.xml index 4edc035a2..323090060 100644 --- a/clearing-parent/reports-service/pom.xml +++ b/clearing-parent/reports-service/pom.xml @@ -33,11 +33,23 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml + com.thoughtworks.xstream xstream 1.4.19 + + org.apache.poi + poi-ooxml + 5.1.0 + + + + org.junit.jupiter + junit-jupiter + test + diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/DOCXService.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/DOCXService.java new file mode 100644 index 000000000..20012d16f --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/DOCXService.java @@ -0,0 +1,90 @@ +package ru.spcex.clearing.reports.services; + +import org.apache.poi.xwpf.usermodel.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Сервис для работы с DOCX файлами + * Читает шаблон .docx и во всех текстовых элементах меняет переданные ключи на соответствующие им значения + */ +public class DOCXService { + /** + * При инициализации сохраняет все имеющиеся ключи (ищет по маске keyPattern), найденные в текстовых элементах документа + */ + private final Map bodyElementForKey = new HashMap<>(); + private final Pattern KEY_PATTERN = Pattern.compile("\\$\\{.*?}"); + private final int MAX_POSITION = 128; + + /** + * Инициализация шаблона + * + * @param templateFile файл шаблона + */ + public void init(File templateFile) throws IOException { + assert templateFile != null && templateFile.exists() && templateFile.isFile(); + try (InputStream inputStream = new FileInputStream(templateFile)) { + XWPFDocument doc = new XWPFDocument(inputStream); + + for (IBodyElement element : doc.getBodyElements()) { + if (element instanceof XWPFTable table) { + collectKeysFromTable(table); + } else if (element instanceof XWPFParagraph paragraph) { + collectKeysFromParagraph(paragraph); + } + } + + System.out.println("hello"); + } + } + + private void collectKeysFromTable(XWPFTable srcTable) { + for (XWPFTableRow row : srcTable.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (IBodyElement element : cell.getBodyElements()) { + if (element instanceof XWPFTable table) { + collectKeysFromTable(table); + } else if (element instanceof XWPFParagraph paragraph) { + collectKeysFromParagraph(paragraph); + } + } + } + } + } + + private void collectKeysFromParagraph(XWPFParagraph paragraph) { + + for (XWPFRun run : paragraph.getRuns()) { + try { + for (int currPos = 0; currPos < MAX_POSITION; currPos++) { + String currText = run.getText(currPos); + if (currText == null) break; + Matcher matcher = KEY_PATTERN.matcher(currText); + while (matcher.find()) { + String key = matcher.group(); + bodyElementForKey.put(key, new TextPositionOnRun(run, currPos)); + } + } + } catch (IndexOutOfBoundsException ignored) { + // can't get all max text position for XWPFRun + } + } + } + + static class TextPositionOnRun { + XWPFRun run; + int pos; + + public TextPositionOnRun(XWPFRun run, int pos) { + this.run = run; + this.pos = pos; + } + } +} diff --git a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/DOCXServiceTest.java b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/DOCXServiceTest.java new file mode 100644 index 000000000..6aad9d549 --- /dev/null +++ b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/DOCXServiceTest.java @@ -0,0 +1,31 @@ +package ru.spcex.clearing.reports.services; + +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.junit.jupiter.api.Test; + +import java.io.*; + +class DOCXServiceTest { + @Test + public void testREC_ACTV() { + String inputFilename = "REC.ACTV_TEST.docx"; + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(inputFilename); + InputStream testStream = getClass().getClassLoader().getResourceAsStream("1.docx"); + OutputStream outputStream = new FileOutputStream("test.docx")) { + XWPFDocument templateDoc = new XWPFDocument(inputStream); + XWPFDocument testDoc = new XWPFDocument(testStream); + testDoc.getParagraphs().get(6).getRuns().get(1).setText("========АОВЛДЫАОЫВЛДОАЛЫВДАОЫВЛДАОЫВ========"); + testDoc.write(outputStream); + System.out.println("h"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Test + public void test() throws IOException { + DOCXService service = new DOCXService(); + service.init(new File(getClass().getClassLoader().getResource("REC.ACTV_TEST.docx").getPath())); + System.out.println("p"); + } +} \ No newline at end of file diff --git a/clearing-parent/reports-service/src/test/resources/REC.ACTV_TEST.docx b/clearing-parent/reports-service/src/test/resources/REC.ACTV_TEST.docx new file mode 100644 index 000000000..aca71b0e5 Binary files /dev/null and b/clearing-parent/reports-service/src/test/resources/REC.ACTV_TEST.docx differ