点关注不迷路,欢迎再访!	

精简博客内容,尽量已行业术语来分享。
努力做到对每一位认可自己的读者负责。
帮助别人的同时更是丰富自己的良机。

前言

在 Java 应用程序中,有时候我们需要将数据导出为 Word 文档,以便进行文档的编辑、打印或共享。本文将介绍如何使用 Java 实现导出 Word 文档的方法,帮助你灵活处理文档导出需求。

一.添加 Apache POI 依赖

    <dependency>
         <groupId>org.apache.poi</groupId>
         <artifactId>poi-ooxml</artifactId>
         <version>3.16</version>
    </dependency>
    <dependency>
         <groupId>org.apache.poi</groupId>
         <artifactId>ooxml-schemas</artifactId>
         <version>1.3</version>
    </dependency>

二.填充文档内容

在导出 Word 文档之前,需要创建一个空的 Word 文档对象

//创建文档对象
XWPFDocument doc = new XWPFDocument();
//页边距
DocxUtil.setDocumentMargin(doc, "1082", "1440", "1082", "1440");

使用 Apache POI 提供的 API,可以向文档中添加段落标题

// 创建段落
XWPFParagraph p = doc.createParagraph();
DocxUtil.setTextFontInfo(p, false, false, text, "宋体", "000000", "24", false, null, false, false, null, 0, null);
DocxUtil.setParagraphSpacingInfo(p, true, "0", "0", "100", "100", true, "240", STLineSpacingRule.AUTO);
DocxUtil.setParagraphAlignInfo(p, ParagraphAlignment.LEFT, TextAlignment.CENTER);

向文档中创建表格

XWPFParagraph paragraph = doc.createParagraph();
paragraph.setAlignment(ParagraphAlignment.CENTER);
XWPFTable table = paragraph.getDocument().createTable(3,3);//创建表格
table.setWidth(500);
table.setCellMargins(20, 20, 20, 20);
//表格属性
CTTblPr tablePr = table.getCTTbl().addNewTblPr();
//表格宽度
CTTblWidth width = tablePr.addNewTblW();
width.setW(BigInteger.valueOf(4000));
//获取第一行
List<XWPFTableCell> tableCells = table.getRow(0).getTableCells();
tableCells.get(0).setText("单元格值");

三.导出文档效果测试

public class ExamTest {
    public static void main(String[] args) throws IOException {
        XWPFDocument doc = new XWPFDocument();
       //页边距
        DocxUtil.setDocumentMargin(doc, "1082", "1440", "1082", "1440");
        addDocxParagraphTitle(doc,"标题");
        addDocxParagraph(doc,"第一个段落内容");
        FileOutputStream outputStream = new FileOutputStream("D://document.docx");
        XWPFParagraph paragraph = doc.createParagraph();
        paragraph.setAlignment(ParagraphAlignment.CENTER);
        addDocxParagraph(doc,null);
        addDocxParagraph(doc,"有边框的表格");
        XWPFTable table = paragraph.getDocument().createTable(3,4);//创建表格
        table.setWidth(500);
        table.setCellMargins(20, 20, 20, 20);
        //表格属性
        CTTblPr tablePr = table.getCTTbl().addNewTblPr();
        //表格宽度
        CTTblWidth width = tablePr.addNewTblW();
        width.setW(BigInteger.valueOf(8000));
        //无边框
        //CTTblBorders tableBorders = table.getCTTbl().getTblPr().addNewTblBorders();
        //tableBorders.addNewBottom().setVal(STBorder.NIL);
        //tableBorders.addNewLeft().setVal(STBorder.NIL);
        //tableBorders.addNewRight().setVal(STBorder.NIL);
        //tableBorders.addNewTop().setVal(STBorder.NIL);
        //tableBorders.addNewInsideH().setVal(STBorder.NIL);
        //tableBorders.addNewInsideV().setVal(STBorder.NIL);
        for (int k = 0; k < 3; k++) {
            List<XWPFTableCell> tableCells = table.getRow(k).getTableCells();
            if(k == 0){
                tableCells.get(0).setText("序号");
            }else{
                tableCells.get(0).setText(String.valueOf(k));
            }
            for (int j = 0; j < 3; j++) {
                if(k == 0){
                    tableCells.get(j+1).setText(String.valueOf(j+1));
                }else{
                    tableCells.get(j+1).setText("");
                }
            }
        }

        doc.write(outputStream);
        outputStream.close();

    }

