excel(二)解析excel

一、自定义封装:

1、pom添加依赖:

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

注意:高版本可能不兼容hasOOXMLHeader,这时只能通过判断名称来初始化wb:

boolean isExcel2007 = fileName.matches("^.+\\.(?i)(xlsx)$");
        Workbook wb = null;
        if (!isExcel2007) {
            // 当excel是2003时,创建excel2003
            wb = new HSSFWorkbook(inputStream);
        } else {
            // 当excel是2007时,创建excel2007
            wb = new XSSFWorkbook(inputStream);
        }

2、util: 

package com.demo.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
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.springframework.web.multipart.MultipartFile;

import com.demo.exception.ExcelException;

public class ExcelUtil {
	 

	/**
	 * @author: 
	 * @date: 2018-5-26 下午4:40:04
	 * @Description: 解析
	 * @param @param excelFile
	 * @throws ExcelException 
	 * @throws IOException 
	 */
	public static List<Map<Integer, String>> getExcelData(
			MultipartFile excelFile,String datePattren,String numberPattern) throws ExcelException, IOException {
		//解析结果集,key表示第i列
		List<Map<Integer, String>> list = new ArrayList<>();
		// 文件类型
		String fileType = "";
		try {
			String fileName = excelFile.getOriginalFilename();
			fileType = fileName.substring(fileName.lastIndexOf(".") + 1,
					fileName.length());
		} catch (Exception e) {
			fileType = "";
		}
		if (!fileType.toLowerCase().equals("xls")
				&& !fileType.toLowerCase().equals("xlsx")) {
			throw new ExcelException("文件格式不支持,请上传xls或xlsx文件");
		}

		if ("xlsx".equals(fileType) || "xls".equals(fileType)) {
			Workbook wb = null;
			InputStream inp = excelFile.getInputStream();
			try {
				if (!inp.markSupported()) {
					inp = new PushbackInputStream(inp, 8);
				}

				if (POIFSFileSystem.hasPOIFSHeader(inp)) {
					wb = new HSSFWorkbook(inp);
				} else if (POIXMLDocument.hasOOXMLHeader(inp)) {
					wb = new XSSFWorkbook(OPCPackage.open(inp));
				}

				if (null == wb) {
					throw new ExcelException("导入失败");
				}
				Sheet data = wb.getSheetAt(0);// 第一个页脚
				// 解析

				for (int i = data.getFirstRowNum() + 1; i <= data
						.getLastRowNum(); i++) {
					// 第i行
					Row row = data.getRow(i);
					Iterator cells = row.cellIterator();
					HashMap<Integer, String> map = new HashMap<>();
					// 循环列
					
					while (cells.hasNext()) {
						// 设置单元格内容为字符串
						Cell cell = (Cell) cells.next();
						//cell.setCellType(Cell.CELL_TYPE_STRING);
						String val ="";
						
						 if(cell != null){  
					            switch (cell.getCellType()) {  
					            case Cell.CELL_TYPE_STRING:  
					                val = cell.getStringCellValue();  
					                break;  
					            case Cell.CELL_TYPE_BOOLEAN:  
					                Boolean val1 = cell.getBooleanCellValue();  
					                val = val1.toString();  
					                break;  
					            case Cell.CELL_TYPE_NUMERIC:  
//					              Double val3 = cell.getNumericCellValue();  
//					              val = val3.toString();  
					                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {     
					                    Date theDate = cell.getDateCellValue();  
					                    SimpleDateFormat dff = new SimpleDateFormat(datePattren);  
					                    val = dff.format(theDate);
					                    
					                 
					                }else{  
					                    DecimalFormat df = new DecimalFormat(numberPattern); 
					                  
					                    val = df.format(cell.getNumericCellValue());
					                   
					                }  
					                break;  
					            case Cell.CELL_TYPE_BLANK:  
					                break;  
					            default:  
					                
					            }  
					        }  
						
						
						
						Integer key = cell.getColumnIndex();
						map.put(key, val);
						//System.out.println("内容为"+key+"  :"+val);
						
					}
					list.add(map);
				}

			} catch (Exception e) {
				throw new ExcelException("未知原因,解析失败");
				// ("保存Excel文件时,请不要将鼠标最终定位在Excel中的可以下拉选值的列上。");
			}
		}
		return list;
	}

}

