java - 删除 XWPFParagraph 会为其保留段落符号 (¶)

标签 java apache-poi xwpf

我正在尝试使用 Apache POI 从 Microsoft Word 文档中删除一组连续的段落。

据我了解,可以通过删除段落的所有运行来删除段落,方法如下:

/*
 * Deletes the given paragraph.
 */
public static void deleteParagraph(XWPFParagraph p) {
    if (p != null) {
        List<XWPFRun> runs = p.getRuns();
        //Delete all the runs
        for (int i = runs.size() - 1; i >= 0; i--) {
            p.removeRun(i);
        }
        p.setPageBreak(false); //Remove the eventual page break
    }
}

其实是可以的,但是有一点奇怪。删除的段落 block 不会从文档中消失,但会转换为一组空行。就像每个段落都会被转换成一个新行。

通过打印代码中的段落内容,我实际上可以看到一个空格(对于每个被删除的空格)。直接从文档中查看内容,启用格式标记的可视化,我可以看到:

enter image description here

¶的竖列对应删除元素的 block 。

你有什么想法吗?我希望我的段落完全被删除。

我还尝试通过替换文本(使用 setText())并删除可以自动添加的最终空格,这样:

p.setSpacingAfter(0);
p.setSpacingAfterLines(0);
p.setSpacingBefore(0);
p.setSpacingBeforeLines(0);
p.setIndentFromLeft(0);
p.setIndentFromRight(0);
p.setIndentationFirstLine(0);
p.setIndentationLeft(0);
p.setIndentationRight(0);

但没有运气。

最佳答案

我会通过删除段落来删除段落,而不是仅删除该段落中的运行。删除段落不是 apache poi 高级 API 的一部分。但是使用 XWPFDocument.getDocument().getBody() 我们可以获得低级别的 CTBody 并且有一个 removeP(int i)

例子:

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

import java.awt.Desktop;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

public class WordRemoveParagraph {

 /*
  * Deletes the given paragraph.
  */

 public static void deleteParagraph(XWPFParagraph p) {
  XWPFDocument doc = p.getDocument();
  int pPos = doc.getPosOfParagraph(p);
  //doc.getDocument().getBody().removeP(pPos);
  doc.removeBodyElement(pPos);
 }

 public static void main(String[] args) throws IOException, InvalidFormatException {

  XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));

  int pNumber = doc.getParagraphs().size() -1;
  while (pNumber >= 0) {
   XWPFParagraph p = doc.getParagraphs().get(pNumber);
   if (p.getParagraphText().contains("delete")) {
    deleteParagraph(p);
   }
   pNumber--;
  }

  FileOutputStream out = new FileOutputStream("result.docx");
  doc.write(out);
  out.close();
  doc.close();

  System.out.println("Done");
  Desktop.getDesktop().open(new File("result.docx"));

 }

}

这会删除文档 source.docx 中文本包含“delete”的所有段落,并将结果保存在 result.docx 中。


编辑:

尽管 doc.getDocument().getBody().removeP(pPos); 有效,但它不会更新 XWPFDocument 的段落列表。因此它将破坏段落迭代器和对该列表的其他访问,因为列表仅在再次阅读文档时更新。

所以更好的方法是使用 doc.removeBodyElement(pPos); 代替。 removeBodyElement(int pos)doc.getDocument().getBody().removeP(pos); 完全相同,如果 pos 指向文档正文中的 pagagraph,因为该段落是还有一个 BodyElement。但除此之外,它还会更新 XWPFDocument 的段落列表。

关于java - 删除 XWPFParagraph 会为其保留段落符号 (¶),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40345285/

相关文章:

java - 无法访问 NPOIFSFileSystem

java - 替换 .docx 中的文本模板(Apache POI、Docx4j 或其他)

java - Hibernate 与子项一起重复 INSERT 记录

java - 无法在 UI Automator 查看器中获取可点击按钮

java - 项目中包含jar。并包括Android Library项目

java - HSSFCell - 确定什么类型的数字

java - 错误: Could not find or load main class pj2 on bash

java - (Akka HTTP)当我将 .XLSX 文件作为数组 [字节] 发送给用户时,用户将获得该文件夹

java - 如何使用 POI XWPF 更改所选文字颜色

java apache poi - xwpfparagraph 到字符串转换