我正在使用 DOCX 文件并检查 document.xml (OOXML) 文件以确定段落的左侧缩进。具体来说,我正在尝试计算从左边距到编号段落的第一个像素的距离。
我发现这非常棘手,尤其是对于编号段落。在某些情况下,缩进等于
indent
,但这并不一致。有时似乎是indent - hanging-indent
。
我怀疑还有其他因素影响缩进计算,因为 MS Word 和 LibreOffice 都能正确呈现缩进。
任何人都可以解释用于计算 OOXML 中编号段落的左缩进的算法或规则吗?任何对相关文档的见解或参考将不胜感激。
(截图中看到的数据是edn格式,但它是通过Apache POI直接从ooxml获取的)
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
确定第一个文本行在其余文本行(如果有)之前悬挂多少,或者在文本之前悬挂多少编号符号。
下图所示:
所以上面的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();
}
}