最近有些配置APN的工作,需要将Excel中的信息,配置成Android apns-conf.xml中的样式。
作为一个程序员,我怎么可能一行行的用眼睛看,然后用手去配置了!
于是,我决定利用Apache POI的支持库,用java程序解析Excel表,
然后按指定格式生成输出文件。
这篇博客主要记录一下Java解析Excel的基本方法,结尾附上demo。
首先附上Apache POI库的下载地址Apache POI - Download Release Artifacts,
选择合适的库后,会自动跳转到镜像地址。
我的demo是基于poi-3.16-beta2写的,不过并没有使用什么高深接口,因此代码应该是通用的。
导入依赖库后,主要的工作其实就是明白依赖库中定义的Excel对象了,这里盗一张图:
如图所示:
每一个Excel文件都将被解析成一个WorkBook对象;
Excel的每一页都将被解析成一个Sheet对象;
然后,Excel中的每一行都是一个Row对象,
每一个单元格都是一个Cell对象。
对这些基本概念有了一些基本了解后,就可以开始上实例了。
如上图所示,为Excel中内容的基本格式,即一些APN需要的信息。
为了方便我解析,我稍微修改了一些格式,将标题栏中每一项的首字母大写(与Java解析Excel无关)。
Java入口函数如下:
public class MainEntrance {
public static void main(String[] args) {
//由于Java解析Excel不可避免的与文件格式耦合
//因此,我只能写一个特质化的工具,而不是写个模板
ApnExcelParseTool excelParseTool = new ApnExcelParseTool();
//传入源文件地址
excelParseTool.setFilePath("/home/zhangjian/Desktop/all_apn_together.xlsx");
try {
//解析Excel得到Workbook对象
Workbook workbook = excelParseTool.initWorkBook();
//每一行具体数据,都将变成一个ApnModel
List outData = new ArrayList<>();
if (workbook != null) {
//将workbook对象,解析成ApnModel
excelParseTool.parseWorkbook(workbook, outData);
}
if (outData.size() > 0) {
//将所有的ApnModel写入到输出文件中
new ApnWriteTool().write("/home/zhangjian/Desktop/apns-conf.xml", outData);
}
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
整个Java主函数的逻辑还是很简单的。
现在我们看看核心类ApnExcelParseTool中的内容,首先看看获取Workbook相关的代码:
class ApnExcelParseTool {
private String mFilePath;
//保存源文件内容
void setFilePath(String filePath) {
mFilePath = filePath;
}
private static final String SUFFIX_2003 = ".xls";
private static final String SUFFIX_2007 = ".xlsx";
Workbook initWorkBook() throws IOException {
File file = new File(mFilePath);
InputStream is = new FileInputStream(file);
Workbook workbook = null;
//根据后缀,得到不同的Workbook子类,即HSSFWorkbook或XSSFWorkbook
if (mFilePath.endsWith(SUFFIX_2003)) {
workbook = new HSSFWorkbook(is);
} else if (mFilePath.endsWith(SUFFIX_2007)) {
workbook = new XSSFWorkbook(is);
}
return workbook;
}
....................
得到Workbook后,就可以开始进一步解析了:
.......................
void parseWorkbook(Workbook workbook, List<ApnModel> apnModelList) {
int numOfSheet = workbook.getNumberOfSheets();
//依次解析每一个Sheet
for (int i = 0; i < numOfSheet; ++i) {
Sheet sheet = workbook.getSheetAt(i);
parseSheet(sheet, apnModelList);
}
}
//保存需要调用的ApnModel中的方法
private List<Method> mUsedMethod;
private void parseSheet(Sheet sheet, List<ApnModel> apnModelList) {
Row row;
int count = 0;
//利用迭代器,取出每一个Row
Iterator<Row> iterator = sheet.iterator();
while(iterator.hasNext()) {
row = iterator.next();
//由于第一行是标题,因此这里单独处理
if (count == 0) {
mUsedMethod = new ArrayList<>();
parseRowAndFindMethod(row);
} else {
//其它行都在这里处理
parseRowAndFillData(row, apnModelList);
}
++count;
}
}
private void parseRowAndFindMethod(Row row) {
//利用parseRow处理每一行,得到每个cell中的String
List<String> rst = parseRow(row);
String methodName;
try {
//根据String得到需要调用的ApnModel中的方法
//由于自己在ApnModel中定义的方法均是类似setMcc、setMnc等
//因此才在一开始,将标题栏中每一项大写
for (String str : rst) {
methodName = "set" + str;
//反射拿到method
mUsedMethod.add(
ApnModel.class.getDeclaredMethod(methodName, String.class));
}
} catch (NoSuchMethodException e) {
System.out.println(e.toString());
}
}
//开始解析具体的数据
private void parseRowAndFillData(Row row, List<ApnModel> apnModelList) {
//同样利用parseRow得到具体每一行的数据
List<String> rst = parseRow(row);
ApnModel apnModel = new ApnModel();
//这里主要debug一下,避免由于Excel的格式可能不太对
//使得每一行的数据解析地不太对
if (mUsedMethod.size() != rst.size()) {
System.out.println("WTF, size not right");
} else {
//利用反射,将数据填充到具体的ApnModel
try {
for (int i = 0; i < mUsedMethod.size(); ++i) {
mUsedMethod.get(i).invoke(apnModel, rst.get(i));
}
//保存到输出结果中
apnModelList.add(apnModel);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
//这里是解析每一行的代码
private List<String> parseRow(Row row) {
List<String> rst = new ArrayList<>();
Cell cell;
//利用迭代器得到每一个cell
Iterator<Cell> iterator = row.iterator();
while (iterator.hasNext()) {
cell = iterator.next();
//定义每一个cell的数据类型
cell.setCellType(CellType.STRING);
//取出cell中的value
rst.add(cell.getStringCellValue());
}
return rst;
}
.................
以上就是Java解析Excel范例的核心代码了。
之后的工作就是将ApnModel中保存的数据,按照需要的格式写入到输出文件了。
这部分代码比较粗糙,也与主题无关,就不直接贴到博客上了。
这里唯一要注意的是,要保证Excel的格式正确。
单元格的内容可以是空白的,因此要保证Excel中仅有数据占有了实际的内容。
如上图所示,数据部分可以空白,但非数据的红色部分就不要有内容了。
最后,demo地址如下:
https://github.com/ZhangJianIsAStark/ExcelParseDemo
这里我只上传了源代码,还需要自己配置Apache POI jar包。