简易Excel数据处理框架

虽然说Excel操作在安卓上面不多见,但是也是有用途的,比如说将一些数据导出到excel文件,可以在外部查看数据。经过大量的框架对比(实际上仅仅看了ApachePOI),我选择了ApachePOI这个office处理的框架。说干就干,我拿起了我500块钱的机械键盘,花了无数个晚上,完成了这个框架。

1.引入ApachePOI框架

dependencies {
    api "org.apache.poi:poi:3.14-beta1"
}

2.编写注解类
A.Excel导入注解类(ExcelInputAttribute)

@Retention(RetentionPolicy.RUNTIME)
@Target({java.lang.annotation.ElementType.FIELD})
public @interface ExcelInputAttribute {
    /**
     * 列名对应的A,B,C,D...,不指定按照默认顺序排序
     *
     * @return
     */
    int column() default -1;
}

B.Excel导出注解类(ExcelOutputAttribute)

@Retention(RetentionPolicy.RUNTIME)
@Target({java.lang.annotation.ElementType.FIELD})
public @interface ExcelOutputAttribute {

    /**
     * Excel中的列名
     *
     * @return
     */
    String name();

    /**
     * 列名对应的A,B,C,D...,不指定按照默认顺序排序
     *
     * @return
     */
    double column() default -1;

    String[] enumdata() default {};

    /**
     * 表头字体颜色
     *
     * @return
     */
    short titletextcolor() default HSSFColor.BLACK.index;

    /**
     * 表头背景颜色
     *
     * @return
     */
    IndexedColors titlebgcolor() default IndexedColors.WHITE;

    short titleboldweight() default HSSFFont.BOLDWEIGHT_NORMAL;

    /**
     * 表头文字是否粗体
     *
     * @return
     */
    boolean isTitleBold() default false;

    /**
     * 表头文字是否斜体
     *
     * @return
     */
    boolean isTitleItalic() default false;

    /**
     * 内容文字水平对齐方向
     *
     * @return
     */
    short titleHorAlignment() default HSSFCellStyle.ALIGN_LEFT;

    /**
     * 内容文字垂直对齐方向
     *
     * @return
     */
    short titleVerAlignment() default HSSFCellStyle.VERTICAL_CENTER;

    /**
     * 表头字体大小
     *
     * @return
     */
    short titleTextSize() default 10;

    /**
     * 是否使用默认的表头单元格样式
     *
     * @return
     */
    boolean isTitleNormalStyle() default true;

    /**
     * 内容字体颜色
     *
     * @return
     */
    short contenttextcolor() default HSSFColor.BLACK.index;

    /**
     * 内容背景颜色
     *
     * @return
     */
    IndexedColors contentbgcolor() default IndexedColors.WHITE;

    short contentboldweight() default HSSFFont.BOLDWEIGHT_NORMAL;

    /**
     * 内容文字是否粗体
     *
     * @return
     */
    boolean isContentBold() default false;

    /**
     * 内容文字是否斜体
     *
     * @return
     */
    boolean isContentItalic() default false;

    /**
     * 内容文字水平对齐方向
     *
     * @return
     */
    short contentHorAlignment() default HSSFCellStyle.ALIGN_LEFT;

    /**
     * 内容文字垂直对齐方向
     *
     * @return
     */
    short contentVerAlignment() default HSSFCellStyle.VERTICAL_CENTER;

    /**
     * 内容字体大小
     *
     * @return
     */
    short contentTextSize() default 10;

    /**
     * 是否使用默认的内容单元格样式
     *
     * @return
     */
    boolean isContentNormalStyle() default true;

}

3.定义实体类
A.导入基础数据类(BaseInputModel)

public abstract class BaseInputModel {
    /**
     * 编写忽略的条件
     * @param row
     * @return
     */
    public abstract boolean ignore(Row row);

    public abstract BaseInputModel create();
}

B.导入数据字段实体类(InputFieldModel)

public class InputFieldModel {
    public int column;
    public Field field;
    public ExcelInputAttribute attribute;
}

C.导入数据字段实体类(OutputFieldModel)

