package com.adtec.moia.service.impl.yh.excel;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import com.alibaba.fastjson.JSONObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
public class EXLSReader {
public static void main(String[] args) {
// 设定Excel文件所在路径
String excelFileName = "C:/Users/Administrator/Desktop/1630992431061.xls";
// 读取Excel文件内容
try {
List<Map<String, Object>> readExcelData = readExcelData(excelFileName,"程序信息表",0,ExcelDataVO.class);
System.out.println(readExcelData+"\n");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// for(int a=0;a<readResult.size();a++){
// System.out.println(readResult.get(a).getName());
// System.out.println(readResult.get(a).getJob());
// System.out.println(readResult.get(a).getAge());
// System.out.println(readResult.get(a).getLocation());
//
// }
// todo 进行业务操作
}
//对象属性名集合
static List<String> columnNameList = new ArrayList<>();
//对象属性类型集合
static List<String> columnTypeNameList = new ArrayList<>();
/*
* @author March
* @Description readExcelData:解析excel表格,并且封装进对象;一行就是一个map,map的key是对象的属性名;属性的数量和位置必须和表的列一一对应
* @warning:Java对象的属性顺序还有数量必须和excel的列的顺序一一对应,否则数据不对应;Java属性的id可以忽略
* @Date 1:36 下午 2020/5/19
* @param url:excel文件地址
* @param readSheetName :表名
* @param ignoreRow:需要忽略的行数,如标题这种
* @param titleRow:列名,作为对象的key
* @return
**/
public static <T> List<Map<String, Object>> readExcelData(String url, String readSheetName, Integer ignoreRow, Class<T> clz) throws Exception {
Optional.ofNullable(url).orElseThrow(() -> new RuntimeException("url文件路径不能为空"));
Optional.ofNullable(readSheetName).orElseThrow(() -> new RuntimeException("readSheetName文件路径不能为空"));
// 从XLSX/ xls文件创建的输入流
try {
FileInputStream fis = new FileInputStream(url);
//封装单元格参数,map就是一行数据,key是
List<Map<String, Object>> hospitalList = new ArrayList();
// 创建工作薄Workbook
Workbook workBook = null;
// 读取2007版,以 .xlsx 结尾
// if (url.toLowerCase().endsWith("xlsx")) {
// try {
// workBook = new XSSFWorkbook(fis);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// 读取2003版,以 .xls 结尾
if (url.toLowerCase().endsWith("xls")) {
try {
workBook = new HSSFWorkbook(fis);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取总共的表格数量
int numberOfSheets = workBook.getNumberOfSheets();
// 循环 numberOfSheets
for (int sheetNum = 0; sheetNum < numberOfSheets; sheetNum++) {
// 得到 工作薄 的第 N个表
Sheet sheet = workBook.getSheetAt(sheetNum);
String sheetName = sheet.getSheetName();
if (readSheetName.equals(sheetName)) {
//行
Row row;
// cell就是每个单元格的值
String cell;
//按顺序获取class的属性的类型的字符串
columnTypeNameList=EXLSReader.parseBeanPropertyTypeName(clz);
//按顺序获取class的属性名称
columnNameList=EXLSReader.paresBeanPropertyName(clz);
//数据封装
for (int i = sheet.getFirstRowNum(); i < sheet.getPhysicalNumberOfRows(); i++) {
//忽略的行数;
if (Integer.compare(i, ignoreRow - 1) != 1) {
continue;
}
// 循环行数
row = sheet.getRow(i);
//存储每行的参数
Map<String, Object> map = new HashMap<>();
for (int j = row.getFirstCellNum(); j < row.getPhysicalNumberOfCells(); j++) {
//遍历列名集合,
for (int k = 0; k < columnNameList.size(); k++) {
//当列名集合的下表和这行的下表相等时就放入map
if (k == j) {
cell=Optional.ofNullable(row.getCell(j).toString()).orElse("");
switch (columnTypeNameList.get(k)){
case "java.lang.Int":
map.put(columnNameList.get(k),Integer.valueOf(StringUtils.contains(cell,".")?cell.substring(0,cell.indexOf(".")):cell));
break;
case "java.lang.Long":
map.put(columnNameList.get(k),Long.valueOf(cell));
break;
case "java.lang.Double":
map.put(columnNameList.get(k),Double.valueOf(cell));
break;
case "java.lang.Float":
map.put(columnNameList.get(k),Float.valueOf(cell));
break;
case "java.math.BigInteger":
map.put(columnNameList.get(k), BigInteger.valueOf(Long.valueOf(cell)));
break;
case "java.math.BigDecimal":
map.put(columnNameList.get(k),BigDecimal.valueOf(Double.valueOf(cell)));
break;
// case "java.util.Date":
// map.put(columnNameList.get(k), DateUtils.parseDate(cell,"yyyy年MM月dd日","yyyy-MM-dd hh:mm:ss","yyyy-MM-dd HH:mm:ss"));
// break;
//默认返回字符串
//如果有需要的拓展类型,在上面的case中增加类型的全类路径名
default:
map.put(columnNameList.get(k),cell);
break;
}
}
}
// System.out.print(cell+"\t");
}
hospitalList.add(map);
// System.out.println();
}
}
}
return hospitalList;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
* @author March
* @Description parseMapListToObjectList:把excel的文件读出,先转为map集合,再转为对象集合
* @Warning:对象的属性名的顺序数量必须和excel表格一一对应
* @Date 1:33 下午 2020/5/21
* @param url:excel文件路径
* @param readSheetName:表名
* @param ignoreRow:忽略的行数(只需要数据,不需要列的字段)
* @param clz:需要转换的对象的class
* @return
**/
public static <T> List<T> parseExcelToMapListToObjectList(String url, String readSheetName, Integer ignoreRow, Class<T> clz) throws IllegalAccessException, InstantiationException, IntrospectionException {
List<T> listInfo = new ArrayList<>();
List<Map<String, Object>> list = null;
try {
list = readExcelData(url, readSheetName, ignoreRow, clz);
} catch (Exception e) {
e.printStackTrace();
}
list.forEach(map -> {
try {
//map转为对象并且加入集合
listInfo.add(EXLSReader.map2bean(map,clz));
} catch (Exception e) {
e.printStackTrace();
}
});
return listInfo;
}
/*
* @author March
* @Description map2bean:把map的值转为对象
* @Warning:对象的属性名和map的key必须一致
* @Date 1:35 下午 2020/5/21
* @param map
* @param clz
* @return
**/
public static <T> T map2bean(Map<String, Object> map, Class<T> clz) throws Exception {
if (null == map) {
throw new RuntimeException();
}
try {
//创建一个需要转换为的类型的对象
T obj = clz.newInstance();
//从Map中获取和属性名称一样的值,把值设置给对象(setter方法)
//得到属性的描述器
BeanInfo b = Introspector.getBeanInfo(clz, Object.class);
PropertyDescriptor[] pds = b.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
//得到属性的setter方法
Method setter = pd.getWriteMethod();
//得到key名字和属性名字相同的value设置给属性
setter.invoke(obj, map.get(pd.getName()));
}
return obj;
} catch (Exception e) {
throw new RuntimeException();
}
}
/*
* @author March
* @Description paresBeanPropertyName:根据class依序获取对象属性的名字
* @Date 11:13 上午 2020/5/21
* @param clz
* @return
**/
public static <T> List<String> paresBeanPropertyName(Class<T> clz) {
//获取class的属性字段;
Field[] fields = clz.getDeclaredFields();
if (fields.length > 0) {
List<String> beanPropertyNames=new ArrayList<>();
try {
//在使用java反射机制获取 JavaBean 的属性值时,如果该属性被声明为private 的,需要将setAccessible设置为true. 默认的值为false
Field.setAccessible(fields, true);
for (int i = 0; i < fields.length; i++) {
//忽略ID字段
if("id".equals(fields[i].getName())){
continue;
}
//获取属性的名字
beanPropertyNames.add(fields[i].getName());
}
return beanPropertyNames;
}catch (Exception e){
e.printStackTrace();
}
}
return null;
}
/*
* @author March
* @Description parseBeanPropertyType:根据class依序获取对象属性的数据类型
* @Date 10:32 上午 2020/5/21
* @param clz
* @return
**/
public static <T> List<String> parseBeanPropertyTypeName(Class<T> clz) {
Field[] fields = clz.getDeclaredFields();
if (fields.length > 0) {
List<String> beanPropertyTypes=new ArrayList<>();
try {
//在使用java反射机制获取 JavaBean 的属性值时,如果该属性被声明为private 的,需要将setAccessible设置为true. 默认的值为false
Field.setAccessible(fields, true);
for (int i = 0; i < fields.length; i++) {
//获取属性的类型的名字
//忽略ID字段
if("id".equals(fields[i].getName())){
continue;
}
beanPropertyTypes.add(fields[i].getType().getName());
}
return beanPropertyTypes;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
public static boolean isNumeric(String str) {
try {
new BigDecimal(str);
} catch (Exception e) {
return false;
}
return true;
}
}