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,兩者的區別可以去網上收索,
基本的方法就大概說了一下,有深入的理解會再補充