public class OutputFieldModel {
    public double column;
    public Field field;
    public ExcelOutputAttribute attribute;
}

D.多表导出数据的信息类(MultiExcelBean)

public class MultiExcelBean {
    public int sheetlx;    //sheet的index
    public String sheetName;    //sheet的名称
    public List datas;     //sheet的数据
    public Class clazz;     //类
}

4.定义回调函数
A.excel导入处理回调(ExcelInputCallback)

public interface ExcelInputCallback<T> {
    void onStartInput();

    void onErrorInput(Exception e);

    void onSuccessInput(List<T> singleSheetDatas);
}

B.excel导出处理回调(ExcelOutputCallback)

public interface ExcelOutputCallback {
    void onStartOutput();

    void onSuccessOutput();

    void onErrorOutput(Exception e);
}

C.导入的方法接口

public interface IExcelInputControl<T extends BaseInputModel> {
    /**
     * 将excel单个sheet导入到数据库中
     *
     * @param filePath 文件路径
     * @param ignore   忽略的行数
     * @param callback 回调
     */
    public void inputSingleSheetExcel(String filePath, ArrayList<Integer> ignore, final ExcelInputCallback callback);

    /**
     * 根据sheet名称将excel单个sheet导入到数据库中
     *
     * @param filePath  文件路径
     * @param sheetName sheet名称
     * @param ignore    忽略的行数
     * @param callback  回调
     */
    public void inputSingleSheetExcelBySheetName(String filePath, String sheetName, ArrayList<Integer> ignore, final ExcelInputCallback callback);

    /**
     * 根据sheet位置将excel单个sheet导入到数据库中
     *
     * @param filePath 文件路径
     * @param position sheet位置
     * @param ignore   忽略的行数
     * @param callback 回调
     */
    public void inputSingleSheetExcelBySheetPosition(String filePath, int position, ArrayList<Integer> ignore, final ExcelInputCallback callback);
}

D.导出的方法接口

public interface IExcelOutputControl<T> {
    /**
     * 导出单个sheet的excel文件
     *
     * @param list
     * @param sheetName
     * @param filePath
     * @param fileName
     * @param callback
     */
    void outputExcelToFile(List<T> list, String sheetName, String filePath, String fileName, ExcelOutputCallback callback);

    /**
     * 导出多个sheet的文件
     *
     * @param multiExcelBeanList
     * @param filePath
     * @param fileName
     * @param callback
     */
    void outputMultiSheetExcelToFile(List<MultiExcelBean> multiExcelBeanList, String filePath,
                                     String fileName, ExcelOutputCallback callback);
}

5.字段排序的类
A.导入类的字段排序(ExcelFiledInputSortCollections)

public class ExcelFiledInputSortCollections implements Comparator<InputFieldModel> {
    private int type = 0;
    public static int ASC_TYPE = 0;//升序,新的文件在下面
    public static int DESC_TYPE = 1;//降序,新的文件在上面

    public ExcelFiledInputSortCollections(int type) {
        this.type = type;
    }

    @Override
    public int compare(InputFieldModel o1, InputFieldModel o2) {
        if (type == DESC_TYPE) {
            return descSort(o1, o2);
        } else {
            return ascSort(o1, o2);
        }
    }

    private int ascSort(InputFieldModel o1, InputFieldModel o2) {
        if (o1.equals(o2)) {
            return 0;
        } else if (o1.column > o2.column) {
            return 1;
        } else {
            return -1;
        }
    }

    private int descSort(InputFieldModel o1, InputFieldModel o2) {
        if (o1.equals(o2)) {
            return 0;
        } else if (o1.column < o2.column) {
            return 1;
        } else {
            return -1;
        }
    }
}

B.导出类的字段排序(ExcelFiledOutputSortCollections)

public class ExcelFiledOutputSortCollections implements Comparator<OutputFieldModel> {
    private int type = 0;
    public static int ASC_TYPE = 0;//升序,新的文件在下面
    public static int DESC_TYPE = 1;//降序,新的文件在上面

    public ExcelFiledOutputSortCollections(int type) {
        this.type = type;
    }

