做ERP的经常要面对数据来源的问题。最头痛的是跨公司,部门,系统的数据交流。
通过实践,我们发现EXCEL是比较合适的格式。相对于XML,JSON,可读性和操作自由度都比较理想。
通常我们用JAVA+POI处理。
首先说一下POI的限制。
1,不能处理太大的数据,文档大小最好在1M以下,行数小于1w;
因为太过“自由”,为了保证可靠性,通常需要对数据预处理,导致效率低下,超过1M的数据可能造成假死。
2,空格,大小写,非法字符,数据格式等等都会造成bug,各种读数据预处理是必须的。
以下列出我常用的几个方法
/**
* @description 处理可能是数字,输出带小数点的情况,全部转成字符(去除所有空格)
*/
public static String getNoSpaceString(Cell cell) {
if (null == cell)
return null;
switch (cell.getCellTypeEnum()) {// 判断格式
case NUMERIC:// 数字,double转数字
return (new BigDecimal(cell.getNumericCellValue())).toString();
case STRING:
return removeSpacing(cell.getStringCellValue());
case FORMULA:// 带公式计算
try {
// 是字符
return removeSpacing(cell.getRichStringCellValue().toString());
} catch (Exception e) {
// 是数字
String s2 = String.valueOf(cell.getNumericCellValue());
return s2;
}
default:
return cell.toString();
}
}
// 去除所有空格
private static String removeSpacing(String input) {
final Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher(input);
return m.replaceAll("");
}
public static float getFloat(Cell cell) {
if (null == cell)
return 0;
switch (cell.getCellTypeEnum()) {// 判断格式
case NUMERIC:// 数字,double转数字
return (float) (cell.getNumericCellValue());
case STRING:
float f;
try {
// 是字符
String s = cell.getStringCellValue();
s = s.replaceAll("[^\\d\\.]", "");
f = Float.parseFloat(s);
} catch (NumberFormatException e) {// 是字符,但是不能转成数字
return 0;
}
return f;
case FORMULA:// 带公式计算
try {
float f2 = Float.parseFloat(cell.getStringCellValue());
return f2;
} catch (NumberFormatException e) {// 是字符,但是不能转成数字
return 0;
} catch (Exception e) {
// 是数字
return (float) (cell.getNumericCellValue());
}
default:
return 0;
}
}
//日期
public static String getDateString(Cell cell) {
if (cell == null)
return null;
switch (cell.getCellTypeEnum()) {// 判断格式
case STRING:
return cell.getStringCellValue();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:// 带公式计算
try {
// 是字符
return cell.getRichStringCellValue().toString();
} catch (Exception e) {
// 是数字
String s2 = String.valueOf(cell.getNumericCellValue());
return s2;
}
case NUMERIC:// 数字 ,尝试转日期
short format = cell.getCellStyle().getDataFormat();
// System.out.println("format:" + format + ";;;;;value:" +
// cell.getNumericCellValue());
SimpleDateFormat sdf = null;
if (format == 14 || format == 31 || format == 57 || format == 58 || (176 <= format && format <= 178)|| (182 <= format && format <= 196) || (210 <= format && format <= 213) || (208 == format)) { // 日期
sdf = new SimpleDateFormat("yyyy-MM-dd");
} else if (format == 20 || format == 32 || format == 183 || (200 <= format && format <= 209)) { // 时间
sdf = new SimpleDateFormat("HH:mm");
} else { // 不是日期格式
return String.valueOf(cell.getNumericCellValue());
}
double value = cell.getNumericCellValue();
Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);
if (date == null) {
return null;
}
String result = "";
try {
result = sdf.format(date);
} catch (Exception e) {
e.printStackTrace();
return "";
}
return result;
default:
return cell.toString();
}
}
3,文件会被做各种未知修改,程序“皮实耐操”优于效率,所谓的鲁棒性要好。
通常用标题栏来确定数据位置,而不是去固定位置找数据,因为经常会有未知栏被插入文件。
4,不要在一个文件里面集成太多内容,宁可为不同用户生成不同文件,不要生成一个大杂烩给所有用户。
因为,后期不!好!改!。找bug,加新功能会要你命的。