关于安卓jxl的excel操作(一)

背景

app导出excel,读取excel,可能不常见,但是你得会。

环境

win10,11

jdk8+

as4+

引入

本次实战中,使用到了三方库 net.sourceforge.jexcelapi

详细的引入如下(gradle):

implementation group: 'net.sourceforge.jexcelapi', name: 'jxl', version: '2.6.12'

文末将会放出全部代码

开发

这里已经引入了jxl的三方库,该库可以实现excel的读写操作。

这里,主要实现的是,导出数据生成excel表,读取execl表的数据。

首先我们要有一个概念,就是excel表内部构造,是现有一个sheet,再有具体的内容!!!

所以,在生成excel表后,第一步,就是创建一个sheet,然后再在这个sheet里面进行数据操作!

其实细心一点就会发现,格式是通用的,如下图:

第一行,一般情况下,都是属性的描述,然后第二行,就是数据的填充,诸如此类。

那么,是不是可以设计一个通用的数据格式,就行数据的通用读写?

博主这里选择的,是一个List<HashMap<String,String>>这样的数据格式,List是对于某个sheet中的所有数据,而HashMap中的key,就是属性,value就是对应的属性值。在填充内容第一行时,做一下特殊处理,就可以把属性写入了,后续只需要index对齐,即可填充全部数据。

上面的思路,是比较通用的,注意一下数组越界的情况即可!

好了,梳理了内容填充的思路,还有一个sheet创建,其实也是大同小异的,进行循环创建即可!

上核心代码

首先,先有sheet再有内容,第一步,就是创建sheet,代码如下:

可以看到,有个api就是createSheet,这个方法,就是创建一个表的意思。

创建完表了,那么,就要利用这个WritableSheet对象,进行表数据的写入了。

代码如下:

这里的逻辑,就是先插入第一行属性数据,后续再插入内容数据,for循环操作,当然有review空间,这里只是基于功能快速实现写的逻辑,实测可以使用!!!

通过上述的写sheet,写内容,那么,就会把全部的数据写到excel表了?其实还有几个坑,只有做过才会发现!

(1)Workbook的write()调用时机问题

如果同一个Workbook多次调用该方法,实测发现,第一次以后,就不会再写入了,直观现象就是,写入的部分逻辑失效,然后代码调用WorkBook.Close方法,会报错。

(2)写入数据时,格式的设置问题

示例代码如下:

sheet.addCell(new Label(col, positionCounter, headInfo.get(col), wcf));

其中wcf就是单元格的格式,测试发现,如果不设置单元格格式,写入会没有内容

以上,就是导出excel的一些流程和注意的坑,下面再说说,读取excel的一些逻辑

其实如果你实现了导出,同样的,是不是导入数据,也是按照导出数据时候的数据处理,就可以了?没错,这里直接上核心代码:

try {
            is = new FileInputStream(path);
            workbook = Workbook.getWorkbook(is);
            //读取excel有多少个表
            Sheet[] sheets = workbook.getSheets();
            if (sheets == null || sheets.length == 0) {
                return new ArrayList<>();
            }
            //单个单元格
            Cell cell;
            List<ExcelInfoBean> result = new ArrayList<>();
            List<String> headList = new ArrayList<>();
            for (int s = 0; s < sheets.length; s++) {
                Sheet sheetCache = sheets[s];
                String sheetName = sheetCache.getName();
                //获取所有单元格里面的数据
                ExcelInfoBean exportBean = new ExcelInfoBean(sheetName, new ArrayList<>());
                int cols = sheetCache.getColumns();
                int rows = sheetCache.getRows();
                //逐行获取
                List<HashMap<String, String>> contentList = new ArrayList<>();
                for (int r = 0; r < rows; r++) {
                    HashMap<String, String> contentHashMap = new HashMap<>();
                    for (int c = 0; c < cols; c++) {
                        cell = sheetCache.getCell(c, r);
                        String content = cell.getContents();
                        if (r == 0) {
                            //头部数据
                            headList.add(content);
                        } else {
                            //非头部数据
                            contentHashMap.put(headList.get(c), content);
                        }
                    }
                    if (r != 0) {
                        contentList.add(contentHashMap);
                    }
                }
                exportBean.setData(contentList);
                result.add(exportBean);
            }
            return result;
        }

本质上,就是获取这个WorkBook,所有表sheet的数量,然后变量sheets,再从sheet中,读取行,列的数据,再写入到你的内存数据中,就可以了!

下面是所有相关的代码:

ExcelInfoBean.class

public class ExcelInfoBean implements Serializable {

    //sheet名字--与数据对象名字一致
    private String sheetTitle;

    //key属性名,value属性值--excel头,excel值
    private List<HashMap<String, String>> data = new ArrayList<>();

    public ExcelInfoBean(@NonNull String sheetTitle, List<HashMap<String, String>> data) {
        this.sheetTitle = sheetTitle;
        this.data = data;
    }

    public String getSheetTitle() {
        return sheetTitle;
    }

    public void setSheetTitle(String sheetTitle) {
        this.sheetTitle = sheetTitle;
    }

    public List<HashMap<String, String>> getData() {
        return data;
    }

    public void setData(List<HashMap<String, String>> data) {
        this.data = data;
    }
}

ExcelUtils.class

public class ExcelUtils implements Serializable {

    private static final WritableCellFormat wcf;