    @Override
    public int compare(OutputFieldModel o1, OutputFieldModel o2) {
        if (type == DESC_TYPE) {
            return descSort(o1, o2);
        } else {
            return ascSort(o1, o2);
        }
    }

    private int ascSort(OutputFieldModel o1, OutputFieldModel o2) {
        if (o1.equals(o2)) {
            return 0;
        } else if (o1.column > o2.column) {
            return 1;
        } else {
            return -1;
        }
    }

    private int descSort(OutputFieldModel o1, OutputFieldModel o2) {
        if (o1.equals(o2)) {
            return 0;
        } else if (o1.column < o2.column) {
            return 1;
        } else {
            return -1;
        }
    }
}

6.操作类
A.导入操作类(ExcelInputUtil)

public class ExcelInputUtil<T extends BaseInputModel> implements IExcelInputControl<T> {
    private Class<T> clazz;
    private static final String TAG = "ExcelInputUtil";

    public ExcelInputUtil(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 默认读取第一个sheet
     *
     * @param filePath
     * @param callback
     */
    @Override
    public void inputSingleSheetExcel(String filePath, ArrayList<Integer> ignore, ExcelInputCallback callback) {
        inputSingleSheetExcelBySheetPosition(filePath, 0, ignore, callback);
    }

    /**
     * 知道sheet名字的情况下使用
     *
     * @param filePath
     * @param sheetName
     * @param callback
     */
    @Override
    public void inputSingleSheetExcelBySheetName(String filePath, String sheetName, ArrayList<Integer> ignore, ExcelInputCallback callback) {
        try {
            callback.onStartInput();
            HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filePath));
            HSSFSheet sheet = workbook.getSheet(sheetName);
            if (sheet != null) {
                callback.onSuccessInput(getSingleSheetDatas(sheet, ignore));
            } else {
                callback.onSuccessInput(null);
            }
        } catch (Exception e) {
            System.out.println(TAG + " error--->" + e.getMessage());
            callback.onErrorInput(e);
        }
    }

    /**
     * 知道位置的情况下使用
     *
     * @param filePath
     * @param position sheet位置
     * @param callback
     */
    @Override
    public void inputSingleSheetExcelBySheetPosition(String filePath, int position, ArrayList<Integer> ignore, ExcelInputCallback callback) {
        try {
            callback.onStartInput();
            HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filePath));
            HSSFSheet sheet = workbook.getSheetAt(position);
            if (sheet != null) {
                callback.onSuccessInput(getSingleSheetDatas(sheet, ignore));
            } else {
                callback.onSuccessInput(null);
            }
        } catch (Exception e) {
            System.out.println(TAG + " error--->" + e.getMessage());
            callback.onErrorInput(e);
        }
    }

    /**
     * 获取单个sheet的数据
     *
     * @param sheet
     * @param ignore
     * @return
     * @throws Exception
     */
    private List<T> getSingleSheetDatas(HSSFSheet sheet, ArrayList<Integer> ignore) throws Exception {
        //解开合并单元格
        releaseSheetMergeRegion(sheet);

        List<T> result = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();
        T bean = clazz.newInstance();
        List<InputFieldModel> fieldModels = getFieldsAndSort(fields);
        StringBuffer json = new StringBuffer("[");
        boolean isNeedDeletePoint = false;
        for (Row row : sheet) {
            // 判断是不是忽略该行数据
            if (ignore.contains(row.getRowNum())) {
                continue;
            }
            try {
                // 跳过空行
                if (row.getCell(0) == null || StringUtil.isBlank(row.getCell(0).getStringCellValue())) {
                    continue;
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (row.getCell(0) != null) {
                    row.getCell(0).setCellType(Cell.CELL_TYPE_STRING);
                }
                if (StringUtil.isBlank(row.getCell(0).getStringCellValue())) {
                    continue;
                }
            }
            boolean isIgnore = bean.ignore(row);
            if (isIgnore) {
                continue;
            }
            //拼接为json
            buildSingleJsonText(fieldModels, json, row);
            isNeedDeletePoint = true;
        }
        if (isNeedDeletePoint) {
            json.deleteCharAt(json.length() - 1);
        }
        json.append("]");
        System.out.println(TAG + " " + fields.length + " json = " + json);
        result.addAll(GsonUtils.getInstance().getListEntityByString(json.toString(), clazz));
        return result;
    }

    /**
     * 构建单个数据
     *
     * @param fieldModels
     * @param json
     * @param row
     */
    private void buildSingleJsonText(List<InputFieldModel> fieldModels, StringBuffer json, Row row) {
        json.append("{");
        for (int i = 0; i < fieldModels.size(); i++) {
            Field field = fieldModels.get(i).field;
            int position = fieldModels.get(i).column;
            String name = field.getName();
            Class<?> type = field.getType();
            json.append("\"");
            json.append(name);
            json.append("\"");
            json.append(":");
            Cell cell = row.getCell(position);
            if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                short format = cell.getCellStyle().getDataFormat();
                SimpleDateFormat sdf = null;
                if (format == 14 || format == 31 || format == 57 || format == 58) {
                    //日期
                    sdf = new SimpleDateFormat("yyyy-MM-dd");
                } else if (format == 20 || format == 32) {
                    //时间
                    sdf = new SimpleDateFormat("HH:mm");
                }
                if (sdf != null) {
                    //如果不为空,说明是时间格式
                    double value = cell.getNumericCellValue();
                    Date date = DateUtil.getJavaDate(value);
                    String time = sdf.format(date);
                    json.append("\"");
                    //内容
                    json.append(time);
                    json.append("\"");
                } else {
                    //说明是普通数据格式
                    appendData(json, type, cell);
                }
            } else {
                appendData(json, type, cell);
            }
            if (i < fieldModels.size() - 1) {
                json.append(",");
            }
        }
        json.append("}");
        json.append(",");
    }

    /**
     * 释放单元格合并
     *
     * @param sheet
     */
    private void releaseSheetMergeRegion(HSSFSheet sheet) {
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
//            if (mergedRegion.getFirstRow() == mergedRegion.getLastRow()) {
//                //横向合并
//                System.out.println(TAG + i + " 单元格合并是横向 " + mergedRegion.getFirstColumn() + " " + mergedRegion.getLastColumn());
//                //需要解开单元格并赋值
//            }
            if (mergedRegion.getFirstColumn() == mergedRegion.getLastColumn()) {
                //纵向合并
                int firstColumn = mergedRegion.getFirstColumn();
                int firstRow = mergedRegion.getFirstRow();
                HSSFRow row = sheet.getRow(mergedRegion.getFirstRow());
                HSSFCell cell = row.getCell(firstColumn);
                if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                    double numericCellValue = cell.getNumericCellValue();
                    //需要解开单元格并赋值
                    for (int j = firstRow + 1; j < mergedRegion.getLastRow() + 1; j++) {
                        row = sheet.getRow(j);
                        row.getCell(firstColumn).setCellValue(numericCellValue);
                    }
                } else {
                    String stringCellValue = cell.getStringCellValue();
                    //需要解开单元格并赋值
                    for (int j = firstRow + 1; j < mergedRegion.getLastRow() + 1; j++) {
                        row = sheet.getRow(j);
                        row.getCell(firstColumn).setCellValue(stringCellValue);
                    }
                }
            }
        }
    }

    private void appendData(StringBuffer json, Class<?> type, Cell cell) {
        cell.setCellType(Cell.CELL_TYPE_STRING);
        if (type == String.class) {
            json.append("\"");
            //内容
            json.append(cell.getStringCellValue());
            json.append("\"");
        } else if (type == Long.class) {
            json.append(cell.getStringCellValue());
        } else if (type == Integer.class) {
            json.append(cell.getStringCellValue());
        } else if (type == Double.class) {
            json.append(cell.getStringCellValue());
        } else {
            json.append("\"");
            //内容
            json.append(cell.getStringCellValue());
            json.append("\"");
        }
    }

    /**
     * 获取全部的字段并排序
     *
     * @param allFields
     * @return
     */
    private List<InputFieldModel> getFieldsAndSort(Field[] allFields) {
        List<InputFieldModel> fieldModels = new ArrayList<InputFieldModel>();
        for (Field field : allFields) {
            if (field.isAnnotationPresent(ExcelInputAttribute.class)) {
                InputFieldModel fieldModel = new InputFieldModel();
                fieldModel.field = field;
                fieldModel.attribute = field.getAnnotation(ExcelInputAttribute.class);
                fieldModel.column = fieldModel.attribute.column();
                fieldModels.add(fieldModel);
            }
        }
        Collections.sort(fieldModels, new ExcelFiledInputSortCollections(ASC_TYPE));
        return fieldModels;
    }

B.导出操作类(ExcelOutputUtil)

public class ExcelOutputUtil<T> implements IExcelOutputControl<T> {
    private Class<T> clazz;
    private static final String TAG = "ExcelOutputUtil";

    public ExcelOutputUtil(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 将list数据导出到excel文档
     *
     * @param list      需要添加的数据
     * @param sheetName 工作表的名称
     * @param filePath  文件路径
     * @param fileName  文件名称
     * @param callback  操作回调
     * @return
     */
    @Override
    public void outputExcelToFile(List<T> list, String sheetName, String filePath, String fileName, final ExcelOutputCallback callback) {
        callback.onStartOutput();
        try {
            // 产生工作薄对象
            HSSFWorkbook workbook = new HSSFWorkbook();
            // 得到所有定义字段
            Field[] allFields = clazz.getDeclaredFields();
            // 得到所有field并存放到一个list中,排序,根据column大小排序
            List<OutputFieldModel> outputFieldModels = getFieldsAndSort(allFields);
            createSingleSheet(list, sheetName, workbook, outputFieldModels, 0);
            outputToExcelFile(filePath, fileName, workbook);
            callback.onSuccessOutput();
        } catch (final Exception e) {
            System.out.println(TAG + " error--->" + e.getMessage());
            callback.onErrorOutput(e);
        }
    }

    /**
     * 导出多个sheet
     *
     * @param multiExcelBeanList 多个sheet信息
     * @param filePath           文件路径
     * @param fileName           文件名称
     * @param callback           操作回调
     */
    @Override
    public void outputMultiSheetExcelToFile(List<MultiExcelBean> multiExcelBeanList, String filePath,
                                            String fileName, final ExcelOutputCallback callback) {
        callback.onStartOutput();
        try {
            // 产生工作薄对象
            HSSFWorkbook workbook = new HSSFWorkbook();
            for (int index = 0; index < multiExcelBeanList.size(); index++) {
                // 得到所有定义字段
                Field[] allFields = multiExcelBeanList.get(index).clazz.getDeclaredFields();
                // 得到所有field并存放到一个list中,排序,根据column大小排序
                List<OutputFieldModel> outputFieldModels = getFieldsAndSort(allFields);
                //获取sheet信息
                List<T> list = multiExcelBeanList.get(index).datas;
                String sheetName = multiExcelBeanList.get(index).sheetName;
                // 产生工作表对象
                createSingleSheet(list, sheetName, workbook, outputFieldModels, multiExcelBeanList.get(index).sheetlx);
            }

            outputToExcelFile(filePath, fileName, workbook);
            callback.onSuccessOutput();
        } catch (final Exception e) {
            System.out.println(TAG + " error--->" + e.getMessage());
            callback.onErrorOutput(e);
        }
    }

    /**
     * 将数据导出到文件
     *
     * @param filePath
     * @param fileName
     * @param workbook
     * @throws IOException
     */
    private void outputToExcelFile(String filePath, String fileName, HSSFWorkbook workbook) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        System.out.println(TAG + " 操作--->数据填写完毕");
        OutputStream output = new FileOutputStream(filePath + "/" + fileName);
        output.flush();
        workbook.write(output);
        output.close();
    }

