使用POI封装获取单元格的值的方法
注意:
a、如果单元格设置为字符串类型,且该字符串又表示时间,这里是按时间格式的字符串读取的,在程序中取到 字符串的值后,根据字符串格式使用时间解析工具解析成Date。
b、解析单元格的值时注意:时间和数值同属NUMERIC,字符串日期的转换,数值读取的精确度问题
c、本博文的解析方法还存在不完美的地方,如果您有好的建议,欢迎交流。后续有好的方法我也会持续更新。
d、本文是在别人的博文基础上修改的,时间久了,文章的链接找不到了,在这里感谢那位作者的无私付出。
1、使用接口定义一些常量
package com.wholesmart.rainfallmonitoring.enhancedservice.poiservice;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.poi.ss.usermodel.DataFormatter;
/**
* 用于excel日期格式转换的常量
*
* @author dyw
* @date 2019年9月16日
*/
public interface POIConstants {
/**
* 年月日时分秒 默认格式
*/
SimpleDateFormat COMMON_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 时间 默认格式
*/
SimpleDateFormat COMMON_TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
/**
* 年月日 默认格式
*/
SimpleDateFormat COMMON_DATE_FORMAT_NYR = new SimpleDateFormat("yyyy-MM-dd");
/**
* 年月 默认格式
*/
SimpleDateFormat COMMON_DATE_FORMAT_NY = new SimpleDateFormat("yyyy-MM");
/**
* 月日 默认格式
*/
SimpleDateFormat COMMON_DATE_FORMAT_YR = new SimpleDateFormat("MM-dd");
/**
* 月 默认格式
*/
SimpleDateFormat COMMON_DATE_FORMAT_Y = new SimpleDateFormat("MM");
/**
* 星期 默认格式
*/
String COMMON_DATE_FORMAT_XQ = "星期";
/**
* 周 默认格式
*/
String COMMON_DATE_FORMAT_Z = "周";
/**
* 07版时间(非日期) 总time
*/
List<Short> EXCEL_FORMAT_INDEX_07_TIME = Arrays.asList(new Short[] { 18, 19, 20, 21, 32, 33, 45, 46, 47, 55, 56,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186 });
/**
* 07版日期(非时间) 总date
*/
List<Short> EXCEL_FORMAT_INDEX_07_DATE = Arrays.asList(new Short[] { 14, 15, 16, 17, 22, 30, 31, 57, 58, 187, 188,
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 });
/**
* 03版时间(非日期) 总time
*/
List<Short> EXCEL_FORMAT_INDEX_03_TIME = Arrays.asList(new Short[] { 18, 19, 20, 21, 32, 33, 45, 46, 47, 55, 56,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186 });
/**
* 07版日期(非日期) 总date
*/
List<Short> EXCEL_FORMAT_INDEX_03_DATE = Arrays.asList(new Short[] { 14, 15, 16, 17, 22, 30, 31, 57, 58, 187, 188,
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 });
/**
* date-年月日时分秒
*/
List<String> EXCEL_FORMAT_INDEX_DATE_NYRSFM_STRING = Arrays.asList("yyyy/m/d\\ h:mm;@", "m/d/yy h:mm",
"yyyy/m/d\\ h:mm\\ AM/PM", "[$-409]yyyy/m/d\\ h:mm\\ AM/PM;@", "yyyy/mm/dd\\ hh:mm:dd",
"yyyy/mm/dd\\ hh:mm", "yyyy/m/d\\ h:m", "yyyy/m/d\\ h:m:s", "yyyy/m/d\\ h:mm", "m/d/yy h:mm;@",
"yyyy/m/d\\ h:mm\\ AM/PM;@");
/**
* date-年月日
*/
List<String> EXCEL_FORMAT_INDEX_DATE_NYR_STRING = Arrays.asList("m/d/yy", "[$-F800]dddd\\,\\ mmmm\\ dd\\,\\ yyyy",
"[DBNum1][$-804]yyyy\"年\"m\"月\"d\"日\";@", "yyyy\"年\"m\"月\"d\"日\";@", "yyyy/m/d;@", "yy/m/d;@", "m/d/yy;@",
"[$-409]d/mmm/yy", "[$-409]dd/mmm/yy;@", "reserved-0x1F", "reserved-0x1E", "mm/dd/yy;@", "yyyy/mm/dd",
"d-mmm-yy", "[$-409]d\\-mmm\\-yy;@", "[$-409]d\\-mmm\\-yy", "[$-409]dd\\-mmm\\-yy;@",
"[$-409]dd\\-mmm\\-yy", "[DBNum1][$-804]yyyy\"年\"m\"月\"d\"日\"", "yy/m/d", "mm/dd/yy", "dd\\-mmm\\-yy");
/**
* date-年月
*/
List<String> EXCEL_FORMAT_INDEX_DATE_NY_STRING = Arrays.asList("[DBNum1][$-804]yyyy\"年\"m\"月\";@",
"[DBNum1][$-804]yyyy\"年\"m\"月\"", "yyyy\"年\"m\"月\";@", "yyyy\"年\"m\"月\"", "[$-409]mmm\\-yy;@",
"[$-409]mmm\\-yy", "[$-409]mmm/yy;@", "[$-409]mmm/yy", "[$-409]mmmm/yy;@", "[$-409]mmmm/yy",
"[$-409]mmmmm/yy;@", "[$-409]mmmmm/yy", "mmm-yy", "yyyy/mm", "mmm/yyyy", "[$-409]mmmm\\-yy;@",
"[$-409]mmmmm\\-yy;@", "mmmm\\-yy", "mmmmm\\-yy");
/**
* date-月日
*/
List<String> EXCEL_FORMAT_INDEX_DATE_YR_STRING = Arrays.asList("[DBNum1][$-804]m\"月\"d\"日\";@",
"[DBNum1][$-804]m\"月\"d\"日\"", "m\"月\"d\"日\";@", "m\"月\"d\"日\"", "[$-409]d/mmm;@", "[$-409]d/mmm", "m/d;@",
"m/d", "d-mmm", "d-mmm;@", "mm/dd", "mm/dd;@", "[$-409]d\\-mmm;@", "[$-409]d\\-mmm");
/**
* date-星期X
*/
List<String> EXCEL_FORMAT_INDEX_DATE_XQ_STRING = Arrays.asList("[$-804]aaaa;@", "[$-804]aaaa");
/**
* date-周X
*/
List<String> EXCEL_FORMAT_INDEX_DATE_Z_STRING = Arrays.asList("[$-804]aaa;@", "[$-804]aaa");
/**
* date-月X
*/
List<String> EXCEL_FORMAT_INDEX_DATE_Y_STRING = Arrays.asList("[$-409]mmmmm;@", "mmmmm", "[$-409]mmmmm");
/**
* time - 时间
*/
List<String> EXCEL_FORMAT_INDEX_TIME_STRING = Arrays.asList("mm:ss.0", "h:mm", "h:mm\\ AM/PM", "h:mm:ss",
"h:mm:ss\\ AM/PM", "reserved-0x20", "reserved-0x21", "[DBNum1]h\"时\"mm\"分\"", "[DBNum1]上午/下午h\"时\"mm\"分\"",
"mm:ss", "[h]:mm:ss", "h:mm:ss;@", "[$-409]h:mm:ss\\ AM/PM;@", "h:mm;@", "[$-409]h:mm\\ AM/PM;@",
"h\"时\"mm\"分\";@", "h\"时\"mm\"分\"\\ AM/PM;@", "h\"时\"mm\"分\"ss\"秒\";@", "h\"时\"mm\"分\"ss\"秒\"_ AM/PM;@",
"上午/下午h\"时\"mm\"分\";@", "上午/下午h\"时\"mm\"分\"ss\"秒\";@", "[DBNum1][$-804]h\"时\"mm\"分\";@",
"[DBNum1][$-804]上午/下午h\"时\"mm\"分\";@", "h:mm AM/PM", "h:mm:ss AM/PM", "[$-F400]h:mm:ss\\ AM/PM");
/**
* date-当formatString为空的时候-年月
*/
Short EXCEL_FORMAT_INDEX_DATA_EXACT_NY = 57;
/**
* date-当formatString为空的时候-月日
*/
Short EXCEL_FORMAT_INDEX_DATA_EXACT_YR = 58;
/**
* time-当formatString为空的时候-时间
*/
List<Short> EXCEL_FORMAT_INDEX_TIME_EXACT = Arrays.asList(new Short[] { 55, 56 });
/**
* 格式化星期或者周显示
*/
String[] WEEK_DAYS = { "日", "一", "二", "三", "四", "五", "六" };
/**
* 07版 excel dataformat
*/
DataFormatter EXCEL_07_DATA_FORMAT = new DataFormatter();
/**
* 小数 正则
*/
Pattern PATTERN_DECIMAL = Pattern.compile("^-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+)$");
/**
* 07版excel后缀名
*/
String EXCEL_SUFFIX_07 = "xlsx";
/**
* 03版excel后缀名
*/
String EXCEL_SUFFIX_03 = "xls";
}
2、获取单元格的值的核心方法
package com.wholesmart.rainfallmonitoring.enhancedservice.poiservice;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import org.apache.poi.ss.usermodel.*;
/**
* 获取EXCEL单元格的值
*
* @author dyw
* @date 2019年9月16日
*/
public class POICellValueUtils {
/**
* 用户模式得到单元格的值
*
* @param workbook
* @param cell
* @return String
*/
public static String getCellValue(Workbook workbook, Cell cell) {
String cellValue = "";
if (cell == null) {
return cellValue;
}
switch (cell.getCellType()) {
case NUMERIC:
cellValue = getDateValue(cell.getCellStyle().getDataFormat(), cell.getCellStyle().getDataFormatString(),
cell.getNumericCellValue());
if (cellValue == null) {
// 使用DecimalFormat为了防止读取到科学计算法字符串,防止Double转换字符串后有好多数位
Double dou = cell.getNumericCellValue();
DecimalFormat decimalFormat = new DecimalFormat("#.######");
String formatNumber = decimalFormat.format(dou);
cellValue = subZeroAndDot(formatNumber);
}
break;
case STRING:
cellValue = String.valueOf(cell.getStringCellValue());
break;
case BOOLEAN:
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case FORMULA:
/**
* 格式化单元格
*/
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
cellValue = getFormulaValue(evaluator.evaluate(cell));
break;
case BLANK:
cellValue = "";
break;
case ERROR:
cellValue = String.valueOf(cell.getErrorCellValue());
break;
case _NONE:
cellValue = "";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
/**
* 用户模式得到公式单元格的值
*
* @param formulaValue
* @return String
*/
public static String getFormulaValue(CellValue formulaValue) {
String cellValue = "";
if (formulaValue == null) {
return cellValue;
}
switch (formulaValue.getCellType()) {
case NUMERIC:
cellValue = String.valueOf(formulaValue.getNumberValue());
break;
case STRING:
cellValue = String.valueOf(formulaValue.getStringValue());
break;
case BOOLEAN:
cellValue = String.valueOf(formulaValue.getBooleanValue());
break;
case BLANK:
cellValue = "";
break;
case ERROR:
cellValue = String.valueOf(formulaValue.getErrorValue());
break;
case _NONE:
cellValue = "";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
/**
* 得到date单元格格式的值
*
* @param dataFormat
* @param dataFormatString
* @param value
* @return String
*/
public static String getDateValue(Short dataFormat, String dataFormatString, double value) {
if (!DateUtil.isValidExcelDate(value)) {
return null;
}
Date date = DateUtil.getJavaDate(value);
/**
* 年月日时分秒
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_NYRSFM_STRING.contains(dataFormatString)) {
return POIConstants.COMMON_DATE_FORMAT.format(date);
}
/**
* 年月日
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_NYR_STRING.contains(dataFormatString)) {
return POIConstants.COMMON_DATE_FORMAT_NYR.format(date);
}
/**
* 年月
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_NY_STRING.contains(dataFormatString)
|| POIConstants.EXCEL_FORMAT_INDEX_DATA_EXACT_NY.equals(dataFormat)) {
return POIConstants.COMMON_DATE_FORMAT_NY.format(date);
}
/**
* 月日
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_YR_STRING.contains(dataFormatString)
|| POIConstants.EXCEL_FORMAT_INDEX_DATA_EXACT_YR.equals(dataFormat)) {
return POIConstants.COMMON_DATE_FORMAT_YR.format(date);
}
/**
* 月
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_Y_STRING.contains(dataFormatString)) {
return POIConstants.COMMON_DATE_FORMAT_Y.format(date);
}
/**
* 星期X
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_XQ_STRING.contains(dataFormatString)) {
return POIConstants.COMMON_DATE_FORMAT_XQ + dateToWeek(date);
}
/**
* 周X
*/
if (POIConstants.EXCEL_FORMAT_INDEX_DATE_Z_STRING.contains(dataFormatString)) {
return POIConstants.COMMON_DATE_FORMAT_Z + dateToWeek(date);
}
/**
* 时间格式
*/
if (POIConstants.EXCEL_FORMAT_INDEX_TIME_STRING.contains(dataFormatString)
|| POIConstants.EXCEL_FORMAT_INDEX_TIME_EXACT.contains(dataFormat)) {
return POIConstants.COMMON_TIME_FORMAT.format(DateUtil.getJavaDate(value));
}
/**
* 单元格为其他未覆盖到的类型
*/
if (DateUtil.isADateFormat(dataFormat, dataFormatString)) {
return POIConstants.COMMON_TIME_FORMAT.format(value);
}
return null;
}
/**
* 日期转星期
*
* @param date
* @return String
*/
private static String dateToWeek(Date date) {
if (date == null) {
return "";
}
// 获得一个日历
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// 指示一个星期中的某天。
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (w < 0)
w = 0;
return POIConstants.WEEK_DAYS[w];
}
/**
* 解析表格数据时存在数值类型末尾有无效零的情况,这个方法用于去除小数点后无效0的
*
* @param s
* @return
*/
private static String subZeroAndDot(String s) {
if (s.indexOf(".") > 0) {
s = s.replaceAll("0+?$", "");// 去掉多余的0
s = s.replaceAll("[.]$", "");// 如最后一位是.则去掉
}
return s;
}
}