From b663824a5a3732ed8a9e4addc00a7539e83539f4 Mon Sep 17 00:00:00 2001 From: akulikov Date: Mon, 12 Dec 2022 21:58:20 +0300 Subject: [PATCH] docx, search keys from doc --- clearing-parent/reports-service/pom.xml | 12 +++ .../reports/services/DOCXService.java | 90 ++++++++++++++++++ .../reports/services/DOCXServiceTest.java | 31 ++++++ .../src/test/resources/REC.ACTV_TEST.docx | Bin 0 -> 10230 bytes 4 files changed, 133 insertions(+) create mode 100644 clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/DOCXService.java create mode 100644 clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/DOCXServiceTest.java create mode 100644 clearing-parent/reports-service/src/test/resources/REC.ACTV_TEST.docx 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 0000000000000000000000000000000000000000..aca71b0e5e12d13ad03f80660147bd8eb5b4fe23 GIT binary patch literal 10230 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 i--qU373o0vzs?