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

cn.cliveyuan.tools.poi.inner.ExcelInnerHelper Maven / Gradle / Ivy

There is a newer version: 4.0.6
Show newest version
package cn.cliveyuan.tools.poi.inner;


import cn.cliveyuan.tools.common.ArrayTools;
import cn.cliveyuan.tools.common.AssertTools;
import cn.cliveyuan.tools.common.FileTools;
import cn.cliveyuan.tools.common.StringTools;
import cn.cliveyuan.tools.common.TableUtils;
import cn.cliveyuan.tools.poi.bean.ExcelReader;
import cn.cliveyuan.tools.poi.bean.ExcelType;
import cn.cliveyuan.tools.poi.bean.ExcelWriter;
import cn.cliveyuan.tools.poi.bean.SheetContent;
import cn.cliveyuan.tools.poi.bean.SheetData;
import cn.cliveyuan.tools.poi.bean.SheetInfo;
import cn.cliveyuan.tools.poi.exception.ExcelException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.cliveyuan.tools.poi.bean.ExcelType.XLS;
import static cn.cliveyuan.tools.poi.bean.ExcelType.XLSM;
import static cn.cliveyuan.tools.poi.bean.ExcelType.XLSX;

/**
 * @author clive
 * Created on 2018/08/01
 * @since 1.0
 */
@Slf4j
public class ExcelInnerHelper {

    private static final Logger logger = LoggerFactory.getLogger(ExcelInnerHelper.class);

    private ExcelInnerHelper() {
    }

    /**
     * 读取Excel
     *
     * @param excelReader excelReader
     * @return
     */
    public static List read(ExcelReader excelReader) {
        if (Objects.isNull(excelReader)) {
            return new ArrayList<>();
        }
        AssertTools.notNull(excelReader, "excelReader is required");
        List resultList = new ArrayList<>();
        List sheetInfoList = excelReader.getSheetInfoList();
        AssertTools.notEmpty(sheetInfoList, "sheetInfoList can't be empty");
        String[] sheetNames = sheetInfoList.stream().map(SheetInfo::getSheetName).toArray(String[]::new);
        Map sheetInfoMap = sheetInfoList.stream().collect(Collectors.toMap(SheetInfo::getSheetName, Function.identity()));
        Map> sheetDataMap = ExcelInnerHelper.readRawExcel(excelReader.getPathname(), sheetNames);
        sheetDataMap.forEach((sheetName, dataArray) -> {
                    SheetInfo sheetInfo = sheetInfoMap.get(sheetName);
                    if (Objects.isNull(sheetInfo)) {
                        log.warn("can't find sheetInfo of sheetName " + sheetName);
                        throw ExcelException.dataConvertError();
                    }
                    SheetData sheetData = new SheetData(sheetName, TableUtils.dataToObject(excelReader.getStartRowNo(), dataArray, sheetInfo.getClazz()));
                    resultList.add(sheetData);
                }
        );
        return resultList;
    }

    /**
     * 生成Excel
     *
     * @param excelWriter excelWriter
     * @return
     */
    public static File write(ExcelWriter excelWriter) {
        AssertTools.notNull(excelWriter, "excelWriter is required");
        return generate(excelWriter);
    }

    /**
     * 读入excel文件,解析后返回
     * key: sheet名, value每行数据
     *
     * @param absoluteFilePath 文件绝对路径
     * @param sheetNames       指定的sheet名
     */
    public static Map> readRawExcel(String absoluteFilePath, String... sheetNames) {
        return doReadRawExcel(absoluteFilePath, sheetNames);
    }


    //region private methods

    private static Map> doReadRawExcel(String absoluteFilePath, String... sheetNames) {
        AssertTools.notBlank(absoluteFilePath, "excel file path is empty");
        File file = new File(absoluteFilePath);
        AssertTools.isTrue(file.exists(), "excel file not exists");
        String extension = FileTools.getExtension(absoluteFilePath);
        if (!XLS.name().equalsIgnoreCase(extension)
                && !XLSX.name().equalsIgnoreCase(extension)
                && !XLSM.name().equalsIgnoreCase(extension)
        ) {
            throw ExcelException.notSupport(extension);
        }
        Map> map = new HashMap();
        try {
            // 检查文件
            // 获得Workbook工作薄对象
            Workbook workbook = getWorkBook(file);
            // 仅读取第一个sheet, 如需读取其他sheet, 需自行封装方法 获取sheet数量:workbook.getNumberOfSheets()
            // 创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
            int numberOfSheets = workbook.getNumberOfSheets();
            List sheets = new ArrayList<>();
            for (int i = 0; i < numberOfSheets; i++) {
                Sheet sheet = workbook.getSheetAt(i);
                if (Objects.isNull(sheet)) {
                    throw ExcelException.failToReadSheet();
                }
                sheets.add(sheet);
            }
            if (ArrayTools.isNotEmpty(sheetNames)) {
                List sheetNameList = Arrays.asList(sheetNames);
                List collect = sheets.stream().filter(x -> sheetNameList.contains(x.getSheetName())).collect(Collectors.toList());
                sheets.clear();
                sheets.addAll(collect);
            }
            for (Sheet sheet : sheets) {
                List list = new ArrayList<>();

                // 获得当前sheet的开始行
                int firstRowNum = sheet.getFirstRowNum();
                // 获得当前sheet的结束行
                int lastRowNum = sheet.getLastRowNum();
                for (int rowNum = firstRowNum; rowNum <= lastRowNum; rowNum++) {
                    // 获得当前行
                    Row row = sheet.getRow(rowNum);
                    if (row == null) {
                        continue;
                    }
                    // 获得当前行的开始列
                    int firstCellNum = row.getFirstCellNum();
                    // 获得当前行的列数
                    int lastCellNum = row.getPhysicalNumberOfCells();
                    String[] cells = new String[row.getPhysicalNumberOfCells()];
                    int blankCol = 0;
                    // 循环当前行
                    for (int cellNum = firstCellNum; cellNum < lastCellNum; cellNum++) {
                        Cell cell = row.getCell(cellNum);
                        String cellStr = getCellValue(cell);
                        if (StringTools.isBlank(cellStr)) {
                            blankCol++;
                        }
                        cells[cellNum] = cellStr;
                    }
                    if (blankCol < lastCellNum) {
                        list.add(cells);
                    }
                }
                map.put(sheet.getSheetName(), list);
            }

        } catch (ExcelException e) {
            throw e;
        } catch (Exception e) {
            logger.error("readExcel ", e);
            throw ExcelException.failToParseExcel();
        }
        return map;
    }

