Java注解应用于Excel导出

自定义表格注解

定义表格注解:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface ExcelField {

    //排序
    int sort();

    //表头
    String header();

}

实体类:

public class User {
    @ExcelField(header="用户ID",sort=1)
    private int id;
    @ExcelField(header="用户姓名",sort=2)
    private String name;
    @ExcelField(header="用户性别",sort=4)
    private String sex;
    @ExcelField(header="用户年龄",sort=3)
    private int age;

    public User() {
        super();
    }
    public User(int id, String name, String sex, int age) {
        super();
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

如何通过上述的条件实现将数据导出到Excel表格?在此就需要先介绍导出Excel表格的相关java工具。

开发中经常会涉及到excel的处理,如导出Excel,导入Excel到数据库中,操作Excel目前有两个框架,一个是apache 的poi, 另一个是 Java Excel。在此只介绍apache的poi。

Apache POI 与 Java Excel

Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件。这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Office文件的开源库。它包含类和方法对用户输入数据或文件到MS Office文档进行解码。

Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。jxl 由于其小巧 易用的特点, 逐渐已经取代了 POI-excel的地位, 成为了越来越多的java开发人员生成excel文件的首选。

这里提供Java Excel的jxl.jar和Apache poi的下载:
http://download.csdn.net/download/yutao_struggle/10186699

poi引入的jar包:
poi-3.17.jar
poi-ooxml-3.17.jar
poi-ooxml-schemas-3.17.jar
commons-collectons4-4.1.jar

Apache POI 的常用类

  • HSSF - 提供读写Microsoft Excel XLS格式档案的功能,它与微软Office97-2003版本兼容。
  • XSSF - 提供读写Microsoft Excel OOXML XLSX XLS格式档案的功能,它与MS-Office版本2007或更高版本兼容。
  • SXSSF - 与XSSF相同,提供大数据的读写。
  • HWPF - 提供读写Microsoft Word DOC97格式档案的功能。
  • XWPF - 提供读写Microsoft Word DOC2003格式档案的功能。
  • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
  • HDGF - 提供读Microsoft Visio格式档案的功能。
  • HPBF - 提供读Microsoft Publisher格式档案的功能。
  • HSMF - 提供读Microsoft Outlook格式档案的功能。

注意:旧版本的POI支持二进制文件格式,如DOC,XLS,PPT等,从版本3.5起,POI支持微软Office的OOXML文件格式,如DOCX,XLSX,PPTX等。

SXSSF

Excel中的工作簿、工作表、行、单元格中的关系:

  • 一个Excel文件对应于一个workbook(如SXSSFWorkbook),
  • 一个workbook可以有多个sheet(SXSSFSheet)组成,
  • 一个sheet是由多个row(SXSSFRow)组成,
  • 一个row是由多个cell(SXSSFFCell)组成

API

org.apache.poi.ss.usermodel.Workbook是创建和维护Excel工作簿的接口,他有三个实现:

  • HSSFWorkbook : 这个类有读取和.xls 格式和写入Microsoft Excel文件的方法。它与微软Office97-2003版本兼容。
  • XSSFWorkbook : 这个类有读写Microsoft Excel和OpenOffice的XML文件的格式.xls或.xlsx的方法。它与MS-Office版本2007或更高版本兼容。
  • SXSSFWorkbook:提供大数据的读写。

与工作簿相似,对应的Sheet、Row、Cell等都有多个实现。

SXSSFWorkbook:工作簿,代表一个Excel 的整个文档

  • SXSSFWorkbook() 创建一个工作簿
  • SXSSFSheet getSheet(String sheetName) 通过名称获取Sheet
  • SXSSFSheet getSheetAt(int index) 通过索引获取Sheet,索引从0开始
  • int getNumberOfSheets() 获取sheet的个数
  • setActiveSheet(int index) 设置默认选中的工作表
  • write(OutputStream stream) 输出工作簿的输出流
  • CellStyle createCellStyle() 获取样式
  • Font createFont() 获取字体
  • SXSSFSheet createSheet() 获取工作表

SXSSFSheet:工作表
SXSSFRow:行
SXSSFCell:单元格
SXSSFCellStyle:单元格样式

SXSSFFont:字体
SXSSFName:名称
SXSSFDataFormat :日期格式化
SXSSFHeader : Sheet的头部
SXSSFFooter :Sheet的尾部
SXSSFDateUtil :日期工具
SXSSFPrintSetup :打印设置
SXSSFErrorConstants:错误信息表

导出Excel实例

public class ExcelExport {
    private SXSSFWorkbook wb;               //工作簿
    private Sheet sheet;                    //工作表
    private Map<String,CellStyle> styles;   //样式
    private int rownum;                     //行数
    private List<Object[]> annotationList;  //注解集合
    public ExcelExport(String title,Class<?> clazz){
        this.wb = new SXSSFWorkbook();
        this.sheet = wb.createSheet("user");
        this.styles = createStyles(this.wb);
        initialize(title,clazz);
    }
    /**
     * @param title 标题
     * @param clazz 对应实体类的class
     */
    private void initialize(String title, Class<?> clazz) {
        //反射获取所有字段及对应的注解
        Field[] fields = clazz.getDeclaredFields();
        this.annotationList = new ArrayList<>();
        for(Field f : fields){
            ExcelField ef = f.getAnnotation(ExcelField.class);
            if(ef != null){
                annotationList.add(new Object[]{ef,f});
            }
        }

        //导入Excel列排序
        Collections.sort(annotationList,new Comparator<Object[]>() {
            @Override
            public int compare(Object[] o1, Object[] o2) {
                return new Integer(((ExcelField)o1[0]).sort()).compareTo(
                        new Integer(((ExcelField)o2[0]).sort()));
            }
        });

        //表头集合
        List<String> headList = new ArrayList<>();
        for(Object[] objs : annotationList){
            headList.add(((ExcelField)objs[0]).header());
        }

        //标题
        if(title!=null && !"".equals(title)){
            Row titleRow = this.sheet.createRow(rownum++);
            Cell titleCell = titleRow.createCell(0);
            //合并单元格,四个参数分别表示:first row,last row ,first column,last column
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headList.size()-1));
            //样式
            titleCell.setCellStyle(this.styles.get("title"));
            titleCell.setCellValue(title);
        }
        //创建表头
        if(headList!=null) {
            //创建一行
            Row contentRow = this.sheet.createRow(rownum++);
            for(int i=0;i<headList.size();i++){
                //添加单元格
                Cell contentCell = contentRow.createCell(i);
                //设置单元格内容
                contentCell.setCellValue(headList.get(i));
                //设置样式
                contentCell.setCellStyle(this.styles.get("header"));
            }
        }
    }
    /**
     * 设置需要导出的数据
     * @param dataList 数据集合
     */
    public void setDataList(List dataList){
        if(dataList != null && dataList.size() > 0){
            Class clazz = dataList.get(0).getClass();           
            for (int i=0;i<dataList.size();i++) {
                int index = 0;
                //创建一行
                Row dataRow = this.sheet.createRow(rownum++);
                for(Object[] objs : annotationList) {
                    String fieldName = ((Field)objs[1]).getName();
                    String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
                    try {
                        Method method = clazz.getMethod(methodName, null);
                        String result = method.invoke(dataList.get(i),null).toString();
                        //创建单元格
                        Cell dataCell = dataRow.createCell(index++);
                        //设置样式
                        dataCell.setCellStyle(this.styles.get("data"));
                        //设置文本
                        dataCell.setCellValue(result);
                    } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    /*
     * 将工作簿写入输出流
     */
    public void write(OutputStream os){
        try {
            this.wb.write(os);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param wb 工作簿
     * @return 样式map集合
     */
    private Map<String, CellStyle> createStyles(Workbook wb) {
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();

        //标题样式
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = wb.createFont();
        titleFont.setFontName("Arial");
        titleFont.setFontHeightInPoints((short) 16);
        titleFont.setBold(true);
        style.setFont(titleFont);
        styles.put("title", style);

        //数据样式
        style = wb.createCellStyle();
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        Font dataFont = wb.createFont();
        dataFont.setFontName("Arial");
        dataFont.setFontHeightInPoints((short) 10);
        style.setFont(dataFont);
        styles.put("data", style);

        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.LEFT);
        styles.put("data1", style);

        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.CENTER);
        styles.put("data2", style);

        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.RIGHT);
        styles.put("data3", style);

        //表头样式
        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font headerFont = wb.createFont();
        headerFont.setFontName("Arial");
        headerFont.setFontHeightInPoints((short) 10);
        headerFont.setBold(true);
        headerFont.setColor(IndexedColors.WHITE.getIndex());
        style.setFont(headerFont);
        styles.put("header", style);

        return styles;
    }

    public static void main(String[] args) {
        //模拟数据,实际应用返回数据库数据封装即可
        List list = new ArrayList();
        User user = new User(1,"zhang","男",23);
        User user1 = new User(2,"wang","女",22);
        list.add(user);
        list.add(user1);

        ExcelExport ex = new ExcelExport("用户表",User.class);
        ex.setDataList(list);
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(new File("D:/user.xlsx"));
            ex.write(fos);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

由此可以通过注解注释相应的字段,选择性的导出部分字段,且可以通过sort来调整导出的列的顺序。有上述程序运行结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/yutao_struggle/article/details/78963674