Excel 导出数据工具类

引用依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>

写一个 ExcelUtils 工具类

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

import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelUtils {

    public static class ExcelDataFormat {
        public static final String CURRENCY = "¥#,##0.0000;¥-#,##0.0000"; // 货币
        public static final String DATETIME = "yyyy/m/d h:mm"; // 日期
        public static final String DECIMAL = "0.00"; // 小数
        public static final String INTEGER = "0"; // 整数
    }

    public static void createExcel(List<Map<String, Object>> datas, String fileName) {
        if (datas.size() > 0) {
            final Map<String, Object> map = datas.get(0);
            final String[] keys = map.keySet().toArray(new String[0]);
            createExcel(keys, datas, fileName);
        }
    }

    public static void createExcel(String[] keys, List<Map<String, Object>> datas, String fileName) {
        createExcel(keys, datas, fileName, new HashMap<>(), new HashMap<>());
    }

    public static void createExcel(
            List<Map<String, Object>> datas,
            String fileName,
            Map<String, String> cellStyleFormatMap,
            Map<String, Integer> columnWidthMap
    ) {
        if (datas.size() > 0) {
            final Map<String, Object> map = datas.get(0);
            final String[] keys = map.keySet().toArray(new String[0]);
            createExcel(keys, datas, fileName, cellStyleFormatMap, columnWidthMap);
        }
    }

    /**
     * 单元格带有不同格式的 Excel
     *
     * @param keys               要输出的key的值,输出的数据列将按照这个顺序
     * @param datas              Map数据列表
     * @param fileName           文件名
     * @param cellStyleFormatMap 键值对应 keys 中的列的单元格数据格式,见 ExcelDataFormat 个别示例,或者查看Excel软件的单元格里的自定义格式列表
     * @param columnWidthMap     键值对应 keys 中的列的单元格宽度
     */
    public static void createExcel(
            String[] keys,
            List<Map<String, Object>> datas,
            String fileName,
            Map<String, String> cellStyleFormatMap,
            Map<String, Integer> columnWidthMap
    ) {
        FileOutputStream os;
        final int MAX_LEN = 60000;
        try {
            os = new FileOutputStream(fileName);
            // 创建Excel的工作书册 Workbook,对应到一个excel文档
            HSSFWorkbook wb = new HSSFWorkbook();

            // 生成样式
            Map<String, HSSFCellStyle> styleMap = new HashMap<>();
            for (int i = 0; i < keys.length; i++) {
                final String formatString = cellStyleFormatMap.get(keys[i]);
                if (formatString != null) {
                    final HSSFCellStyle style = wb.createCellStyle();
                    final HSSFDataFormat dataFormat = wb.createDataFormat();
                    style.setDataFormat(dataFormat.getFormat(formatString));
                    styleMap.put(keys[i], style);
                }
            }

            int size = datas.size() / MAX_LEN;
            for (int i = 0; i < size; i++) {
                // 创建Excel的工作sheet,对应到一个excel文档的 tab
                HSSFSheet sheet = wb.createSheet("sheet" + (i + 1));
                for (int j = 0; j < MAX_LEN; j++) {
                    Map<String, Object> model = datas.get(i * MAX_LEN + j);
                    setCell(keys, model, sheet, j, cellStyleFormatMap, styleMap);
                }
                for (int i1 = 0; i1 < keys.length; i1++) {
                    if (columnWidthMap.containsKey(keys[i1])) {
                        sheet.setColumnWidth(i1, columnWidthMap.get(keys[i1]));
                    }
                }
            }

            int tempSize = datas.size() % MAX_LEN;
            if (tempSize > 0) {
                HSSFSheet sheet = wb.createSheet("sheet" + (size + 1));
                // 设置 Sheet 数据
                for (int z = 0; z < tempSize; z++) {
                    Map<String, Object> model = datas.get(size * MAX_LEN + z);
                    setCell(keys, model, sheet, z, cellStyleFormatMap, styleMap);
                }
                for (int i1 = 0; i1 < keys.length; i1++) {
                    if (columnWidthMap.containsKey(keys[i1])) {
                        sheet.setColumnWidth(i1, columnWidthMap.get(keys[i1]));
                    }
                }
            }
            wb.write(os);
            os.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 具有数据格式的单元格
     */
    public static void setCell(
            String[] keys, Map<String, Object> model, HSSFSheet sheet, int index,
            Map<String, String> cellStyleFormatMap, Map<String, HSSFCellStyle> styleMap
    ) {
        // 创建Excel的sheet的一行
        HSSFRow row = sheet.createRow(index);

        // 创建一个Excel的单元格
        for (int i = 0; i < keys.length; i++) {
            HSSFCell cell = row.createCell(i);
            Object v = model.get(keys[i]);
            if (index > 0) {
                try {
                    // 设置样式
                    if (styleMap.containsKey(keys[i])) {
                        final HSSFCellStyle style = styleMap.get(keys[i]);
                        cell.setCellStyle(style);
                    }
                    // 判断数据类型,转为对应的类型。如果不转为对应类型,默认打开显示的效果是文本的效果
                    final String formatString = cellStyleFormatMap.get(keys[i]);
                    if (ExcelDataFormat.CURRENCY.equals(formatString)) {
                        if (v != null) {
                            cell.setCellValue((new BigDecimal(v.toString())).doubleValue());
                        }
                    } else if (ExcelDataFormat.DECIMAL.equals(formatString)) {
                        if (v != null) {
                            cell.setCellValue(Double.parseDouble(v.toString()));
                        }
                    } else if (ExcelDataFormat.INTEGER.equals(formatString)) {
                        if (v != null) {
                            // 直接用 Long.parseLong 转换会报错,先转为 double 类型再转为整型
                            cell.setCellValue((long) Double.parseDouble(v.toString()));
                        }
                    } else {
                        cell.setCellValue(v != null ? v.toString() : "");
                    }

                } catch (Exception e) {
                    System.out.println();
                    System.out.println(String.format("转换数据类型时出现错误:key=%s, value=%s ", keys[i], v));
                    System.out.println(String.format("错误信息:%", e.toString()));
                }

            } else {
                cell.setCellValue(v != null ? v.toString() : "");
            }

        }
    }

    /**
     * 读取 Excel
     *
     * @param pathname 文件路径名
     */
    public static Object[][] readExcel(String pathname) {
        File file = new File(pathname);
        HSSFWorkbook workbook = null;
        try {
            workbook = new HSSFWorkbook(new FileInputStream(file));
        } catch (IOException e) {
            System.out.printf("错误信息:%s%n", e.toString());
            return null;
        }
        //获得表格中的第0个Sheet
        final HSSFSheet sheet = workbook.getSheetAt(0);
        //得到有多少行
        int numberRows = sheet.getPhysicalNumberOfRows();
        //获得第一行有多少列
        int numberCells = sheet.getRow(0).getPhysicalNumberOfCells();
        //获得第一行第一列所在的位置
        int numberFirst = sheet.getRow(0).getFirstCellNum();
        //创建一个Object二维数组,用来作为参数返回。
        //因为第一行是说明,则跳过第一行,所以行数减一
        Object[][] data = new Object[numberRows][];
        //创建一个保存列的对象
        HSSFRow row = null;
        for (int i = sheet.getFirstRowNum(); i < numberRows; i++) {
            //得到第i+1行,即第二行的实际数据
            row = sheet.getRow(i);
            // 创建一个字符数组,用来保存一行中,每一列的数据
            String[] strings = new String[numberCells];
            //row.getFirstCellNum() 获得一行中实际数据所在列,不一为第一列,如图第4行
            for (int j = numberFirst; j < numberCells; j++) {
                // 数据是通过key-value方式保存,遍历是会出现空指针异常(图中红色部分)。
                //出现的多余没有输入的单元格会出现异常,并对没有数据输入的单元格(红色部分)是进行空字符处理
                try {
                    //设置为字符类型,这里主要是因为在获取Excel数据时,
                    //数字出现小数点,主要用于不加小数点,可以简单这么理解。大家可以看一下源码就知道什么原因了
                    row.getCell(j).setCellType(CellType.STRING);
                } catch (NullPointerException e) {
                    //出现空指针异常,说明数据没有输入,即空数据,做空字符串处理
                    strings[j] = "";
                    //跳过当前循环
                    continue;
                }
                // 保存数据
                strings[j] = row.getCell(j).getStringCellValue();
            }
            //把获得数据添加到data
            data[i] = strings;
        }
        return data;
    }

}

如果有数据的话,写个类进行测试一下

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {

    public static List<Map<String, Object>> getDatas() {
        List<Map<String, Object>> datas = new ArrayList<>();
        String[] name = {
                "aaa",
                "bbb",
                "ccc",
                "ddd",
                "eee"
        };
        int[] sum = {1, 2, 3, 4, 5};
        BigDecimal[] price = {
                new BigDecimal(10.245),
                new BigDecimal(54.234),
                new BigDecimal(9.12948),
                new BigDecimal(0.342),
                new BigDecimal(101)
        };
        for (int i = 0; i < name.length; i++) {
            final HashMap<String, Object> item = new HashMap<>();
            item.put("name", name[i]);
            item.put("sum", sum[i]);
            item.put("price", price[i]);
            datas.add(item);
        }
        return datas;

    }

    public static void main(String[] args) {
        // 获取数据
        final List<Map<String, Object>> datas = getDatas();

        // 设置字段头列表的名称
        final HashMap<String, Object> map = new HashMap<>();
        map.put("name", "药品名称");
        map.put("sum", "数量");
        map.put("price", "单价(元)");
        datas.add(0, map);

        System.out.println(datas);

        // 输出的列字段与顺序
        String[] keys = {"name", "sum", "price"};

        // 单元格数据格式
        Map<String, String> cellStyleFormatMap = new HashMap<>();
        cellStyleFormatMap.put("sum", ExcelUtils.ExcelDataFormat.INTEGER);
        cellStyleFormatMap.put("price", ExcelUtils.ExcelDataFormat.CURRENCY);
        // 单元格宽度
        Map<String, Integer> cellWidthMap = new HashMap<>();
        cellWidthMap.put("price", 6000);

        // 创建excel文件
        String fileName = "C:\\Users\\Administrator\\Desktop\\test.xls";
        ExcelUtils.createExcel(keys, datas, fileName, cellStyleFormatMap, cellWidthMap);

    }


}

相关参考链接:


设置单元格格式时遇到问题

POI Excel HSSFCell 设置单元格数字格式
在报表系统中遇到一个问题,需要设置数字格式,因为默认文本格式,需要手动刷数值格式,解决代码如下:

// HeCG95
// (1)设置 HSSFCell 为数值类型,如果传入字符串,后面一步设置格式也失效的
HSSFCell.setCellValue(Float.parseFloat(value));
// (2)设置样式
HSSFCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));