    /**
     * 创建单个sheet
     *
     * @param list
     * @param sheetName
     * @param workbook
     * @param outputFieldModels
     * @param sheetlx
     * @throws IllegalAccessException
     */
    private void createSingleSheet(List<T> list, String sheetName, HSSFWorkbook workbook,
                                   List<OutputFieldModel> outputFieldModels, int sheetlx) throws IllegalAccessException {
        // 产生工作表对象
        HSSFSheet sheet = workbook.createSheet();
        sheet.createFreezePane(0, 1, 0, 1);
        // 设置工作表的名称.
        workbook.setSheetName(sheetlx, sheetName);
        HSSFRow row;
        row = sheet.createRow(0);// 产生一行
        //普通列样式/
        HSSFFont font = workbook.createFont();
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        font.setFontName("Arail narrow"); // 字体
        font.setColor(HSSFFont.COLOR_NORMAL); // 字体颜色
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); // 字体宽度
        cellStyle.setFont(font);

        // 创建表格头
        createTableTitle(workbook, outputFieldModels, sheet, row, cellStyle);

        //将数据写入表格,写入各条记录,每条记录对应excel表中的一行
        inputSheetDatas(list, workbook, outputFieldModels, sheet, cellStyle);
    }

    /**
     * 写入单个sheet数据
     *
     * @param list
     * @param workbook
     * @param outputFieldModels
     * @param sheet
     * @param cellStyle
     * @throws IllegalAccessException
     */
    private void inputSheetDatas(List<T> list, HSSFWorkbook workbook, List<OutputFieldModel> outputFieldModels, HSSFSheet sheet, HSSFCellStyle cellStyle) throws IllegalAccessException {
        HSSFRow row;
        HSSFCell cell;
        for (int i = 0; i < list.size(); i++) {
            row = sheet.createRow(i + 1);
            T vo = (T) list.get(i); // 得到导出对象.
            for (int j = 0; j < outputFieldModels.size(); j++) {
                //填写每个单元格内容
                // 获得field
                Field field = outputFieldModels.get(j).field;
//                    // 设置实体类私有属性可访问
                ExcelOutputAttribute attr = outputFieldModels.get(j).attribute;
                int col = j;
                // 根据指定的顺序获得列号
//                    if (-1 != attr.column()) {
//                        col = attr.column();
//                    }
                cell = row.createCell(col);
                if (attr.isContentNormalStyle()) {
                    cell.setCellStyle(cellStyle);
                } else {
                    cell.setCellStyle(getCellStyle(workbook, attr.contentbgcolor().getIndex(),
                            attr.contenttextcolor(), attr.contentboldweight(),
                            attr.isContentBold(), attr.isContentItalic(),
                            attr.contentHorAlignment(), attr.contentVerAlignment(),
                            attr.contentTextSize()));
                }
                // 如果数据存在就填入,不存在填入空格
                Class<?> classType = (Class<?>) field.getType();
                if (field.get(vo) != null) {
                    String str = String.valueOf(field.get(vo));
                    if (classType.isAssignableFrom(List.class)) {
                        if (str.length() > 1) {
                            cell.setCellValue(str.substring(1, str.length() - 1));
                        } else {
                            cell.setCellValue(str);
                        }
                    } else {
                        String[] enumdata = attr.enumdata();
                        if (enumdata != null && enumdata.length > 0) {
                            for (int k = 0; k < enumdata.length; k += 2) {
                                String enumdatum = enumdata[k];
                                if (str.equals(enumdatum)) {
                                    str = enumdata[k + 1];
                                    break;
                                }
                            }
                        }
                        cell.setCellValue(str);
                    }
                }
            }
        }
    }

    /**
     * 写入表头
     *
     * @param workbook
     * @param outputFieldModels
     * @param sheet
     * @param row
     * @param cellStyle
     */
    private void createTableTitle(HSSFWorkbook workbook, List<OutputFieldModel> outputFieldModels, HSSFSheet sheet, HSSFRow row, HSSFCellStyle cellStyle) {
        HSSFCell cell;
        for (int i = 0; i < outputFieldModels.size(); i++) {
            int col = i;   //按照顺序遍历字段
            // 根据指定的顺序获得列号
            ExcelOutputAttribute excelOutputAttribute = outputFieldModels.get(i).attribute;
            // 创建列
            cell = row.createCell(col);
            if (excelOutputAttribute.isTitleNormalStyle()) {
                cell.setCellStyle(cellStyle);
            } else {
                cell.setCellStyle(getCellStyle(workbook, excelOutputAttribute.titlebgcolor().getIndex(),
                        excelOutputAttribute.titletextcolor(), excelOutputAttribute.titleboldweight(),
                        excelOutputAttribute.isTitleBold(), excelOutputAttribute.isTitleItalic(),
                        excelOutputAttribute.titleHorAlignment(), excelOutputAttribute.titleVerAlignment(),
                        excelOutputAttribute.titleTextSize()));
            }
            sheet.setColumnWidth(col, (int) ((excelOutputAttribute.name().getBytes().length <= 4 ? 6 : excelOutputAttribute.name().getBytes().length) * 1.0 * 256));
            // 设置列中写入内容为String类型
            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
            // 写入列名
            cell.setCellValue(excelOutputAttribute.name());
        }
    }

    /**
     * 获取全部的字段并排序
     *
     * @param allFields
     * @return
     */
    private List<OutputFieldModel> getFieldsAndSort(Field[] allFields) {
        List<OutputFieldModel> outputFieldModels = new ArrayList<OutputFieldModel>();
        for (Field field : allFields) {
            if (field.isAnnotationPresent(ExcelOutputAttribute.class)) {
                OutputFieldModel outputFieldModel = new OutputFieldModel();
                outputFieldModel.field = field;
                outputFieldModel.attribute = field.getAnnotation(ExcelOutputAttribute.class);
                outputFieldModel.column = outputFieldModel.attribute.column();
                outputFieldModels.add(outputFieldModel);
            }
        }
        //排序,根据column大小排序
        Collections.sort(outputFieldModels, new ExcelFiledOutputSortCollections(ASC_TYPE));
        return outputFieldModels;
    }

    /**
     * 获取单元格样式
     *
     * @param workbook
     * @param bgcolor
     * @param textcolor
     * @param boldweight
     * @param isBold
     * @param isItalic
     * @param horAlignment
     * @param verAlignment
     * @param textsize
     * @return
     */
    private HSSFCellStyle getCellStyle(HSSFWorkbook workbook, short bgcolor, short textcolor, short boldweight,
                                       boolean isBold, boolean isItalic, short horAlignment, short verAlignment, short textsize) {
        HSSFFont font = workbook.createFont();
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        font.setFontName("Arail narrow"); // 字体
        font.setColor(textcolor); // 字体颜色
        font.setBoldweight(boldweight); // 字体宽度
        font.setBold(isBold);
        font.setItalic(isItalic);
        font.setFontHeightInPoints(textsize);
        cellStyle.setFont(font);
        //设置背景色
        cellStyle.setFillForegroundColor(bgcolor);
        cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        //设置水平对齐的样式为居中对齐;
        cellStyle.setAlignment(horAlignment);
        //设置垂直对齐的样式为居中对齐;
        cellStyle.setVerticalAlignment(verAlignment);
        return cellStyle;
    }
}

