POI生成Word多级标题格式

该博客介绍了如何使用 Apache POI 库在 Java 中操作 Word 文档,包括通过模板文件创建标题样式和自定义标题样式的方法。详细步骤涉及创建模板文件、设置文档整体样式、定义标题级别和字体属性,并展示了生成标题后的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、使用模板文件生成标题
1、创建模板文件

新建一个doc文件,如format.doc,创建标题,如标题1、标题2……
在这里插入图片描述

2、获得模板文档的整体样式
// 新建的word文档对象
XWPFDocument doc = new XWPFDocument();
// word整体样式
// 读取模板文档
XWPFDocument template = new XWPFDocument(new FileInputStream("D:\\test\\poi\\word\\format.docx"));
// 获得模板文档的整体样式
CTStyles wordStyles = template.getStyle();
// 获取新建文档对象的样式
XWPFStyles newStyles = doc.createStyles();
// 关键行// 修改设置文档样式为静态块中读取到的样式
newStyles.setStyles(wordStyles);
3、使用标题样式
// 标题1,1级大纲
XWPFParagraph para1 = doc.createParagraph();
// 关键行// 1级大纲
para1.setStyle("1");
XWPFRun run1 = para1.createRun();
// 标题内容
run1.setText("标题1");

// 标题2,2级大纲
XWPFParagraph para2 = doc.createParagraph();
// 关键行// 2级大纲
para2.setStyle("2");
XWPFRun run2 = para2.createRun();
// 标题内容
run2.setText("标题2");

// 正文
XWPFParagraph paraX = doc.createParagraph();
XWPFRun runX = paraX.createRun();
for(int i=0;i<100;i++) {
	// 正文内容
	runX.setText("正文\r\n");
}

// word写入到文件
FileOutputStream fos;
try {
	fos = new FileOutputStream("D:\\test\\poi\\word\\test.docx");
	doc.write(fos);
	fos.close();
} catch (Exception e) {
	// TODO 自动生成的 catch 块
	e.printStackTrace();
}
4、结果展示

在这里插入图片描述

二、自定义标题
1、生成标题方法
 /**
     * 
     * @param doc
     * @param styles
     * @param strStyleId	标题id
     * @param headingLevel	标题级别
     * @param pointSize	字体大小(/2)
     * @param hexColor	字体颜色
     * @param typefaceName	字体名称(默认宋体)
     */
    public void createHeadingStyle(XWPFDocument doc, XWPFStyles styles, String strStyleId, 
    		int headingLevel, int pointSize, String hexColor, String typefaceName) {
    	//创建样式
    	CTStyle ctStyle = CTStyle.Factory.newInstance();
    	//设置id
        ctStyle.setStyleId(strStyleId);
        
        CTString styleName = CTString.Factory.newInstance();
        styleName.setVal(strStyleId);
        ctStyle.setName(styleName);
        
        CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
        indentNumber.setVal(BigInteger.valueOf(headingLevel));
        
     // 数字越低在格式栏中越突出
        ctStyle.setUiPriority(indentNumber);
        
        CTOnOff onoffnull = CTOnOff.Factory.newInstance();
        ctStyle.setUnhideWhenUsed(onoffnull);
        
     // 样式将显示在“格式”栏中
        ctStyle.setQFormat(onoffnull);
        
     // 样式定义给定级别的标题
        CTPPr ppr = CTPPr.Factory.newInstance();
        ppr.setOutlineLvl(indentNumber);
        ctStyle.setPPr(ppr);
        
        XWPFStyle style = new XWPFStyle(ctStyle);

        CTHpsMeasure size = CTHpsMeasure.Factory.newInstance();
        size.setVal(new BigInteger(String.valueOf(pointSize)));
        CTHpsMeasure size2 = CTHpsMeasure.Factory.newInstance();
        size2.setVal(new BigInteger(String.valueOf(pointSize)));
        
        CTFonts fonts = CTFonts.Factory.newInstance();
        if(typefaceName == null || typefaceName.equals("")) typefaceName = "宋体";
        fonts.setAscii(typefaceName);	//字体

        CTRPr rpr = CTRPr.Factory.newInstance();
        rpr.setRFonts(fonts);
        rpr.setSz(size);
        rpr.setSzCs(size2);	//字体大小
        
        CTColor color=CTColor.Factory.newInstance();
        color.setVal(hexToBytes(hexColor));
        rpr.setColor(color);	//字体颜色
        style.getCTStyle().setRPr(rpr);
        // is a null op if already defined

        style.setType(STStyleType.PARAGRAPH);
        styles.addStyle(style);
    }
    
    public static byte[] hexToBytes(String hexString) {
        HexBinaryAdapter adapter = new HexBinaryAdapter();
        byte[] bytes = adapter.unmarshal(hexString);
        return bytes;
   }
