All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jchanghong.poi.excel.cell.CellUtil Maven / Gradle / Ivy

The newest version!
package com.jchanghong.poi.excel.cell;

import com.jchanghong.core.date.DateUtil;
import com.jchanghong.core.util.StrUtil;
import com.jchanghong.poi.excel.ExcelUtil;
import com.jchanghong.poi.excel.StyleSet;
import com.jchanghong.poi.excel.editors.TrimEditor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FormulaError;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.ss.util.SheetUtil;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Excel表格中单元格工具类
 *
 * @author looly
 * @since 4.0.7
 */
@SuppressWarnings("deprecation")
public class CellUtil {

	/**
	 * 获取单元格值
	 *
	 * @param cell {@link Cell}单元格
	 * @return 值,类型可能为:Date、Double、Boolean、String
	 * @since 4.6.3
	 */
	public static Object getCellValue(Cell cell) {
		return getCellValue(cell, false);
	}

	/**
	 * 获取单元格值
	 *
	 * @param cell            {@link Cell}单元格
	 * @param isTrimCellValue 如果单元格类型为字符串,是否去掉两边空白符
	 * @return 值,类型可能为:Date、Double、Boolean、String
	 */
	public static Object getCellValue(Cell cell, boolean isTrimCellValue) {
		if (null == cell) {
			return null;
		}
		return getCellValue(cell, cell.getCellTypeEnum(), isTrimCellValue);
	}

	/**
	 * 获取单元格值
	 *
	 * @param cell       {@link Cell}单元格
	 * @param cellEditor 单元格值编辑器。可以通过此编辑器对单元格值做自定义操作
	 * @return 值,类型可能为:Date、Double、Boolean、String
	 */
	public static Object getCellValue(Cell cell, CellEditor cellEditor) {
		if (null == cell) {
			return null;
		}
		return getCellValue(cell, cell.getCellTypeEnum(), cellEditor);
	}

	/**
	 * 获取单元格值
	 *
	 * @param cell            {@link Cell}单元格
	 * @param cellType        单元格值类型{@link CellType}枚举
	 * @param isTrimCellValue 如果单元格类型为字符串,是否去掉两边空白符
	 * @return 值,类型可能为:Date、Double、Boolean、String
	 */
	public static Object getCellValue(Cell cell, CellType cellType, final boolean isTrimCellValue) {
		return getCellValue(cell, cellType, isTrimCellValue ? new TrimEditor() : null);
	}