3、测试:


package com.demo.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.demo.exception.ExcelException;
import com.demo.util.ExcelUtil;


@Controller
public class Test {

	/*
	 * 使用postman测试时,必须是post请求,选择body,把默认的text改为file,选择文件,key即为controller接口的参数
	 */
	@ResponseBody
	@RequestMapping("/test")
	public void goalMonth(@RequestParam("file") MultipartFile[] files) {
		
		MultipartFile excelFile = null;
		if (files != null && files.length > 0) {
			excelFile = files[0];
		} 
		
		// 解析的数据
		List<Map<Integer, String>> excelList = null;
		try {
			excelList = ExcelUtil.getExcelData(excelFile, "yyyy-MM", "0");
		} catch (ExcelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		for(int i=0;i<excelList.size();i++){
			Map<Integer,String> excelMap = excelList.get(i);
			//第一列
			String provice = excelMap.get(0);
			//第二列
			String info = excelMap.get(1);
			//第三列
			String city = excelMap.get(2);
			//System.out.println("第"+(i+1)+"行:"+provice);
			System.out.println("//"+info);
			System.out.println("put(\""+provice+"\""+","+"\""+city+"\")");
		}
	}
}
		

postman测试,:

例如解析 

中模板的数据:将金额的格式设为保留小数点后两位:List<Map<Integer, String>>   excelList = ExcelUtil.getExcelData(excelFile, "yyyy-MM-dd", "0.00");

,得到的结果集应该为:

{  {0:"哈尔滨",1:"",2:"601.00"},{0:"哈尔滨",1:"",2:"3010.00"},{0:"洛阳",1:"",2:"40000.00"},

{0:"邯郸",1:"丛台区",2:"22050.00"},{0:"洛阳",1:"",2:"6000.00"}}

(注意,此util只解析了第一个页脚:    Sheet data = wb.getSheetAt(0);// 第一个页脚。如果一个excel文件有多个页脚,可以使用wb的getNumberOfSheets获取页脚总数,然后循环页脚)。

二、常见问题:

1、poi原样读取百分比:poi读取百分比数据会读成小数,如果需要原样读取,需要单独转化下:

if (cell.getCellStyle().getDataFormatString().indexOf("%") != -1) {
System.out.println(cell.getNumericCellValue()*100+"%");
}

2、poi读取Excel表格中公式的计算值:读取Excel表格,需要保存格式为Number而读取到Excel中有公式时,会报错。

使用下面的处理方式可以解决该问题。

switch (cell.getCellType()) {
    case HSSFCell.CELL_TYPE_FORMULA: //公式类型
    // cell.getCellFormula();
    try {
        value = String.valueOf(cell.getNumericCellValue());    
    } catch (IllegalStateException e) {
         value = String.valueOf(cell.getRichStringCellValue());
    }
     break;
   }

三、小数精度问题:如纯数字的单元格,读取后 后面会加上 .0,1 --> 1.0;再如2.2 --> 2.1999999997,解决方法:

public class CommonUtil {

  private static NumberFormat numberFormat = NumberFormat.getNumberInstance();

  static {
    numberFormat.setGroupingUsed(false);
  }

  public static String getCellValue(Cell cell) {
    if (null == cell) {
      return "";
    }
    Object value;
    switch (cell.getCellTypeEnum()) {
      // 省略
      case NUMERIC:
        double d = cell.getNumericCellValue();  
        value = numberFormat.format(d);    // 关键在这里!
      //省略 
    }
    return value == null ? "" : value.toString();
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_t_y_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值