2、调用生成标题方法
// 新建的word文档对象
XWPFDocument doc = new XWPFDocument();
// 获取新建文档对象的样式
XWPFStyles newStyles = doc.createStyles();
String heading1 = "My Heading 1";
docUtils.createHeadingStyle(doc, newStyles, heading1, 1, 45, "000000", "宋体");
XWPFParagraph para1 = doc.createParagraph();
para1.setStyle("My Heading 1");
XWPFRun run1 = para1.createRun();
run1.setText("My Heading 1");
// word写入到文件
FileOutputStream fos;
try {
	fos = new FileOutputStream("D:\\test\\poi\\word\\test.docx");
	doc.write(fos);
	fos.close();
} catch (Exception e) {
	// TODO 自动生成的 catch 块
	e.printStackTrace();
}
3、结果展示

在这里插入图片描述
参考文章:

以下是Java POI生成Word多级目录的完整代码示例: ```java import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.poi.xwpf.usermodel.BreakType; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFStyle; import org.apache.poi.xwpf.usermodel.XWPFStyles; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNumId; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering.AbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering.Num; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STNumberFormat; public class GenerateWordWithMultiLevelTOC { public static void main(String[] args) throws IOException, XmlException { // 创建一个空白的Word文档对象 XWPFDocument document = new XWPFDocument(); // 添加自定义样式 addCustomHeadingStyle(document, "标题 1", 1); addCustomHeadingStyle(document, "标题 2", 2); addCustomHeadingStyle(document, "标题 3", 3); // 添加多级目录 addMultiLevelTOC(document, "目录", 1, 3); // 添加正文内容 XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); run.setText("这是一级标题"); run.addBreak(BreakType.TEXT_WRAPPING); run.setText("这是一级标题下的内容"); paragraph = document.createParagraph(); run = paragraph.createRun(); run.setText("这是二级标题"); run.addBreak(BreakType.TEXT_WRAPPING); run.setText("这是二级标题下的内容"); paragraph = document.createParagraph(); run = paragraph.createRun(); run.setText("这是三级标题"); run.addBreak(BreakType.TEXT_WRAPPING); run.setText("这是三级标题下的内容"); // 输出到文件 FileOutputStream out = new FileOutputStream(new File("output.docx")); document.write(out); out.close(); document.close(); } /** * 添加自定义标题样式 * * @param document Word文档对象 * @param strStyleName 样式名称 * @param headingLevel 标题级别 */ private static void addCustomHeadingStyle(XWPFDocument document, String strStyleName, int headingLevel) { // 获取样式表对象 XWPFStyles styles = document.createStyles(); // 创建一个新样式 XWPFStyle style = document.createStyle(); // 设置样式名称 style.setStyleId(strStyleName); // 设置样式类型为标题 style.setType(STStyleType.PARAGRAPH); // 设置样式基础样式为正文 style.setBasedOn("Normal"); // 设置样式字体 style.getCTStyle().addNewRPr().addNewRFonts().setAscii("宋体"); style.getCTStyle().getRPr().getRFonts().setHAnsi("宋体"); style.getCTStyle().getRPr().getRFonts().setCs("宋体"); // 设置样式段落属性 style.getCTStyle().addNewPPr().addNewSpacing().setBeforeLines(BigInteger.valueOf(0)); style.getCTStyle().getPPr().getSpacing().setBeforeAutospacing(true); style.getCTStyle().getPPr().getSpacing().setBefore(BigInteger.valueOf(0)); style.getCTStyle().getPPr().getSpacing().setAfter(BigInteger.valueOf(0)); style.getCTStyle().getPPr().getSpacing().setLineRule(STLineSpacingRule.AUTO); style.getCTStyle().getPPr().getSpacing().setLine(BigInteger.valueOf(240)); // 设置样式级别 CTAbstractNum abstractNum = CTAbstractNum.Factory.newInstance(); abstractNum.setAbstractNumId(BigInteger.valueOf(10 + headingLevel)); CTLvl lvl = abstractNum.addNewLvl(); lvl.setIlvl(BigInteger.valueOf(headingLevel - 1)); lvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL); lvl.addNewLvlText().setVal("%" + headingLevel); lvl.addNewStart().setVal(BigInteger.valueOf(1)); CTNumbering numbering = document.getDocument().getBody().addNewNumTbl(); CTNum num = numbering.addNewNum(); num.setNumId(BigInteger.valueOf(10 + headingLevel)); num.addNewAbstractNumId().setVal(BigInteger.valueOf(10 + headingLevel)); XWPFAbstractNum abs = new XWPFAbstractNum(abstractNum); XWPFNumbering numbering1 = new XWPFNumbering(numbering); BigInteger abstractNumID = numbering1.addAbstractNum(abs); BigInteger numID = numbering1.addNum(abstractNumID); style.getCTStyle().getPPr().addNewNumPr().addNewIlvl().setVal(BigInteger.valueOf(headingLevel - 1)); style.getCTStyle().getPPr().getNumPr().addNewNumId().setVal(numID); // 将样式添加到样式表 styles.addStyle(style); } /** * 添加多级目录 * * @param document Word文档对象 * @param strTitle 目录标题 * @param nMinHeadingLevel 最小标题级别 * @param nMaxHeadingLevel 最大标题级别 */ private static void addMultiLevelTOC(XWPFDocument document, String strTitle, int nMinHeadingLevel, int nMaxHeadingLevel) { // 创建一个新段落 XWPFParagraph paragraph = document.createParagraph(); // 设置段落对齐方式为居中 paragraph.setAlignment(ParagraphAlignment.CENTER); // 创建一个新运行 XWPFRun run = paragraph.createRun(); // 设置运行文本 run.setText(strTitle); // 设置运行字体 run.setFontSize(16); run.setBold(true); // 添加一个分页符 paragraph = document.createParagraph(); run = paragraph.createRun(); run.addBreak(BreakType.PAGE); // 获取所有标题段落 List<XWPFParagraph> headingParagraphs = new ArrayList<XWPFParagraph>(); for (XWPFParagraph p : document.getParagraphs()) { String text = p.getText(); if (text != null && text.length() > 0) { int headingLevel = getHeadingLevel(p); if (headingLevel >= nMinHeadingLevel && headingLevel <= nMaxHeadingLevel) { headingParagraphs.add(p); } } } // 创建一个新表格 XWPFTable table = document.createTable(); // 创建表格行 XWPFTableRow row = table.getRow(0); // 创建表格单元格 XWPFTableCell cell = row.getCell(0); // 设置单元格文本 cell.setText(strTitle); // 设置单元格样式 cell.setVerticalAlignment(XWPFVertAlign.CENTER); cell.setColor("C0C0C0"); cell.setBold(true); // 创建一个新编号 CTNumbering numbering = CTNumbering.Factory.newInstance(); // 获取所有标题段落的编号 for (XWPFParagraph p : headingParagraphs) { int headingLevel = getHeadingLevel(p); // 创建一个新编号项 CTAbstractNum abstractNum = numbering.addNewAbstractNum(); abstractNum.setAbstractNumId(BigInteger.valueOf(headingLevel)); // 创建一个新编号级别 CTLvl lvl = abstractNum.addNewLvl(); lvl.setIlvl(BigInteger.valueOf(headingLevel - nMinHeadingLevel)); lvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL); lvl.addNewLvlText().setVal("%" + headingLevel); lvl.addNewStart().setVal(BigInteger.valueOf(1)); // 获取段落编号 CTNum num = numbering.addNewNum(); num.setNumId(BigInteger.valueOf(headingLevel)); num.addNewAbstractNumId().setVal(BigInteger.valueOf(headingLevel)); // 将段落编号添加到编号项 XWPFAbstractNum abs = new XWPFAbstractNum(abstractNum); XWPFNumbering numbering1 = new XWPFNumbering(numbering); BigInteger abstractNumID = numbering1.addAbstractNum(abs); BigInteger numID = numbering1.addNum(abstractNumID); // 设置段落编号 p.setNumID(numID); } // 遍历所有标题段落,添加目录项 for (XWPFParagraph p : headingParagraphs) { int headingLevel = getHeadingLevel(p); // 创建一个新段落 paragraph = document.createParagraph(); // 创建一个新运行 run = paragraph.createRun(); // 设置运行文本 run.setText(getHeadingText(p)); // 设置运行字体 run.setFontSize(12); // 设置段落缩进 paragraph.setIndentationLeft(headingLevel * 720); // 添加目录项 addTOCItem(paragraph, p); } } /** * 获取段落标题级别 * * @param paragraph 段落对象 * @return 标题级别 */ private static int getHeadingLevel(XWPFParagraph paragraph) { String style = paragraph.getStyle(); if (style != null && style.startsWith("标题 ")) { return Integer.parseInt(style.substring(3)); } return -1; } /** * 获取段落标题文本 * * @param paragraph 段落对象 * @return 标题文本 */ private static String getHeadingText(XWPFParagraph paragraph) { String text = paragraph.getText(); if (text != null && text.length() > 0) { int pos = text.indexOf(' '); if (pos > 0) { return text.substring(pos + 1); } } return text; } /** * 添加目录项 * * @param paragraph 目录段落 * @param headingParagraph 标题段落 */ private static void addTOCItem(XWPFParagraph paragraph, XWPFParagraph headingParagraph) { // 获取段落编号 BigInteger numID = headingParagraph.getNumID(); // 获取段落编号对象 XWPFNum num = headingParagraph.getDocument().getNumbering().getNum(numID); // 获取段落编号级别 int ilvl = num.getCTNum().getLvlOverrideArray(0).getIlvl().intValue(); // 获取段落编号文本 String numText = num.getCTNum().getLvlOverrideArray(0).getLvl().getLvlText().getVal(); // 获取段落文本 String text = getHeadingText(headingParagraph); // 创建一个新运行 XWPFRun run = paragraph.createRun(); // 设置运行文本 run.setText(numText + " " + text); // 设置运行字体 run.setFontSize(12); // 设置运行样式 run.getCTR().addNewRPr().addNewNoProof(); // 创建一个新运行 run = paragraph.createRun(); // 设置运行文本 run.setText(" "); } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值