    private static Workbook getWorkBook(File file) throws IOException {
        // 获得文件名
        String fileName = file.getName();
        // 创建Workbook工作薄对象,表示整个excel
        Workbook workbook;
        // 获取excel文件的io流
        InputStream is = new FileInputStream(file);
        // 根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
        if (fileName.endsWith(XLS.name().toLowerCase())
                || fileName.endsWith(XLS.name())) {
            // 2003
            workbook = new HSSFWorkbook(is);
        } else {
            // 2007
            workbook = new XSSFWorkbook(is);
        }

        return workbook;
    }

    private static String getCellValue(Cell cell) {
        String cellValue = StringTools.EMPTY;
        if (Objects.isNull(cell)) {
            return cellValue;
        }
        switch (cell.getCellTypeEnum()) {
            case NUMERIC:
                DecimalFormat df = new DecimalFormat("0");
                cellValue = df.format(cell.getNumericCellValue());
                break;
            case STRING:
                cellValue = String.valueOf(cell.getStringCellValue());
                break;
            case BOOLEAN:
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA:
                cellValue = String.valueOf(cell.getCellFormula());
                break;
            case _NONE:
                cellValue = "[未知类型]";
                break;
            case ERROR:
                cellValue = "[非法字符]";
                break;
            default:
        }
        return cellValue;
    }

    private static File generate(ExcelWriter param) {
        String filePath = param.getFilePath();
        ExcelType excelType = param.getFileType();
        AssertTools.notBlank(filePath, "file path can't be empty");
        AssertTools.notNull(excelType, "excel type is required");
        AssertTools.notEmpty(param.getSheetContentList(), "sheetContentList can't be empty");

        File file = new File(filePath);
        if (!file.exists()) {
            boolean result = file.mkdirs();
            if (!result) throw ExcelException.failToMkdirs();
        }
        String name = param.getFileName();
        if (StringTools.isBlank(name)) {
            name = UUID.randomUUID().toString();
        }
        String fileName = name + "." + excelType.name().toLowerCase();
        if (!filePath.endsWith("/")) filePath = filePath + "/";
        file = new File(filePath + fileName);
        try (FileOutputStream fos = new FileOutputStream(file)) {
            Workbook wb;
            if (excelType.equals(XLS)) wb = new HSSFWorkbook();
            else wb = new XSSFWorkbook();

            for (SheetContent sheetContent : param.getSheetContentList()) {
                String[] headers = sheetContent.getHeaders();
                Collection data = sheetContent.getData();
                AssertTools.isTrue(ArrayTools.isNotEmpty(headers), "headers can't be empty");
                AssertTools.isTrue(CollectionUtils.isNotEmpty(data), "data can't be empty");

                Sheet sheet = wb.createSheet(sheetContent.getSheetName());
                Row firstRow = sheet.createRow(0);
                //创建表头
                for (int i = 0; i < headers.length; i++) {
                    Cell cell = firstRow.createCell(i);
                    cell.setCellValue(headers[i]);
                }

                //处理数据
                Iterator it = data.iterator();
                int index = 0;
                while (it.hasNext()) {
                    index++;
                    Row row = sheet.createRow(index);
                    Object t = it.next();
                    //反射
                    Class clazz = t.getClass();
                    Field[] fields = clazz.getDeclaredFields();
                    for (int i = 0; i < fields.length; i++) {
                        Field field = fields[i];
                        PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                        Method getMethod = pd.getReadMethod();
                        if (getMethod != null) {
                            Object invoke = getMethod.invoke(t);
                            String value = StringTools.EMPTY;
                            if (invoke != null) {
                                if (invoke instanceof Date) {
                                    value = TableUtils.SDF.format((Date) invoke);
                                } else value = invoke.toString();
                            }
                            Cell cell = row.createCell(i);
                            cell.setCellValue(value);
                        }

                    }
                }
            }
            wb.write(fos);
            return file;
        } catch (Exception e) {
            log.error("excel generate exception", e);
            throw ExcelException.failToGenerateExcel();
        }
    }

    //endregion
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy