Android将Excel表格解析成json文件
来源:互联网 发布:淘宝联盟qq群推广步揍 编辑:程序博客网 时间:2024/05/21 01:48
Android TV开发,设置模块一般是一个菜单树,也即多级联动菜单,我们可以做成配置项文件,这样做的好处是,不需要根据每个客户需求去控制菜单列表里的菜单项显示隐藏,减少项目维护成本。
那么这个配置项怎么去设计比较好呢?因为需求是产品控制的,我们希望配置项文件由产品来编写和维护,对于产品来说,我们让他去编写json配置文件或者xml文件,有点为难人,术业有专攻,他们更喜欢可视化操作,简单、直观,于是我们想到了Excel表格,因为每次测试的buglist或者产品的功能需求矩阵都是以Excel表形式发给我们的。
按道理来说,我们拿到Menu Tree Excel表,程序去解析这个表格,构建菜单实体类就行了,为什么要再解析成json文件呢?因为每次解析Excel表格获取数据,效率肯定很低,目前知道的Java读取Excel的工具有jxl跟poi方式,两个都有数据量大小限制,并且解析大量数据会很耗时,这个会影响UI绘制,所以我们只希望应用首次安装解析一次产品推送在系统中的Excel表格,然后转成json文件,并保存在系统级别目录中, 以后应用每次启动去解析json配置项获取数据就好。
解析Excel,这里采用jxl,是综合了jxl和poi优缺点以及具体的需求来抉择的。jxl稍微轻量级点,但是不支持xlsx格式,所以只能用 Microsoft Office 2007及之前版本,poi功能强大点,但是要引入的库比较多,使用起来也稍复杂,我们解析Excel表操作一般只会走一次,除非产品变更了需求,会再解析一次,大部分时候,我们程序都是做json转菜单实体类操作。
下面就开始我们的实践吧!
menu tree excel表
步骤一:定义菜单实体类
SettingMenuBean
public class SettingMenuBean implements Parcelable { public String menuId; //菜单id public String parentId; //菜单父级id public String menuName; //菜单名 public String menuIcon; //菜单图标 public String type; //菜单显示样式 public List<SettingMenuBean> menus = new ArrayList<>(); //子菜单 @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.menuId); dest.writeString(this.parentId); dest.writeString(this.menuName); dest.writeString(this.menuIcon); dest.writeString(this.type); dest.writeList(this.menus); } public SettingMenuBean() { } protected SettingMenuBean(Parcel in) { this.menuId = in.readString(); this.parentId = in.readString(); this.menuName = in.readString(); this.menuIcon = in.readString(); this.type = in.readString(); this.menus = new ArrayList<>(); in.readList(this.menus, SettingMenuBean.class.getClassLoader()); } public static final Parcelable.Creator<SettingMenuBean> CREATOR = new Parcelable.Creator<SettingMenuBean>() { @Override public SettingMenuBean createFromParcel(Parcel source) { return new SettingMenuBean(source); } @Override public SettingMenuBean[] newArray(int size) { return new SettingMenuBean[size]; } };}
因为菜单包含子菜单,存在递归关系,为了方便解析,我们还需定义一个菜单列表实体类
SettingMenuListBean
public class SettingMenuListBean { private List<SettingMenuBean> menuList; public List<SettingMenuBean> getMenuList() { return menuList; } public void setMenuList(List<SettingMenuBean> menuList) { this.menuList = menuList; }}
步骤二:读取excel表格,并转换成json字符串, 这里分别使用jxl和gson工具
public static String generateJson(Context context) { String filePath = context.getFilesDir().getPath() + "/setting_config.xls"; File readFile = new File(filePath); if (!readFile.exists()) { return null; } List<SettingMenuBean> allMenus = new ArrayList<>(); try { FileInputStream inStream = new FileInputStream(readFile); Workbook wb = Workbook.getWorkbook(inStream); Sheet sheet = wb.getSheet(0); int row = sheet.getRows(); for (int i = 1; i < row; i++) { Cell menuId = sheet.getCell(0, i); Cell parentId = sheet.getCell(1, i); Cell menuName = sheet.getCell(2, i); Cell menuIcon = sheet.getCell(3, i); Cell type = sheet.getCell(4, i); SettingMenuBean menuBean = new SettingMenuBean(); menuBean.menuId = menuId.getContents(); menuBean.parentId = parentId.getContents(); menuBean.menuName = menuName.getContents(); if (!TextUtils.isEmpty(menuIcon.getContents())) { menuBean.menuIcon = menuIcon.getContents(); } if (!TextUtils.isEmpty(type.getContents())) { menuBean.type = type.getContents(); } allMenus.add(menuBean); } wb.close(); } catch (Exception e) { e.printStackTrace(); } List<SettingMenuBean> finalMenus = new ArrayList<>(); for (SettingMenuBean menuBean : allMenus) { if (!TextUtils.isEmpty(menuBean.parentId)) { menuBean.menus = getSubMenuByPid(menuBean.menuId, allMenus); if ("0".equals(menuBean.parentId)) { // 一级菜单 finalMenus.add(menuBean); } } } SettingMenuListBean menus = new SettingMenuListBean(); menus.setMenuList(finalMenus); Gson gson = new Gson(); return gson.toJson(menus); }
/** * 根据parentId获取子菜单 * */ private static List<SettingMenuBean> getSubMenuByPid(@NonNull String pId, List<SettingMenuBean> allMenus) { List<SettingMenuBean> list = new ArrayList<>(); for (SettingMenuBean menuBean : allMenus) { if (pId.equals(menuBean.parentId)) { list.add(menuBean); } } return list; }
附:Excel表里面某一列有跨几行的场景处理办法
try { FileInputStream inStream = new FileInputStream(readFile); Workbook wb = Workbook.getWorkbook(inStream); Sheet sheet = wb.getSheet(0); int row = sheet.getRows(); Range[] rangeCell = sheet.getMergedCells(); for (int i = 0; i < row; i++) { String name = getData(0, i, sheet, rangeCell); String school = getData(1, i, sheet, rangeCell); String major = getData(2, i, sheet, rangeCell); Person person = new Person(); person.setName(name); person.setSchool(school); person.setMajor(major); persons.add(person); } wb.close(); } catch (Exception e) { e.printStackTrace(); }
private static String getData(int column, int row, Sheet sheet, Range[] rangeCell) { String str = sheet.getCell(column, row).getContents(); for (Range r : rangeCell) { if (row > r.getTopLeft().getRow() && row <= r.getBottomRight().getRow() && column >= r.getTopLeft().getColumn() && column <= r.getBottomRight().getColumn()) { str = sheet.getCell(r.getTopLeft().getColumn(), r.getTopLeft().getRow()).getContents(); } } return str; }
步骤三:将生成的json配置文件保存在指定的系统目录中(最好跟表格保存在一个目录中,方便json文件和Excel文件数据同步)
public static void saveJsonFile(String jsonStr, String filePath) { FileOutputStream outStream = null; boolean dirMake = false; boolean fileMake = false; try { File file = new File(filePath); if (!file.exists()) { File dir = new File(file.getParent()); dirMake = dir.mkdirs(); fileMake = file.createNewFile(); } if (dirMake && fileMake) { outStream = new FileOutputStream(file); if (!TextUtils.isEmpty(jsonStr)) { outStream.write(jsonStr.getBytes()); } outStream.flush(); } } catch (IOException e) { Log.d(TAG, "saveJsonFile: IOException"); } finally { try { if (outStream != null) { outStream.close(); } } catch (IOException e) { Log.d(TAG, "saveJsonFile: IOException"); } } }
最终生成的json配置文件(菜单实体类中的menuId和parentId只作为解析Excel表格表示菜单层级关系用,实际json配置项,不需要这两个字段,我们获取子菜单,可以直接”subMenuList = menu.menus”,所以需要手动去掉这两项)
{ "menus": [ { "menuName": "@STR_PICTURE", "menuIcon": "@picture_bg_selecctor", "type": "SUBMENU", "menus": [ { "menuName": "@STR_PICTURE_PRESET", "type": "SELECT" }, { "menuName": "@STR_BACKLIGHT", "type": "SEEKBAR" } ] }, { "menuName": "@STR_SOUND", "menuIcon": "@voice_bg_selector", "type": "SUBMENU", "menus": [ { "menuName": "@STR_SOUND_PRESET", "type": "SUBMENU", "menus": [ { "menuName": "@STR_SOUND_MODE", "type": "POPVIEW" } ] }, { "menuName": "@STR_TV_PLACEMENT", "type": "POPVIEW" } ] } ]}
update(2017/08/22)
1、配置文件中菜单icon和name加“@”标识,表明这是资源名,考虑到多语言翻译问题,配置项不直接使用菜单名。
2、添加资源名映射到xml资源id方法
/** * @param context * @param name @STR_PICTURE * @param type string * @return R.string.STR_PICTURE */ public static int getResourceId(Context context, String name, String type) { if (!TextUtils.isEmpty(name)) { name = name.replaceAll("@", ""); } try { return context.getResources().getIdentifier(name, type, context.getPackageName()); } catch (Exception e) { return 0; } }
3、增加读取配置项文件的方法
public static String readJsonFile(String filePath) { String str; FileInputStream inStream = null; try { File readFile = new File(filePath); if (!readFile.exists()) { return null; } inStream = new FileInputStream(readFile); ByteArrayOutputStream stream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = inStream.read(buffer)) != -1) { stream.write(buffer, 0, length); } str = stream.toString(); stream.close(); return str; } catch (IOException e) { return null; } finally { try { if (inStream != null) { inStream.close(); } } catch (IOException e) { Log.d(TAG, "readJsonFile: IOException"); } } }
3、增加动态申请SD卡读写权限方法
AndroidManifest.xml
<!-- SD卡写权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- SD卡读权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Java代码
private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"}; public static void verifyStoragePermissions(Context ctx) { try { //检测是否有写的权限 int permission = ActivityCompat.checkSelfPermission(ctx, "android.permission.WRITE_EXTERNAL_STORAGE"); if (permission != PackageManager.PERMISSION_GRANTED) { // 没有写的权限,去申请写的权限,会弹出对话框 ActivityCompat.requestPermissions((Activity) ctx, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } } catch (Exception e) { e.printStackTrace(); } }
4、 格式化时间显示
/** * 从时间(毫秒)中提取出时间(时:分:秒) * */ public static String getTimeFromMillisecond(long millisecond) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); Date date = new Date(millisecond); return simpleDateFormat.format(date); }
- Android将Excel表格解析成json文件
- 利用Python将excel表格转换为json文件
- 将xls表格文件转为xml文件以及json格式的文件,支持2010xls解析
- javascript中实现将统计表格保存成excel文件
- 怎么将pdf文件转换成excel表格
- 怎么将pdf文件转换成excel表格
- 将PDF文件中的表格转换成Excel怎么转换
- Json字符串转excel表格文件
- 浏览器将内容表格生成excel文件
- unity C#将excel解析为json
- java-将xlsx(excel)文件转换成json
- 用Python将excel文件导出成json
- java-将xlsx(excel)文件转换成json
- Android解析Excel文件
- javascript将json格式数组下载为excel表格
- 如何将excel格式的中国三级地址文件转换成android需要的json格式的文件(一)
- 如何将excel格式的中国三级地址文件转换成android需要的json格式的文件(二)
- EXCEL表格转换成json数据工具
- Linux下nodejs(一):UEditor 使用
- CSS中清除浮动的方式探究
- SLF4J: Class path contains multiple SLF4J bindings.
- Codeforces
- HTTP协议—— 简单认识TCP/IP协议
- Android将Excel表格解析成json文件
- POJ 2993 Emag eht htiw Em Pleh(模拟)
- Listener等外部类获取Spring Bean
- URL URI 两者存在的区别
- [玩耍]Python实现备份CSDN博客(未完成)
- tensorflow 学习笔记10 网络模型的保存与提取
- 如何设计出MySQL高性能表
- [POJ 1062] 昂贵的聘礼 [最短路+枚举] [dijkstra]
- Python对内存的使用(深拷贝和浅拷贝)