excel導入導出

Java中excel的導入導出

1.excel的導出

注意不要直接複製使用
我是直接在controller中使用,下面controller代碼中,ColumnInfoEntity類只是用來存放導出excel標題的工具類而已,可以自己隨便寫一個,爲了代碼的簡潔,就寫導出三個字段了,ExcelUtil.exportExcelFile就是自定義的導出類和方法了,“彙總申請表”是導出的表名,headList表示標題的list,第三個參數就是導出的數據,最後一個就是response響應信息

@RequestMapping(value = "/exportSummaryApplication", method = RequestMethod.GET)
public void exportSummaryApplication(HttpServletResponse response) throws IOException{
	List<MaterielFormQuery> list = materielFormMapper.findAllByQuery();
	List<ColumnInfoEntity> headList = new ArrayList<ColumnInfoEntity>();
	headList.add(new ColumnInfoEntity("測試字段1", "pointRegionCode"));
	headList.add(new ColumnInfoEntity("測試字段2", "pointRegionName"));
	headList.add(new ColumnInfoEntity("測試字段3", "cityLevel"));
	ExcelUtil.exportExcelFile("彙總申請表", headList, JSONArray.parseArray(JSON.toJSONString(list)), response);
}

先po出工具類的頭吧

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sf.materielmanage.constant.MaterielManageConstant;
public class ExcelUtil {
    public static final String OFFICE_EXCEL_2003_POSTFIX = "xls";  
    public static final String OFFICE_EXCEL_2010_POSTFIX = "xlsx";  
    public static final String EMPTY = "";  
    public static final String POINT = "."; 
    public static int totalRows; //sheet中總行數  
    public static int totalCells; //每一行總單元格數  
    public static int totalHCells; //標題單元格數 
    public static String DEFAULT_DATE_PATTERN="yyyy年MM月dd日";//默認日期格式
    public static int DEFAULT_COLOUMN_WIDTH = 25;
    public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); 
}	

ExcelUtil工具類的exportExcelFile的方法,調用了exportExcelXNoTitle方法,其中ExcelUtil工具類中的方法基本都可以複製套用的。

public static void exportExcelFile(String title, List<ColumnInfoEntity> headList, JSONArray dataArray, HttpServletResponse response) throws IOException{
	ByteArrayOutputStream output = new ByteArrayOutputStream();	
	exportExcelXNoTitle(headList,dataArray,null,0,output);
	byte[] content = output.toByteArray();
    InputStream input = new ByteArrayInputStream(content);
	response.reset();
	response.setContentType("application/octet-stream");
	title = URLEncoder.encode(title, "UTF-8");
    response.setHeader("Content-Disposition", "attachment;filename="+title+".xlsx");  
    response.setContentLength(content.length);
    ServletOutputStream outputStream = response.getOutputStream();
    BufferedInputStream bis = new BufferedInputStream(input);
    BufferedOutputStream bos = new BufferedOutputStream(outputStream);
    byte[] buff = new byte[8192];
    int bytesRead;
    while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
        bos.write(buff, 0, bytesRead);
    }
    bis.close();
    bos.close();
    outputStream.flush();
    outputStream.close();
}

exportExcelXNoTitle方法的代碼