    private static void addDocxParagraphTitle(XWPFDocument doc, String title) {
        // 标题
        XWPFParagraph titleP = doc.createParagraph();
        DocxUtil.setTextFontInfo(titleP, false, false, title, "宋体", "000000", "44", true, null, false,
                false, null, 0, null);
        DocxUtil.setParagraphSpacingInfo(titleP, true, "0", "0", "0", "50", true, "240", STLineSpacingRule.AUTO);
        DocxUtil.setParagraphAlignInfo(titleP, ParagraphAlignment.CENTER, TextAlignment.CENTER);
    }

    private static void addDocxParagraph(XWPFDocument doc, String text) {
        XWPFParagraph p = doc.createParagraph();
        DocxUtil.setTextFontInfo(p, false, false, text, "宋体", "000000", "24", false, null, false, false, null, 0, null);
        DocxUtil.setParagraphSpacingInfo(p, true, "0", "0", "100", "100", true, "240", STLineSpacingRule.AUTO);
        DocxUtil.setParagraphAlignInfo(p, ParagraphAlignment.LEFT, TextAlignment.CENTER);
    }
}

四.docx 版 word 工具类

import java.math.BigInteger;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.xwpf.usermodel.Borders;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.TextAlignment;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.VerticalAlign;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTColor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTInd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSignedTwipsMeasure;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STUnderline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalAlignRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;

public class DocxUtil {

	private DocxUtil() {}

	/**
	 * 将 .docx 格式的 word 写到输出流,并关闭 word 对象
	 * @param docx .docx 格式的 word
	 * @param os 输出流
	 * @throws IOException  if an I/O error occurs.
	 */
	public static void writeToOutputStreamAndClose(XWPFDocument docx, OutputStream os) throws IOException {
		try {
			if (docx != null) {
				docx.write(os);
				os.flush();
			}
		} finally {
			if (docx != null) {
				docx.close();
			}
		}
	}

	public static void setCellText(XWPFTableCell cell, String text, String bgcolor, int width) {
		CTTc cttc = cell.getCTTc();
		CTTcPr ctPr = cttc.addNewTcPr();
		CTShd ctshd = ctPr.addNewShd();
		ctPr.addNewTcW().setW(BigInteger.valueOf(width));
		ctshd.setFill(bgcolor);
		ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
		//必须强转,要必然ant编译不过去
		CTP ctp = (CTP)cttc.getPList().get(0);
		ctp.addNewPPr().addNewJc().setVal(STJc.CENTER);
		cell.setText(text);
	}

