简介

  • 一种用java代码读写文档(Excel、word、PPT)的方式

    读写Excel方面

  • 针对不同的Excel版本,要采用不同的工具类。
    • HSSFWorkbook:操作Excel2003以前的版本,扩展名为.xls
    • XSSFWorkbook:操作2007的版本,扩展名是.xlsx
  • 如果版本匹配错了,会抛出异常:
    • org.apache.poi.openxml4j.exceptions.InvalidOperationException
    • org.apache.poi.poifs.filesystem.OfficeXmlFileException
  • 从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的API—-SXSSF
  • 当数据量超出65536条后,在使用HSSFWorkbook或XSSFWorkbook,程序会报OutOfMemoryError:Javaheap space;内存溢出错误。这时应该用SXSSFworkbook。

    参考文章

    读取各种文档的类

  • HSSF–读写.xls格式文档
  • XSSF–读写.xlsx格式文档
  • HWPF–读写.doc格式文档
  • HSLF–读写PPT

    工作簿概念

  • 打个比方,工作簿就像一本书或者一本账册,工作表就像其中的一张或一篇。工作簿中包含一个或多个工作表,工作表依托于工作簿存在。
  • 新建Excel文档(.xls)其实就是新建工作簿,然后在里面可以有sheet1、sheet2等等。

    代码实例

  • 一个较为复杂的例子

    public void excel() throws Exception{
        String excelName = year+"泛珠赛全国总决赛终评评委打分审核表("+model+")"; //工作簿名称
        Workbook wb = new HSSFWorkbook();
        Map<String, CellStyle> styles = createStyles(wb); //设置各种单元格对应的样式
        for (int i = 0; i < pingweiList.size(); i++) {
            //创建Excel表格
            CreatePingweiScore(wb, styles, headers,pingweiList.get(i), model,year);
        }
    
        // 写出
        String file = excelName+".xls"; //文件命名
        FileOutputStream out  = new FileOutputStream(file);
        wb.write(out);
        out.close();
    }
    
    /* 
    * 设置各种单元格对应的样式
    * (基本上样式都是应用于单元格的,没见过应用在行上的顶多设置下行高这样)
    */
    private static Map<String, CellStyle> createStyles(Workbook wb){
        Map<String, CellStyle> styles = new HashMap<>();
        CellStyle style;
    
        /*设置标题格式*/
        Font titleFont = wb.createFont();
        //字号
        titleFont.setFontHeightInPoints((short)18);
        //加粗
        titleFont.setBold(true);
        //设置单元格样式
        style = wb.createCellStyle();
        //水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //将字体样式加入到样式当中
        style.setFont(titleFont);
        //将样式应用到标题当中
        styles.put("title", style);
    
        /*设置表头格式*/
        Font monthFont = wb.createFont();
        monthFont.setFontHeightInPoints((short)11);
        monthFont.setBold(true);
        //字体颜色
        monthFont.setColor(IndexedColors.BLACK.getIndex());
        style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFont(monthFont);
        //自动换行
        style.setWrapText(true);
        //应用到表头
        styles.put("header", style);
    
        /*设置单元格*/
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setWrapText(true);
        //右边框
        cellStyle.setBorderRight(BorderStyle.THIN);
        //右边框颜色
        cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        //应用到单元格
        styles.put("cell", cellStyle);
    
        return styles;//styles:应用单元-单元属性的Map集合
    }
    
    /*
    * 设置Excel表格
    */
    private int CreatePingweiScore(Workbook wb, Map<String, CellStyle> styles,
                               String[] headers,String pid, String model,int year){
        //所有作品的分
        List<PingweiScore> pingweiScoreList =
                pingweiScoreService.selectByPidAndModelAndYear(pid,model,year);
    
        String titleName = year+"泛珠赛全国总决赛终评评委打分审核表("+model+")";
        String pingweiName = "评委"+pid;
    
        //打印设置
        Sheet sheet = wb.createSheet(pingweiName); //pingweiName为表名
        PrintSetup printSetup = sheet.getPrintSetup();
        printSetup.setLandscape(true); //true表示页面方向为横向,false为纵向
        sheet.setFitToPage(true);
        sheet.setHorizontallyCenter(true);
    
        //title row
        Row titleRow = sheet.createRow(0);
        titleRow.setHeightInPoints(45);
        Cell titleCell = titleRow.createCell(0);
        titleCell.setCellValue(titleName);
        titleCell.setCellStyle(styles.get("title"));
        sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$J$1")); //从A1到J1单元格合并;可以直接CellRangeAddress(起始行,终止行,起始列,终止列)
    
        //Second row
        Row secondRow = sheet.createRow(1);
        secondRow.setHeightInPoints(40); //行高
        Cell secondCell = secondRow.createCell(0);
        secondCell.setCellValue("评委编号:"+pid+"          评委签名:");
        secondCell.setCellStyle(styles.get("header")); //设置单元格样式
        sheet.addMergedRegion(CellRangeAddress.valueOf("$A$2:$J$2")); //合并单元格,前面设置的样式都应用到了这些单元格上了
    
        //header row
        Row headerRow = sheet.createRow(2);
        headerRow.setHeightInPoints(40);
        Cell headerCell;
        for (int i = 0; i < headers.length; i++) {
            headerCell = headerRow.createCell(i);
            headerCell.setCellValue(headers[i]);
            headerCell.setCellStyle(styles.get("header"));
        }
    
        //评委分数
        int rownum = 3; //前三列为固定值先不管
        for (int i = 0; i < pingweiScoreList.size(); i++) {
            Row row = sheet.createRow(rownum++);
            for (int j = 0; j < headers.length; j++) {
                Cell cell = row.createCell(j);
                //逐项分数写入
                switch (j){
                    case 0: cell.setCellValue(pingweiScoreList.get(i).getProId());break;
                    case 1: cell.setCellValue(pingweiScoreList.get(i).getBianHao());break;
                    case 2: cell.setCellValue(pingweiScoreList.get(i).getProName());break;
                    case 3: cell.setCellValue(pingweiScoreList.get(i).getOption1());break;
                    case 4: cell.setCellValue(pingweiScoreList.get(i).getOption2());break;
                    case 5: cell.setCellValue(pingweiScoreList.get(i).getOption3());break;
                    case 6: cell.setCellValue(pingweiScoreList.get(i).getOption4());break;
                    case 7: cell.setCellValue(pingweiScoreList.get(i).getOption5());break;
                    case 8: cell.setCellValue(pingweiScoreList.get(i).getOption6());break;
                    case 9: cell.setCellValue(pingweiScoreList.get(i).getTotalScore());break;
                }
            }
        }
    
        //所有行第1~3列的宽度,分别用来填写序号、作品编号和作品名称
        sheet.setColumnWidth(0, 10*256); //10 characters wide
        sheet.setColumnWidth(1, 10*256); //10 characters wide
        sheet.setColumnWidth(2, 30*256); //30 characters wide
        //后面列的宽度
        for (int i = 3; i < headers.length; i++) {
            sheet.setColumnWidth(i, 9*256); //9 characters wide
        }
        return  0;
    

    }

  • 其中write(Outputstream)为HSSFWork唯一写出方法

    一些样式设置参考

    解析Excel保存到数据库

    public class ResolveExcelServiceImpl implements ResolveExcelService {
    
        private static final String SUFFIX_2003=".xls";
        private static final String SUFFIX_2007=".xlsx";
    
        @Override
        public List<Works> resolveExcel(MultipartFile file) throws BusinessException {
            List<Works> list=new ArrayList<Works>();
            if(file==null){
                throw new BusinessException(ReturnCode.CODE_FAIL,"文件不存在!");
            }
            //获取文件名
            String originalFilename=file.getOriginalFilename();
            Workbook workbook=null;
            //判断格式
            try{
                if(originalFilename.endsWith(SUFFIX_2003)){
                    /*
                    getInputStream()返回InputStream
                    经测试,全部文件都返回ByteArrayInputStream
                    */
                    workbook=new HSSFWorkbook(file.getInputStream());
                }else if(originalFilename.endsWith(SUFFIX_2007)){  //不知道为什么这种格式会抛异常
                    workbook=new XSSFWorkbook(file.getInputStream());
                }
            }catch (Exception e){
                e.printStackTrace();
                throw new BusinessException(ReturnCode.CODE_FAIL,"格式错误!");
            }
            if(null==workbook){
                throw new BusinessException(ReturnCode.CODE_FAIL,"格式错误!");
            }else{
                //获取所有工作表的数量
                int numOfSheet=workbook.getNumberOfSheets();
                //遍历这些表
                for(int i=0;i<numOfSheet;i++){
                    //获取一个sheet
                    Sheet sheet=workbook.getSheetAt(i);
                    int lastRowNum=sheet.getLastRowNum();
                    //从第三行开始,第1行一般是标题,第二行是表头
                    for(int j=2;j<=lastRowNum;j++){
                        Row row=sheet.getRow(j);
                        Works works=new Works();
                        //获取序号单元格
                        if(row.getCell(0)!=null){
                            row.getCell(0).setCellType(Cell.CELL_TYPE_STRING);
                            //获取单元格内容(将内容当做字符串处理)
                            String code=row.getCell(0).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^\\d{1,2}$",code);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"序号错误!");
                            }
                            works.setCode(code);
                        }
                        //编号
                        if(row.getCell(1)!=null){
                            row.getCell(1).setCellType(Cell.CELL_TYPE_STRING);
                            String bianHao=row.getCell(1).getStringCellValue();
                            //校验编号长度
                            boolean matche=Pattern.matches("^\\d{6}$",bianHao);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"序号错误!");
                            }
                            works.setBianHao(bianHao);
                        }
                        //名称
                        if(row.getCell(2)!=null){
                            row.getCell(2).setCellType(Cell.CELL_TYPE_STRING);
                            String name=row.getCell(2).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^[\\u4E00-\\u9FA5\\w\\-\\——]{1,}$",name);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"作品名称错误!");
                            }
                            works.setName(name);
                        }
                        //分赛区
                        if(row.getCell(3)!=null){
                            row.getCell(3).setCellType(Cell.CELL_TYPE_STRING);
                            String district=row.getCell(3).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^[\\u4E00-\\u9FA5]{1,}$",district);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"分赛区名称错误!");
                            }
                            works.setPartName(district);
                        }
                        //学校
                        if(row.getCell(4)!=null){
                            row.getCell(4).setCellType(Cell.CELL_TYPE_STRING);
                            String school=row.getCell(4).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^[\\u4E00-\\u9FA5]{1,}$",school);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"学校名称错误!");
                            }
                            works.setSchool(school);
                        }
                        //指导老师
                        if(row.getCell(5)!=null){
                            row.getCell(5).setCellType(Cell.CELL_TYPE_STRING);
                            String teachers=row.getCell(5).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^[\\u4E00-\\u9FA5\\s,,、]{1,}$",teachers);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"老师姓名格式错误!");
                            }
                            works.setTeachers(teachers);
                        }
                        //学生
                        if(row.getCell(6)!=null){
                            row.getCell(6).setCellType(Cell.CELL_TYPE_STRING);
                            String students=row.getCell(6).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^[\\u4E00-\\u9FA5\\s,,、]{1,}$",students);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"学生姓名格式错误!");
                            }
                            works.setStudents(students);
                        }
                        //组别
                        if(row.getCell(7)!=null){
                            row.getCell(7).setCellType(Cell.CELL_TYPE_STRING);
                            String model=row.getCell(7).getStringCellValue();
                            //正则对比
                            boolean matche=Pattern.matches("^[\\u4E00-\\u9FA5]{1,}$",model);
                            if(!matche){
                                throw new BusinessException(ReturnCode.CODE_FAIL,"组别格式错误!");
                            }
                            works.setModel(model);
                        }
                        list.add(works);
                    }
                }
            }
            return list;
    }