欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Springboot 之 使用POI操作excel

程序员文章站 2022-07-13 17:08:39
...

为了方便地使用poi操作excel,在这里,使用类BubbleSheet对Poi中的Sheet进行封装,BubbleSheet类如下所示:

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;

import java.util.ArrayList;
import java.util.List;

public class BubbleSheet {

    private Sheet sheet;

    private Row nowRow;

    private Integer nowRowNo;

    private HSSFWorkbook wb;

    private List<HSSFCellStyle> cellStylesList = new ArrayList<HSSFCellStyle>();

    BubbleSheet(HSSFWorkbook wb) {
        this.wb = wb;
        this.sheet = wb.createSheet();
        createCellStyleList();
        nowRowNo = -1;
        setNowRowWithRowNo(0);
    }

    private HSSFCellStyle createCellStyle(int poiColorIndex, int r, int g, int b) {
        HSSFCellStyle cellStyle =  wb.createCellStyle();

        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); //左边框
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); //上边框
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); //右边框

        HSSFPalette palette = wb.getCustomPalette();
        palette.setColorAtIndex((short)poiColorIndex, (byte) r, (byte) g, (byte) b);
        cellStyle.setFillForegroundColor((short)poiColorIndex);
        cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

        return cellStyle;
    }

    private void createCellStyleList() {
        cellStylesList.add(createCellStyle(HSSFColor.LIME.index, 255, 255, 255)); // 默认的白色
        cellStylesList.add(createCellStyle(HSSFColor.BLUE.index, 211, 209, 207));  // 内容浅灰色
        cellStylesList.add(createCellStyle(HSSFColor.GREEN.index, 186, 210, 170)); // 表头浅绿色
    }

    public void mergeCells(Integer firstRow, Integer lastRow, Integer firstCol, Integer lastCol, String content, int colorIndex) {
        CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
        //在sheet里增加合并单元格
        sheet.addMergedRegion(cra);
        Cell cell_1 = nowRow.createCell(firstCol); // 选择第一行的第一个单元格,因为位置在这个位置,所以设置的是合并的单元格
        cell_1.setCellStyle(cellStylesList.get(colorIndex));
        // 设置单元格的内容
        cell_1.setCellValue(content);

        // 设置合并单元格的边框
        RegionUtil.setBorderBottom(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 下边框
        RegionUtil.setBorderLeft(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 左边框
        RegionUtil.setBorderRight(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 有边框
        RegionUtil.setBorderTop(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 上边框
    }

    public void setLineValues(Integer col, String[] titleNames, int colorIndex) {
        for(String stp: titleNames) {
            Cell ctp = nowRow.createCell(col ++);
            ctp.setCellValue(stp);
            ctp.setCellStyle(cellStylesList.get(colorIndex));
        }
    }

    public void setNowRowWithRowNo(Integer rowNo) {
        // 这里的逻辑感觉很奇怪,主要是在getRow、createRow以及样式设置上的相互作用的结果。
        if(rowNo == null) rowNo = 0 ;
        if(nowRowNo.equals(rowNo)) { // 如果是合并单元格行后面的创建单元时,不需要重新生成这行了。
            return ;
        }
        Row row = sheet.getRow(rowNo); // 使用这个的原因是:需要设置合并单元格的外边框样式,如果不用这个会出错。
        if(row == null){
            row = sheet.createRow(rowNo);
        }
        nowRowNo = rowNo;
        setNowRow(row);
    }

    private void setNowRow(Row nowRow) {
        this.nowRow = nowRow;
    }

    public void createFreezePane(int startRowNo, int endRowNo, int startColNo, int endColNo) {
        sheet.createFreezePane( startRowNo, endRowNo, startColNo, endColNo);
    }
}

接下来使用BubbleSheet方便操作表格的例子如下:

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

public class bubbleSheet_ex {

    static final  private String[] titleNames = {
            "广告位", "月度", "项目名称", "预定量",
            "预计本月金额", "直客公司",
            "所属区域", "对应销售", "媒介", "当月比例"};

    public static int stepHigh = 0;

    public static void main(String[] args) {

        HSSFWorkbook wb =  new HSSFWorkbook();
        BubbleSheet bs = new BubbleSheet(wb);
        bs.setNowRowWithRowNo(0); // 设置要操作哪一行
        bs.mergeCells(0, 0, 0, 1, titleNames[0], 0); // 设置第一行第一个标题
        final String[] titleNames_temp = Arrays.copyOfRange(titleNames, 1, titleNames.length);

        bs.setNowRowWithRowNo(0); // 设置要操作哪一行
        bs.setLineValues(2, titleNames_temp, 0); // 设置第一行除第一个以外的标题

        stepHigh = 10;
        int firstRow_temp = 1;
        bs.setNowRowWithRowNo(firstRow_temp); // 设置要操作哪一行
        bs.mergeCells(firstRow_temp, firstRow_temp + stepHigh, 0, 1, "模块1", 1);

        firstRow_temp = 13;
        bs.setNowRowWithRowNo(firstRow_temp); // 设置要操作哪一行
        bs.mergeCells(firstRow_temp, firstRow_temp + stepHigh, 0, 1, "模块2", 2);

        saveexcel(wb, "e:/test_bs.xls");
    }

    private static void saveexcel(HSSFWorkbook wb, String filename) {
        // 保存文件
        File file = new File(filename);
        try {
            file.createNewFile(); // 创建文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            FileOutputStream fos = new FileOutputStream(file);
            try {
                wb.write(fos);
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

从例子中可以看出,BubbleSheet经常用的方法有mergeCells以及setLineValues,从名字可以看出两者的用途,在使用这两个方法之前,都要用setNowRowWithRowNo方法,用来指明是要操作哪一行的。

在我的工作中检验发现,BubbleSheet是可靠的,且在操作表格时非常便捷。