Примечание
Эта статья представляет собой простую инкапсуляцию с использованием org.apache.poi, которая подходит для большинства функций импорта и экспорта Excel. В процессе можно использовать рефлексию.Если есть ученики с крайним обсессивно-компульсивным расстройством в отношении успеваемости, просто посмотрите.
последовательность
Так как poi сам по себе является лишь набором инструментов для офисного ПО типа excel, то при импорте и экспорте какого-то обычного excel необходимо делать упрощенную инкапсуляцию для упрощения связывания кода.
1. Статус-кво
Я испытал инкапсуляцию кода нескольких компаний, и импорт и экспорт обычно существуют в следующих ситуациях.
1.1 Импорт
- Передайте адрес файла, верните объект Sheet, выполните цикл по бизнес-коду, выполните соответствующее преобразование типов, бизнес-обработку (инфраструктура кода в 2000 г.)
- Передайте адрес файла, верните объект List
и напрямую выполните внешнее принудительное преобразование. - Передать адрес файла, вернуть объект List
, внешне преобразовать строковый объект в соответствующий тип
Резюме: Если есть только вышеперечисленный выбор, то я больше склоняюсь ко второму, ведь он очень дружелюбен к внешнему миру
1.2 Экспорт
- Пройдите лист инкапсуляции непосредственно в логическом коде и передайте его в метод генерации файла (фреймворк кода в 2000 году).
- Сначала выполните цикл по объекту List, преобразуйте его в объект List
- Напрямую передайте объект List с fieldName в метод, сгенерированный инкапсулированным excel, преобразуйте объект Model в JSONObject внутренне, а затем используйте метод jsonObj.get() для работы
- Сначала преобразуйте список в JSONArray, передайте fieldName в метод, сгенерированный инкапсулированным excel, внутренне преобразуйте объект модели в JSONObject, а затем используйте метод jsonObj.get() для работы. (При использовании этого подхода, согласно анализу, он должен быть выполнен для выполнения jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor("гггг-ММ-дд ЧЧ:мм:сс")); Эта строка кода может быть для решения проблема формата типа даты)
Резюме: Если есть только вышеперечисленные варианты, то я больше склоняюсь к третьему, который проходит только один раз и внешне не обрабатывается. Однако, согласно четвертому моду, в третьем режиме все еще будет проблема с форматом даты, и мы разберем, как с этим бороться позже.
2. Импорт
2.1 Определение метода
/**
* excel导入
* @param keys 字段名称数组,如 ["id", "name", ... ]
* @param filePath 文件物理地址
* @return
* @author yzChen
* @date 2016年12月18日 下午2:46:51
*/
public static List<Map<String, Object>> imp(String filePath, String[] keys)
throws Exception {}
2.2 Модуль обработки циклов
// 遍历该行所有列
for (short j = 0; j < cols; j++) {
cell = row.getCell(j);
if(null == cell) continue; // 为空时,下一列
// 根据poi返回的类型,做相应的get处理
if(Cell.CELL_TYPE_STRING == cell.getCellType()) {
value = cell.getStringCellValue();
} else if(Cell.CELL_TYPE_NUMERIC == cell.getCellType()) {
value = cell.getNumericCellValue();
// 由于日期类型格式也被认为是数值型,此处判断是否是日期的格式,若时,则读取为日期类型
if(cell.getCellStyle().getDataFormat() > 0) {
value = cell.getDateCellValue();
}
} else if(Cell.CELL_TYPE_BOOLEAN == cell.getCellType()) {
value = cell.getBooleanCellValue();
} else if(Cell.CELL_TYPE_BLANK == cell.getCellType()) {
value = cell.getDateCellValue();
} else {
throw new Exception("At row: %s, col: %s, can not discriminate type!");
}
map.put(keys[j], value);
}
2.3 Использование
String filePath = "E:/order.xls";
String[] keys = new String[]{"id","brand"};
List<Map<String, Object>> impList;
try {
impList = ExcelUtil.imp(filePath, keys);
for (Map<String, Object> map : impList) {
System.out.println(map.get("brand"));
}
} catch (Exception e) {
e.printStackTrace();
}
2.4 Анализ
- Запись должна передавать только имя файла и ключ, который необходимо прочитать извне.
- Для внутренней обработки соответствующая обработка была выполнена для числовых типов, дат и строковых типов, а внешне соответствующий тип может быть принудительно принудительно задан.
3. Экспорт
3.1 Определение метода
/**
* excel导出
* @param fileNamePath 导出的文件名称
* @param sheetName 导出的sheet名称
* @param list 数据集合
* @param titles 第一行表头
* @param fieldNames 字段名称数组
* @return
* @throws Exception
* @author yzChen
* @date 2017年5月6日 下午3:53:47
*/
public static <T> File export(String fileNamePath, String sheetName,
List<T> list, String[] titles, String[] fieldNames) throws Exception {}
3.2 Модуль обработки циклов
// 遍历生成数据行,通过反射获取字段的get方法
for (int i = 0; i < list.size(); i++) {
t = list.get(i);
HSSFRow row = sheet.createRow(i+1);
Class<? extends Object> clazz = t.getClass();
for(int j = 0; j < fieldNames.length; j++){
methodName = "get" + capitalize(fieldNames[j]);
try {
method = clazz.getDeclaredMethod(methodName);
} catch (java.lang.NoSuchMethodException e) { // 不存在该方法,查看父类是否存在。此处只支持一级父类,若想支持更多,建议使用while循环
if(null != clazz.getSuperclass()) {
method = clazz.getSuperclass().getDeclaredMethod(methodName);
}
}
if(null == method) {
throw new Exception(clazz.getName() + " don't have menthod --> " + methodName);
}
ret = null == method.invoke(t) ? null : method.invoke(t) + "";
setCellGBKValue(row.createCell(j), ret + "");
}
}
3.3 Использование
String[] titles = new String[]{"Id", "Brand"};
String[] fieldNames = new String[]{"id", "brand"};
List<Order> expList = new ArrayList<Order>();
Order order = new Order();
order.setId(1L);
order.setBrand("第三方手动阀");
expList.add(order);
order = new Order();
order.setId(2L);
order.setBrand("scsdsad");
expList.add(order);
String fileNamePath = "E:/order.xls";
try {
ExcelUtil.export(fileNamePath, "订单", expList, titles, fieldNames);
} catch (Exception e) {
e.printStackTrace();
}
3.4 Резюме
- Запись в основном должна передаваться в сбор данных списка, а также имя поля fieldNames.
- Внутренняя обработка заключается в непосредственном получении возвращаемого значения метода get посредством отражения и преобразовании его в строку для экспорта.
- Чтобы быть совместимым с дизайном наследования некоторых общих полей родительского класса, добавляется слой чтения методов родительского класса.
4. Об обработке экспорта типа даты
1.1 Экспорт содержимого указанного формата из поля даты
- Рекомендуется добавить поле расширения в класс Model и инкапсулировать метод get, а содержимое предназначено только для преобразования исходного поля.При экспорте fieldName может передать поле расширения. Такой как createTime, пример выглядит следующим образом:
private Date createTime;
private String createTimeStr; // 扩展字段
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getCreateTimeStr() {
createTimeStr = DateUtil.formatDatetime(this.createTime);
return createTimeStr;
}