Java对Excel表格的导出一直是对我有种可怕噩梦的东西,每次对要建立行与列,并一个一个放值,我是从心底拒绝的。

处于项目需求,需要导出表格,于是找到网上一版很好的开发, 《不想用POI?几行代码完成Excel导出导入》原文链接:  https://juejin.im/post/5c3b683ee51d4551d14175ee

但是、我们项目不支持如此进行开发,

================================分割线=================================

因为需要引入xml文件进行开发,于是,只能自己动手封装一个满足需求的类:

一、需求:

查询统计的数据 List,进行数据导出,并且表头有合并单元格的需求。

直接上图:以下是部分结果(由于全部截取失真)

二、设计思路:

表头::把表头与数据插入表格对象进行分开。表头部分,每一行做为一个list, 使用String[]进行存储。每次分析表头,进行解析,生成表头。

表体::需要插入的数据使用list中存入 map对象,其中的对象字段名称与表头部分相同,就可以进行数据的插入。

代码如下:

/**

 * Created by 闲一 on 2019/2/20.
 */
package com.test;
 
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.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
 
public class POItest2 {
     
    @Test
    public void test1() throws IOException {
        List<String[]> list = new ArrayList<>();
        String[] arr = {"部门""云速"};
        String[] arr1 = {"总计""10000000"};
        String[] arr2 = {"单位""元"};
        list.add(arr);
        list.add(arr1);
        list.add(arr2);
        XSSFWorkbook workbook = new XSSFWorkbook();
        workbook = workbookList(workbook, "come""", list);
 
        String[] arra0 = {"name""名称""1""1"};
        String[] arra1 = {"Person""人类""1""2"};
        String[] arrb1 = {"Amions""动物""1""1"};
        List<String[]> lista = new ArrayList<>();
        List<List<String[]>> titles = new ArrayList<>();
        lista.add(arra0);
        lista.add(arra1);
        lista.add(arrb1);
        titles.add(lista);
        String[] arr11 = {"""""2""1"};
        List<String[]> list1 = new ArrayList<>();
        list1.add(arr11);
        String[] arr21 = {"sex""性别""1""1"};
        list1.add(arr21);
        String[] arr31 = {"kaka""咳咳""1""1"};
        list1.add(arr31);
        String[] arr41 = {"kaka""小米""1""1"};
        list1.add(arr41);
        titles.add(list1);
 
        workbook = workbookinList(workbook, "come""", titles, new ArrayList<>());
        workbook = workbookinList(workbook, "come""", titles, new ArrayList<>());
 
        String path = "d:/data/2019-02-19-04.csv";
        wirteOutWorkbook(workbook, path);
    }
 
