poi导入导出

poi导出:

pom文件:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>

接口:

@GetMapping("/poiExport")
     public void poiExport(HttpServletResponse response, HttpServletRequest request);

实现类:

 @Override
    public void poiExport(HttpServletResponse response, HttpServletRequest request) {
        //poi导出其实和poi下载模板没有什么区别,多了插入数据而已
        String [] excelHeader = {"原零件号","原零件名称","参考零件号","参考零件名称","长","宽"};
        //数据可以从数据库读取
        List<Object> list = new ArrayList<>();
        Object[] obj1 = {"张三","173*****311‬","a1","A","IOS","是"};
        Object[] obj2 = {"李四","138*****742","a2","B","安卓","否"};
        list.add(obj1);
        list.add(obj2);
        FileExport.exportExcel(excelHeader, list, "下载模板", response, request);
    }
    

工具类代码:

public class FileExport {

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

    /** CSV文件列分隔符 */
    private static final String CSV_COLUMN_SEPARATOR = ",";

    private static final String CSV_COLUM_TABLE = "\t";

    /** CSV文件列分隔符 */
    private static final String CSV_RN = "\r\n";

    /**
     * 导出Excel文件
     *
     * @param excelHeader
     *            导出文件中表格头
     * @param list
     *            导出的内容
     * @param response
     *            HttpServletResponse对象,用来获得输出流向客户端写导出的文件
     * @param sheetName
     *            Excel的sheet名称,加上时间戳作为导出文件的名称
     */
    public static void exportExcel(String [] excelHeader, List<Object> list, String sheetName, HttpServletResponse response, HttpServletRequest request) {
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet(sheetName);
        HSSFRow row = sheet.createRow((int) 0);
        /******设置单元格是否显示网格线******/
        sheet.setDisplayGridlines(true);

        /******设置头单元格样式******/
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        Font fontHeader = wb.createFont();
        fontHeader.setBold(true);
        fontHeader.setFontHeight((short) 240);
        style.setFont(fontHeader);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);

        /******设置头内容******/
        for (int i = 0; i < excelHeader.length; i++) {
            HSSFCell cell = row.createCell(i);
            //cell.setCellValue("  " +excelHeader[i] + "  ");
            cell.setCellValue(excelHeader[i]);
            cell.setCellStyle(style);
        }

        /******设置内容单元格样式******/
        HSSFCellStyle styleCell = wb.createCellStyle();
        Font fontCell = wb.createFont();
        //fontCell.setColor(HSSFColor.BLACK.index);
        styleCell.setAlignment(HorizontalAlignment.CENTER);
        styleCell.setFont(fontCell);
        styleCell.setBorderBottom(BorderStyle.THIN);
        styleCell.setBorderLeft(BorderStyle.THIN);
        styleCell.setBorderRight(BorderStyle.THIN);
        styleCell.setBorderTop(BorderStyle.THIN);
        /******设置单元格内容******/
        for (int i = 0; i < list.size(); i++) {
            row = sheet.createRow(i + 1);
            /******设置行高******/
            row.setHeightInPoints(20);
            Object[] obj = (Object[]) list.get(i);
            for (int j = 0; j < excelHeader.length; j++) {
                styleCell.setWrapText(false);
                HSSFCell cell = row.createCell(j);
                if (obj[j] != null){
                    cell.setCellValue(obj[j].toString());
                }else{
                    cell.setCellValue("");
                }
                //if(obj[j].toString().length()>20)
                //	styleCell.setWrapText(true);
                cell.setCellStyle(styleCell);
                sheet.autoSizeColumn(j);
            }
        }