-------------------------------------------------------------------------------------------这里是华丽的分割线-------------------------------------------------------------------------------------------

下面就到了使用的环节了
1.导入excel数据
A.定义数据结构

public class CdExcelInfoModel extends BaseInputModel {
    /**
     * 编号
     */
    @ExcelInputAttribute(column = 0)
    public String no;
    /**
     * 演唱者名称,歌手
     */
    @ExcelInputAttribute(column = 1)
    public String playerName;
    /**
     * cd名称
     */
    @ExcelInputAttribute(column = 2)
    public String cdName;
    /**
     * cd购买价格
     */
    @ExcelInputAttribute(column = 3)
    public double price;
    /**
     * 碟片数量
     */
    @ExcelInputAttribute(column = 4)
    public int discNum;

    @Override
    public boolean ignore(Row row) {
        if ("总计".equals(row.getCell(0).getStringCellValue())) {
            return true;
        }
        return false;
    }

    @Override
    public BaseInputModel create() {
        return this;
    }
}

B.调用方法

        IExcelInputControl<CdExcelInfoModel> inputControl = new ExcelInputUtil<CdExcelInfoModel>(CdExcelInfoModel.class);
        //获取第一个sheet的数据
        inputControl.inputSingleSheetExcel("filePath", new ArrayList<Integer>(), callback);
        //获取指定sheet名字的数据
        inputControl.inputSingleSheetExcelBySheetName("filePath", "sheetname", new ArrayList<Integer>(), callback);
        //获取指定位置的sheet的数据,sheetPosition从0开始
        inputControl.inputSingleSheetExcelBySheetPosition("filePath", sheetPosition, new ArrayList<Integer>(), callback);

