POI 导出 Word 文档基础模板,导出表格和转换纸张方向

适用场景

通过 apache poi 库导出带表格的 word 文件,并且表格的宽度可能过宽,需要纸张横向或者更大的纸张

需要的包

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.1</version>
</dependency>

模板代码

import cn.hutool.extra.spring.SpringUtil;
import com.ylkj.tydb.common.service.UserService;
import com.ylkj.tydb.export.domain.HeaderCell;
import com.ylkj.tydb.export.domain.WordStyle;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.math.BigInteger;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

public abstract class AbstractFileTemplate {

    private Date exportDate;
    /**
     * 换行符标记
     */
    private static final String LINE_MARK = "\n";
    /**
     * A4纸宽度
     */
    private static final BigInteger PAPER_A4_W = BigInteger.valueOf(11907);
    /**
     * A4纸高度
     */
    private static final BigInteger PAPER_A4_H = BigInteger.valueOf(16840);

    public XWPFDocument exportWord() {
        UserService userService = SpringUtil.getBean(UserService.class);
        userService.setSessionUser();
        XWPFDocument document = new XWPFDocument();
        createDocument(document);
        return document;
    }

    /**
     * 创建文档方法
     * @param document 文档
     */
    abstract protected void createDocument(XWPFDocument document);

    /**
     * 获取导出文件名称
     * @return 导出文件名称
     */
    abstract public String getFileName();

    /**
     * 设置换行
     * @param value     需要换行的内容
     * @param paragraph 当前段落
     * @param style     文字格式
     */
    protected void setText(String value, XWPFParagraph paragraph, WordStyle style) {
        XWPFRun run = paragraph.createRun();

        if (value.indexOf(LINE_MARK) > 0) {
            //设置换行
            String[] text = value.split(LINE_MARK);
            run = paragraph.insertNewRun(0);
            for (int f = 0; f < text.length; f++) {
                if (f == 0) {
                    run.setText(text[f].trim());
                } else {
                    run.addCarriageReturn();//硬回车
                    run.setText(text[f].trim());
                }
            }
        } else {
            run.setText(value);
        }
        run.setColor(style.getColor());
        run.setFontSize(style.getFontSize());
        run.setBold(style.isBold());
    }

    protected WordStyle getMainTextWordStyle(){
        return new WordStyle();
    }

    protected WordStyle getKeyPointTextWordStyle(){
        WordStyle style = new WordStyle();
        style.setBold(true);
        return style;
    }

    protected void setTable(List<HeaderCell> headerData, List<LinkedHashMap<String,Object>> dataList, String tableName, XWPFDocument document, boolean pageHorizontal){
        //若是需要将纸张方向改变为横向,需要提前将之前的方向设定为纵向作为分割,否则会将之前的内容也变为横向
        if(pageHorizontal){
            XWPFParagraph paragraph = document.createParagraph();
            CTSectPr ctSectPr = paragraph.getCTP().addNewPPr().addNewSectPr();
            CTPageSz ctPageSz = ctSectPr.addNewPgSz();
            // 必须要设置下面两个参数,否则整个的代码是无效的
            ctPageSz.setW(PAPER_A4_W);
            ctPageSz.setH(PAPER_A4_H);
            ctPageSz.setOrient(STPageOrientation.PORTRAIT);
        }
        // 设置表格的标题
        setText(tableName,document.createParagraph(),getKeyPointTextWordStyle());

        XWPFTable infoTable = document.createTable();
        infoTable.setWidthType(TableWidthType.PCT);

        // 表格标题行
        XWPFTableRow headers = infoTable.getRow(0);
        if(headerData!=null && headerData.size()>=1){
            XWPFTableCell cell = headers.getCell(0);
            cell.setText(headerData.get(0).getLabel());
            cell.setWidth(headerData.get(0).getColumnWidth());
        }
        for (int i = 1; i < headerData.size(); i++) {
            XWPFTableCell cell = headers.addNewTableCell();
            cell.setText(headerData.get(i).getLabel());
            cell.setWidth(headerData.get(i).getColumnWidth());
        }

        // 表格的数据行
        for (LinkedHashMap<String,Object> item : dataList){
            XWPFTableRow row = infoTable.createRow();
            for (int cellNum = 0; cellNum < headerData.size(); cellNum++) {
                XWPFTableCell cell = row.getCell(cellNum);
                cell.setText(item.get(headerData.get(cellNum).getCode())+"");
                cell.setWidth(headerData.get(cellNum).getColumnWidth());
            }
        }
        // 若是需要将纸张方向改变为横向,在这里设置,纸张的方向由分割后最后的段落指定
        if(pageHorizontal){
            XWPFParagraph paragraph = document.createParagraph();
            CTSectPr ctSectPr = paragraph.getCTP().addNewPPr().addNewSectPr();
            CTPageSz ctPageSz = ctSectPr.addNewPgSz();
            // 必须要设置下面两个参数,否则整个的代码是无效的
            // A3纸横向 宽度为A4纸宽度两倍,高度为A4纸高度
            ctPageSz.setW(PAPER_A4_W.multiply(BigInteger.valueOf(2)));
            ctPageSz.setH(PAPER_A4_H);
            ctPageSz.setOrient(STPageOrientation.LANDSCAPE);
        }
    }
    protected void setTable(List<HeaderCell> headers, List<LinkedHashMap<String,Object>> dataList, String tableName, XWPFDocument document){
        setTable(headers,dataList,tableName,document,false);
    }

    public Date getExportDate() {
        return exportDate;
    }

    public void setExportDate(Date exportDate) {
        this.exportDate = exportDate;
    }
}

转换纸张方向的关键代码

XWPFParagraph paragraph = document.createParagraph();
CTSectPr ctSectPr = paragraph.getCTP().addNewPPr().addNewSectPr();
CTPageSz ctPageSz = ctSectPr.addNewPgSz();
// 必须要设置下面两个参数,否则整个的代码是无效的
// A3纸横向 宽度为A4纸宽度两倍,高度为A4纸高度
ctPageSz.setW(PAPER_A4_W.multiply(BigInteger.valueOf(2)));
ctPageSz.setH(PAPER_A4_H);
ctPageSz.setOrient(STPageOrientation.LANDSCAPE);

假如想要在同一个文档中多次调整纸张的方向和大小,就要在需要调节的纸张的末尾添加一个额外的段落来修改 CTSectPr对象,下面的代码会使整个文档都变成调整后的纸张样式。

CTDocument1 document1 = document.getDocument();
CTBody body = document1.getBody();
CTSectPr ctSectPr = body.addNewSectPr();
CTPageSz ctPageSz = ctSectPr.addNewPgSz();
ctPageSz.setW(PAPER_A4_W.multiply(BigInteger.valueOf(2)));
ctPageSz.setH(PAPER_A4_H);
ctPageSz.setOrient(STPageOrientation.LANDSCAPE);

另附上用到的两个实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class HeaderCell {

    private String code;
    private String label;
    private int span = 1;
    private List<HeaderCell> children;
    private String columnWidth = "300";

    public HeaderCell(String code, String label) {
        this.code = code;
        this.label = label;
    }

    public HeaderCell(String code, String label, String columnWidth) {
        this.code = code;
        this.label = label;
        this.columnWidth = columnWidth;
    }

    public void setChildren(List<HeaderCell> children) {
        if(children!=null){
            this.span = children.size();
            this.children = children;
        }
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class WordStyle {

    private String color = "000000";
    private int fontSize = 16;
    private boolean bold = false;

}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值