如何计算 DOCX 文件中 OOXML (document.xml) 中编号段落的左缩进?

问题描述 投票:0回答:1

我正在使用 DOCX 文件并检查 document.xml (OOXML) 文件以确定段落的左侧缩进。具体来说,我正在尝试计算从左边距到编号段落的第一个像素的距离。

我发现这非常棘手,尤其是对于编号段落。在某些情况下,缩进等于

indent
,但这并不一致。有时似乎是
indent - hanging-indent

我怀疑还有其他因素影响缩进计算,因为 MS Word 和 LibreOffice 都能正确呈现缩进。

任何人都可以解释用于计算 OOXML 中编号段落的左缩进的算法或规则吗?任何对相关文档的见解或参考将不胜感激。

(截图中看到的数据是edn格式,但它是通过Apache POI直接从ooxml获取的)

enter image description here

enter image description here

ms-word apache-poi openxml
1个回答
0
投票

Office Open XML 格式之外的 edn 格式存储 XML 的缩进如下所示:

...
<w:ind w:left="1440" w:hanging="480"/>
...

数值以 Twip(二十分之一英寸点)为单位,1440 Twip = 1 英寸。每英寸有 72 英寸点,并乘以 20 以避免 XML 中的浮点。因此每英寸有 1440 缇。

left
hanging
的含义如下:
left
决定从左页边框到文本的左缩进。
hanging
确定第一个文本行在其余文本行(如果有)之前悬挂多少,或者在文本之前悬挂多少编号符号。

下图所示:

enter image description here

所以上面的XML意思是:左缩进1英寸,悬挂缩进1/3英寸。

可以直接通过

Paragraph.setIndentFromLeft
Paragraph.setIndentationHanging
在段落设置中设置文本缩进。对于编号,也可以通过编号级别中的段落属性进行设置。

显示两者的完整示例:

import java.io.FileOutputStream;

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

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STNumberFormat;

import java.util.ArrayList;
import java.util.Arrays;

import java.math.BigInteger;

public class CreateWordListIndentation {

 public static void main(String[] args) throws Exception {

  ArrayList<String> documentList = new ArrayList<String>(
   Arrays.asList(
    new String[] {
     "One",
     "Two",
     "Three"
    }));

  // set numbering
  CTAbstractNum cTAbstractNum = CTAbstractNum.Factory.newInstance();
  //Next we set the AbstractNumId. This requires care.
  //Since we are in a new document we can start numbering from 0.
  //But if we have an existing document, we must determine the next free number first.
  cTAbstractNum.setAbstractNumId(BigInteger.valueOf(0));

  //Bullet list
  CTLvl cTLvl = cTAbstractNum.addNewLvl();
  cTLvl.addNewNumFmt().setVal(STNumberFormat.BULLET);
  cTLvl.addNewLvlText().setVal("-");

  XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
  XWPFDocument document = new XWPFDocument();
  XWPFNumbering numbering = document.createNumbering();

  BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
  BigInteger numID = numbering.addNum(abstractNumID);

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run=paragraph.createRun();
  run.setText("The list having defined gap between bullet point and text set by paragraph settings:");

  for (String string : documentList) {
   paragraph = document.createParagraph();
   paragraph.setNumID(numID);
   // set font size by paragraph run properties - used for the bukllet sysmbol
   paragraph.getCTP().getPPr().addNewRPr().addNewSz().setVal(BigInteger.valueOf(48)); // half pt
   // set indents in Twips (twentieth of an inch point), 1440 Twips = 1 inch
   paragraph.setIndentFromLeft(1440); // indent from left 1440 Twips = 1 inch
   paragraph.setIndentationHanging(1440/3); // indentation hanging 1440/3 Twips = 1/3 inch
                                            // so bullet point hangs 1/3 inch before the text at indentation 2/3 inch from left
   run = paragraph.createRun();
   run.setText(string);
   run.setFontSize(24);
  }

  paragraph = document.createParagraph();
  

  // the same bust set by numbering settings
  cTAbstractNum = CTAbstractNum.Factory.newInstance();
  cTAbstractNum.setAbstractNumId(BigInteger.valueOf(1));

  //Bullet list
  cTLvl = cTAbstractNum.addNewLvl();
  cTLvl.addNewNumFmt().setVal(STNumberFormat.BULLET);
  cTLvl.addNewLvlText().setVal("-");
  // paragraph properties in numbering level providing indentation
  cTLvl.addNewPPr();
  cTLvl.getPPr().addNewInd();
  cTLvl.getPPr().getInd().setLeft(1440);
  cTLvl.getPPr().getInd().setHanging(1440/3);

  abstractNum = new XWPFAbstractNum(cTAbstractNum);
  numbering = document.createNumbering();

  abstractNumID = numbering.addAbstractNum(abstractNum);
  numID = numbering.addNum(abstractNumID);

  paragraph = document.createParagraph();
  run = paragraph.createRun();
  run.setText("The list having defined gap between bullet point and text set by numbering settings:");

  for (String string : documentList) {
   paragraph = document.createParagraph();
   paragraph.setNumID(numID);
   // set font size by paragraph run properties - used for the bukllet sysmbol
   paragraph.getCTP().getPPr().addNewRPr().addNewSz().setVal(BigInteger.valueOf(48)); // half pt
   run = paragraph.createRun();
   run.setText(string);
   run.setFontSize(24);
  }

  paragraph = document.createParagraph();

  FileOutputStream out = new FileOutputStream("./CreateWordListIndentation.docx");
  document.write(out);
  out.close();
  document.close();

 }
}
© www.soinside.com 2019 - 2024. All rights reserved.