	/**
	 * 获取单元格值
* 如果单元格值为数字格式,则判断其格式中是否有小数部分,无则返回Long类型,否则返回Double类型 * * @param cell {@link Cell}单元格 * @param cellType 单元格值类型{@link CellType}枚举,如果为{@code null}默认使用cell的类型 * @param cellEditor 单元格值编辑器。可以通过此编辑器对单元格值做自定义操作 * @return 值,类型可能为:Date、Double、Boolean、String */ public static Object getCellValue(Cell cell, CellType cellType, CellEditor cellEditor) { if (null == cell) { return null; } if (null == cellType) { cellType = cell.getCellTypeEnum(); } if(CellType.BLANK == cellType){ // 空白单元格可能为合并单元格 cell = getMergedRegionCell(cell); cellType = cell.getCellTypeEnum(); } Object value; switch (cellType) { case NUMERIC: value = getNumericValue(cell); break; case BOOLEAN: value = cell.getBooleanCellValue(); break; case FORMULA: // 遇到公式时查找公式结果类型 value = getCellValue(cell, cell.getCachedFormulaResultTypeEnum(), cellEditor); break; case BLANK: value = StrUtil.EMPTY; break; case ERROR: final FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); value = (null == error) ? StrUtil.EMPTY : error.getString(); break; default: value = cell.getStringCellValue(); } return null == cellEditor ? value : cellEditor.edit(cell, value); } /** * 设置单元格值
* 根据传入的styleSet自动匹配样式
* 当为头部样式时默认赋值头部样式,但是头部中如果有数字、日期等类型,将按照数字、日期样式设置 * * @param cell 单元格 * @param value 值 * @param styleSet 单元格样式集,包括日期等样式 * @param isHeader 是否为标题单元格 */ public static void setCellValue(Cell cell, Object value, StyleSet styleSet, boolean isHeader) { if (null == cell) { return; } if (null != styleSet) { final CellStyle headCellStyle = styleSet.getHeadCellStyle(); final CellStyle cellStyle = styleSet.getCellStyle(); if (isHeader && null != headCellStyle) { cell.setCellStyle(headCellStyle); } else if (null != cellStyle) { cell.setCellStyle(cellStyle); } } if (value instanceof Date) { if (null != styleSet && null != styleSet.getCellStyleForDate()) { cell.setCellStyle(styleSet.getCellStyleForDate()); } } else if (value instanceof TemporalAccessor) { if (null != styleSet && null != styleSet.getCellStyleForDate()) { cell.setCellStyle(styleSet.getCellStyleForDate()); } } else if (value instanceof Calendar) { if (null != styleSet && null != styleSet.getCellStyleForDate()) { cell.setCellStyle(styleSet.getCellStyleForDate()); } } else if (value instanceof Number) { if ((value instanceof Double || value instanceof Float || value instanceof BigDecimal) && null != styleSet && null != styleSet.getCellStyleForNumber()) { cell.setCellStyle(styleSet.getCellStyleForNumber()); } } setCellValue(cell, value, null); } /** * 设置单元格值
* 根据传入的styleSet自动匹配样式
* 当为头部样式时默认赋值头部样式,但是头部中如果有数字、日期等类型,将按照数字、日期样式设置 * * @param cell 单元格 * @param value 值 * @param style 自定义样式,null表示无样式 */ public static void setCellValue(Cell cell, Object value, CellStyle style) { if (null == cell) { return; } if (null != style) { cell.setCellStyle(style); } if (null == value) { cell.setCellValue(StrUtil.EMPTY); } else if (value instanceof FormulaCellValue) { // 公式 cell.setCellFormula(((FormulaCellValue) value).getValue()); } else if (value instanceof Date) { cell.setCellValue((Date) value); } else if (value instanceof TemporalAccessor) { if (value instanceof Instant) { cell.setCellValue(Date.from((Instant) value)); } else if (value instanceof LocalDateTime) { cell.setCellValue((LocalDateTime) value); } else if (value instanceof LocalDate) { cell.setCellValue((LocalDate) value); } } else if (value instanceof Calendar) { cell.setCellValue((Calendar) value); } else if (value instanceof Boolean) { cell.setCellValue((Boolean) value); } else if (value instanceof RichTextString) { cell.setCellValue((RichTextString) value); } else if (value instanceof Number) { cell.setCellValue(((Number) value).doubleValue()); } else { cell.setCellValue(value.toString()); } } /** * 获取已有行或创建新行 * * @param row Excel表的行 * @param cellIndex 列号 * @return {@link Row} * @since 4.0.2 */ public static Cell getOrCreateCell(Row row, int cellIndex) { Cell cell = row.getCell(cellIndex); if (null == cell) { cell = row.createCell(cellIndex); } return cell; } /** * 判断指定的单元格是否是合并单元格 * * @param sheet {@link Sheet} * @param locationRef 单元格地址标识符,例如A11,B5 * @return 是否是合并单元格 * @since 5.1.5 */ public static boolean isMergedRegion(Sheet sheet, String locationRef) { final CellLocation cellLocation = ExcelUtil.toLocation(locationRef); return isMergedRegion(sheet, cellLocation.getX(), cellLocation.getY()); } /** * 判断指定的单元格是否是合并单元格 * * @param cell {@link Cell} * @return 是否是合并单元格 * @since 5.1.5 */ public static boolean isMergedRegion(Cell cell) { return isMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()); } /** * 判断指定的单元格是否是合并单元格 * * @param sheet {@link Sheet} * @param x 列号,从0开始 * @param y 行号,从0开始 * @return 是否是合并单元格 */ public static boolean isMergedRegion(Sheet sheet, int x, int y) { final int sheetMergeCount = sheet.getNumMergedRegions(); CellRangeAddress ca; for (int i = 0; i < sheetMergeCount; i++) { ca = sheet.getMergedRegion(i); if (y >= ca.getFirstRow() && y <= ca.getLastRow() && x >= ca.getFirstColumn() && x <= ca.getLastColumn()) { return true; } } return false; } /** * 合并单元格,可以根据设置的值来合并行和列 * * @param sheet 表对象 * @param firstRow 起始行,0开始 * @param lastRow 结束行,0开始 * @param firstColumn 起始列,0开始 * @param lastColumn 结束列,0开始 * @param cellStyle 单元格样式,只提取边框样式 * @return 合并后的单元格号 */ public static int mergingCells(Sheet sheet, int firstRow, int lastRow, int firstColumn, int lastColumn, CellStyle cellStyle) { final CellRangeAddress cellRangeAddress = new CellRangeAddress(// firstRow, // first row (0-based) lastRow, // last row (0-based) firstColumn, // first column (0-based) lastColumn // last column (0-based) ); if (null != cellStyle) { RegionUtil.setBorderTop(cellStyle.getBorderTopEnum(), cellRangeAddress, sheet); RegionUtil.setBorderRight(cellStyle.getBorderRightEnum(), cellRangeAddress, sheet); RegionUtil.setBorderBottom(cellStyle.getBorderBottomEnum(), cellRangeAddress, sheet); RegionUtil.setBorderLeft(cellStyle.getBorderLeftEnum(), cellRangeAddress, sheet); } return sheet.addMergedRegion(cellRangeAddress); } /** * 获取合并单元格的值
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 * * @param sheet {@link Sheet} * @param locationRef 单元格地址标识符,例如A11,B5 * @return 合并单元格的值 * @since 5.1.5 */ public static Object getMergedRegionValue(Sheet sheet, String locationRef) { final CellLocation cellLocation = ExcelUtil.toLocation(locationRef); return getMergedRegionValue(sheet, cellLocation.getX(), cellLocation.getY()); } /** * 获取合并单元格的值
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 * * @param sheet {@link Sheet} * @param x 列号,从0开始,可以是合并单元格范围中的任意一列 * @param y 行号,从0开始,可以是合并单元格范围中的任意一行 * @return 合并单元格的值 * @since 4.6.3 */ public static Object getMergedRegionValue(Sheet sheet, int x, int y) { return getCellValue(getMergedRegionCell(sheet, x, y)); } /** * 获取合并单元格
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 * * @param cell {@link Cell} * @return 合并单元格 * @since 5.1.5 */ public static Cell getMergedRegionCell(Cell cell) { return getMergedRegionCell(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()); } /** * 获取合并单元格
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 * * @param sheet {@link Sheet} * @param x 列号,从0开始,可以是合并单元格范围中的任意一列 * @param y 行号,从0开始,可以是合并单元格范围中的任意一行 * @return 合并单元格,如果非合并单元格,返回坐标对应的单元格 * @since 5.1.5 */ public static Cell getMergedRegionCell(Sheet sheet, int x, int y) { final List addrs = sheet.getMergedRegions(); int firstColumn; int lastColumn; int firstRow; int lastRow; for (CellRangeAddress ca : addrs) { firstColumn = ca.getFirstColumn(); lastColumn = ca.getLastColumn(); firstRow = ca.getFirstRow(); lastRow = ca.getLastRow(); if (y >= firstRow && y <= lastRow) { if (x >= firstColumn && x <= lastColumn) { return SheetUtil.getCell(sheet, firstRow, firstColumn); } } } return SheetUtil.getCell(sheet, y, x); } // -------------------------------------------------------------------------------------------------------------- Private method start /** * 获取数字类型的单元格值 * * @param cell 单元格 * @return 单元格值,可能为Long、Double、Date */ private static Object getNumericValue(Cell cell) { final double value = cell.getNumericCellValue(); final CellStyle style = cell.getCellStyle(); if (null != style) { final short formatIndex = style.getDataFormat(); // 判断是否为日期 if (isDateType(cell, formatIndex)) { return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装 } final String format = style.getDataFormatString(); // 普通数字 if (null != format && format.indexOf(StrUtil.C_DOT) < 0) { final long longPart = (long) value; if (((double) longPart) == value) { // 对于无小数部分的数字类型,转为Long return longPart; } } } // 某些Excel单元格值为double计算结果,可能导致精度问题,通过转换解决精度问题。 return Double.parseDouble(NumberToTextConverter.toText(value)); } /** * 是否为日期格式
* 判断方式: * *
	 * 1、指定序号
	 * 2、org.apache.poi.ss.usermodel.DateUtil.isADateFormat方法判定
	 * 
* * @param cell 单元格 * @param formatIndex 格式序号 * @return 是否为日期格式 */ private static boolean isDateType(Cell cell, int formatIndex) { // yyyy-MM-dd----- 14 // yyyy年m月d日---- 31 // yyyy年m月------- 57 // m月d日 ---------- 58 // HH:mm----------- 20 // h时mm分 -------- 32 if (formatIndex == 14 || formatIndex == 31 || formatIndex == 57 || formatIndex == 58 || formatIndex == 20 || formatIndex == 32) { return true; } return org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell); } // -------------------------------------------------------------------------------------------------------------- Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy