poi创建Excel设计

      电商商务,目前为止,做网站后台管理系统对到处数据的要求不是很高,反正自己公司内部用的嘛,能拉出来就行了,尽量简单。但是随着业务的发展,供应链系统出来了,涉及到订单,采购,库存,退款退货,财务等模块的集成。系统的生成Excel的业务越来越多,于是乎每个人都自己copy一段前人实现的代码,直接修改修改就生成一个Excel了。

       这个操作方法,刚刚系统还小的时候,也没有什么关系,来回就那么点代码,可是当系统复杂了,导出的业务多了,每次代码review都看到一大段相同的代码,很不爽。于是乎写成公用类也就成为必然了。

 

下面是我设计生成Excel文件的设计:

一、生成一个文本Excel的抽象接口是要有如下几个方法:

package com.hqb360.common.excel;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 功能描述: 创建Excel接口
 *
 * @author: Zhenbin.Li
 * Date: 13-11-19 Time:下午12:42
 */
public interface ExportExcelAware<T> {

    /**
     * 创建生成Excel文件
     *
     * <p>需要实现接口中的每一个方法, 接口中的方法都对应生成Excel的一个功能</p>     *
     * @param response HttpServletResponse
     * @param exportList 输出到Excel表格list
     */
    public void create(HttpServletResponse response, List<T> exportList);

    /**
     * 初始化Excel报表标题
     *
     * @return 报表标题
     */
    public String initTitle();

    /**
     * 初始化Excel文件名称
     *
     * @return
     */
    public String initFileName();

    /**
     * 初始化Excel Sheet名称
     *
     * @return
     */
    public String initSheetName();

    /**
     * 获得报表列头标题
     *
     * 1、如果是一行列头标题,则可以通过如下代码实现:
     * 		String[][] colTitles = { { "列1", "列2", "列3" } }
     * 		return colTitles;
     * 2、如果是二行列头标题,则可以通过如下代码实现:
     * 		String[][] colTitles = { { "行1列1", "行1列2", null, "行1列4" },
     * 								 { null, "行2列2", "行2列3", "行2列4" }};
     * 		return colTitles;
     * 	  将显示的列标题实际效果为:
     * 	   <table border="1">
     * 			<tr align="center">
     * 				<td rowspan="2">行1列1</td>
     * 				<td colspan="2">行1列2</td>
     * 				<td>行1列4</td>
     * 			</tr>
     * 			<tr align="center">
     * 				<td>行2列2</td>
     * 				<td>行2列3</td>
     * 				<td>行2列4</td>
     * 			</tr>
     * 		</table>
     * @return 列头标题
     */
    public String[][] initColTitles();

    /**
     * 处理Excel报表展示的数据
     *
     * @param exportList 输出到Excel list集合
     * @return 1、列表,List(String[]);
     *         2、有合并一列的数据,Map(List(String[]));
     *         3、有合并两列的数据,Map(Map(List(String[])))。
     */
    public Object handleBodyData(List<T> exportList);

    /**
     * 初始化Excel报表展示的样式
     *
     * @return 列表,Map(int,String );
     */
    public Object initRowStyle();

    /**
     * 初始化Excel列宽
     *
     * @return 列宽
     */
    public int[] initColumnWidth();

    /**
     * 初始化Excel报表备注信息
     *
     * @return 报表备注信息
     */
    public String[] initRemark();

}

 

 二、抽象实现

package com.hqb360.common.excel;

import com.google.common.collect.Maps;
import com.hqb360.common.lang.ArrayUtil;
import com.hqb360.common.lang.DateUtil;
import com.hqb360.common.lang.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 功能描述:创建Excel抽象实现
 *
 * @author: Zhenbin.Li
 * Date: 13-11-19 Time:下午12:44
 */
public abstract class DefaultExportExcelAdapter<T> implements ExportExcelAware<T> {

    /**
     * 文件下载的header key
     */
    private static final String RESOURCE_HEADER_KEY = "Content-Disposition";

    /**
     * 文件下载的contentType
     */
    private static final String RESOURCE_CONTENT_TYPE = "application/octet-stream;charset=UTF-8";