2.导出excel数据
A.定义数据结构

public class ExportSsqInfoModel {
    /**
     * 期数
     */
    @ExcelOutputAttribute(name = "期数", column = 1)
    public String lottery_no;
    /**
     * 显示的开奖结果
     */
    @ExcelOutputAttribute(name = "红球1", column = 2)
    public String lottery_red_one_txt;
    @ExcelOutputAttribute(name = "红球2", column = 3)
    public String lottery_red_two_txt;
    @ExcelOutputAttribute(name = "红球3", column = 4)
    public String lottery_red_three_txt;
    @ExcelOutputAttribute(name = "红球4", column = 5)
    public String lottery_red_four_txt;
    @ExcelOutputAttribute(name = "红球5", column = 6)
    public String lottery_red_five_txt;
    @ExcelOutputAttribute(name = "红球6", column = 7)
    public String lottery_red_six_txt;
    @ExcelOutputAttribute(name = "蓝球", column = 8)
    public String lottery_blue_txt;
    @ExcelOutputAttribute(name = "开奖时间", column = 9)
    public String time;
}

B.调用方法

        IExcelOutputControl<ExportSsqInfoModel> util = new ExcelOutputUtil<>(ExportSsqInfoModel.class);
        List<MultiExcelBean> multiExcelBeans = new ArrayList<>();
        MultiExcelBean historyModel = new MultiExcelBean();
        historyModel.datas = historyData;
        historyModel.clazz = ExportSsqInfoModel.class;
        historyModel.sheetName = "双色球开奖结果";
        historyModel.sheetlx = 0;
        multiExcelBeans.add(historyModel);

        MultiExcelBean statisticsModelBlue = new MultiExcelBean();
        statisticsModelBlue.datas = blueStatisticsData;
        statisticsModelBlue.clazz = ExportSsqStatisticsModel.class;
        statisticsModelBlue.sheetName = "蓝球统计";
        statisticsModelBlue.sheetlx = 1;
        multiExcelBeans.add(statisticsModelBlue);

        MultiExcelBean statisticsModelRed = new MultiExcelBean();
        statisticsModelRed.datas = redStatisticsData;
        statisticsModelRed.clazz = ExportSsqStatisticsModel.class;
        statisticsModelRed.sheetName = "红球统计";
        statisticsModelRed.sheetlx = 2;
        multiExcelBeans.add(statisticsModelRed);
        util.outputMultiSheetExcelToFile(multiExcelBeans, path, fileName, new ExcelOutputCallback() {
            @Override
            public void onStartOutput() {

            }

            @Override
            public void onSuccessOutput() {

            }

            @Override
            public void onErrorOutput(Exception e) {

            }
        });

3.其他说明

A.导出注解描述
name  是列名;如例子所示,表头列名是“收费类型”。
column   是列数(0代表第一列,1代表第二列,以此类推);如例子所示,该字段是在excel的第21列。如果字段不填写column,则按照默认的字段名根据字母排序。
enumdata   是映射表(奇数位置的是key;偶数位置的是value,也就是导出数据的显示文字);enumdata的数组可以为空,但是数组长度必须为偶数。
titletextcolor
titlebgcolor
titleboldweight
isTitleBold
isTitleItalic
titleHorAlignment
titleVerAlignment
titleTextSize
isTitleNormalStyle
B.如果字段的类型是自定义的model,则需要重写model的toString方法,用于在excel显示必要的内容。

C.如果需要添加字段,则把column的值写成需要插进的字段之间,,,如20.5表示插在20-21之间的字段。

别问我使用了什么设计模式,老子写代码从来都是一把梭(滑稽.jpg)
当初写这个库目的只是熟悉注解以及反射的使用,还有个人项目里面要用到,这才花时间写了这个代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容