这个问题是困扰了我好几天,走了很多弯路。但是这个问题解决后我对POI就有了新的认识。或者说对word结构有了新的认识。
一开始自己建了头部不分栏,内容分栏的文档。类似于下图这样。
分栏文档
将word文档另存为成XML文件如下图所示
分栏后的XML结构
分栏后此时word文档就拥有了两个 sectPr 标签组,sectPr这个标签组就是用来标识分栏结构了,从里面的一些属性也可以看出来。 单纯的分栏结构还是比较简单的,跟着文件,依葫芦画瓢。
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
splitColumn(document);
document.write(new FileOutputStream("D:\\workspace\\demo\\src\\test\\resources\\CreateWordFormulaFromLaTeX.docx"));
}
/**
* 分栏
* @param document
*/
private static void splitColumn(XWPFDocument document) {
XWPFParagraph paragraph = document.createParagraph();
paragraph.createRun().setText("4444444444444444444444444444444444444444444");
document.createParagraph().createRun().setText("33333333333333333333333333333333333333333333333333");
CTP ctp1 = document.createParagraph().getCTP();
CTBorder bottom = ctp1.addNewPPr().addNewPBdr().addNewTop();
bottom.setVal(STBorder.Enum.forInt(3));
// 分栏
CTBody body = document.getDocument().getBody();
CTSectPr ctSectPr1 = body.addNewP().addNewPPr().addNewSectPr();
ctSectPr1.addNewCols().setNum(BigInteger.valueOf(1));
XWPFRun run = document.createParagraph().createRun();
run.setText("sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss");
run.setTextHighlightColor("lightGray");
CTSectPr ctSectPr = body.addNewSectPr();
ctSectPr.addNewType().setVal(STSectionMark.Enum.forString("continuous"));
CTColumns ctColumns = ctSectPr.addNewCols();
ctColumns.setNum(BigInteger.valueOf(2));
ctColumns.setSep(STOnOff.Enum.forInt(1));
}
分栏问题是解决,但是页眉,页脚,页边距这些设置全都不生效了。也就是加入示例二
中的代码。没办法还是得老老实实看源码结构。将上面文档改成如下图这样。
另存为XML文档
分栏后页眉页脚的word结构
POI生成的页眉页脚结构
看完word结构后 比对POI生成的代码, 可以看出来word第一个sectPr实在P(段落)标签里面的,POI生成的sectPr是直接在body下面的。知道了问题那就找解决问题的方法。
给分栏设置页边距还是比较简单的只要传入CTSectPr对象就可以了
private static void setDocumentMarginForSec(CTSectPr sectPr,String left,String top, String right, String bottom) {
CTPageMar ctpagemar = sectPr.addNewPgMar();
if (!org.springframework.util.StringUtils.isEmpty(left)) {
ctpagemar.setLeft(new BigInteger(left));
}
if (!org.springframework.util.StringUtils.isEmpty(top)) {
ctpagemar.setTop(new BigInteger(top));
}
if (!org.springframework.util.StringUtils.isEmpty(right)) {
ctpagemar.setRight(new BigInteger(right));
}
if (!org.springframework.util.StringUtils.isEmpty(bottom)) {
ctpagemar.setBottom(new BigInteger(bottom));
}
ctpagemar.setHeader(new BigInteger(top).divide(new BigInteger("2")));
ctpagemar.setFooter(new BigInteger(bottom).divide(new BigInteger("2")));
}
纠结了很久的问题在于页眉页脚的设置 ,因为它在sect上是一个ref并不是直接加上去了。就是找这个关系找了很久。
其实把代码往里看几层就能找到,但是当时就困扰了很久。学会页眉的构造方式。创建相应方法如下
private static void createHeaderForSec(XWPFDocument document, CTSectPr ctSectPr1, String text,boolean withSplitLine) {
// 页眉文字
CTP ctp = CTP.Factory.newInstance();
XWPFParagraph paragraph = new XWPFParagraph(ctp, document);
ctp.addNewR().addNewT().setStringValue(text);
ctp.addNewR().addNewT().setSpace(SpaceAttribute.Space.PRESERVE);
XWPFParagraph paragraph2 = null;
if (withSplitLine){
// 分割线
CTP splitLine = CTP.Factory.newInstance();
paragraph2 = new XWPFParagraph(splitLine, document);
CTBorder bottom = splitLine.addNewPPr().addNewPBdr().addNewTop();
bottom.setVal(STBorder.Enum.forInt(3));
}
HdrDocument hdrDoc = HdrDocument.Factory.newInstance();
XWPFHeader header = (XWPFHeader) document.createRelationship(XWPFRelation.HEADER, XWPFFactory.getInstance(), 1);
CTHdrFtr hdr = header._getHdrFtr();
hdr.addNewP();
hdr.setPArray(0,paragraph.getCTP());
if (withSplitLine){
hdr.addNewP();
hdr.setPArray(1,paragraph2.getCTP());
}
CTHdrFtrRef ctHdrFtrRef = ctSectPr1.addNewHeaderReference();
ctHdrFtrRef.setType(STHdrFtr.DEFAULT);
ctHdrFtrRef.setId(document.getRelationId(header));
header.setHeaderFooter(hdr);
hdrDoc.setHdr(hdr);
header.setXWPFDocument(document);
}
页脚也是相同的原理
private static void createFooterForSec(XWPFDocument document, CTSectPr ctSectPr1) {
CTP pageNo = CTP.Factory.newInstance();
XWPFParagraph paragraph = new XWPFParagraph(pageNo, document);
CTPPr begin = pageNo.addNewPPr();
begin.addNewPStyle().setVal(STYLE_FOOTER);
begin.addNewJc().setVal(STJc.CENTER);
pageNo.addNewR().addNewFldChar().setFldCharType(STFldCharType.BEGIN);
pageNo.addNewR().addNewInstrText().setStringValue("PAGE \\* MERGEFORMAT");
pageNo.addNewR().addNewFldChar().setFldCharType(STFldCharType.SEPARATE);
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR end = pageNo.addNewR();
CTRPr endRPr = end.addNewRPr();
endRPr.addNewNoProof();
endRPr.addNewLang().setVal(LANG_ZH_CN);
end.addNewFldChar().setFldCharType(STFldCharType.END);
FtrDocument ftrDoc = org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument.Factory.newInstance();
XWPFFooter footer = (XWPFFooter) document.createRelationship(XWPFRelation.FOOTER, XWPFFactory.getInstance(), 1);
footer.setXWPFDocument(document);
CTHdrFtr ftr = footer._getHdrFtr();
ftr.addNewP();
ftr.setPArray(0,paragraph.getCTP());
CTHdrFtrRef ctHdrFtrRef = ctSectPr1.addNewFooterReference();
ctHdrFtrRef.setType(STHdrFtr.DEFAULT);
ctHdrFtrRef.setId(document.getRelationId(footer));
footer.setHeaderFooter(ftr);
ftrDoc.setFtr(ftr);
footer.setXWPFDocument(document);
}
整理不易 对你有用的话点个赞吧
原网址: 访问
创建于: 2023-06-05 17:03:38
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论