    /**
     * 将数据写入指定Excel对象中
     *
     * @param workbook  Excel对象
     * @param sheetName sheet名
     * @param style     Excel类型
     * @param titles    标题串 {{['person','人类',1,2]},
     *                  {['name','名称',1,1], ['sex','性别',1,1]}}   【 字段名称,标题,所占行数,所占列数】
     * @param values    内容集
     * @return True\False
     */
    public XSSFWorkbook workbookinList(XSSFWorkbook workbook, String sheetName, String style, List<List<String[]>> titles, List<Map<String, Object>> values) {
        // 生成一个表格
        Sheet sheet;
        sheet = workbook.getSheet(sheetName);
        if (sheet == null) {
            if (null == sheetName || "".equals(sheetName)) {
                sheet = workbook.createSheet(); // sheetName 为空则使用默认值
            else {
                sheet = workbook.createSheet(sheetName);
            }
        }
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short15);
        // 第一行生成账单标题
        Row row = null;
        int rowNumCount = 0 == sheet.getLastRowNum() ? 0 : sheet.getLastRowNum() + 2;//获得总行数
        // 存储标题在Excel文件中的序号
        Map<String, Integer> titleOrder = new HashMap<>();
        for (int j = 0; j < titles.size(); j++) {
            List<String[]> list = titles.get(j);
            row = sheet.createRow(rowNumCount + j);
            int curCol = 0//当前列数名称
            for (int i = 0; i < list.size(); i++) {
                org.apache.poi.ss.usermodel.Cell cell = row.createCell(curCol);
                String[] title = list.get(i);
                cell.setCellValue(title[1]); // 标题值
                // 需要记录每次的列位置
                int rowNum = Integer.valueOf(title[2]) - 1// 需要占用的行数
                int colNum = Integer.valueOf(title[3]) - 1// 需要占用的列数
                if (0 != rowNum || 0 != colNum) {
                    int curRow = rowNumCount + j;
                    CellRangeAddress region = new CellRangeAddress(curRow - rowNum, curRow, curCol, curCol + colNum);
                    sheet.addMergedRegion(region);
                    curCol += Integer.valueOf(title[3]);
                else {
                    curCol++;
                }
                // 最后一行包含所有列
                if (j == titles.size() - 1) {
                    titleOrder.put(title[0], i);
                }
            }
        }
        /*
         * 写入正文
         */
        Iterator<Map<String, Object>> iterator = values.iterator();
        int index = rowNumCount + 1// 行号
        while (iterator.hasNext()) {
            index++; // 出去标题行,从第一行开始写
            row = sheet.createRow(index);
            Map<String, Object> value = iterator.next();
            for (Map.Entry<String, Object> map : value.entrySet()) {
                // 获取列名
                String title = map.getKey();
                // 根据列名获取序号
                Integer i = titleOrder.get(title);
                if (i == null) {
                    continue;
                }
                // 在指定序号处创建cell
                Cell cell = row.createCell(i);
                // 获取列的值
                Object object = map.getValue();
                // 判断object的类型
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                if (object instanceof Double) {
                    cell.setCellValue((Double) object);
                else if (object instanceof Date) {
                    String time = simpleDateFormat.format((Date) object);
                    cell.setCellValue(time);
                else if (object instanceof Calendar) {
                    Calendar calendar = (Calendar) object;
                    String time = simpleDateFormat.format(calendar.getTime());
                    cell.setCellValue(time);
                else if (object instanceof Boolean) {
                    cell.setCellValue((Boolean) object);
                else {
                    if (object == null) {
                        cell.setCellValue("");
                    else {
                        cell.setCellValue(object.toString());
                    }
                }
            }
        }
        return workbook;
    }
 
    /**
     * 将数据写入Excel文件中
     *
     * @param workbook  Excel对象
     * @param sheetName sheet名
     * @param style     Excel类型
     * @param dataList  标题串+内容集 {{'部门','201930'},{'总计','10000万'}}
     * @return True\False
     */
    public XSSFWorkbook workbookList(XSSFWorkbook workbook, String sheetName, String style, List<String[]> dataList) {
        // 生成一个表格
        Sheet sheet;
        sheet = workbook.getSheet(sheetName);
        if (sheet == null) {
            if (null == sheetName || "".equals(sheetName)) {
                sheet = workbook.createSheet(); // sheetName 为空则使用默认值
            else {
                sheet = workbook.createSheet(sheetName);
            }
        }
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short15);
        // 第一行生成账单标题
        Row row = null;
        int rowNumCount = 0 == sheet.getLastRowNum() ? 0 : sheet.getLastRowNum() + 2;//获得总行数
        // 存储标题在Excel文件中的序号
        for (int i = 0; i < dataList.size(); i++) {
            row = sheet.createRow(rowNumCount + i);
            row.createCell(0).setCellValue(dataList.get(i)[0]);
            row.createCell(1).setCellValue(dataList.get(i)[1]);
        }
        return workbook;
    }
 
    /**
     * 文件写出
     *
     * @param workbook
     * @param path
     * @throws IOException
     */
    public void wirteOutWorkbook(XSSFWorkbook workbook, String path) throws IOException {
        String dirPath = path.substring(0, path.lastIndexOf('.'));
        File dirFile = new File(dirPath);
        if (!dirFile.exists() && !dirFile.isDirectory()) {
            dirFile.mkdirs();
        }
        File file = new File(path);
        if (file.exists()) {
            file.delete();
        }
        OutputStream outputStream = new FileOutputStream(file);
        workbook.write(outputStream);
        outputStream.close();
        workbook.close();
    }
}

如有疑问,欢迎留言讨论!

 

Java的POI的封装与应用的更多相关文章

  1. java的poi技术写Excel的Sheet

    在这之前写过关于java读,写Excel的blog如下: Excel转Html java的poi技术读,写Excel[2003-2007,2010] java的poi技术读取Excel[2003-20 ...

  2. Java使用POI读取和写入Excel指南

    Java使用POI读取和写入Excel指南 做项目时经常有通过程序读取Excel数据,或是创建新的Excel并写入数据的需求: 网上很多经验教程里使用的POI版本都比较老了,一些API在新版里已经废弃 ...

  3. java的poi技术读取Excel数据到MySQL

    这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 ...

  4. java的poi技术读,写Excel[2003-2007,2010]

    在上一篇blog:java的poi技术读取Excel[2003-2007,2010] 中介绍了关于java中的poi技术读取excel的相关操作 读取excel和MySQL相关: java的poi技术 ...

  5. java的poi技术读取Excel[2003-2007,2010]

    这篇blog主要是讲述java中poi读取excel,而excel的版本包括:2003-2007和2010两个版本, 即excel的后缀名为:xls和xlsx. 读取excel和MySQL相关: ja ...

  6. Java Struts2 POI创建Excel文件并实现文件下载

    Java Struts2 POI创建Excel文件并实现文件下载2013-09-04 18:53 6059人阅读 评论(1) 收藏 举报 分类: Java EE(49) Struts(6) 版权声明: ...

  7. Java利用POI导入导出Excel中的数据

         首先谈一下今天发生的一件开心的事,本着一颗android的心我被分配到了PB组,身在曹营心在汉啊!好吧,今天要记录和分享的是Java利用POI导入导出Excel中的数据.下面POI包的下载地 ...

  8. java使用poi读取ppt文件和poi读取excel、word示例

    java使用poi读取ppt文件和poi读取excel.word示例 http://www.jb51.net/article/48092.htm

  9. Atitit. C# java 的api 目录封装结构映射总结

    Atitit. C#  java 的api 目录封装结构映射总结 C# java ref System.Reflection System.Type, java.lang.ref concurrent ...

随机推荐

  1. jquery validation验证身份证号、护照、电话号码、email

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. Spring-IOC MethodInvokingFactoryBean 类源码解析

    MethodInvokingFactoryBean MethodInvokingFactoryBean的作用是,通过定义类和它的方法,然后生成的bean是这个方法的返回值,即可以注入方法返回值. Me ...

  3. Kubernetes 初探

    一.容器: 1. 容器是运行一个或一组进程的方法,使得这些进程和主机上其他进程相隔离 2. 容器类似于虚拟机,但不同于虚拟机 容器                                    ...

  4. 基于swoole的聊天室模型

    client.html: <!doctype html><html><head> <meta charset="utf-8"> &l ...

  5. kendo ui - MultiSelect 多选系列

    kendo-ui 官网:https://www.telerik.com/documentation 初始化 grid: 引入文件: <link rel="stylesheet" ...

  6. [转]C结构体之位域(位段)

    有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C语言又提供了一种数据结构 ...

  7. Kafka设计解析(十七)Kafka 0.11客户端集群管理工具AdminClient

    转载自 huxihx,原文链接 Kafka 0.11客户端集群管理工具AdminClient 很多用户都有直接使用程序API操作Kafka集群的需求.在0.11版本之前,kafka的服务器端代码(即添 ...

  8. psql: 致命错误: 对用户"user1"的对等认证失败

    操作系统:Debian8 登录pg时可能会有提示错误: $ psql -U user1 -d exampledb psql: 致命错误: 对用户"user1"的对等认证失败 打开以 ...

  9. C++之指针指向二维数组

    一维指针通经常使用指针表示,其指向的地址是数组第一元素所在的内存地址,例如以下 int ary[4][5]; int(*aryp)[5] = ary; 那么ary[4]相当于int(*aryp).下面 ...

  10. iOS开发网络篇—发送GET和POST请求(使用NSURLSession) - 转

    说明: 1.该文主要介绍如何使用NSURLSession来发送GET请求和POST请求 2.本文将不再讲解NSURLConnection的使用,如有需要了解NSURLConnection如何发送请求. ...