最近遇到一个新需求,关于使用POI解析excel的,正常的遍历解析经常会用到,但是这次要求按照单元格自定义的名字去解析
首先定义好单元格名称 右键定义
这个叫单元格ID 也叫单元格地址,不过管理这个的地方叫名称管理器
这个地方按照你需要去定义范围,我得都是全局唯一的,所以我直接整个工作簿搜索
你要把全部都定义好
接着先读取一下试试
http://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Workbook.html
这个是官方文档,你们可以自己点进去看依一下
public static void main(String[] args) throws Exception {
try {
FileInputStream is = new FileInputStream("D:\\测试工作表.xls");
// 读取文件进来
HSSFWorkbook workbook = new HSSFWorkbook(is);
List<HSSFName> allNames = workbook.getAllNames();
System.out.println("allNames = " + allNames);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
这里你就能得到你定义所有的单元格的自定义名称
你也可以按照名称单独读取
那么怎么得到他的位置信息呢,下边这样就可以了
关键代码是这样的
// 所有的别名
List<HSSFName> allNames = workbook.getAllNames();
for (int i = 0; i < allNames.size(); i++) {
AreaReference[] arefs = AreaReference.generateContiguous(null, allNames.get(i).getRefersToFormula());
for (int j = 0; j < arefs.length; j++) {
CellReference[] crefs = arefs[j].getAllReferencedCells();
for (int k = 0; k < crefs.length; k++) {
Sheet sheet = workbook.getSheet(crefs[k].getSheetName());
row = sheet.getRow(crefs[k].getRow());
cell = row.getCell(crefs[k].getCol());
// 命名分析 这里因为要存key-value所以需要根据单元格命名去定义key值,方便以后存取
// 自定义的名字
String refName = allNames.get(i).getNameName();
String key = checkTaskTemplate(refName);
// 类型分析
String value = FormatCell(cell);
map.put(key, value);
}
}
}
/**
* 格式化Cell 根据你的要求去自己修改
*
* @param cell
* @return
*/
private static String FormatCell(Cell cell) {
String value = "";
switch (cell.getCellType()) {
// 数字
case NUMERIC:
//如果为时间格式的内容
if (HSSFDateUtil.isCellDateFormatted(cell)) {
//注:format格式 yyyy-MM-dd hh:mm:ss 中小时为12小时制,若要24小时制,则把小h变为H即可,yyyy-MM-dd HH:mm:ss
DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Instant instant = HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
value = sdf.format(localDateTime);
break;
} else {
DecimalFormat df = new DecimalFormat("0");// 避免科学记数法
value = String.valueOf(df.format(cell.getNumericCellValue()));
// value = String.valueOf(cell.getNumericCellValue());
// String[] split = value.split("\\.");
// //整型不保留小数部分
// if (split[1].length() == 1 && split[1].equals("0")) {
// value = split[0];
// break;
// }
break;
}
// 字符串
case STRING:
value = cell.getStringCellValue();
break;
// Boolean
case BOOLEAN:
value = cell.getBooleanCellValue() + "";
break;
// 公式
case FORMULA:
value = cell.getCellFormula() + "";
break;
// 空值
case BLANK:
value = "空";
break;
// 故障
case ERROR:
value = "非法字符";
break;
default:
value = "未知类型";
break;
}
return String.valueOf(value).trim().replaceAll("[\b\r\n\t]*", "");
}
还有一种情况是 按照列或者行去读取
老规矩 先定义好"表头"
上代码 直接看吧
HSSFName name = workbook.getName("部门");
CellReference cellReference = new CellReference(name.getRefersToFormula());
String[] cellRefParts = cellReference.getCellRefParts();
for (int i = 0; i < cellRefParts.length; i++) {
System.out.println("cellRefParts = " + cellRefParts[i]);
}
HSSFSheet sheet = workbook.getSheet(cellRefParts[0]);
// 行
int startRow = Integer.parseInt(cellRefParts[1]);
System.out.println("startRow = " + startRow);
// 列
int column = CellReference.convertColStringToIndex(cellRefParts[2]);
System.out.println("column = " + column);
HashSet<String> columnSet = getColumnSet(sheet, startRow, column);
System.out.println("columnSet = " + columnSet);
这是执行结果,是不是很6
关键代码
/**
* @param sheet 需要读取的sheet
* @param column 指定需要获取的列数,例如第一列 1
* @param startRow 指定从第几行开始读取数据
* @return 返回读取列数据的set
*/
public static HashSet<String> getColumnSet(HSSFSheet sheet, int startRow , int column ) {
HashSet<String> hashSet = new HashSet<>();
for (int rowIndex = startRow; rowIndex < sheet.getPhysicalNumberOfRows(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
Cell content = row.getCell(column);
String s = FormatCell(content);
//对于内容进行操作
hashSet.add(s);
}
return hashSet;
}
这个暂时写了一半,因为写一半的时候…需求取消了,我????!!!!!!!
所以烂尾,但是主要方法都在里边了,官方文档真的写的很清楚 还有很多操作属性的,比如去创建一个excel的时候去设置一些系统信息都可以
因为没有用到所以代码被我删了
workbook.createInformationProperties();//创建文档信息
只剩下这一行,但是根据API,如果你真的用到了,可以仔细阅读文档