	/**
	 * @Description: 跨列合并
	 */
	public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell,
			int toCell) {
		for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
			XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
			if (cellIndex == fromCell) {
				cell.getCTTc().addNewTcPr().addNewHMerge()
						.setVal(STMerge.RESTART);
			} else {
				cell.getCTTc().addNewTcPr().addNewHMerge()
						.setVal(STMerge.CONTINUE);
			}
		}
	}

	/**
	 * @Description: 跨行合并
	 */
	public static void mergeCellsVertically(XWPFTable table, int col, int fromRow,
			int toRow) {
		for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
			XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
			if (rowIndex == fromRow) {
				cell.getCTTc().addNewTcPr().addNewVMerge()
						.setVal(STMerge.RESTART);
			} else {
				cell.getCTTc().addNewTcPr().addNewVMerge()
						.setVal(STMerge.CONTINUE);
			}
		}
	}

	/**设置word表格宽度,单位:一像素的1/12*/
	public static void setTableWidth(XWPFTable table, String width) {
		CTTbl ttbl = table.getCTTbl();
		CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl
				.getTblPr();
		CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr
				.addNewTblW();
		CTJc ctJc = tblPr.addNewJc();
		ctJc.setVal(STJc.Enum.forString("center"));
		tblWidth.setW(new BigInteger(width));
		tblWidth.setType(STTblWidth.DXA);
	}

	/** 设置段落边框 */
	public static void setParagraphBorder(XWPFParagraph p, Borders lborder,
			Borders tBorders, Borders rBorders, Borders bBorders,
			Borders btborders) {
		if (lborder != null) {
			p.setBorderLeft(lborder);
		}
		if (tBorders != null) {
			p.setBorderTop(tBorders);
		}
		if (rBorders != null) {
			p.setBorderRight(rBorders);
		}
		if (bBorders != null) {
			p.setBorderBottom(bBorders);
		}
		if (btborders != null) {
			p.setBorderBetween(btborders);
		}
	}

	/** 设置段落对齐 */
	public static void setParagraphAlignInfo(XWPFParagraph p,
			ParagraphAlignment pAlign, TextAlignment valign) {
		p.setAlignment(pAlign);
		p.setVerticalAlignment(valign);
	}

	/** 设置段落缩进信息 1厘米≈567 */
	public static void setParagraphIndInfo(XWPFParagraph p, String firstLine,
			String firstLineChar, String hanging, String hangingChar,
			String right, String rigthChar, String left, String leftChar) {
		CTPPr ctPpr = null;
		if (p.getCTP() != null) {
			if (p.getCTP().getPPr() != null) {
				ctPpr = p.getCTP().getPPr();
			} else {
				ctPpr = p.getCTP().addNewPPr();
			}
		}
		CTInd pInd = ctPpr.getInd() != null ? ctPpr.getInd() : ctPpr.addNewInd();
		if (firstLine != null) {
			pInd.setFirstLine(new BigInteger(firstLine));
		}
		if (firstLineChar != null) {
			pInd.setFirstLineChars(new BigInteger(firstLineChar));
		}
		if (hanging != null) {
			pInd.setHanging(new BigInteger(hanging));
		}
		if (hangingChar != null) {
			pInd.setHangingChars(new BigInteger(hangingChar));
		}
		if (left != null) {
			pInd.setLeft(new BigInteger(left));
		}
		if (leftChar != null) {
			pInd.setLeftChars(new BigInteger(leftChar));
		}
		if (right != null) {
			pInd.setRight(new BigInteger(right));
		}
		if (rigthChar != null) {
			pInd.setRightChars(new BigInteger(rigthChar));
		}
	}

	/** 
	 * 设置段落间距信息
	 * 一行=100 一磅=20
	 */
	public static void setParagraphSpacingInfo(XWPFParagraph p, boolean isSpace,
			String before, String after, String beforeLines, String afterLines,
			boolean isLine, String line, STLineSpacingRule.Enum lineValue) {
		CTPPr ppr = null;
		if (p.getCTP() != null) {
			if (p.getCTP().getPPr() != null) {
				ppr = p.getCTP().getPPr();
			} else {
				ppr = p.getCTP().addNewPPr();
			}
		}
		CTSpacing pSpacing = ppr.getSpacing() != null ? ppr.getSpacing()
				: ppr.addNewSpacing();
		if (isSpace) {
			// 段前磅数
			if (before != null) {
				pSpacing.setBefore(new BigInteger(before));
			}
			// 段后磅数
			if (after != null) {
				pSpacing.setAfter(new BigInteger(after));
			}
			// 段前行数
			if (beforeLines != null) {
				pSpacing.setBeforeLines(new BigInteger(beforeLines));
			}
			// 段后行数
			if (afterLines != null) {
				pSpacing.setAfterLines(new BigInteger(afterLines));
			}
		}
		if (isLine) {
			if (line != null) {
				pSpacing.setLine(new BigInteger(line));
			}
			if (lineValue != null) {
				pSpacing.setLineRule(lineValue);
			}
		}
	}

	/**
	 * 设置字体信息 设置字符间距信息(CTSignedTwipsMeasure).
	 *
	 * @param p {@link XWPFParagraph}
	 * @param isInsert 是否插入新段落
	 * @param isNewLine 是否插入换行符
	 * @param content 内容
	 * @param fontFamily 字体
	 * @param colorVal 字体颜色
	 * @param fontSize 字体大小,word中的数值字号×2=本参数
	 * @param isBlod 是否粗体
	 * @param underPatterns 下划线
	 * @param isItalic 是否斜体
	 * @param isStrike 是否添加中划线
	 * @param verticalAlign            SUPERSCRIPT上标 SUBSCRIPT下标
	 * @param position            字符位置 1磅=2
	 * @param spacingValue the spacing value
	 */
	public static void setTextFontInfo(XWPFParagraph p, boolean isInsert,
			boolean isNewLine, String content, String fontFamily,
			String colorVal, String fontSize, boolean isBlod,
			UnderlinePatterns underPatterns, boolean isItalic,
			boolean isStrike, VerticalAlign verticalAlign, int position,String spacingValue) {
		XWPFRun pRun = null;
		if (isInsert) {
			pRun = p.createRun();
		} else {
			if (p.getRuns() != null && p.getRuns().size() > 0) {
				//必须强转,要必然ant编译不过去
				pRun = (XWPFRun)p.getRuns().get(0);
			} else {
				pRun = p.createRun();
			}
		}
		if (isNewLine) {
			pRun.addBreak();
		}
		pRun.setText(content);
		// 设置字体样式
		pRun.setBold(isBlod);
		pRun.setItalic(isItalic);
		pRun.setStrikeThrough(isStrike);
		if (underPatterns != null) {
			pRun.setUnderline(underPatterns);
		}
		pRun.setColor(colorVal);
		if (verticalAlign != null) {
			pRun.setSubscript(verticalAlign);
		}
		pRun.setTextPosition(position);

		CTRPr pRpr = null;
		if (pRun.getCTR() != null) {
			pRpr = pRun.getCTR().getRPr();
			if (pRpr == null) {
				pRpr = pRun.getCTR().addNewRPr();
			}
		} else {
			// pRpr = p.getCTP().addNewR().addNewRPr();
		}
		// 设置字体
		CTFonts fonts = pRpr.isSetRFonts() ? pRpr.getRFonts() : pRpr
				.addNewRFonts();
		fonts.setAscii(fontFamily);
		fonts.setEastAsia(fontFamily);
		fonts.setHAnsi(fontFamily);

		// 设置字体大小
		CTHpsMeasure sz = pRpr.isSetSz() ? pRpr.getSz() : pRpr.addNewSz();
		sz.setVal(new BigInteger(fontSize));

		CTHpsMeasure szCs = pRpr.isSetSzCs() ? pRpr.getSzCs() : pRpr
				.addNewSzCs();
		szCs.setVal(new BigInteger(fontSize));
		
		if(spacingValue!=null){
			//设置字符间距信息
			CTSignedTwipsMeasure ctSignedTwipsMeasure=pRpr.isSetSpacing()?pRpr.getSpacing(): pRpr.addNewSpacing();
			ctSignedTwipsMeasure.setVal(new BigInteger(spacingValue));
		}
	}

	/**
	 * 为段落添加超链接.
	 *
	 * @param url the url
	 * @param text the text
	 * @param paragraph the paragraph
	 * @param fontFamily 字体
	 * @param fontSize 字体大小,word中的数值字号×2=本参数
	 * @param isBlod 是否粗体
	 * @param isItalic 是否斜体
	 * @param isStrike 是否添加中划线
	 * @param verticalAlign the vertical align
	 * @param position            1磅=2
	 * @param spacingValue the spacing value
	 * @Description: 添加超链接
	 */
	public static void appendExternalHyperlink(String url, String text,
			XWPFParagraph paragraph, String fontFamily, String fontSize,
			boolean isBlod, boolean isItalic, boolean isStrike,
			String verticalAlign, String position,String spacingValue) {
		// Add the link as External relationship
		String id = paragraph
				.getDocument()
				.getPackagePart()
				.addExternalRelationship(url,
						XWPFRelation.HYPERLINK.getRelation()).getId();
		// Append the link and bind it to the relationship
		CTHyperlink cLink = paragraph.getCTP().addNewHyperlink();
		cLink.setId(id);

		// Create the linked text
		CTText ctText = CTText.Factory.newInstance();
		ctText.setStringValue(text);
		CTR ctr = CTR.Factory.newInstance();
		CTRPr rpr = ctr.addNewRPr();

		// 设置超链接样式
		CTColor color = CTColor.Factory.newInstance();
		color.setVal("0000FF");
		rpr.setColor(color);
		rpr.addNewU().setVal(STUnderline.SINGLE);
		if (isBlod) {
			rpr.addNewB().setVal(STOnOff.Enum.forString("true"));
		}
		if (isItalic) {
			rpr.addNewI().setVal(STOnOff.Enum.forString("true"));
		}
		if (isStrike) {
			rpr.addNewStrike().setVal(STOnOff.Enum.forString("true"));
		}
		if (verticalAlign != null) {
			rpr.addNewVertAlign().setVal(
					STVerticalAlignRun.Enum.forString(verticalAlign));
		}
		rpr.addNewPosition().setVal(new BigInteger(position));

		// 设置字体
		CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr
				.addNewRFonts();
		fonts.setAscii(fontFamily);
		fonts.setEastAsia(fontFamily);
		fonts.setHAnsi(fontFamily);

		// 设置字体大小
		CTHpsMeasure sz = rpr.isSetSz() ? rpr.getSz() : rpr.addNewSz();
		sz.setVal(new BigInteger(fontSize));

		CTHpsMeasure szCs = rpr.isSetSzCs() ? rpr.getSzCs() : rpr.addNewSzCs();
		szCs.setVal(new BigInteger(fontSize));

		if(spacingValue!=null){
			//设置字符间距信息
			CTSignedTwipsMeasure ctSignedTwipsMeasure=rpr.isSetSpacing()?rpr.getSpacing(): rpr.addNewSpacing();
			ctSignedTwipsMeasure.setVal(new BigInteger(spacingValue));
		}
		
		ctr.setTArray(new CTText[] { ctText });
		cLink.setRArray(new CTR[] { ctr });
	}

	public static void addNewPage(XWPFDocument document, BreakType breakType) {
		XWPFParagraph xp = document.createParagraph();
		xp.createRun().addBreak(breakType);
	}

	/** 设置页边距 1厘米约等于567 */
	public static void setDocumentMargin(XWPFDocument document,String left,String top,String right,String bottom){
		CTSectPr sectPr =document.getDocument().getBody().isSetSectPr()?document.getDocument().getBody().getSectPr():document.getDocument().getBody().addNewSectPr();
		CTPageMar ctpagemar=sectPr.addNewPgMar();
		ctpagemar.setLeft(new BigInteger(left));
		ctpagemar.setTop(new BigInteger(top));
		ctpagemar.setRight(new BigInteger(right));
		ctpagemar.setBottom(new BigInteger(bottom));
	}

	/**
	 * 设置纸张大小,纸张的大小的单位为1/20个像素。
	 * <br/>各种纸张大小(以像素为单位)详见https://www.gnu.org/software/gv/manual/html_node/Paper-Keywords-and-paper-size-in-points.html
	 * <br/>以下是一些常用的纸张的大小(以像素为单位):
	 * <pre>
	 * Letter       612x792
	 * LetterSmall  612x792
	 * Tabloid      792x1224
	 * Ledger       1224x792
	 * Legal        612x1008
	 * Statement    396x612
	 * Executive    540x720
	 * A0           2384x3371
	 * A1           1685x2384
	 * A2           1190x1684
	 * A3           842x1190
	 * A4           595x842
	 * A4Small      595x842
	 * A5           420x595
	 * B4           729x1032
	 * B5           516x729
	 * Folio        612x936
	 * Quarto       610x780
	 * 10x14        720x1008
	 * </pre>
	 * @param doc
	 * @param width 纸张的宽度,单位为1/20个像素
	 * @param height 纸张的高度,单位为1/20个像素
	 */
	public static void setPageSize(XWPFDocument doc, String width, String height){
		CTDocument1 document = doc.getDocument();
		CTBody body = document.getBody();
		if (!body.isSetSectPr()) {
			body.addNewSectPr();
		}
		CTSectPr section = body.getSectPr();
		if (!section.isSetPgSz()) {
			section.addNewPgSz();
		}
		CTPageSz pageSize = section.getPgSz();
		// 单位1/20个像素
		pageSize.setW(new BigInteger(width));
		// 单位1/20个像素
		pageSize.setH(new BigInteger(height));
	}
}

测试效果
在这里插入图片描述

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