安卓读写Excel文件(基于xxl-excel,非jxl.jar,支持xls,xlsx)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010724819/article/details/84645600

  最近多了一个安卓端读写Excel的需求,移动端的处理能力有限,而且谷歌并没有对应的支持,所以在网上搜索了很多框架,最终将视线定格在了xxl-excel框架,在Idea中run了一下,非常完美。

感谢大神的框架:xxl-excel

安卓代码详见:点击下载

Java代码:点击下载

下面展示一下Java读写Excel的情况:

写Excel:

读取Excel:

主要使用的是:poi 和poi-ooxml

所以突发奇想,能不能将其应用到安卓中进行文件读写,可惜并没有相关支持。

转念一想,原作者使用的是maven托管我这边直接在android studio中进行引入应该可以,所以便开始了又一次的踩坑之旅:

首先创建项目,接着导入依赖:

总共三个依赖:

implementation 'com.xuxueli:xxl-excel:1.1.1'
implementation 'org.apache.poi:poi:3.17'
implementation 'org.apache.poi:poi-ooxml:3.17'

导入之后便可以进行代码测试了,我这里模拟器版本是安卓4.4,所以没有添加动态权限申请,设备版本比较高的同学请自行添加哈。

页面很简单:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnImport"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="读取"/>

        <Button
            android:id="@+id/btnExport"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="导出"/>

    </LinearLayout>

    <TextView
        android:id="@+id/tvShow"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

下面就是逻辑测试了,这里只做简单的调用:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final String path = Environment.getExternalStorageDirectory().getPath();
        final List<ShopDTO> shopDTOS = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ShopDTO shopDTO = new ShopDTO(i, "test" + i);
            shopDTOS.add(shopDTO);
        }


        //导出
        findViewById(R.id.btnExport).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ExcelExportUtil.exportToFile(path + "/test.xlsx", shopDTOS);
            }
        });
        //导入
        findViewById(R.id.btnImport).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                List<Object> shopDatas = ExcelImportUtil.importExcel(path + "/test.xlsx", ShopDTO.class);
                if (shopDatas == null) {
                    Toast.makeText(MainActivity.this, "暂无数据,请先导出!", Toast.LENGTH_SHORT).show();
                    return;
                }
                List<ShopDTO> shopDTOs = (List<ShopDTO>) (List) shopDatas;
                StringBuffer stringBuffer = new StringBuffer();
                for (ShopDTO shopDTO : shopDTOs) {
                    stringBuffer.append(shopDTO.toString() + "\n");
                }
                ((TextView) findViewById(R.id.tvShow)).setText(stringBuffer.toString());
            }
        });
    }
}

但是问题来了,报错:

65536报错,这个报错相比大家只要接触过大型项目都遇到过吧!解决方式:

转自其他博主博客:

第一步:在项目的app目录下的grade文件里面的defaultConfig闭包下添加:   multiDexEnabled true

第二步:在dependencies下添加依赖   compile 'com.android.support:multidex:1.0.0'

第三步:在你自定义继承于Application的类里(这步都不用解释吧,如果我没猜错,你的命名跟我一样MyApplication)重写protected void attachBaseContext(Context base)方法,调用 MultiDex.install(this)初始化

日常报错:

简单百度了一下,应该是因为awt支持的原因,安卓没有Java对应的awt包。

所以我这边拉取博主的Demo,注释掉了所有和awt相关的样式:

package com.marsjiang.myapplication.utils;

import com.xuxueli.poi.excel.annotation.ExcelField;
import com.xuxueli.poi.excel.annotation.ExcelSheet;
import com.xuxueli.poi.excel.util.FieldReflectionUtil;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * Excel导出工具
 *
 * @author xuxueli 2017-09-08 22:27:20
 */