    /**
     * Excel Sheet默认名称
     */
    private static final String DEFAULT_SHEET_NAME = "sheet";

    /**
     * 生成Excel文件Session
     */
    private Map<SessionKey, Object> exportSession = Maps.newHashMap();

    @Override
    public synchronized void create(HttpServletResponse response, List<T> exportList) {

        // 初始化Session
        initSession(response, exportList);

        // 验证必要参数
        validExportSession();

        String sheetName = exportSession.get(SessionKey.SHEET_NAME) == null ?
                DEFAULT_SHEET_NAME : (String) exportSession.get(SessionKey.SHEET_NAME);
        ExportExcelFactory exportExcelFactory = new ExportExcelFactory(sheetName);

        // 表格名称
        StringBuffer titleBuffer = new StringBuffer();
        titleBuffer.append(exportSession.get(SessionKey.TITLE)).append("(导出时间:")
                .append(DateUtil.formatDateTime()).append(")");

        //列头标题
        String[][] colTitles = (String[][]) exportSession.get(SessionKey.COL_TITLES);
        exportExcelFactory.setCols(colTitles[0].length);
        exportExcelFactory.createCaption(titleBuffer.toString());
        exportExcelFactory.createColCaption(colTitles);

        Object bodyData = exportSession.get(SessionKey.BODY_DATA);
        if (bodyData != null) {
            Object rowColor = exportSession.get(SessionKey.ROW_COLOR);
            if (rowColor == null) {
                exportExcelFactory.createBody(bodyData);
            } else {
                exportExcelFactory.createBody(bodyData, rowColor);
            }
        }

        if (exportSession.get(SessionKey.COLUMN_WIDTH) != null) {
            int[] columnWidths = (int[]) exportSession.get(SessionKey.COLUMN_WIDTH);
            if (ArrayUtil.isNotEmpty(columnWidths)) {
                exportExcelFactory.setColumnWidth(columnWidths);
            }
        }

        if (exportSession.get(SessionKey.REMARKS) != null) {
            String[] remarks = (String[]) exportSession.get(SessionKey.REMARKS);
            if (ArrayUtil.isEmpty(remarks)) {
                exportExcelFactory.createRemarks(remarks);
            }
        }

        String excelFileName = initFileName() + ".xls";
        try {
            excelFileName = new String(excelFileName.getBytes("GBK"),"ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("导出Excel业务, encode文件名称异常, excelFileName=" + excelFileName, e);
        }

        // 写文件
        OutputStream os = null;
        response.reset();

        // 写入下载响应头信息
        writeDownloadResHeader(excelFileName, response);
        try {
            os = response.getOutputStream();
            exportExcelFactory.createFile(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException("导出Excel业务, 生成Excel文件异常", e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * Excel标题,继承时必须要实现
     *
     * @return
     */
    @Override
    public abstract String initTitle();

    /**
     * 获取导出Excel文件名称
     *
     * @return
     */
    @Override
    public String initFileName() {
        StringBuffer fileName = new StringBuffer();
        fileName.append(initTitle()).append("(").append(DateUtil.format(new Date(), "yyyyMMddHHmmss")).append(")");
        return fileName.toString();
    }

    @Override
    public String initSheetName() {
        return "sheet";
    }

    /**
     * Excel列属性值,继承时必须要实现
     *
     * @return
     */
    @Override
    public abstract String[][] initColTitles();

    /**
     * 必须要传入值
     *
     * @return
     */
    @Override
    public abstract Object handleBodyData(List<T> exportList);

    /**
     * 设置单元格样式
     *
     * @return
     */
    @Override
    public Object initRowStyle() {
        return null;
    }

    @Override
    public int[] initColumnWidth() {
        return null;
    }

    /**
     * 导出Excel有无备注信息
     *
     * @return
     */
    @Override
    public String[] initRemark() {
        return null;
    }

    /**
     * 写入下载响应头信息
     * <p>声明响应类型和内容类型</p>
     *
     * @param fileName 文件名
     * @param response HTTP响应
     */
    protected static void writeDownloadResHeader(String fileName, HttpServletResponse response) {

        response.addHeader(RESOURCE_HEADER_KEY, "attachment; filename=" + fileName);
        response.setContentType(RESOURCE_CONTENT_TYPE);
    }

    /**
     * Excel文件Session属性值枚举
     */
    protected enum SessionKey {

        RESPONSE,
        BODY_DATA,
        TITLE,
        FILE_NAME,
        COL_TITLES,
        ROW_COLOR,
        REMARKS,
        COLUMN_WIDTH,
        SHEET_NAME
    }

    /**
     * 初始化生成Excel SessionKey
     *
     * @param response
     * @param exportList
     */
    protected void initSession(HttpServletResponse response, List exportList) {

        exportSession.put(SessionKey.RESPONSE, response);
        //报表数据
        exportSession.put(SessionKey.BODY_DATA, handleBodyData(exportList));
        // 报表标题
        exportSession.put(SessionKey.TITLE, initTitle());
        // 文件名称
        exportSession.put(SessionKey.FILE_NAME, initFileName());
        // 列名称
        exportSession.put(SessionKey.COL_TITLES, initColTitles());
        // 行颜色
        exportSession.put(SessionKey.ROW_COLOR, initRowStyle());
        // 备注
        exportSession.put(SessionKey.REMARKS, initRemark());
        // 列宽度
        exportSession.put(SessionKey.COLUMN_WIDTH, initColumnWidth());
        // Sheet名称
        exportSession.put(SessionKey.SHEET_NAME, initSheetName());
    }

    /**
     * 验证Session参数
     */
    protected void validExportSession() {

        if (exportSession.get(SessionKey.TITLE) == null
                || StringUtil.isBlank(String.valueOf(exportSession.get(SessionKey.TITLE)))) {
            throw new RuntimeException("导出Excel业务, Excel表名称为空");
        }

        if (exportSession.get(SessionKey.FILE_NAME) == null
                || StringUtil.isBlank(String.valueOf(exportSession.get(SessionKey.FILE_NAME)))) {
            throw new RuntimeException("导出Excel业务, Excel文件名称为空");
        }

        if (exportSession.get(SessionKey.COL_TITLES) == null
                || ArrayUtil.isEmpty((String[][]) exportSession.get(SessionKey.COL_TITLES))) {
            throw new RuntimeException("导出Excel业务, Excel列属性名称为空");
        }

    }
}

 

 三、测试实现方法,只需要实现抽象方法即可

/**
     * 导出库存列表
     *
     * @param response
     * @return
     */
    @RequestMapping(value = "/invoicing/itemSkusWarehouse/exportItemSkusWarehouse.resource",
            method = RequestMethod.GET)
    public String exportItemSkusWarehouse(HttpServletResponse response) {

        final List<ItemSkuWarehouseExportDo> list = itemSkusWarehouseQueryBiz
                .findItemSkuWarehouseStatisticsForExport().getItemSkuWarehouseExportDos();

        new DefaultExportExcelAdapter<ItemSkuWarehouseExportDo>() {

            @Override
            public String initTitle() {
                return "库存列表";
            }

            @Override
            public String[][] initColTitles() {
                String[][] colTitles = {{"所属类目", "SKU ID", "SKU名称", "良品库", "申购库", "次品库", "赠品库", "寄存库", "成本价", "合计"}};
                return colTitles;
            }

            @Override
            public Object handleBodyData(List<ItemSkuWarehouseExportDo> exportList) {

                List<String[]> exports = Lists.newArrayList();
                if (CollectionUtil.isNotEmpty(exportList)) {
                    for (ItemSkuWarehouseExportDo itemSkuWarehouseExportDo : exportList) {
                        String[] itemSkuWarehouseExportDoArray = new String[initColTitles()[0].length];
                        itemSkuWarehouseExportDoArray[0] = itemSkuWarehouseExportDo.getBelongCatName();
                        itemSkuWarehouseExportDoArray[1] = itemSkuWarehouseExportDo.getSkuId().toString();
                        itemSkuWarehouseExportDoArray[2] = itemSkuWarehouseExportDo.getSkuName();
                        itemSkuWarehouseExportDoArray[3] = itemSkuWarehouseExportDo.getStandardWarehouse().toString();
                        itemSkuWarehouseExportDoArray[4] = itemSkuWarehouseExportDo.getApWarehouse().toString();
                        itemSkuWarehouseExportDoArray[5] = itemSkuWarehouseExportDo.getSubstandardWarehouse().toString();
                        itemSkuWarehouseExportDoArray[6] = itemSkuWarehouseExportDo.getDonationWarehouse().toString();
                        itemSkuWarehouseExportDoArray[7] = itemSkuWarehouseExportDo.getRegisterWarehouse().toString();
                        itemSkuWarehouseExportDoArray[8] = NumberFormatUtil.formatForIgnoreZero(itemSkuWarehouseExportDo.getCostPrice() , 5);
                        itemSkuWarehouseExportDoArray[9] = itemSkuWarehouseExportDo.getCountWarehouse().toString();
                        exports.add(itemSkuWarehouseExportDoArray);
                    }
                }
                return exports;
            }

            @Override
            public String initSheetName() {
                return "库存列表";
            }

            @Override
            public int[] initColumnWidth() {
                int[] columnWidths = {150, 100, 500, 0, 0, 0, 0, 0, 0, 0};
                return columnWidths;
            }

        }.create(response, list);

        return null;
    }

 四、生成Excel工厂实现

package com.hqb360.common.lang.excel;

import com.hqb360.common.lang.StringUtil;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

/**
 * 功能描述:生成Excel工厂类
 *
 * @author: Zhenbin.Li
 * Date: 13-11-17 Time:上午10:04
 */
public class ExportExcelFactory {

    /** 工作薄 */
    private HSSFWorkbook workbook;

    /** 工作表 */
    private HSSFSheet sheet;

    /** 当前行数 */
    private int currentRow = 0;

    /** 总列数 */
    private int totalCols;

    /** Excel Sheet名称 */
    private final String sheetName;

    /**
     * 默认构造方法
     */
    public ExportExcelFactory(String sheetName) {
        this.sheetName = sheetName;
        workbook = new HSSFWorkbook();
        sheet = workbook.createSheet(getSheetName());
    }

    /**
     * 设置列宽
     *
     * @param columnWidth 列宽信息
     */
    @SuppressWarnings("deprecation")
	public void setColumnWidth(int[] columnWidth) {
        for (int i = 0; i < columnWidth.length; i++) {
            if (columnWidth[i] != 0) {
                if (sheet.getColumnWidth((short) i) != (columnWidth[i] * 37.5)) {
                    sheet.setColumnWidth((short) i, (short) (columnWidth[i] * 37.5));
                }
            }
        }
    }

    /**
     * 设置列数
     *
     * @param cols 列数
     */
    public void setCols(int cols) {
        this.totalCols = cols;
    }

    /**
     * 创建标题
     *
     * @param caption 标题
     */
    public void createCaption(String caption) {
        HSSFFont font = ExportExcelUtil.getFont(workbook, 10, HSSFFont.BOLDWEIGHT_BOLD, HSSFColor.BLACK.index);
        HSSFCellStyle style = ExportExcelUtil.getStyle(workbook, font, HSSFCellStyle.ALIGN_CENTER);

        HSSFRow row = sheet.createRow(currentRow);
        ExportExcelUtil.createCell(row, 0, style, caption);
        for (int i = 1; i < totalCols; i++) {
            ExportExcelUtil.createCell(row, i, style, "");
        }

        ExportExcelUtil.mergeCol(sheet, 0, totalCols - 1, currentRow);
        currentRow++;
    }

    /**
     * 创建一行列标题
     *
     * @param colCaption 一行列标题
     */
    public void createColCaption(String[] colCaption) {
        HSSFFont font = ExportExcelUtil.getFont(workbook, 0, HSSFFont.BOLDWEIGHT_BOLD, HSSFColor.BLACK.index);
        HSSFCellStyle style = ExportExcelUtil.getStyle(workbook, font, HSSFCellStyle.ALIGN_CENTER);

        HSSFRow row = sheet.createRow(currentRow);
        for (int i = 0; i < colCaption.length; i++) {
            ExportExcelUtil.createCell(row, i, style, colCaption[i]);
        }
        currentRow++;
    }

    /**
     * 创建多行列标题
     *
     * @param colCaption 多行列标题
     */
    public void createColCaption(String[][] colCaption) {
        HSSFFont font = ExportExcelUtil.getFont(workbook, 10, HSSFFont.BOLDWEIGHT_BOLD, HSSFColor.BLACK.index);
        HSSFCellStyle style = ExportExcelUtil.getStyle(workbook, font, HSSFCellStyle.ALIGN_CENTER);
        int[][][] spans = getSpans(colCaption);

        for (int i = 0; i < colCaption.length; i++) {
            HSSFRow row = sheet.createRow(currentRow);
            for (int j = 0; j < colCaption[i].length; j++) {
                ExportExcelUtil.createCell(row, j, style, colCaption[i][j]);

                if (spans[i][j] != null) {
                    ExportExcelUtil
                            .mergeRegion(sheet, currentRow, j, currentRow + spans[i][j][0] - 1, j + spans[i][j][1] - 1);
                }
            }
            currentRow++;
        }
    }

    /**
     * 创建EXCEL的主体数据
     *
     * @param data 主体数据,可支持的数据格式有:
     *             1、简单列表 List(String[]);
     *             2、合并一列 Map(List(String[]));
     *             3、合并二列 Map(Map(List(String[]))。
     */
    @SuppressWarnings("rawtypes")
	public void createBody(Object data) {
        int nestedCount = ExportExcelUtil.getNestedCount(data);

        if (nestedCount == 0) {
            createBody((List<String[]>)data);
        } else if (nestedCount == 1) {
            ExportExcelUtil.createOneMapBody(workbook, sheet, (Map) data, currentRow);
        } else if (nestedCount == 2) {
            ExportExcelUtil.createTwoMapBody(workbook, sheet, (Map) data, currentRow);
        } else {
            throw new IllegalArgumentException("不支持的数据格式");
        }
    }

    /**
     * 创建列表的主体数据
     *
     * @param list List(String[])列表数据
     */
    protected void createBody(List<String[]> list) {

        HSSFFont font = ExportExcelUtil.getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.BLACK.index);
        HSSFCellStyle style = ExportExcelUtil.getStyle(workbook, font, HSSFCellStyle.ALIGN_CENTER);

        for (int index = 0; index < list.size(); index++) {
            HSSFRow row = sheet.createRow(currentRow);
            String[] stringArray = list.get(index);
            for (int j = 0; j < stringArray.length; j++) {
                ExportExcelUtil.createCell(row, j, style, stringArray[j]);
            }
            currentRow++;
        }
    }

    /**
     * 创建EXCEL的主体数据
     *
     * @param data 主体数据,可支持的数据格式有:
     *             1、简单列表 List(String[]);
     *             2、合并一列 Map(List(String[]));
     *             3、合并二列 Map(Map(List(String[]))。
     */
	@SuppressWarnings("rawtypes")
	public void createBody(Object data, Object color) {
        int nestedCount = ExportExcelUtil.getNestedCount(data);

        if (nestedCount == 0) {
            ExportExcelUtil.createBodyColor(workbook, sheet, (List) data, (Map) color, currentRow);
        } else if (nestedCount == 1) {
            ExportExcelUtil.createOneMapBody(workbook, sheet, (Map) data, currentRow);
        } else if (nestedCount == 2) {
            ExportExcelUtil.createTwoMapBody(workbook, sheet, (Map) data, currentRow);
        } else {
            throw new IllegalArgumentException("不支持的数据格式");
        }
    }

    /**
     * 创建备注信息
     *
     * @param remarks 备注信息
     */
    public void createRemarks(String[] remarks) {
        HSSFFont font = ExportExcelUtil.getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.RED.index);
        HSSFCellStyle style = ExportExcelUtil.getStyle(workbook, font, HSSFCellStyle.ALIGN_LEFT);

        for (int i = 0; i < remarks.length; i++) {
            HSSFRow row = sheet.createRow(currentRow);
            ExportExcelUtil.createCell(row, 0, style, remarks[i]);

            for (int j = 1; j < totalCols; j++) {
                ExportExcelUtil.createCell(row, j, style, "");
            }

            ExportExcelUtil.mergeCol(sheet, 0, totalCols - 1, currentRow);
            currentRow++;
        }
    }

    /**
     * 创建本地路径的EXCEL文件
     *
     * @param filePath EXCEL文件路径
     */
    public void createFile(String filePath) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(filePath);
            workbook.write(out);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("无法创建文件:" + filePath);
        } catch (IOException e) {
            throw new RuntimeException("无法写入文件:" + filePath);
        } finally {
            ExportExcelUtil.closeOutputStream(out);
        }
    }

    /**
     * 把EXCEL文件写入到输出流中
     *
     * @param out 输出流
     * @throws java.io.IOException
     */
    public void createFile(OutputStream out) throws IOException {
        workbook.write(out);
    }


    /**
     * 根据多行报表标题获得一个合并的行列信息
     *
     * @param colTitles 列标题
     * @return 报表标题合并的行列信息:第一维对应标题的行,第二维对应标题的列,
     *         第三维对应标题的合并行和列,已经被合并的行或列则对应的第三维为null。
     */
    public static int[][][] getSpans(String[][] colTitles) {
        int[][][] spans = new int[colTitles.length][][];

        for (int i = 0; i < colTitles.length; i++) {
            spans[i] = new int[colTitles[i].length][];
            for (int j = 0; j < colTitles[i].length; j++) {
                if (colTitles[i][j] != null) {
                    spans[i][j] = new int[2];
                    spans[i][j][0] = ExportExcelUtil.getRowSpan(colTitles, i, j);
                    spans[i][j][1] = ExportExcelUtil.getColSpan(colTitles, i, j);
                }
            }
        }

        return spans;
    }

    /**
     * 获取Excel Sheet名称
     *
     * @return
     */
    public String getSheetName() {
        return sheetName;
    }
}

 

package com.hqb360.common.lang.excel;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;

/**
 * 功能描述: ExportExcelFactory.java类抽取其方法工具类
 *
 * @author: Zhenbin.Li
 * Date: 13-11-17 Time:上午10:20
 */
@SuppressWarnings("deprecation")
public class ExportExcelUtil {

    /**
     * 创建列表的主体数据
     *
     * @param workbook
     * @param list       List(String[])列表数据
     * @param color
     * @param sheet
     * @param currentRow
     */
    @SuppressWarnings("rawtypes")
	protected static void createBodyColor(HSSFWorkbook workbook, HSSFSheet sheet, 
			List list, Map color, int currentRow) {

        HSSFFont font_black = getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.BLACK.index);
        HSSFCellStyle style_black = getStyle(workbook, font_black, HSSFCellStyle.ALIGN_CENTER);
        HSSFFont font_red = getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.RED.index);
        HSSFCellStyle style_red = getStyle(workbook, font_red, HSSFCellStyle.ALIGN_CENTER);
        HSSFFont font_green = getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.GREEN.index);
        HSSFCellStyle style_green = getStyle(workbook, font_green, HSSFCellStyle.ALIGN_CENTER);

        for (int index = 0; index < list.size(); index++) {
            String rowColor = (String) color.get(index);


            HSSFRow row = sheet.createRow(currentRow);
            String[] stringArray = (String[]) list.get(index);
            for (int j = 0; j < stringArray.length; j++) {
                if (rowColor != null) {
                    if (rowColor.equals("RED")) {
                        createCell(row, j, style_red, stringArray[j]);
                    } else if (rowColor.equals("GREEN")) {
                        createCell(row, j, style_green, stringArray[j]);
                    } else {
                        createCell(row, j, style_black, stringArray[j]);
                    }
                } else {
                    createCell(row, j, style_black, stringArray[j]);
                }

            }
            currentRow++;
        }
    }

    /**
     * 创建合并一列的主体数据
     *
     * @param map        Map(List(String[])) 嵌套一层的Map数据
     * @param sheet
     * @param currentRow
     */
    @SuppressWarnings("rawtypes")
	protected static void createOneMapBody(HSSFWorkbook workbook, HSSFSheet sheet, Map map, int currentRow) {

        HSSFFont font = getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.BLACK.index);
        HSSFCellStyle style = getStyle(workbook, font, HSSFCellStyle.ALIGN_CENTER);

        for (Iterator it = map.keySet().iterator(); it.hasNext(); ) {
            String key = (String) it.next();
            List list = (List) map.get(key);
            int size = list.size();
            mergeRow(sheet, currentRow, currentRow + size - 1, 0);

            for (int i = 0; i < size; i++) {
                HSSFRow row = sheet.createRow(currentRow);
                createCell(row, 0, style, key);

                String[] stringArray = (String[]) list.get(i);
                for (int j = 0; j < stringArray.length; j++) {
                    createCell(row, j + 1, style, stringArray[j]);
                }
                currentRow++;
            }
        }
    }

    /**
     * 创建合并二列的主体数据
     *
     * @param map        Map(Map(List(String[]))) 嵌套二层的Map数据
     * @param sheet
     * @param currentRow
     */
    @SuppressWarnings("rawtypes")
	protected static void createTwoMapBody(HSSFWorkbook workbook, HSSFSheet sheet, Map map, int currentRow) {

        HSSFFont font = getFont(workbook, 10, HSSFFont.BOLDWEIGHT_NORMAL, HSSFColor.BLACK.index);
        HSSFCellStyle style = getStyle(workbook, font, HSSFCellStyle.ALIGN_CENTER);

        //第一列的合并行数
        int[] rowSpans = getRowSpanOfTwoMap(map);
        int rowCount = 0;
        for (Iterator iterator = map.keySet().iterator(); iterator.hasNext(); rowCount++) {

            String key1 = (String) iterator.next();
            Map map1 = (Map) map.get(key1);

            mergeRow(sheet, currentRow, currentRow + rowSpans[rowCount] - 1, 0);

            for (Iterator it2 = map1.keySet().iterator(); it2.hasNext(); ) {
                String key2 = (String) it2.next();
                List list = (List) map1.get(key2);
                int size = list.size();
                mergeRow(sheet, currentRow, currentRow + size - 1, 1);

                for (int i = 0; i < size; i++) {
                    HSSFRow row = sheet.createRow(currentRow);
                    createCell(row, 0, style, key1);
                    createCell(row, 1, style, key2);

                    String[] stringArray = (String[]) list.get(i);
                    for (int j = 0; j < stringArray.length; j++) {
                        createCell(row, j + 2, style, stringArray[j]);
                    }
                    currentRow++;
                }
            }
        }
    }

    /**
     * 创建单元格
     *
     * @param row   行对象
     * @param index 在行中创建单元格的位置,从0开始。
     * @param style 单元格样式
     * @param value 单元格的值
     */
	protected static void createCell(HSSFRow row, int index, HSSFCellStyle style, String value) {

        HSSFCell cell = row.createCell((short) index);
        //cell.setEncoding(HSSFCell.ENCODING_UTF_16);
        cell.setCellStyle(style);
        cell.setCellValue(value);
    }

    /**
     * 合并行
     *
     * @param sheet
     * @param startRow 起始行(从0开始)
     * @param endRow   结束行(从0开始)
     * @param col      列位置(从0开始)
     */
	protected static void mergeRow(HSSFSheet sheet, int startRow, int endRow, int col) {

        sheet.addMergedRegion(new Region(startRow, (short) col, endRow, (short) col));
    }

    /**
     * 合并列
     *
     * @param sheet
     * @param startCol 起始列(从0开始)
     * @param endCol   结束列(从0开始)
     * @param row      行位置(从0开始)
     */
	protected static void mergeCol(HSSFSheet sheet, int startCol, int endCol, int row) {

        sheet.addMergedRegion(new Region(row, (short) startCol, row, (short) endCol));
    }

    /**
     * 合并区域
     *
     * @param sheet
     * @param startRow 起始行(从0开始)
     * @param startCol 起始列(从0开始)
     * @param endRow   结束行(从0开始)
     * @param endCol   结束列(从0开始)
     */
	protected static void mergeRegion(HSSFSheet sheet, int startRow, int startCol, int endRow, int endCol) {

        sheet.addMergedRegion(new Region(startRow, (short) startCol, endRow, (short) endCol));
    }

    /**
     * 关闭输出流
     *
     * @param out 输出流
     */
    protected static void closeOutputStream(OutputStream out) {

        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {

            }
        }
    }

    /**
     * 根据字体高度和字体类型获得字体对象
     *
     * @param fontHeight 字体高度
     * @param boldweight 字体类型
     * @param color      字体颜色
     * @return 字体对象
     */
    protected static HSSFFont getFont(HSSFWorkbook workbook, int fontHeight, short boldweight, short color) {

        HSSFFont font = workbook.createFont();
        font.setFontHeightInPoints((short) fontHeight);
        font.setFontName("新宋体");
        font.setColor(color);
        font.setBoldweight(boldweight);
        return font;
    }

    /**
     * 根据字体和对其方式获得单元格样式
     *
     * @param font  字体
     * @param align 对其方式
     * @return 单元格样式
     */
    protected static HSSFCellStyle getStyle(HSSFWorkbook workbook, HSSFFont font, short align) {

        HSSFCellStyle style = workbook.createCellStyle();
        style.setFont(font);
        //边框
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setRightBorderColor(HSSFColor.BLACK.index);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setTopBorderColor(HSSFColor.BLACK.index);
        //对齐方式
        style.setAlignment(align);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        return style;
    }

    /**
     * 获得报表标题在某行某列的行跨度
     *
     * @param colTitles 报表列标题
     * @param row       行
     * @param col       列
     * @return 行跨度
     */
    protected static int getRowSpan(String[][] colTitles, int row, int col) {

        int rowSpan = 1;
        if (colTitles[row][col] != null) {
            for (int i = row + 1; i < colTitles.length; i++) {
                if (colTitles[i][col] == null) {
                    rowSpan++;
                } else {
                    break;
                }
            }
        }
        return rowSpan;
    }

    /**
     * 获得报表标题在某行某列的列跨度
     *
     * @param colTitles 报表列标题
     * @param row       行
     * @param col       列
     * @return 列跨度
     */
    protected static int getColSpan(String[][] colTitles, int row, int col) {

        int colSpan = 1;
        if (colTitles[row][col] != null) {
            for (int i = col + 1; i < colTitles[row].length; i++) {
                if (colTitles[row][i] == null) {
                    if (row == 0) {
                        colSpan++;
                    } else if (colTitles[row - 1][i] == null) {
                        colSpan++;
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }
        }
        return colSpan;
    }

    /**
     * 获得Map或List数据的嵌套层次数。
     *
     * @param obj Map 或 List
     * @return 如果参数为null则返回-1;
     *         如果参数为List则返回0;
     *         如果为一层Map(Map中value为List)则返回1;
     *         如果为二层Map(Map中value为Map,再深层为List,则返回2;
     *         ......
     */
    @SuppressWarnings("rawtypes")
	protected static int getNestedCount(Object obj) {

        if (obj == null) {
            return -1;
        } else if (obj instanceof List) {
            return 0;
        } else if (obj instanceof Map) {
            Map map = (Map) obj;
            if (map.size() > 0) {
                Object o = map.get(map.keySet().iterator().next());
                return getNestedCount(o) + 1;
            } else {
                return 1;
            }
        }
        throw new IllegalArgumentException("参数不为List或Map");
    }

    /**
     * 获得两层嵌套Map的针对报表的第一列合并行情况
     *
     * @param map Map(Map(List))两层嵌套Map
     * @return 对应报表的第一列合并行情况
     */
    @SuppressWarnings({ "rawtypes", "unused" })
	protected static int[] getRowSpanOfTwoMap(Map map) {

        int[] spans = new int[map.size()];
        Iterator it = map.keySet().iterator();
        for (int i = 0; it.hasNext(); i++) {
            Object key = it.next();
            Map map2 = (Map) map.get(key);
            Iterator it2 = map2.keySet().iterator();
            for (int i2 = 0; it2.hasNext(); i2++) {
                Object key2 = it2.next();
                List list = (List) map2.get(key2);
                spans[i] += list.size();
            }
        }
        return spans;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值