diff --git a/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar b/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar index c07dcb29..00bb17a4 100644 Binary files a/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar and b/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar differ diff --git a/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/output/util/OutputWordUtil.java b/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/output/util/OutputWordUtil.java index c2b6a19c..38c92287 100644 --- a/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/output/util/OutputWordUtil.java +++ b/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/output/util/OutputWordUtil.java @@ -423,145 +423,183 @@ public class OutputWordUtil { FormFile formFile = processfile.get(0); DCContext fileDCContext = SDK.getBOAPI().getFileDCContext(formFile); + // 加载目标文件和待合并文档2 Document docs1 = new Document(); docs1.loadFromFile(outFile.getPath()); Document docs2 = new Document(); docs2.loadFromFile(fileDCContext.getFilePath()); + try { + // 删除docs1的最后一个节(保留原有逻辑) + Section lastSection1 = docs1.getLastSection(); + docs1.getSections().remove(lastSection1); - Section lastSection1 = docs1.getLastSection(); + // 在docs2中查找"三、流程图"的位置 + TextSelection[] selectionsInDocs2 = docs2.findAllString("三、流程图", true, true); - // 删除最后一个节 - docs1.getSections().remove(lastSection1); + if (selectionsInDocs2.length > 0) { + // 获取第一个匹配的位置 + TextSelection selectionInDocs2 = selectionsInDocs2[0]; - // 提取所有表格 - List allTables = extractAllTables(docs2); + // 获取包含文本的段落 - 通过遍历节和段落来查找 + Paragraph targetParagraphInDocs2 = findParagraphContainingSelection(docs2, selectionInDocs2); - if (allTables.size() >= 4) { - // 拆分表格:前2个表格,后2个表格 - List
firstTwoTables = allTables.subList(0, 1); + if (targetParagraphInDocs2 != null) { + // 提取docs2中"三、流程图"前面和后面的内容 + List contentBeforeFlowChart = extractContentBeforeParagraph(docs2, targetParagraphInDocs2); + List contentAfterFlowChart = extractContentAfterParagraph(docs2, targetParagraphInDocs2); - TextPosition position = findTextPosition(docs1, "流程图"); + // 在docs1中查找"流程图"文本位置 + Paragraph targetParagraphInDocs1= findAutoNumberedFlowchartParagraph(docs1); - if (position != null) { - // 在前面插入前2个表格 - insertTablesBeforeText(docs1, firstTwoTables, position); - - // 获取docs2中剩余的内容(除了前两个表格) - List remainingContent = extractRemainingContent(docs2, firstTwoTables.size()); - - // 将剩余内容插入到docs1的最后一节 - insertContentToLastSection(docs1, remainingContent); + if (targetParagraphInDocs1 != null) { + System.out.println("成功找到自动编号的流程图段落: '" + targetParagraphInDocs1.getText().trim() + "'"); - // 保存合并后的文档 - docs1.saveToFile(outFile.getPath(), FileFormat.Docx); + if (targetParagraphInDocs1 != null) { + // 在docs1的"流程图"前面插入docs2中"三、流程图"前面的内容 + insertContentBeforeParagraph(docs1, contentBeforeFlowChart, targetParagraphInDocs1); - docs1.dispose(); - docs2.dispose(); + // 在docs1的"流程图"后面插入docs2中"三、流程图"后面的内容 + insertContentAfterParagraph(docs1, contentAfterFlowChart, targetParagraphInDocs1); - System.out.println("文档合并成功!"); + + // 保存合并后的文档 + docs1.saveToFile(outFile.getPath(), FileFormat.Docx); + System.out.println("文档合并成功!"); + } else { + System.out.println("在目标文档中未找到包含'流程图'的段落"); + } + } else { + System.out.println("在目标文档中未找到文本'流程图'"); + } + } else { + System.out.println("在源文档中未找到包含'三、流程图'的段落"); + } } else { - System.out.println("未找到文本'流程图'"); + System.out.println("在源文档中未找到文本'三、流程图'"); } - } else { - System.out.println("源文档中的表格数量不足4个,当前只有: " + allTables.size()); + } finally { + docs1.dispose(); + docs2.dispose(); } - - } - /** - * 提取剩余内容(除了前n个表格) + * 查找自动编号的"1.流程图"段落 */ - private static List extractRemainingContent(Document document, int tablesToSkip) { - List remainingContent = new ArrayList<>(); - int skippedTables = 0; + private static Paragraph findAutoNumberedFlowchartParagraph(Document document) { + System.out.println("开始查找自动编号的流程图段落..."); - for (int i = 0; i < document.getSections().getCount(); i++) { - Section section = document.getSections().get(i); - for (int j = 0; j < section.getBody().getChildObjects().getCount(); j++) { - DocumentObject obj = section.getBody().getChildObjects().get(j); + for (Section section : (Iterable
) document.getSections()) { + for (Paragraph paragraph : (Iterable) section.getParagraphs()) { + String paragraphText = paragraph.getText().trim(); - if (obj instanceof Table) { - if (skippedTables < tablesToSkip) { - skippedTables++; - continue; // 跳过前n个表格 + // 检查段落是否包含"流程图" + if (paragraphText.contains("流程图")) { + System.out.println("找到包含'流程图'的段落: '" + paragraphText + "'"); + + // 检查是否是自动编号段落 + if (isAutoNumberedParagraph(paragraph)) { + System.out.println("这是一个自动编号段落"); + + // 进一步验证是否符合"1.流程图"的格式 + if (isNumberedFlowchartFormat(paragraph, paragraphText)) { + System.out.println("符合编号流程图格式"); + return paragraph; + } + } else { + System.out.println("这不是自动编号段落"); } } - - // 克隆对象以避免重复引用问题 - remainingContent.add(obj.deepClone()); - } - } - return remainingContent; - } - - - - - /** - * 将内容插入到最后一节 - */ - private static void insertContentToLastSection(Document docs1, List content) { - int lastSectionIndex = docs1.getSections().getCount() - 1; - Section lastSection = docs1.getSections().get(lastSectionIndex); - - // 在插入前添加分页符(可选) - Paragraph pageBreak = new Paragraph(docs1); - pageBreak.appendBreak(BreakType.Page_Break); - lastSection.getBody().getChildObjects().add(pageBreak); - - // 插入剩余内容 - for (DocumentObject obj : content) { - lastSection.getBody().getChildObjects().add(obj); - } - } - - - - - /** - * 提取文档中的所有表格 - */ - private static List
extractAllTables(Document doc) { - List
tables = new ArrayList<>(); - - for (Object sectionObj : doc.getSections()) { - Section section = (Section) sectionObj; - - for (Object obj : section.getBody().getChildObjects()) { - if (obj instanceof Table) { - tables.add((Table) obj); - } } } - return tables; + System.out.println("未找到符合条件的自动编号流程图段落"); + return null; } + + /** - * 查找文本位置 + * 验证是否符合编号流程图的格式 */ - private static TextPosition findTextPosition(Document doc, String targetText) { - for (int s = 0; s < doc.getSections().getCount(); s++) { - Section section = doc.getSections().get(s); + private static boolean isNumberedFlowchartFormat(Paragraph paragraph, String paragraphText) { + // 检查文本是否包含"流程图" + if (!paragraphText.contains("流程图")) { + return false; + } - for (int p = 0; p < section.getParagraphs().getCount(); p++) { - Paragraph paragraph = section.getParagraphs().get(p); - String paragraphText = paragraph.getText(); + // 检查格式:数字 + 点 + 文本 + // 匹配 "1.流程图", "1. 流程图", "1.流程图说明" 等格式 + if (paragraphText.matches("^\\d+\\..*流程图.*") || + paragraphText.matches("^\\d+\\.\\s*流程图.*")) { + return true; + } - if (paragraphText.contains(targetText)) { - return new TextPosition(s, p, paragraphText.indexOf(targetText)); + // 对于复杂的自动编号,可能数字和文本是分开的 + // 这种情况下主要依靠 isAutoNumberedParagraph 的判断 + return true; + } + + + + + /** + * 判断段落是否是自动编号段落 + */ + private static boolean isAutoNumberedParagraph(Paragraph paragraph) { + // 方法1:检查列表格式 + if (paragraph.getListFormat() != null) { + // 检查是否有列表级别 + if (paragraph.getListFormat().getListLevelNumber() >= 0) { + System.out.println(" 通过列表级别判断为自动编号"); + return true; + } + + + } + + // 方法2:检查格式特征 + if (paragraph.getFormat() != null) { + // 自动编号通常有特定的缩进 + if (paragraph.getFormat().getLeftIndent() > 0 || + paragraph.getFormat().getFirstLineIndent() != 0) { + System.out.println(" 通过缩进格式判断为自动编号"); + return true; + } + } + + // 方法3:检查文本模式(数字. 开头) + String text = paragraph.getText().trim(); + if (text.matches("^\\d+\\..*")) { + System.out.println(" 通过文本模式判断为自动编号"); + return true; + } + + return false; + } + + + /** + * 查找包含文本选择的段落 + */ + private static Paragraph findParagraphContainingSelection(Document doc, TextSelection selection) { + for (int i = 0; i < doc.getSections().getCount(); i++) { + Section section = doc.getSections().get(i); + for (int j = 0; j < section.getParagraphs().getCount(); j++) { + Paragraph paragraph = section.getParagraphs().get(j); + // 检查这个段落是否包含选中的文本 + if (paragraph.getText().contains(selection.getSelectedText())) { + return paragraph; } } } @@ -569,65 +607,154 @@ public class OutputWordUtil { } /** - * 在指定文本前插入表格 + * 提取文档中指定段落之前的所有内容 */ - private static void insertTablesBeforeText(Document mainDoc, List
tables, TextPosition position) { - Section mainSection = mainDoc.getSections().get(position.getSectionIndex()); - Paragraph targetParagraph = mainSection.getParagraphs().get(position.getParagraphIndex()); - int insertIndex = mainSection.getBody().getChildObjects().indexOf(targetParagraph); + private static List extractContentBeforeParagraph(Document doc, Paragraph targetParagraph) { + List content = new ArrayList<>(); - // 在前方插入表格(反向插入以保持顺序) - for (int i = tables.size() - 1; i >= 0; i--) { - Table clonedTable = tables.get(i).deepClone(); - mainSection.getBody().getChildObjects().insert(insertIndex, clonedTable); + boolean foundTarget = false; - // 在每个表格前添加一个空段落作为间隔 - Paragraph spacingPara = new Paragraph(mainDoc); - mainSection.getBody().getChildObjects().insert(insertIndex, spacingPara); + // 遍历所有节 + for (int i = 0; i < doc.getSections().getCount(); i++) { + Section section = doc.getSections().get(i); + + // 遍历节中的所有子对象 + for (int j = 0; j < section.getBody().getChildObjects().getCount(); j++) { + DocumentObject obj = section.getBody().getChildObjects().get(j); + + if (obj == targetParagraph) { + foundTarget = true; + break; + } + + // 克隆并添加对象 + DocumentObject clonedObj = cloneDocumentObject(obj); + if (clonedObj != null) { + content.add(clonedObj); + } + } + + if (foundTarget) { + break; + } } + + return content; } /** - * 在指定文本后插入表格 + * 提取文档中指定段落之后的所有内容 */ - private static void insertTablesAfterText(Document mainDoc, List
tables, TextPosition position) { - Section mainSection = mainDoc.getSections().get(position.getSectionIndex()); - Paragraph targetParagraph = mainSection.getParagraphs().get(position.getParagraphIndex()); - int insertIndex = mainSection.getBody().getChildObjects().indexOf(targetParagraph) + 1; + private static List extractContentAfterParagraph(Document doc, Paragraph targetParagraph) { + List content = new ArrayList<>(); - // 在后方插入表格 - for (Table table : tables) { - Table clonedTable = table.deepClone(); - mainSection.getBody().getChildObjects().insert(insertIndex, clonedTable); - insertIndex++; + boolean foundTarget = false; - // 在每个表格后添加一个空段落作为间隔 - Paragraph spacingPara = new Paragraph(mainDoc); - mainSection.getBody().getChildObjects().insert(insertIndex, spacingPara); - insertIndex++; + // 遍历所有节 + for (int i = 0; i < doc.getSections().getCount(); i++) { + Section section = doc.getSections().get(i); + + // 遍历节中的所有子对象 + for (int j = 0; j < section.getBody().getChildObjects().getCount(); j++) { + DocumentObject obj = section.getBody().getChildObjects().get(j); + + if (foundTarget) { + // 克隆并添加目标之后的对象 + DocumentObject clonedObj = cloneDocumentObject(obj); + if (clonedObj != null) { + content.add(clonedObj); + } + } + + if (obj == targetParagraph) { + foundTarget = true; + } + } } + + return content; } /** - * 文本位置信息类 + * 在指定段落前插入内容 */ - static class TextPosition { - private int sectionIndex; - private int paragraphIndex; - private int textOffset; + private static void insertContentBeforeParagraph(Document doc, List content, Paragraph targetParagraph) { + // 找到目标段落所在的节和索引 + int targetIndex = -1; + Section targetSection = null; - public TextPosition(int sectionIndex, int paragraphIndex, int textOffset) { - this.sectionIndex = sectionIndex; - this.paragraphIndex = paragraphIndex; - this.textOffset = textOffset; + for (int i = 0; i < doc.getSections().getCount(); i++) { + Section section = doc.getSections().get(i); + for (int j = 0; j < section.getBody().getChildObjects().getCount(); j++) { + if (section.getBody().getChildObjects().get(j) == targetParagraph) { + targetSection = section; + targetIndex = j; + break; + } + } + if (targetSection != null) break; } - public int getSectionIndex() { return sectionIndex; } - public int getParagraphIndex() { return paragraphIndex; } - public int getTextOffset() { return textOffset; } + if (targetSection != null && targetIndex != -1) { + // 在目标位置之前插入内容(逆序插入以保证顺序正确) + for (int i = content.size() - 1; i >= 0; i--) { + DocumentObject obj = content.get(i); + targetSection.getBody().getChildObjects().insert(targetIndex, obj); + } + } } + + + + + + /** + * 在指定段落之后插入内容 + */ + private static void insertContentAfterParagraph(Document document, List content, Paragraph targetParagraph) { + + + + int lastSectionIndex = document.getSections().getCount() - 1; + Section lastSection = document.getSections().get(lastSectionIndex); + + // 在插入前添加分页符(可选) + Paragraph pageBreak = new Paragraph(document); + pageBreak.appendBreak(BreakType.Page_Break); + lastSection.getBody().getChildObjects().add(pageBreak); + + // 插入剩余内容 + for (DocumentObject obj : content) { + lastSection.getBody().getChildObjects().add(obj); + } + + + } + + + + + /** + * 克隆文档对象 + */ + private static DocumentObject cloneDocumentObject(DocumentObject obj) { + try { + if (obj instanceof Paragraph) { + return ((Paragraph) obj).deepClone(); + } else if (obj instanceof Table) { + return ((Table) obj).deepClone(); + } + // 可以添加其他类型的处理 + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + /** * 生成word文件 * @@ -1073,13 +1200,17 @@ public class OutputWordUtil { for (int i = 2; i < doc2.getSections().getCount(); i++) { Section targetSection = doc2.getSections().get(i); - PageSetup pageSetup = targetSection.getPageSetup(); - PageOrientation orientation = pageSetup.getOrientation(); - // 根据合并文档节的页面方向选择模板 - PageOrientation mergeOrientation = pageSetup.getOrientation(); - Document templateDoc = (mergeOrientation == PageOrientation.Landscape) ? doc3 : doc1; + double width = targetSection.getPageSetup().getPageSize().getWidth(); + double height = targetSection.getPageSetup().getPageSize().getHeight(); + + // 实际方向(根据尺寸) + boolean actualLandscape = isLandscapeBySize(width, height); + + Document templateDoc = actualLandscape ? doc3 : doc1; + + // 复制模板文档的页眉和页脚到新文档 HeaderFooter sourceHeader = templateDoc.getSections().get(0).getHeadersFooters().getHeader(); @@ -1114,10 +1245,16 @@ public class OutputWordUtil { Section targetSection = doc2.getSections().get(i); HeaderFooter targetFooter = targetSection.getHeadersFooters().getFooter(); - PageSetup pageSetup = targetSection.getPageSetup(); + double width = targetSection.getPageSetup().getPageSize().getWidth(); + double height = targetSection.getPageSetup().getPageSize().getHeight(); + + // 实际方向(根据尺寸) + boolean actualLandscape = isLandscapeBySize(width, height); + + Document templateDoc = actualLandscape ? doc3 : doc1; + + - PageOrientation mergeOrientation = pageSetup.getOrientation(); - Document templateDoc = (mergeOrientation == PageOrientation.Landscape) ? doc3 : doc1; HeaderFooter sourceFooter = templateDoc.getSections().get(0).getHeadersFooters().getFooter(); targetFooter.getChildObjects().clear(); @@ -1859,6 +1996,18 @@ public class OutputWordUtil { } + /** + * 判断是否为横向 + * @param width + * @param height + * @return + */ + public static boolean isLandscapeBySize(double width, double height) { + return width > height; + } + + + /** * 生成word文件 *