public class ExcelExportUtil {
    private static Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);


    /**
     * 导出Excel对象
     *
     * @param sheetDataListArr  Excel数据
     * @return
     */
    public static Workbook exportWorkbook(List<?>... sheetDataListArr){

        // data array valid
        if (sheetDataListArr==null || sheetDataListArr.length==0) {
            throw new RuntimeException(">>>>>>>>>>> xxl-excel error, data array can not be empty.");
        }

        // book (HSSFWorkbook=2003/xls、XSSFWorkbook=2007/xlsx)
        Workbook workbook = new HSSFWorkbook();

        // sheet
        for (List<?> dataList: sheetDataListArr) {
            makeSheet(workbook, dataList);
        }

        return workbook;
    }

    private static void makeSheet(Workbook workbook, List<?> sheetDataList){
        // data
        if (sheetDataList==null || sheetDataList.size()==0) {
            throw new RuntimeException(">>>>>>>>>>> xxl-excel error, data can not be empty.");
        }

        // sheet
        Class<?> sheetClass = sheetDataList.get(0).getClass();
        ExcelSheet excelSheet = sheetClass.getAnnotation(ExcelSheet.class);

        String sheetName = sheetDataList.get(0).getClass().getSimpleName();
        int headColorIndex = -1;
        if (excelSheet != null) {
            if (excelSheet.name()!=null && excelSheet.name().trim().length()>0) {
                sheetName = excelSheet.name().trim();
            }
//            headColorIndex = excelSheet.headColor().getIndex();
        }

        Sheet existSheet = workbook.getSheet(sheetName);
        if (existSheet != null) {
            for (int i = 2; i <= 1000; i++) {
                String newSheetName = sheetName.concat(String.valueOf(i));  // avoid sheetName repetition
                existSheet = workbook.getSheet(newSheetName);
                if (existSheet == null) {
                    sheetName = newSheetName;
                    break;
                } else {
                    continue;
                }
            }
        }

        Sheet sheet = workbook.createSheet(sheetName);

        // sheet field
        List<Field> fields = new ArrayList<Field>();
        if (sheetClass.getDeclaredFields()!=null && sheetClass.getDeclaredFields().length>0) {
            for (Field field: sheetClass.getDeclaredFields()) {
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                fields.add(field);
            }
        }

        if (fields==null || fields.size()==0) {
            throw new RuntimeException(">>>>>>>>>>> xxl-excel error, data field can not be empty.");
        }

        // sheet header row
        CellStyle[] fieldDataStyleArr = new CellStyle[fields.size()];
        int[] fieldWidthArr = new int[fields.size()];
        Row headRow = sheet.createRow(0);
        for (int i = 0; i < fields.size(); i++) {

            // field
            Field field = fields.get(i);
            ExcelField excelField = field.getAnnotation(ExcelField.class);

            String fieldName = field.getName();
            int fieldWidth = 0;
            HorizontalAlignment align = null;
            if (excelField != null) {
                if (excelField.name()!=null && excelField.name().trim().length()>0) {
                    fieldName = excelField.name().trim();
                }
                fieldWidth = excelField.width();
                align = excelField.align();
            }

            // field width
            fieldWidthArr[i] = fieldWidth;

            // head-style、field-data-style
//            CellStyle fieldDataStyle = workbook.createCellStyle();
//            if (align != null) {
//                fieldDataStyle.setAlignment(align);
//            }
//            fieldDataStyleArr[i] = fieldDataStyle;
//
//            CellStyle headStyle = workbook.createCellStyle();
//            headStyle.cloneStyleFrom(fieldDataStyle);
//            if (headColorIndex > -1) {
//                headStyle.setFillForegroundColor((short) headColorIndex);
//                headStyle.setFillBackgroundColor((short) headColorIndex);
//                headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//            }

            // head-field data
            Cell cellX = headRow.createCell(i, CellType.STRING);
//            cellX.setCellStyle(headStyle);
            cellX.setCellValue(String.valueOf(fieldName));
        }

        // sheet data rows
        for (int dataIndex = 0; dataIndex < sheetDataList.size(); dataIndex++) {
            int rowIndex = dataIndex+1;
            Object rowData = sheetDataList.get(dataIndex);

            Row rowX = sheet.createRow(rowIndex);

            for (int i = 0; i < fields.size(); i++) {
                Field field = fields.get(i);
                try {
                    field.setAccessible(true);
                    Object fieldValue = field.get(rowData);

                    String fieldValueString = FieldReflectionUtil.formatValue(field, fieldValue);

                    Cell cellX = rowX.createCell(i, CellType.STRING);
                    cellX.setCellValue(fieldValueString);
                    cellX.setCellStyle(fieldDataStyleArr[i]);
                } catch (IllegalAccessException e) {
                    logger.error(e.getMessage(), e);
                    throw new RuntimeException(e);
                }
            }
        }

        // sheet finally
        for (int i = 0; i < fields.size(); i++) {
            int fieldWidth = fieldWidthArr[i];
            if (fieldWidth > 0) {
                sheet.setColumnWidth(i, fieldWidth);
            } else {
//                sheet.autoSizeColumn((short)i);
            }
        }
    }

    /**
     * 导出Excel文件到磁盘
     *
     * @param filePath
     * @param sheetDataListArr  数据,可变参数,如多个参数则代表导出多张Sheet
     */
    public static void exportToFile(String filePath, List<?>... sheetDataListArr){
        // workbook
        Workbook workbook = exportWorkbook(sheetDataListArr);

        FileOutputStream fileOutputStream = null;
        try {
            // workbook 2 FileOutputStream
            fileOutputStream = new FileOutputStream(filePath);
            workbook.write(fileOutputStream);

            // flush
            fileOutputStream.flush();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException(e);
        } finally {
            try {
                if (fileOutputStream!=null) {
                    fileOutputStream.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 导出Excel字节数据
     *
     * @param sheetDataListArr
     * @return
     */
    public static byte[] exportToBytes(List<?>... sheetDataListArr){
        // workbook
        Workbook workbook = exportWorkbook(sheetDataListArr);

        ByteArrayOutputStream byteArrayOutputStream = null;
        byte[] result = null;
        try {
            // workbook 2 ByteArrayOutputStream
            byteArrayOutputStream = new ByteArrayOutputStream();
            workbook.write(byteArrayOutputStream);

            // flush
            byteArrayOutputStream.flush();

            result = byteArrayOutputStream.toByteArray();
            return result;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException(e);
        } finally {
            try {
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new RuntimeException(e);
            }
        }
    }

}

  接着引用我们重写的类:

  

import com.marsjiang.myapplication.utils.ExcelExportUtil;
import com.marsjiang.myapplication.utils.ExcelImportUtil;

然后运行一下:

成功生成了xlsx文件,再来读取一下:

猜你喜欢

转载自blog.csdn.net/u010724819/article/details/84645600