天天看點

POI導入導出

利用poi可以實作excel檔案導入和導出功能   本例子結合了springboot做demo

pom檔案

<properties>
    <java.version>1.8</java.version>

</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>1.5.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-freemarker -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
        <version>1.5.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.16</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.16</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>3.16</version>
    </dependency>



</dependencies>
      

一個demo的controller類

@RestController
public class DemoController {
    private final Logger LOGGER = LoggerFactory.getLogger(DemoController.class);

    @RequestMapping("upload")
    public Object upload(@PathVariable("file") MultipartFile file) throws Exception {
        if (file == null || file.getInputStream() == null) {
            LOGGER.error("檔案上傳失敗");
            return "檔案上傳失敗";
        }

        if (file.getSize() > 5 * 1024 * 1024) {
            LOGGER.error("檔案太大,上傳失敗");
            return "檔案太大,上傳失敗";
        }
        FileTypeUtil.FileType fileType = FileTypeUtil.getFileType(file.getInputStream());
        //XLS_DOC --》2007之前的excel類型  XLSX_DOCX--》  2007之後的excel類型
        if (fileType == FileTypeUtil.FileType.XLS_DOC) {
            LOGGER.info("開始解析XLS_DOC檔案");
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook(file.getInputStream());
            List<User> getData = readOldExcel(hssfWorkbook);
            if (getData == null) {
                LOGGER.error("解析失敗...");
                return "檔案資料解析失敗";
            }
            LOGGER.info("資料解析成功");
            file.getInputStream().close();
            return getData;
        } else if (fileType == FileTypeUtil.FileType.XLSX_DOCX) {
            LOGGER.info("開始解析XLSX_DOCX檔案");
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file.getInputStream());
            List<User> getData = readExcel(xssfWorkbook);
            if (getData == null) {
                LOGGER.error("解析失敗...");
                return "檔案資料解析失敗";
            }
            LOGGER.info("資料解析成功");
            file.getInputStream().close();
            return getData;
        } else {
            LOGGER.error("上傳檔案類型不正确");
            return "檔案類型不正确";
        }

    }

    @RequestMapping("download")
    public void  download(HttpServletResponse response) throws Exception {
        //擷取模闆的輸入流
        InputStream inputStream = UploadController.class.getClassLoader().getResourceAsStream("templates" + File.separator + "xx.xlsx");
        if (inputStream == null) {
            LOGGER.error("模闆檔案的路徑不正确");

        }
        //測試資料
        List<User> users = new ArrayList<User>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId(i + 1);
            user.setUsername("張三" + i + 1);
            user.setPassword("123" + i + 1);
            users.add(user);
        }
        //擷取模闆的工作薄
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        XSSFSheet sheetAt = workbook.getSheetAt(0);
        XSSFRow row = sheetAt.getRow(0);
        short rowHeight = row.getHeight();
        XSSFRow row1 = null;
        XSSFCell cell = null;
        for (int j = 0; j < users.size(); j++) {
            User user = users.get(j);
            row1 = sheetAt.createRow(j + 1);
            row1.setHeight(rowHeight);
            cell = row1.createCell(0);
            cell.setCellValue(user.getId());

            cell = row1.createCell(1);
            cell.setCellValue(user.getUsername());

            cell = row1.createCell(2);
            cell.setCellValue(user.getPassword());
        }
        String filename = new String("檔案".getBytes("UTF-8"),"ISO8859-1");
        LOGGER.info("檔案名"+filename);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename="+filename+".xlsx");
        workbook.write(response.getOutputStream());
        LOGGER.info("檔案下載下傳成功!!");
        response.getOutputStream().flush();
        response.getOutputStream().close();
        workbook.close();


    }

    //處理2007之前的excel
    private List<User> readOldExcel(HSSFWorkbook hssfWorkbook) {
        List<User> users = new ArrayList<User>();
        HSSFSheet sheetAt = hssfWorkbook.getSheetAt(0);
        HSSFCell cell = null;
        HSSFRow row = null;
        for (int i = sheetAt.getFirstRowNum(); i < sheetAt.getPhysicalNumberOfRows(); i++) {
            row = sheetAt.getRow(i);
            if (row == null) {
                LOGGER.warn("擷取到一個空行-------》》》》》》" + i + "行");
                continue;
            }
            Object[] objects = new Object[row.getLastCellNum()];
            for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
                cell = row.getCell(j);
                switch (cell.getCellTypeEnum()) {
                    case STRING:
                        objects[j] = cell.getStringCellValue();
                        System.out.println(cell.getStringCellValue());
                        break;
                    case _NONE:
                        objects[j] = "";
                        break;
                    case BOOLEAN:
                        objects[j] = cell.getBooleanCellValue();
                        System.out.println(cell.getBooleanCellValue());
                        break;
                    case NUMERIC:
                        //處理double類型的  1.0===》1
                        DecimalFormat df = new DecimalFormat("0");
                        String s = df.format(cell.getNumericCellValue());
                        objects[j] = s;
                        System.out.println(s);
                        break;
                    default:
                        objects[j] = cell.toString();
                }
            }
            //處理資料
            if (objects != null) {
                User user = new User();
                user.setId(Integer.parseInt(objects[0].toString()));
                user.setUsername((String) objects[1]);
                user.setPassword(objects[2].toString());
                users.add(user);
            }
        }
        return users;
    }


    //處理2007之後的excel
    private List<User> readExcel(XSSFWorkbook xssfWorkbook) {
        List<User> users = new ArrayList<User>();
        //獲得excel第一個工作薄
        XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
        //行
        XSSFRow row = null;
        //列
        XSSFCell cell = null;
        for (int i = sheet.getFirstRowNum(); i < sheet.getPhysicalNumberOfRows(); i++) {
            //擷取每一行
            row = sheet.getRow(i);
            //判斷是否出現空行
            if (row == null) {
                LOGGER.warn("擷取到一個空行-------》》》》》》" + i + "行");
                continue;
            }
            Object[] objects = new Object[row.getLastCellNum()];
            for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
                cell = row.getCell(j);

                if (cell == null) {
                    LOGGER.warn("擷取到一個空列------------》》》》》》" + j + "列");
                    continue;
                }
                //第一行資料
                switch (cell.getCellTypeEnum()) {
                    case STRING:
                        objects[j] = cell.getStringCellValue();
                        System.out.println(cell.getStringCellValue());
                        break;
                    case _NONE:
                        objects[j] = "";
                        break;
                    case BOOLEAN:
                        objects[j] = cell.getBooleanCellValue();
                        System.out.println(cell.getBooleanCellValue());
                        break;
                    case NUMERIC:
                        //處理double類型的  1.0===》1
                        DecimalFormat df = new DecimalFormat("0");
                        String s = df.format(cell.getNumericCellValue());
                        objects[j] = s;
                        System.out.println(s);
                        break;
                    default:
                        objects[j] = cell.toString();
                }

            }
            //處理資料
            if (objects != null) {
                User user = new User();
                user.setId(Integer.parseInt(objects[0].toString()));
                user.setUsername((String) objects[1]);
                user.setPassword(objects[2].toString());
                users.add(user);
            }

        }
        return users;
    }

    //處理excel中的圖檔 2007之後  ---》擷取   String裡面儲存着  這個圖檔的坐标
    private Map<String, PictureData> getExcelPic(XSSFWorkbook xssfWorkbook, XSSFSheet xssfSheet) {
        Map<String, PictureData> map = new HashMap<String, PictureData>();
        for (POIXMLDocumentPart poixmlDocument : xssfWorkbook.getRelations()) {
            if (poixmlDocument instanceof XSSFDrawing) {
                //拿到 drawing
                XSSFDrawing xssfDrawing = (XSSFDrawing) poixmlDocument;
                //拿到所有的圖形
                List<XSSFShape> shapes = xssfDrawing.getShapes();
                for (XSSFShape xssfShape : shapes) {
                    if (xssfShape instanceof XSSFPicture) {
                        //拿到picture
                        XSSFPicture xssfPicture = (XSSFPicture) xssfShape;
                        //拿到anchor  這裡存在 圖檔的坐标
                        XSSFClientAnchor size = xssfPicture.getPreferredSize();
                        int row1 = size.getRow1();
                        short col1 = size.getCol1();
                        //自定義一個坐标
                        String xy = String.valueOf(row1) + "_" + String.valueOf(col1);
                        map.put(xy, (PictureData) xssfPicture.getPictureData());
                    }
                }
            }
        }
        return map;
    }

    //處理excel中的圖檔 2007之前
    private Map<String, PictureData> getOldExcelPic(HSSFWorkbook hssfWorkbook, HSSFSheet hssfSheet) {
        Map<String, PictureData> map = new HashMap<String, PictureData>();
        //需要先擷取 所有的圖檔  通過 workbook
        List<HSSFPictureData> pictures = hssfWorkbook.getAllPictures();
        if (pictures.size() > 0) {
            //通過sheet 獲得sheet裡面所有的 shape
            List<HSSFShape> children = hssfSheet.getDrawingPatriarch().getChildren();
            for (HSSFShape hssfShape : children) {
                //通過shape 獲得anchor  來擷取圖檔坐标
                HSSFAnchor anchor = hssfShape.getAnchor();
                if (hssfShape instanceof HSSFPicture) {
                    //獲得picture
                    HSSFPicture hssfPicture = (HSSFPicture) hssfShape;
                    //2007之前的需要通過   picture的索引 ----》  在全局的圖檔資訊裡面擷取圖檔資料
                    int i = hssfPicture.getPictureIndex() - 1;
                    //獲得圖檔資料
                    HSSFPictureData hssfPictureData = pictures.get(i);
                    //拿到圖檔的坐标
                    String xy = anchor.getDx1() + "_" + anchor.getDy1();
                    map.put(xy, (PictureData) hssfPictureData);
                }
            }
            return map;
        } else {
            return null;
        }
    }
}