Bootstrap

JAVA用poi包导入Excel

JAVA用poi包导入Excel

一、先看效果

1、点击【数据导入】按钮,弹窗里,可以下载模板,可以选择导入的Excel文件
在这里插入图片描述
2、下载的模板,第一行是标题,后边几行是数据
在这里插入图片描述

3、导入结果,有结果回馈,如果错误有下载
在这里插入图片描述
4、下载的错误模板,只回显错误的,错误字段会标红
在这里插入图片描述
也可以在标红的单元格,鼠标点击显示为啥标红
在这里插入图片描述

二、JAVA代码实现

1、ctrl层

/**
	 * 通过excel导入数据
	 *
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/importExcelWithAbnormal", method = RequestMethod.POST)
	public Result<?> importExcelWithAbnormal(HttpServletRequest request, HttpServletResponse response) {

		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();

		Result<?> res = wsInstallationBaseInfoService.importExcelWithAbnormal(fileMap, localPath);

		return res;

	}

2、service层
(这个方法有点长,用的亲可以再封装下)
演示了3种情况,excel里的批注怎么加,枚举怎么赋值,String、Integer怎么赋值

import org.framework.common.api.vo.Result;
import java.util.*;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.multipart.MultipartFile;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import cn.hutool.core.collection.CollUtil;
import java.util.stream.Collectors;
import org.springframework.util.ObjectUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;

private final static String excel2003L =".xls";
private final static String excel2007U =".xlsx";

public Result<?> importExcelWithAbnormal(Map<String, MultipartFile> fileMap, String uploadPath) {
       
       // excel的列标题,做校验是否为模板
		List<String> titleArr = CollUtil.newArrayList("地市","县(市、区)","乡镇(街道)","行政村名称","行政村编号","设备名称","水质标准");
        List<String> propertyList = CollUtil.newArrayList("cityName","countyName","townName","villageName","villageCode","installationName","waterQualityNorm");
        // 枚举 演示匹配
        List<DictModel> waterQualityNormDictList = baseMapper.getDictItemByCode("waterQualityNorm");
        Map<String, String> waterQualityNormDictMap = waterQualityNormDictList.stream().collect(Collectors.toMap(DictModel::getText, DictModel::getValue));

		// 开始
        List<List<Object>> lstDatas = new ArrayList<>();
        List<JSONObject> errorRowList = new ArrayList<>();
        int successLines = 0, errorLines = 0;
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            String fileName = file.getOriginalFilename();
            String fileType = fileName.substring(fileName.lastIndexOf("."));
            if(!excel2003L.equals(fileType) && !excel2007U.equals(fileType)){
                return Result.error("请上传excel文件!");
            }
            try{
                // 判断是否是导入模板
                XSSFWorkbook wb1 = new XSSFWorkbook(file.getInputStream());
                Sheet sheet1 = wb1.getSheetAt(0);
                Boolean isTemplate = true;
                if (!ObjectUtils.isEmpty(sheet1)){
                    Row row = sheet1.getRow(0);
                    if (ObjectUtils.isEmpty(row) || row.getPhysicalNumberOfCells() != titleArr.size()){
                        isTemplate = false;
                    }else {
                        for (int i = 0; i < titleArr.size() ; i++) {
                            Cell cell = row.getCell(i);
                            if (!titleArr.get(i).equals(cell.getStringCellValue())){
                                isTemplate = false;
                                break;
                            }
                        }
                    }
                }else {
                    isTemplate = false;
                }
                if (!isTemplate){
                    return Result.error("导入模板不正确!请使用正确的导入模板");
                }
                int rowSize = sheet1.getLastRowNum();

                Row row;
                for(int i = 1; i <= rowSize; i++) {
                    row = sheet1.getRow(i);
                    if (row == null) {
                        continue;
                    }
                    WsInstallationBaseInfo baseInfo = new WsInstallationBaseInfo();
                   
                    boolean error = false;
                    List<Object> item = new ArrayList<>();
                    List<Integer> errorRow = new ArrayList<>();
                    List<JSONObject> commentList = new ArrayList<>();
                    boolean hasComment = false;
                    

                    for(int a = 0; a < titleArr.size(); a++) {
                        Cell cell = row.getCell(a);
                        boolean cellFlag = false;
                        if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
                            //空值
                            if (a < 7) {
                                cellFlag = true;
                                item.add("空");
                            } else {
                                item.add(ExcelExportUtil.getCellValueByCell(cell));
                            }
                        } else {
                            String cellValueByCell = ExcelExportUtil.getCellValueByCell(cell);
                            item.add(cellValueByCell);
                            if (propertyList.get(a).equals("cityName")) {
                            	// 市
                                // 1、此处演示如何加提示
                                baseInfo.setCityName(cellValueByCell);
                                
                                if(true){
                                    //市不存在
                                    cellFlag = true;
                                    String realName = "我是来女士 ";
                                    if(StringUtils.isNotEmpty(realName)){
                                        JSONObject comment = new JSONObject();
                                        comment.put("num",a);
                                        comment.put("tex","系统中数据:"+realName);
                                        hasComment = true;
                                        commentList.add(comment);
                                    }
                                }
                            }else if(propertyList.get(a).equals("waterQualityNorm")){// 出水水质标准
                            // 2、此处演示枚举如何由value匹配为key
                                baseInfo.setWaterQualityNorm(waterQualityNormDictMap.getOrDefault(cellValueByCell, null));
                            }else{// 3、此处演示其他字符串
                                setBaseInfoProperty(baseInfo, propertyList.get(a), cellValueByCell);
                            }
                        }
                        if(cellFlag){
                            errorRow.add(a);
                            error = true;
                        }
                    }

                    if(error){
                        lstDatas.add(item);
                        JSONObject errorRowJSON = new JSONObject();
                        errorRowJSON.put("errorRow",errorRow);
                        errorRowJSON.put("hasComment",hasComment);
                        errorRowJSON.put("commentList",commentList);
                        errorRowList.add(errorRowJSON);
                        errorLines++;
                    }else {
                        if(this.save(baseInfo)){

                            successLines++;
                        }else{
                            errorLines++;
                        }
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (errorLines == 0) {
            return Result.ok("共" + successLines + "行数据全部导入成功!");
        } else {
            SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
            Sheet sheet = workbook.createSheet("错误数据");
            ExcelExportUtil writer = new ExcelExportUtil(sheet,workbook);
            List<Integer> cellNum = new ArrayList<>();
            for(int i = 0; i < titleArr.size(); i++){
                cellNum.add(i);
                sheet.setColumnWidth(i, 12 * 256);
            }
            writer.writeTitle(titleArr);
            sheet.createFreezePane( 0, 1, 0, 1 );
            writer.writeData(lstDatas);
            for(int i = 0; i < errorRowList.size(); i++){
                JSONObject errorRowJSON = errorRowList.get(i);
                List<Integer> cellList = (List<Integer>)errorRowJSON.get("errorRow");
                writer.setCellFontColor(false, HSSFColor.RED.index,true,i+1,cellList);
                //批注
                boolean hasComment = errorRowJSON.getBoolean("hasComment");
                if(hasComment){
                    List<JSONObject> commentList = (List<JSONObject>)errorRowJSON.get("commentList");
                    for(JSONObject comment : commentList){
                        writer.setComment(i+1,comment.getIntValue("num"),comment.getString("tex"));
                    }
                }
            }
            FileOutputStream fos = null;
            String dir = uploadPath + File.separator + "temp" + File.separator;
            File f = new File(dir);
            if(!f.exists()){
                f.mkdirs();
            }
            String fileName = UUIDGenerator.generate() +".xlsx";
            try {
                fos = new FileOutputStream(dir+fileName);
                workbook.write(fos);
                fos.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(fos != null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            JSONObject result = new JSONObject(5);
            int totalCount = successLines + errorLines;
            result.put("totalCount", totalCount);
            result.put("errorCount", errorLines);
            result.put("successCount", successLines);
            result.put("msg", "总上传行数:" + totalCount + ",已导入行数:" + successLines + ",错误行数:" + errorLines);
            result.put("fileUrl", "/sys/common/static/" + "temp"+ File.separator+fileName);
            result.put("fileName", fileName);
            result.put("code", 200);
            Result res = Result.ok(result);
            res.setCode(201);
            res.setMessage("文件导入成功,但有错误。");
            return res;
        }
    }

3、service层中的反射方法

/**
     * 用反射,给 entity ,设置其他属性
     * @param baseInfo
     * @param propertyName
     * @param value
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static void setBaseInfoProperty(WsInstallationBaseInfo baseInfo, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = WsInstallationBaseInfo.class.getDeclaredField(propertyName);
        field.setAccessible(true);

        // 看接收实体的属性类型
        Class<?> type=field.getType();
        if(type == String.class){
            if (value instanceof Integer){
                field.set(baseInfo, String.valueOf(value));
            }else if(value instanceof String){
                field.set(baseInfo, value);
            }
        }else if(type == Integer.class){
            if (value instanceof Integer){
                field.set(baseInfo, value);
            }else if(value instanceof String){
                field.set(baseInfo, Integer.valueOf((String)value));
            }
        }
    }

Excel操作的公共类

import cn.hutool.poi.excel.RowUtil;
import cn.hutool.poi.excel.cell.CellUtil;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.framework.common.util.DateUtils;
import org.framework.common.util.ExportExcel;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class ExcelExportUtil {
    private SXSSFWorkbook workbook;
    /** Excel中对应的Sheet */
    private Sheet sheet;
    private CellStyle headCellStyle;
    private CellStyle cellStyle;

    /** 当前行 */
    private AtomicInteger currentRow = new AtomicInteger(0);

    public ExcelExportUtil(Sheet sheet,SXSSFWorkbook workbook) {
        this.workbook = workbook;
        this.sheet = sheet;
        this.headCellStyle = ExportExcel.getTitleStyle(workbook,false);
        this.cellStyle = ExportExcel.getStyle(workbook);
    }

    /**
     * 合并单元格
     * @param firstRow 开始行
     * @param lastRow 结束行
     * @param firstColumn 开始列
     * @param lastColumn 结束列
     * @param content 合并后内容
     * @param isSetHeaderStyle 是否为列头
     * @return
     */
    public ExcelExportUtil merge(int firstRow, int lastRow, int firstColumn, int lastColumn, Object content, boolean isSetHeaderStyle) {
        CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
        sheet.addMergedRegion(region);
        setBorderStyle(region,isSetHeaderStyle?this.headCellStyle:this.cellStyle);

        // 设置内容
        if (null != content) {
            final Cell cell = getOrCreateCell(firstColumn, firstRow);
            generateValue(content, cell,isSetHeaderStyle);
        }
        return this;
    }

    /**
     * 设置合并单元格的边框样式
     * @param region
     * @param cellStyle
     */
    public void setBorderStyle(CellRangeAddress region,CellStyle cellStyle){
        RegionUtil.setBorderBottom(cellStyle.getBorderBottom(), region, sheet, workbook);
        RegionUtil.setBorderLeft(cellStyle.getBorderLeft(), region, sheet, workbook);
        RegionUtil.setBorderRight(cellStyle.getBorderRight(), region, sheet, workbook);
        RegionUtil.setBorderTop(cellStyle.getBorderTop(), region, sheet, workbook);
    }

    /**
     * 获取或创建指定坐标单元格
     *
     * @param x X坐标,从0计数,即列号
     * @param y Y坐标,从0计数,即行号
     */
    public Cell getOrCreateCell(int x, int y) {
        return getCell(x, y, true);
    }

    

    /**
     * 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回<code>null</code>
     *
     * @param x X坐标,从0计数,即列号
     * @param y Y坐标,从0计数,即行号
     * @param isCreateIfNotExist 单元格不存在时是否创建
     */
    public Cell getCell(int x, int y, boolean isCreateIfNotExist) {
        final Row row = isCreateIfNotExist ? RowUtil.getOrCreateRow(this.sheet, y) : this.sheet.getRow(y);
        if (null != row) {
            return isCreateIfNotExist ? CellUtil.getOrCreateCell(row, x) : row.getCell(x);
        }
        return null;
    }


    /**
     * 创建单元格
     * @param row
     * @param cellNum
     * @param value
     */
    public void createCell(Row row, int cellNum, Object value) {
        Cell cell = row.createCell(cellNum);
        generateValue(value, cell,false);
    }

    private void generateValue(Object value, Cell cell,boolean isSetHeaderStyle) {
        if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value);
        } else if (value instanceof Double) {
            cell.setCellValue((Double) value);
        } else if (value instanceof Date) {
            cell.setCellValue((Date) value);
        } else if (value instanceof Calendar) {
            cell.setCellValue((Calendar) value);
        } else if (value instanceof RichTextString) {
            cell.setCellValue((RichTextString) value);
        }else if(value instanceof Integer){
            cell.setCellValue((Integer) value);
        }else{
            cell.setCellValue(value+"");
        }
        cell.setCellStyle(isSetHeaderStyle?this.headCellStyle:this.cellStyle);
    }

    /**
     * 写入标题
     * @param rowData
     * @return
     */
    public ExcelExportUtil writeTitle(Iterable<?> rowData) {
        Row row = this.sheet.createRow(this.currentRow.getAndIncrement());
        int i = 0;
        for (Object value : rowData) {
            this.createCell(row,i,value);
            i++;
        }
        return this;
    }


    /**
     * 写入内容数据
     * @param lstDatas
     * @return
     */
    public ExcelExportUtil writeData(List<List<Object>> lstDatas) {
        if(!ObjectUtils.isEmpty(lstDatas)){
            int rowNum = 0;
            Row row;
            for(List<Object> rowData : lstDatas){
                row = this.sheet.createRow(this.currentRow.getAndIncrement());
                int i = 0;
                for (Object value : rowData) {
                    this.createCell(row,i,value);
                    i++;
                }
                rowNum++;
                //每当行数达到设置的值就刷新数据到硬盘,以清理内存
                if(rowNum / 1000 == 0){
                    try {
                        ((SXSSFSheet)sheet).flushRows(1000);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return this;
    }

    /**
     * 设置单元格字体颜色
     * @param isTitle 是否为列头
     * @param color 颜色值
     * @param bold 字体是否加粗
     * @param row 行号
     * @param cellNum 单元格号
     */
    public void setCellFontColor(boolean isTitle,short color,boolean bold,int row, List<Integer> cellNum) {
        CellStyle style = isTitle ? ExportExcel.getTitleStyle(workbook,false) : ExportExcel.getStyle(workbook);
        Font font = ExportExcel.getFont(workbook,bold);
        font.setColor(color);
        style.setFont(font);
        for(int c : cellNum){
            Cell cell = this.getCell(c,row,false);
            if(cell != null){
                cell.setCellStyle(style);
            }
        }
    }


    public static String getCellValueByCell(Cell cell) {
        //判断是否为null或空串
        if (cell == null || cell.toString().trim().equals("") || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
            return "";
        }
        String cellValue = "";
        int cellType=cell.getCellType();

        switch (cellType) {
            case Cell.CELL_TYPE_STRING: //字符串类型
                cellValue= cell.getStringCellValue().trim();
                break;
            case Cell.CELL_TYPE_BOOLEAN:  //布尔类型
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_NUMERIC: //数值类型
                if (HSSFDateUtil.isCellDateFormatted(cell)) {  //判断日期类型
                    cellValue = DateUtils.formatDate(cell.getDateCellValue(), "yyyy-MM-dd");
                } else {  //否
                    cellValue = new DecimalFormat("#.######").format(cell.getNumericCellValue());
                }
                break;
            default: //其它类型,取空串吧
                cellValue = "";
                break;
        }
        return cellValue;
    }

    /**
     * 给单元格设置批注
     * @param rowNum 行号
     * @param cellNum 列号
     * @param richText 批注内容
     */
    public void setComment(int rowNum, int cellNum,String richText){
        Cell cell = this.getCell(cellNum,rowNum,false);
        Drawing p = sheet.createDrawingPatriarch();
        XSSFClientAnchor clientAnchor = new XSSFClientAnchor(0,0,0,0,cellNum,rowNum,cellNum,rowNum);
        Comment comment = p.createCellComment(clientAnchor);
        // 输入批注信息
        comment.setString(new XSSFRichTextString(richText));
        cell.setCellComment(comment);
    }

}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;