        OutputStream ouputStream = null;
        try {

            String encoding = "UTF-8";
            /** 获取浏览器相关的信息 */
            String userAgent = request.getHeader("user-agent");
            /** 判断是否为msie浏览器 */
            /*if (userAgent.toLowerCase().indexOf("msie") != -1){
                encoding = "gbk";
            }*/

            response.setCharacterEncoding(encoding);
            response.setContentType("application/vnd.ms-excel");
            //String fileName = sheetName;
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMMSS");
            //fileName += (dateFormat.format(new Date())).toString()+".xls";
            String fileName =(dateFormat.format(new Date())).toString()+".xls";
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, encoding));
            ouputStream = response.getOutputStream();
            wb.write(ouputStream);
            ouputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(ouputStream!=null) {
                    ouputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 导出CSV文件
     * @param dataList 集合数据
     * @param colNames 表头部数据
     * @param mapKey 查找的对应数据
     */
    public static boolean doExport(List<Map<String, Object>> dataList, String colNames, String mapKey, OutputStream os) {
        try {
            StringBuffer buf = new StringBuffer();

            String[] colNamesArr = null;
            String[] mapKeyArr = null;

            colNamesArr = colNames.split(",");
            mapKeyArr = mapKey.split(",");

            /******完成数据csv文件的封装******/
            /******输出列头******/
            for (int i = 0; i < colNamesArr.length; i++) {
                buf.append(colNamesArr[i]).append(CSV_COLUMN_SEPARATOR);
            }
            buf.append(CSV_RN);

            if (null != dataList) {
                /******输出数据******/
                for (int i = 0; i < dataList.size(); i++) {
                    for (int j = 0; j < mapKeyArr.length; j++) {
                        buf.append(dataList.get(i).get(mapKeyArr[j])).append(CSV_COLUM_TABLE).append(CSV_COLUMN_SEPARATOR);
                    }
                    buf.append(CSV_RN);
                }
            }
            /******写出响应******/
            os.write(buf.toString().getBytes("GBK"));
            os.flush();
            return true;
        } catch (Exception e) {
            logger.error("doExport错误...", e);
        }
        return false;
    }

    /**
     * 设置响应格式
     * @param fileName
     * @param response
     * @throws UnsupportedEncodingException
     */
    public static void responseSetProperties(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        /******设置文件后缀******/
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String fn = fileName + sdf.format(new Date()).toString() + ".csv";
        /******读取字符编码******/
        String utf = "UTF-8";

        /******设置响应******/
        response.setContentType("application/ms-txt.numberformat:@");
        response.setCharacterEncoding(utf);
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "max-age=30");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fn, utf));
    }
}

项目运行,生成后的文件打开可以看到

poi导入导出

poi导入:

我们把上面生成的excel导入进来

接口:

@RequestMapping(value = "/poiImport",method = RequestMethod.POST)
     public void poiImport(HttpServletRequest request,@RequestParam("file") MultipartFile file) throws IOException;