原文链接:POI Excel HSSFCell 设置单元格数字格式


对Excel的各个单元格的格式进行判断并转换

    /**
     * 对Excel的各个单元格的格式进行判断并转换
     */
    public static String getCellValue(Cell cell) {
        String cellValue = "";
        if (cell == null) {
            return cellValue;
        }
        // 判断数据的类型
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_NUMERIC: // 数字
                //short s = cell.getCellStyle().getDataFormat();
                if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式
                    SimpleDateFormat sdf = null;
                    // 验证short值
                    if (cell.getCellStyle().getDataFormat() == 14) {
                        sdf = new SimpleDateFormat("yyyy/MM/dd");
                    } else if (cell.getCellStyle().getDataFormat() == 21) {
                        sdf = new SimpleDateFormat("HH:mm:ss");
                    } else if (cell.getCellStyle().getDataFormat() == 22) {
                        sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    } else {
                        throw new RuntimeException("日期格式错误!!!");
                    }
                    Date date = cell.getDateCellValue();
                    cellValue = sdf.format(date);
                } else {//处理数值格式
                    cell.setCellType(Cell.CELL_TYPE_STRING);
                    cellValue = String.valueOf(cell.getRichStringCellValue().getString()).trim();
                }
                break;
            case Cell.CELL_TYPE_STRING: // 字符串
                cellValue = String.valueOf(cell.getStringCellValue()).trim();
                break;
            case Cell.CELL_TYPE_BOOLEAN: // Boolean
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_FORMULA: // 公式
                cellValue = String.valueOf(cell.getCellFormula());
                break;
            case Cell.CELL_TYPE_BLANK: // 空值
                cellValue = "";
                break;
            case Cell.CELL_TYPE_ERROR: // 故障
                cellValue = "非法字符";
                break;
            default:
                cellValue = "未知类型";
                break;
        }
        return cellValue;
    }

原文链接 对Excel的各个单元格的格式进行判断并转换

其他链接

《Excel 导出数据工具类》有1条评论

发表评论