    static {
        WritableFont wf = new WritableFont(WritableFont.createFont("宋体"), 12,
                WritableFont.NO_BOLD, false);
        wcf = new WritableCellFormat(wf);
        try {
            wcf.setAlignment(jxl.format.Alignment.CENTRE);// 左右居中
            wcf.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);// 上下居中
//            wcf.setBorder(Border.ALL, BorderLineStyle.THIN); // 设置边框
//            wcf.setWrap(true); // 是否换行;
        } catch (WriteException e) {
            e.printStackTrace();
        }
    }

    private static class SingleHolder implements Serializable {
        public final static ExcelUtils mInstance = new ExcelUtils();
    }

    public static ExcelUtils getInstance() {
        return SingleHolder.mInstance;
    }

    /**
     * 生成excel
     *
     * @param beans       一个对象,对应一个表格
     * @param fileAllPath 文件全路径--如/ddd/dd/
     */
    public boolean exportData(String fileAllPath, String fileName, ExcelInfoBean... beans) {
        if (beans == null || beans.length == 0) {
            return true;
        }
        //数据处理
        OutputStream os = null;
        WritableWorkbook wwb = null;
        try {
            File file = new File(fileAllPath);
            if (!file.exists()) {
                file.mkdirs();
            }
            os = new FileOutputStream(file.getAbsoluteFile() + File.separator + fileName);
            wwb = Workbook.createWorkbook(os);
            for (int i = 0; i < beans.length; i++) {
                ExcelInfoBean cacheInfo = beans[i];
                //开始处理数据
                String sheetName = cacheInfo.getSheetTitle();
                //建立表
                WritableSheet sheet = wwb.createSheet(sheetName, i);
                List<HashMap<String, String>> contentList = cacheInfo.getData();
                if (contentList != null && !contentList.isEmpty()) {
                    //写入数据
                    //第一行为属性头
                    List<String> headInfo = new ArrayList<>();
                    HashMap<String, String> headMap = contentList.get(0);
                    for (Map.Entry<String, String> mapCache : headMap.entrySet()) {
                        headInfo.add(mapCache.getKey());
                    }
                    int positionCounter = 0;
                    if (!headInfo.isEmpty()) {
                        for (int col = 0; col < headInfo.size(); col++) {
                            sheet.addCell(new Label(col, positionCounter, headInfo.get(col), wcf));
                        }
                        //写入表头
                        positionCounter += 1;
                    }
                    //写入内容
                    for (int c = 0; c < contentList.size(); c++) {
                        HashMap<String, String> contentMap = contentList.get(c);
                        if (contentMap != null && !contentMap.isEmpty()) {
                            for (int col = 0; col < headInfo.size(); col++) {
                                String headInfoCache = headInfo.get(col);
                                //通过表头,获取数据
                                String contentValue = contentMap.get(headInfoCache);
                                //写入到对应的位置
                                sheet.addCell(new Label(col, positionCounter, contentValue, wcf));
                            }
                            positionCounter += 1;
                        }
                    }
                }
            }
            //至此写入
            wwb.write();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (wwb != null) {
                try {
                    wwb.close();
                } catch (IOException | WriteException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * 读取excel
     */
    public List<ExcelInfoBean> importData(@NonNull String path) {
        File file = new File(path);
        if (!file.exists()) {
            return new ArrayList<>();
        }
        //读取excel
        InputStream is = null;
        Workbook workbook = null;
        try {
            is = new FileInputStream(path);
            workbook = Workbook.getWorkbook(is);
            //读取excel有多少个表
            Sheet[] sheets = workbook.getSheets();
            if (sheets == null || sheets.length == 0) {
                return new ArrayList<>();
            }
            //单个单元格
            Cell cell;
            List<ExcelInfoBean> result = new ArrayList<>();
            List<String> headList = new ArrayList<>();
            for (int s = 0; s < sheets.length; s++) {
                Sheet sheetCache = sheets[s];
                String sheetName = sheetCache.getName();
                //获取所有单元格里面的数据
                ExcelInfoBean exportBean = new ExcelInfoBean(sheetName, new ArrayList<>());
                int cols = sheetCache.getColumns();
                int rows = sheetCache.getRows();
                //逐行获取
                List<HashMap<String, String>> contentList = new ArrayList<>();
                for (int r = 0; r < rows; r++) {
                    HashMap<String, String> contentHashMap = new HashMap<>();
                    for (int c = 0; c < cols; c++) {
                        cell = sheetCache.getCell(c, r);
                        String content = cell.getContents();
                        if (r == 0) {
                            //头部数据
                            headList.add(content);
                        } else {
                            //非头部数据
                            contentHashMap.put(headList.get(c), content);
                        }
                    }
                    if (r != 0) {
                        contentList.add(contentHashMap);
                    }
                }
                exportBean.setData(contentList);
                result.add(exportBean);
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return new ArrayList<>();
    }

}

that's all----------------------------------------------------------------------------------------------

相关推荐
Winston Wood3 分钟前
Perfetto学习大全
android·性能优化·perfetto
星星会笑滴1 小时前
vue+node+Express+xlsx+emements-plus实现导入excel,并且将数据保存到数据库
vue.js·excel·express
Dnelic-3 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen5 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年13 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
开心点幸运点14 小时前
Excel——宏教程(1)
excel
建群新人小猿15 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神16 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛16 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法17 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526