实现类:

 @Override
    public void poiImport(HttpServletRequest request,@RequestParam("file") MultipartFile file) throws IOException {
        Map<String, Object> map = new HashMap<String, Object>();
        // 判断文件是否为空
       if (!StringUtils.isEmpty(file)) {
            try {
                List<RefPartDo> excelBeans = FileImport.readExcel(file, RefPartDo.class);
                System.out.println(excelBeans.size());
                for(RefPartDo ep : excelBeans){
                    System.out.println(ep.toString());
                }
                //........逻辑
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
    }

实体类:

@Data
public class RefPartDo {

    @ExcelColumn("原零件号")
    private String partNo;

    @ExcelColumn("原零件名称")
    private String partName;

    @ExcelColumn("参考零件号")
    private String refPartNo;

    @ExcelColumn("参考零件名称")
    private String refPartName;;

    @ExcelColumn("长")
    private String length;
    
    @ExcelColumn("宽")
    private String width;
    
}

自定义注解:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelColumn{

    public String value() default "";
}

工具类:

public class FileImport {

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0");// 格式化 number为整

    private static final DecimalFormat DECIMAL_FORMAT_PERCENT = new DecimalFormat("##.00%");//格式化分比格式,后面不足2位的用0补齐

//	private static final DecimalFormat df_per_ = new DecimalFormat("0.00%");//格式化分比格式,后面不足2位的用0补齐,比如0.00,%0.01%

//	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); // 格式化日期字符串

    private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance("yyyy/MM/dd");

    private static final DecimalFormat DECIMAL_FORMAT_NUMBER  = new DecimalFormat("0.00E000"); //格式化科学计数器

    private static final Pattern POINTS_PATTERN = Pattern.compile("0.0+_*[^/s]+"); //小数匹配

    /**
     * 对外提供读取excel 的方法
     * @param file
     * @return
     * @throws IOException
     */
    public static List<List<Object>> readExcel(MultipartFile file) throws IOException {
        String extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase();
        if(Objects.equals("xls", extension) || Objects.equals("xlsx", extension)) {
            return readExcel(file.getInputStream());
        } else {
            throw new IOException("不支持的文件类型");
        }
    }

    /**
     * 对外提供读取excel 的方法
     * @param file
     * @param cls
     * @return
     * @throws IOException
     */
    public static <T> List<T> readExcel(MultipartFile file, Class<T> cls) throws IOException {
        String extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase();
        if(Objects.equals("xls", extension) || Objects.equals("xlsx", extension)) {
            return readExcel(file.getInputStream(), cls);
        } else {
            throw new IOException("不支持的文件类型");
        }
    }

    /**
     * 读取 office excel
     *
     * @param stream
     * @return
     * @throws IOException
     */
    private static List<List<Object>> readExcel(InputStream inputStream) throws IOException {
        List<List<Object>> list = new LinkedList<>();
        Workbook workbook = null;
        try {
            workbook = WorkbookFactory.create(inputStream);
            int sheetsNumber = workbook.getNumberOfSheets();
            for (int n = 0; n < sheetsNumber; n++) {
                Sheet sheet = workbook.getSheetAt(n);
                Object value = null;
                Row row = null;
                Cell cell = null;
                for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getPhysicalNumberOfRows(); i++) { // 从第二行开始读取
                    row = sheet.getRow(i);
                    if (StringUtils.isEmpty(row)) {
                        continue;
                    }
                    List<Object> linked = new LinkedList<>();
                    for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                        cell = row.getCell(j);
                        if (StringUtils.isEmpty(cell)) {
                            continue;
                        }
                        value = getCellValue(cell);
                        linked.add(value);
                    }
                    list.add(linked);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(workbook);
            IOUtils.closeQuietly(inputStream);
        }
        return list;
    }

    /**
     * 获取excel数据 将之转换成bean
     *
     * @param path
     * @param cls
     * @param <T>
     * @return
     */
    private static <T> List<T> readExcel(InputStream inputStream, Class<T> cls) {
        List<T> dataList = new LinkedList<T>();
        Workbook workbook = null;
        try {
            workbook = WorkbookFactory.create(inputStream);
            Map<String, List<Field>> classMap = new HashMap<String, List<Field>>();
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                if (annotation != null) {
                    String value = annotation.value();
                    if (!classMap.containsKey(value)) {
                        classMap.put(value, new ArrayList<Field>());
                    }
                    field.setAccessible(true);
                    classMap.get(value).add(field);
                }
            }
            Map<Integer, List<Field>> reflectionMap = new HashMap<Integer, List<Field>>();
            int sheetsNumber = workbook.getNumberOfSheets();
            for (int n = 0; n < sheetsNumber; n++) {
                Sheet sheet = workbook.getSheetAt(n);
                for (int j = sheet.getRow(0).getFirstCellNum(); j < sheet.getRow(0).getLastCellNum(); j++) { //首行提取注解
                    Object cellValue = getCellValue(sheet.getRow(0).getCell(j));
                    if (classMap.containsKey(cellValue)) {
                        reflectionMap.put(j, classMap.get(cellValue));
                    }
                }
                Row row = null;
                Cell cell = null;
                for (int i = sheet.getFirstRowNum() + 1; i < sheet.getPhysicalNumberOfRows(); i++) {
                    row = sheet.getRow(i);
                    T t = cls.newInstance();
                    for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
                        cell = row.getCell(j);
                        if (reflectionMap.containsKey(j)) {
                            Object cellValue = getCellValue(cell);
                            List<Field> fieldList = reflectionMap.get(j);
                            for (Field field : fieldList) {
                                try {
                                    field.set(t, cellValue);

                                  /*  if(cellValue instanceof String){
                                       field.set(t, cellValue);
                                    }
                                    if(cellValue instanceof Double){
                                        field.setDouble(t, (Double) cellValue);
                                    }
                                    if(cellValue instanceof Integer){
                                        field.setInt(t, (Integer) cellValue);
                                    }*/
                                } catch (Exception e) {
                                    //logger.error()
                                }
                            }
                        }
                    }
                    dataList.add(t);
                }
            }
        } catch (Exception e) {
            dataList = null;
        } finally {
            IOUtils.closeQuietly(workbook);
            IOUtils.closeQuietly(inputStream);
        }
        return dataList;
    }

    /**
     * 获取excel 单元格数据
     *
     * @param cell
     * @return
     */
    private static Object getCellValue(Cell cell) {
        Object value = null;
        switch (cell.getCellTypeEnum()) {
            case _NONE:
                break;
            case STRING:
                value = cell.getStringCellValue();
                break;
            case NUMERIC:
                if(DateUtil.isCellDateFormatted(cell)){ //日期
                    value = FAST_DATE_FORMAT.format(DateUtil.getJavaDate(cell.getNumericCellValue()));//统一转成 yyyy/MM/dd
                } else if("@".equals(cell.getCellStyle().getDataFormatString())
                        || "General".equals(cell.getCellStyle().getDataFormatString())
                        || "0_ ".equals(cell.getCellStyle().getDataFormatString())){
                    //文本  or 常规 or 整型数值
                    //value = DECIMAL_FORMAT.format(cell.getNumericCellValue());
                    value = cell.getNumericCellValue();
                } else if(POINTS_PATTERN.matcher(cell.getCellStyle().getDataFormatString()).matches()){ //正则匹配小数类型
                    value = cell.getNumericCellValue();  //直接显示
                } else if("0.00E+00".equals(cell.getCellStyle().getDataFormatString())){//科学计数
                    value = cell.getNumericCellValue();	//待完善
                    value = DECIMAL_FORMAT_NUMBER.format(value);
                } else if("0.00%".equals(cell.getCellStyle().getDataFormatString())){//百分比
                    value = cell.getNumericCellValue(); //待完善
                    value = DECIMAL_FORMAT_PERCENT.format(value);
                } else if("# ?/?".equals(cell.getCellStyle().getDataFormatString())){//分数
                    value = cell.getNumericCellValue();
                } else { //货币
                    value = cell.getNumericCellValue();
                    value = DecimalFormat.getCurrencyInstance().format(value);
                }
                break;
            case BOOLEAN:
                value = cell.getBooleanCellValue();
                break;
            case BLANK:
                //value = ",";
                break;
            default:
                value = cell.toString();
        }
        return value;
    }
}

postman导入文件:控制台可以看到

poi导入导出

PS:问题

1.导入的时候,如果你把实体类字段类型改为非 String  类型,你会发现工具类解析不了,工具类相关代码也有注释,我有尝试去修改工具类,也不行。大佬看到的话可以指点一下

2. 如果你是自己定义的表格,后台如果解析不成功的话,可以看看列名是否有空格,有空格的话,是解析不了的。

参考帖子:https://blog.csdn.net/phil_jing/article/details/78307819

可能解决该问题的帖子:https://www.yuque.com/calmer/blog/java-poi#zg9evr

上一篇:一种城市居住区划配套设施完备情况的评估模型


下一篇:IPC技术_Windows平台_C#写入_C++读取