guyue_1991 2024-05-21 12:15 采纳率: 0%
浏览 103
已结题

poi合并多个word成一个新word,原word中横版没了.

用apache poi合并多个word并生成一个新word,现在遇到个问题,原word中有竖版有横版,怎么在合并时按原始word的排版保留原样式.

/**
     * 多个word合并,按照文件顺序合并为一个word
     *
     * @param mergeFileName 指定合并后的目标文件名
     * @param fileNames     指定所有需要合并的word文件名
     */
    public static void mergeMultiWord(String mergeFileName, List<String> fileNames) {
        try {
            OutputStream dest = new FileOutputStream(mergeFileName);
            ArrayList<XWPFDocument> documentList = new ArrayList<>();
            XWPFDocument mergeDoc = null;
            for (int i = 0; i < fileNames.size(); i++) {
                FileInputStream in = new FileInputStream(fileNames.get(i));
                OPCPackage open = OPCPackage.open(in);
                XWPFDocument document = new XWPFDocument(open);
                documentList.add(document);
            }
            for (int i = 0; i < documentList.size(); i++) {
                mergeDoc = documentList.get(0);
                XWPFDocument document = documentList.get(i);

                if (i != documentList.size() - 1) {
                    // 最后一页不再设置分页符
                    document.createParagraph().setPageBreak(true);
                }

                if (i != 0) {
                    appendBody(mergeDoc, document);
                }
            }
            mergeDoc.write(dest);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        Map<String, String> map = new HashMap<>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }
        appendBody(src1Body, src2Body, map);
    }

    private static void appendBody(CTBody src, CTBody append, Map<String, String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);

        String srcString = src.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        if (map != null && !map.isEmpty()) {
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src.set(makeBody);
    }

以上是我现在的代码

  • 写回答

27条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-21 12:15
    关注
    获得0.70元问题酬金

    引自免费微信小程序:皆我百晓生

    为了确保合并后的Word文档能保留原文档的排版样式,你需要使用Apache POI中的XWPFDocument类进行操作。下面是一个详细的步骤和示例代码,展示了如何合并多个Word文档,并保持原有的排版风格。

    首先,确保你已经添加了Apache POI的依赖。如果你使用的是Maven,可以在pom.xml文件中添加以下依赖:

    <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.0.0</version>
        </dependency>
    </dependencies>
    

    接下来是合并Word文档的Java代码示例:

    import org.apache.poi.xwpf.usermodel.*;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    
    public class WordMerger {
    
        public static void main(String[] args) throws IOException {
            List<File> sourceDocuments = new ArrayList<>();
            // 添加要合并的Word文档路径到列表中
            sourceDocuments.add(new File("path_to_document1.docx"));
            sourceDocuments.add(new File("path_to_document2.docx"));
    
            mergeDocuments(sourceDocuments, "merged_document.docx");
        }
    
        private static void mergeDocuments(List<File> sourceDocuments, String outputFilePath) throws IOException {
            XWPFDocument destinationDoc = new XWPFDocument();
    
            for (File sourceFile : sourceDocuments) {
                XWPFDocument sourceDoc = new XWPFDocument(new FileInputStream(sourceFile));
    
                int i = 0;
                for (IBodyElement bodyElement : sourceDoc.getBodyElements()) {
                    if (i > 0) {
                        // 如果不是第一个文档,插入一个分页符
                        destinationDoc.createParagraph().insertNewRun(0).addBreak(BreakType.PAGE);
                    }
                    copyBodyElement(bodyElement, destinationDoc);
                    i++;
                }
    
                sourceDoc.close();
            }
    
            FileOutputStream out = new FileOutputStream(outputFilePath);
            destinationDoc.write(out);
            destinationDoc.close();
            out.close();
        }
    
        private static void copyBodyElement(IBodyElement element, XWPFDocument destinationDoc) {
            switch (element.getElementType()) {
                case PARAGRAPH:
                    XWPFParagraph destPara = destinationDoc.createParagraph();
                    destPara.setParagraphStyle(element.getParagraphStyle());
                    for (IRunElement runElement : ((XWPFParagraph) element).getRuns()) {
                        IRunElement destRun = destPara.createRun();
                        destRun.setText(runElement.getText(0));
                        destRun.setBold(runElement.isBold());
                        destRun.setFontFamily(runElement.getFontFamily());
                        destRun.setFontSize(runElement.getFontSize());
                        // 处理其他格式属性...
                    }
                    break;
                case TABLE:
                    XWPFTable destTable = destinationDoc.createTable(((XWPFTable) element).getNumRows(), ((XWPFTable) element).getNumColumns());
                    for (int row = 0; row < ((XWPFTable) element).getNumRows(); row++) {
                        XWPFTableRow destRow = destTable.getRow(row);
                        for (int cell = 0; cell < ((XWPFTable) element).getRow(row).getCellCount(); cell++) {
                            XWPFTableCell destCell = destRow.getCell(cell);
                            for (IRunElement runElement : ((XWPFTableCell) element.getRow(row).getCell(cell)).getParagraphs().get(0).getRuns()) {
                                IRunElement destRun = destCell.getParagraphs().get(0).createRun();
                                destRun.setText(runElement.getText(0));
                                destRun.setBold(runElement.isBold());
                                destRun.setFontFamily(runElement.getFontFamily());
                                destRun.setFontSize(runElement.getFontSize());
                                // 处理其他格式属性...
                            }
                        }
                    }
                    break;
                // 处理其他元素类型...
                default:
                    break;
            }
        }
    }
    

    这段代码首先读取每个源Word文档,然后逐个处理文档中的段落、表格等元素,并将它们复制到目标文档中。注意,这里只处理了段落和表格,你可能需要根据实际需求扩展其他元素类型的处理(例如图片、列表等)。

    运行这个程序后,它会创建一个新的Word文档,其中包含了所有源文档的内容,并尽可能地保留了原始的排版样式。如果你发现某些样式没有正确保留,可以检查代码中的样式设置部分,看看是否有遗漏的属性。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 5月29日
  • 赞助了问题酬金20元 5月21日
  • 修改了问题 5月21日
  • 创建了问题 5月21日

悬赏问题

  • ¥30 vb net 使用 sendMessage 如何输入鼠标坐标
  • ¥200 求能开发抖音自动回复卡片的软件
  • ¥15 关于freesurfer使用freeview可视化的问题
  • ¥100 谁能在荣耀自带系统MagicOS版本下,隐藏手机桌面图标?
  • ¥15 求SC-LIWC词典!
  • ¥20 有关esp8266连接阿里云
  • ¥15 C# 调用Bartender打印机打印
  • ¥15 我这个代码哪里有问题 acm 平台上显示错误 90%,我自己运行好像没什么问题
  • ¥50 C#编程中使用printDocument类实现文字排版打印问题
  • ¥15 找会编程的帅哥美女 可以用MATLAB里面的simulink编程,用Keil5编也可以。