`
liyebing
  • 浏览: 56707 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

通用的excel报表生成工具类

 
阅读更多

下面这个工具类是今天半天的劳动成果。

以后自己也可能用得到。在此做一个记录。涉及公司的信息的代码以及注释已经删除。哈哈。。。。

依赖了开源的POI工具包,网址:http://poi.apache.org/

 

这个工具类自己还没经过严格测试,简单测了一下,大体差不多是OK 的。

源码中注释掉的部分即为测试代码

 

上源码罗:

 

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.util.CollectionUtils;


/**
 * 生成Excel报表工具类
 */
public class ExcelProductUtil {

    /**
     * 生成列数固定格式的报表
     * 
     * @param contentList 报表的内容
     * @param title  报表头描述以及T对象的属性描述
     *                Map<String,String>:key : T对象的属性描述
     *                                   value:报表头文字描述 
     * @param seq    关联属性在报表中出现的顺序
     *        Map<String,String>:key : T对象的属性描述 
     *                           value:属性对应的顺序  
     * @param sheetName sheet的名称
     * @param rowNum 起始行(大于等于0)
     * 
     * 注意: title与seq均不能为空
     *      seq中的key必须与title的Key完全一致    
     *      seq中的value必须是从1开始的连续正整数   
     *      title中的Key必须来自于T的属性名称 
     *               
     */
    public static HSSFWorkbook productReportSameColumn(List<? extends Object> contentList,
                                                       Map<String, String> title,
                                                       Map<String, Integer> seq, 
                                                       String sheetName,
                                                       int rowNum) {
        //创建新的Excel工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        try {
            //校验title中的属性值必须在T中存在
            checkBeforeReportSameColumn(contentList, title, seq, sheetName, rowNum);

            HSSFSheet sheet = getSheet(sheetName, workbook);

            //生成报表的头部描述信息
            createReportSameColumnHead(sheet, title, seq, rowNum);

            //生成报表的文件体
            createReportSameColumnBody(sheet, title, contentList, seq, rowNum);

        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        return workbook;
    }

    /**
     * 创建新的Excel工作薄
     * @param sheetName
     * @return
     */
    private static HSSFSheet getSheet(String sheetName, HSSFWorkbook workbook) {
        HSSFSheet sheet = workbook.createSheet(sheetName);
        return sheet;
    }

    /**
     * 生成报表的文件体
     * 
     * @param workbook
     * @param title
     * @param contentList
     * @throws IllegalAccessException 
     * @throws IllegalArgumentException 
     */
    private static void createReportSameColumnBody(HSSFSheet sheet, Map<String, String> title,
                                                   List<? extends Object> contentList,
                                                   Map<String, Integer> seq, int rowNum)
                                                    throws IllegalArgumentException,
                                                               IllegalAccessException 
    {
        ++rowNum;
        for (Object content : contentList) {

            HSSFRow row = sheet.createRow(rowNum);

            Field[] fields = content.getClass().getDeclaredFields();
            for (Field f : fields) {
                f.setAccessible(true);
                String name = f.getName();
                if (title.containsKey(name)) {

                    HSSFCell cell = row.createCell(seq.get(name));
                    cell.setCellValue((String) f.get(content));
                }
            }
            ++rowNum;
        }
    }

    /**
     * 生成报表的头部描述信息
     * 
     * @param workbook
     * @param title
     */
    private static void createReportSameColumnHead(HSSFSheet sheet, Map<String, String> title,
                                                   Map<String, Integer> seq, int rowNum) {
        //获取排序之后的属性列表
        List<Map.Entry<String, Integer>> headDesList = getSoredPropertisList(seq);

        HSSFRow row = sheet.createRow(rowNum);

        for (Map.Entry<String, Integer> entry : headDesList) {
            String headName = title.get(entry.getKey());
            HSSFCell cell = row.createCell(entry.getValue());
            cell.setCellValue(headName);
        }
    }

    /**
     * 获取排序之后的属性列表
     * 
     * @param seq
     * @return
     */
    private static List<Map.Entry<String, Integer>> getSoredPropertisList(Map<String, Integer> seq) {

        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(seq
            .entrySet());

        //排序
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return o1.getValue() - o2.getValue();
            }
        });
        return list;
    }

    /**
     * 校验title中的属性值必须在T中存在
     * 
     * @param contentList
     * @param title
     */
    private static void checkBeforeReportSameColumn(List<? extends Object> contentList,
                                                    Map<String, String> title,
                                                    Map<String, Integer> seq, 
                                                    String sheetName,
                                                    int rowNum) {
        if (CollectionUtils.isEmpty(contentList) || CollectionUtils.isEmpty(title)
            || CollectionUtils.isEmpty(seq) || StringUtil.isBlank(sheetName)) {
            throw new RuntimeException("传入参数不能为空!");
        }
        if (rowNum < 0) {
            throw new RuntimeException("rowNum必须大于等于0!");
        }

        //获取T的属性名称
        List<String> propertiesNamesOfT = getTPropertiesName(contentList.get(0));

        //获取title的属性名称
        List<String> titlesNames = getTitleNames(title);

        //属性比较
        compareProperties(propertiesNamesOfT, titlesNames);

        //seq中的key必须与title的Key完全一致
        compareKey(title, seq);

        //seq中的value必须是从1开始的连续正整数
        compareSeqValue(seq);
    }

    /**
     * seq中的value必须是从1开始的连续正整数
     * 
     * @param seq
     */
    private static void compareSeqValue(Map<String, Integer> seq) {

        List<Map.Entry<String, Integer>> list = getSoredPropertisList(seq);

        if (list.get(0).getValue() != 1 || list.get(list.size() - 1).getValue() != list.size()) {
            throw new RuntimeException("seq中的value必须是从1开始的连续正整数");
        }

    }

    /**
     * seq中的key必须与title的Key完全一致
     * 
     * @param title
     * @param seq
     */
    private static void compareKey(Map<String, String> title, Map<String, Integer> seq) {
        Set<String> titleSet = title.keySet();
        Set<String> seqSet = seq.keySet();

        if (titleSet.size() != seqSet.size()) {
            throw new RuntimeException("seq中的key必须与title的Key必须完全一致!");
        }

        Set<String> titleTempSet = new HashSet<String>();
        titleTempSet.addAll(titleSet);
        titleTempSet.addAll(seqSet);
        if (titleTempSet.size() != seqSet.size()) {
            throw new RuntimeException("seq中的key必须与title的Key必须完全一致!");
        }
    }

    /**
     * 属性比较:titlesNames是否在propertiesNamesOfT中存在
     * 
     * @param propertiesNamesOfT
     * @param titlesNames
     */
    private static void compareProperties(List<String> propertiesNamesOfT, List<String> titlesNames) {
        List<String> tempPropertiesNamesOfT = new ArrayList<String>();
        List<String> tempTitlesNames = new ArrayList<String>();

        //对数组中的字符串转换成小写
        for (String tName : propertiesNamesOfT) {
            String temp = tName.toLowerCase();
            tempPropertiesNamesOfT.add(temp);
        }
        for (String tName : titlesNames) {
            String temp = tName.toLowerCase();
            tempTitlesNames.add(temp);
        }
        if (!tempPropertiesNamesOfT.containsAll(titlesNames)) {
            throw new RuntimeException("title中的某些属性值在T对象中不存在!");
        }
    }

    /**
     * 获取title的属性名称
     * 
     * @param title
     * @return
     */
    private static List<String> getTitleNames(Map<String, String> title) {
        List<String> titleNames = new ArrayList<String>();
        for (Map.Entry<String, String> entry : title.entrySet()) {
            titleNames.add(entry.getKey());
        }
        return titleNames;
    }

    /**
     * 获取T的属性名称
     * 
     * @param t
     * @return
     */
    private static List<String> getTPropertiesName(Object o) {
        List<String> list = new ArrayList<String>();

        Field[] fields = o.getClass().getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            list.add(f.getName());
        }
        return list;
    }

    //    private static class BankLog {
    //        private String name;
    //        private String password;
    //
    //        public String getName() {
    //            return name;
    //        }
    //
    //        public void setName(String name) {
    //            this.name = name;
    //        }
    //
    //        public String getPassword() {
    //            return password;
    //        }
    //
    //        public void setPassword(String password) {
    //            this.password = password;
    //        }
    //    }
    //
    //    public static void main(String[] args) throws Exception {
    //
    //        List<BankLog> bankLog = new ArrayList<BankLog>();
    //        BankLog bankLog1 = new BankLog();
    //        bankLog1.setName("111");
    //        bankLog1.setPassword("222");
    //        BankLog bankLog2 = new BankLog();
    //        bankLog2.setName("0000");
    //        bankLog2.setPassword("333");
    //        bankLog.add(bankLog1);
    //        bankLog.add(bankLog2);
    //
    //        Map<String, String> title = new HashMap<String, String>();
    //        title.put("name", "名字");
    //        title.put("password", "密码");
    //
    //        Map<String, Integer> seq = new HashMap<String, Integer>();
    //        seq.put("name", 2);
    //        seq.put("password", 1);
    //
    //        String sheetName = "Sheet1";
    //        int rowNum = 1;
    //
    //        HSSFWorkbook book = productReportSameColumn(bankLog, title, seq, sheetName, rowNum);
    //        String filename = "text.xls";
    //        FileOutputStream fOut = new FileOutputStream(filename);
    //        book.write(fOut);
    //        fOut.flush();
    //        fOut.close();
    //    }
}
分享到:
评论

相关推荐

    java导出excel文档通用工具类

    java导出excel文档通用工具类,使用方便。 可选择性的生成报表表头。

    EXCEL集成工具箱V8.0完整增强版(精简)

    EXCEL集成工具箱V8.0 多国语言版(2003-2010通用)增强版! * 软件大小: 22.90MB * 软件授权: 免费共享软件 * 软件语言: 多国语言[中文繁体/简体/英文] * 开 发 商: 创思维软件工作室 * 更新时间: 2010-09-22...

    MIP2000通用信息管理平台XP标准版

    方便的Word和Excel接口:提供与Word和Excel的访问接口,通过Word模板和Excel模板定义,来生成一些指定的报表格式文件。实现如公文、发票、信封等格式文件的套打功能。 强大的数据导出:支持数据到Word、Excel、文本...

    勤哲excel服务器2010教程

    1.1 Excel服务器是信息系统工具 3 1.2 用Excel服务器构建信息系统 3 1.3 基于Excel服务器的信息系统架构 8 1.4 如何学习使用Excel服务器 10 第2章、 安装与卸载 12 2.1 安装概述 12 2.2 标准版安装 13 2.3 Excel...

    人力资源管理软件(完全免费)

    考勤报表,生成各类统计报表,可定制方案 考勤班次,支持多班次定义 考勤班组 考勤机定义,支持多种多台考勤机,可动态扩展 出差记录管理(人力资源软件) 请假记录管理(人力资源软件) 调休记录管理(人力资源...

    万能后台管理模板javaweb

    28. SQL编辑器:强大的SQL编辑器,支持编辑语句复杂查询语句,生成动态报表,可导出excel --------------------------------------------------------------------------------------------------------------------...

    1345个易语言模块

    edb 数据库转Excel模块 1.0.ec edb数据库转Excel模块 1.3.ec edb转xls.ec eOgre.ec errcode.ec EtfAPI.ec EtfAPI30.ec ETimeFly API模块.ec Exact.ec excels.ec excel保存.ec Excel功能模块.ec EXE→SWF 转换模块.ec...

    管得多2003

    本系统便捷的查询,汇总,数据分析,数据备份,word,excel工具功能,会给你带来更多的方便。并内置职工档案管理系统、学生档案管理系统、学生成绩管理系统、客户关系管理系统、源程序片断管理系统、文件管理 等多套...

    税审V6升级

    (2)Excel报表和数据源中链接数据速度提高6倍 6.改进了凭证抽查 (1)修正了按摘要排除不准确的问题 (2)修正了已抽凭证有时没有保存的问题 (3)提高了生成抽凭表的速度 (4)对行数多的凭证汇总功能进行了改进(汇总凭证...

    asp.net知识库

    常用编码工具类,支持base64,md5,des,crc32 也谈谈技术面试 在C#里把ArrayList转换为Array 或 把Array转换为ArrayList C# 2.0 在.NET 2.0中,让你的组件也可以绑定 .NET20 一种简单的窗口控件UI状态控制方法 翻译MSDN...

    Access 2000数据库系统设计(PDF)---001

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和 工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白 窗体 30213.3.3 向窗体页眉上添加一个...

    Access 2000数据库系统设计(PDF)---002

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和 工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白 窗体 30213.3.3 向窗体页眉上添加一个...

    Access 2000数据库系统设计(PDF)---018

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白窗体 30213.3.3 向窗体页眉上添加一个标签 ...

    Access 2000数据库系统设计(PDF)---003

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和 工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白 窗体 30213.3.3 向窗体页眉上添加一个...

    Access 2000数据库系统设计(PDF)---011

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白窗体 30213.3.3 向窗体页眉上添加一个标签 ...

    Access 2000数据库系统设计(PDF)---020

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白窗体 30213.3.3 向窗体页眉上添加一个标签 ...

    Access 2000数据库系统设计(PDF)---009

    29613.2.2 工具箱 29713.2.3 Access的控件向导、生成器和 工具栏 29813.3 使用工具箱添加控件 30013.3.1 创建作为主窗体基础的查询 30113.3.2 创建一个具有页眉和页脚的空白 窗体 30213.3.3 向窗体页眉上添加一个...

Global site tag (gtag.js) - Google Analytics