private static void exportExcelXNoTitle(List<ColumnInfoEntity> headList,JSONArray jsonArray,String datePattern,int colWidth, OutputStream out) {
    if(datePattern==null) {
        datePattern = DEFAULT_DATE_PATTERN;
    }
    // 聲明一個工作薄 緩存大於1000行時會把之前的行寫入硬盤
    SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
    workbook.setCompressTempFiles(true);
    //表頭樣式
    CellStyle titleStyle = workbook.createCellStyle();
    titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    Font titleFont = workbook.createFont();
    titleFont.setFontHeightInPoints((short) 20);
    titleFont.setBoldweight((short) 700);
    titleStyle.setFont(titleFont);
    titleStyle.setFillBackgroundColor(IndexedColors.YELLOW.getIndex());
    //titleStyle.setFillBackgroundColor(IndexedColors.WHITE.getIndex());
    titleStyle.setFillBackgroundColor(HSSFColor.RED.index);
    // 列頭樣式
    CellStyle headerStyle = workbook.createCellStyle();
    // 設置邊框
    headerStyle.setBorderTop((short) 1);
    headerStyle.setBorderRight((short) 1);
    headerStyle.setBorderBottom((short) 1);
    headerStyle.setBorderLeft((short) 1);
    // 水平居中
    headerStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    // 生成一個字體
    Font headerFont = workbook.createFont();
    headerFont.setFontHeightInPoints((short) 12);
    headerFont.setColor(IndexedColors.BLACK.getIndex());
    headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
    headerStyle.setFont(headerFont);
    // 單元格樣式
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
    cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
    cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
    cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
    cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    // 垂直居中
    cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
    // 生成一個字體
    Font cellFont = workbook.createFont();
    cellFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
    cellStyle.setFont(cellFont);
    cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
    DataFormat format = workbook.createDataFormat();
    cellStyle.setDataFormat(format.getFormat("@"));
    // 生成一個(帶標題)表格
    SXSSFSheet sheet = (SXSSFSheet) workbook.createSheet();
    //設置列寬 //至少字節數
    int minBytes = colWidth<DEFAULT_COLOUMN_WIDTH?DEFAULT_COLOUMN_WIDTH:colWidth;
    int[] arrColWidth = new int[headList.size()];
    // 產生表格標題行,以及設置列寬
    String[] properties = new String[headList.size()];
    String[] headers = new String[headList.size()];
    int ii = 0;
    for(ColumnInfoEntity columnInfo:headList){
        properties[ii] = columnInfo.getColumn();
        headers[ii] = columnInfo.getColumnName();
        int bytes = columnInfo.getColumn().getBytes().length;
        arrColWidth[ii] =  bytes < minBytes ? minBytes : bytes;
        sheet.setColumnWidth(ii,arrColWidth[ii]*256);
        ii++;
    }
    // 寫導出表格標題
    int rowIndex = 0;
    if(rowIndex == 0){
        //如果數據超過了,則在第二頁顯示
        if ( rowIndex != 0 ) {
            sheet = (SXSSFSheet) workbook.createSheet();
        }
        //列頭 rowIndex =0
        SXSSFRow headerRow = (SXSSFRow) sheet.createRow(0);
        for(int i=0;i<headers.length;i++)
        {
            headerRow.createCell(i).setCellValue(headers[i]);
            headerRow.getCell(i).setCellStyle(headerStyle);
        }
        //數據內容從 rowIndex=1開始
        rowIndex = 1;
    }
    // 遍歷集合數據,產生數據行
    for (Object obj : jsonArray) {
        if(rowIndex == 65535){
            //如果數據超過了,則在第二頁顯示
            if ( rowIndex != 0 ) {
                sheet = (SXSSFSheet) workbook.createSheet();
            }
            //列頭 rowIndex =0
            SXSSFRow headerRow = (SXSSFRow) sheet.createRow(0);
            for(int i=0;i<headers.length;i++)
            {
                headerRow.createCell(i).setCellValue(headers[i]);
                headerRow.getCell(i).setCellStyle(headerStyle);
            }
            //數據內容從 rowIndex=1開始
            rowIndex = 1;
        }
        JSONObject jo = (JSONObject) JSONObject.toJSON(obj);
        SXSSFRow dataRow = (SXSSFRow) sheet.createRow(rowIndex);
        for (int i = 0; i < properties.length; i++)
        {
            SXSSFCell newCell = (SXSSFCell) dataRow.createCell(i);
            Object o =  jo.get(properties[i]);
            String cellValue = "";
            if(o==null) {
                cellValue = "";
            }
            else if(o instanceof Date) {
                cellValue = sdf.format(o);
            }
            else if(o instanceof Float || o instanceof Double || o instanceof BigDecimal) {
                cellValue= new BigDecimal(o.toString()).setScale(5,BigDecimal.ROUND_HALF_UP).toString();
            }
            else {
                cellValue = o.toString();
            }
            newCell.setCellValue(cellValue);
            newCell.setCellStyle(cellStyle);
        }
        rowIndex++;
    }
    try {
        workbook.write(out);
        workbook.dispose();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.excel的導入

excel的導入也是利用自定義的ExcelUtil工具類中的方法,同樣直接在controller層使用代碼,同樣請勿直接複製使用,因爲下列代碼中有多個自定義的類,下列代碼只是作爲導入工具類入口的引用,multpartFile爲接收到的上傳excel文件,ExcelUtil.readExcel爲導入的工具類和方法

@RequestMapping(value = "/uploadMaterielApply", method = RequestMethod.POST)
@ResponseBody
public ResultData uploadMaterielApply(MultipartFile multpartFile){
	if(multpartFile == null){
		logger.error("導入失敗,導入文件爲NULL");
		return new ResultData(false,"導入文件爲NULL");	
	}
	MaterielApply apply = new MaterielApply();
	List<Map<String, Object>> list = null;
	List<MaterielApply> appList = new ArrayList<MaterielApply>();
	Map<String,Object> head = new HashMap<String,Object>();
	head.put("物料編碼", "itemCode");
	head.put("申請數量", "applyQtyStr");
	head.put("其他說明", "remark");
	try {
		list = ExcelUtil.readExcel(multpartFile, head);
		for(Map<String, Object> map : list){
			MaterielApply materielApply = JSON.parseObject(JSON.toJSONString(map),MaterielApply.class);
			appList.add(materielApply);	
		}
		apply.setMaterielApplyList(appList);
		apply = materielApplyService.getUploadApplyMateriel(apply);
		return new ResultData(apply);
	} catch (IOException e) {
		return new ResultData(false,"導入失敗");
	} catch (MaterielManageException e) {
		logger.error("導入失敗{}"+e.getMsg());
		return new ResultData(false,e.getMsg());
	}
}

readExcel方法代碼如下,其中ExcelUtil工具類中的方法基本都可以複製套用的。

public static List<Map<String, Object>> readExcel(MultipartFile file,Map<String,Object> head) throws IOException{
	// 判斷file是否爲空
	if(file == null || EMPTY.equals(file.getOriginalFilename().trim())){
		return null;
	}else{
		String postfix = getPostfix(file.getOriginalFilename());
		if(!EMPTY.equals(postfix)){
			if(OFFICE_EXCEL_2003_POSTFIX.equals(postfix)){
				//後綴名爲xls
				return readXls(file,head);
			}else if(OFFICE_EXCEL_2010_POSTFIX.equals(postfix)){
				//後綴名爲xlsx
				return readXlsx(file,head);	
			}else{
				return null;
			}
		}
	}
	return null;
}

貼出後綴爲xlsx的excel的導入方法

public static List<Map<String, Object>> readXlsx(MultipartFile file,Map<String,Object> head) throws IOException{
	List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();  
	// IO流讀取文件  
    InputStream input = null;  
    XSSFWorkbook wb = null; 
    try {
		input = file.getInputStream();
		long size = input.available();
		if(size > 10485760){
			return list;
		}
		// 創建文檔
		wb = new XSSFWorkbook(input);
		// 讀取sheet頁
		int sheetNum = wb.getNumberOfSheets();
		if(sheetNum < MaterielManageConstant.LOOP_2000){
			for(int numSheet = 0;numSheet < sheetNum;numSheet++){
				XSSFSheet xssfSheet = wb.getSheetAt(numSheet);  
				if(xssfSheet == null){continue;}
				totalRows = xssfSheet.getLastRowNum(); 
				//獲取excel上的標題
				XSSFRow headerRow = xssfSheet.getRow(0);
				if(headerRow == null){continue;}
				//標題的單元格數
				totalHCells = headerRow.getLastCellNum();
				Map<String,Object> mapHeader = new HashMap<String,Object>();
				if(totalHCells < MaterielManageConstant.LOOP_10000){
					for(int i = 0;i < totalHCells;i++){
						String headStr = headerRow.getCell(i).getStringCellValue().trim();
						if(StringUtils.isNotEmpty(headStr)){mapHeader.put(String.valueOf(i), head.get(headStr));}
					}	
				}
				//讀取數據,從第二行開始
				if(totalRows < MaterielManageConstant.LOOP_100000){
					for(int j = 1;j <= totalRows;j++){
						XSSFRow xssfRow = xssfSheet.getRow(j);
						if(xssfRow != null){
							totalCells = xssfRow.getLastCellNum();
							//讀取列,從第一列開始
	                        Map <String,Object> data = new HashMap<String,Object>();
	                        if(totalCells < MaterielManageConstant.LOOP_10000){
	                        	for(int m = 0;m < totalCells;m++){
		                        	XSSFCell cell = xssfRow.getCell(m); 
		                        	if(cell == null){continue;}
		                            data.put((String) mapHeader.get(String.valueOf(m)), getXValue(cell).trim());
		                        }	
	                        }
	                        list.add(data);
						}
					}	
				}
			}	
		}
		return list;
	} catch (IOException e) {
		e.printStackTrace();
	} finally{
		input.close();
	}
	return null;
}

其實後綴爲xls的excel方法和上面的方法差不多,只是把上面方法中的XSSFWorkbook換爲了HSSFWorkbook,兩者的區別可以去網上收索,
基本的方法就大概說了一下,有深入的理解會再補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章