匯出excel
首先了解下Jakarta POI HSSF API常用元件和樣式
類名 | 作用 |
---|---|
HSSFWorkbook | excel的檔案物件 |
HSSFSheet | excel的表單 |
HSSFRow | excel的行 |
HSSFCell | excel的格子單元 |
HSSFFont | excel字型 |
HSSFDataFormat | 日期格式 |
HSSFHeader | sheet頭 |
HSSFFooter | sheet尾(只有列印的時候才能看到效果) |
HSSFCellStyle | cell樣式 |
一、匯入poi所需要的jar包
這兩個jar包的版本一定要一致,不然可能會報異常java.lang.NoClassDefFoundError: org/apache/poi/UnsupportedFileFormatException
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
二、編寫匯出excel的工具類
1、HSSFWorkbook建立Excel檔案物件
2、HSSFWorkbook物件返回或者建立Sheet物件
3、Sheet物件返回行物件,用行物件得到Cell物件
4、對Cell物件進行讀寫操作
public class ExcelUtil {
/**
* 匯出excel
* @param title 匯出表的標題
* @param rowsName 匯出表的列名
* @param dataList 需要匯出的資料
* @param fileName 生成excel檔案的檔名
* @param response
*/
public void exportExcel(String title,String[] rowsName,List<Object[]> dataList,String fileName,HttpServletResponse response) throws Exception{
OutputStream output = response.getOutputStream();
response.reset();
response.setHeader("Content-disposition", "attachment; filename="+fileName);
response.setContentType("application/msexcel");
this.export(title,rowsName,dataList,fileName,output);
this.close(output);
}
/**
* 匯出資料
* @param title 匯出表的標題
* @param rowName 匯出表的列名
* @param dataList 需要匯出的資料
* @param fileName 生成excel檔案的檔名
* @param out
* @throws Exception
*/
private void export(String title,String[] rowName,List<Object[]> dataList,String fileName,OutputStream out) throws Exception {
try {
// 建立工作簿物件
HSSFWorkbook workbook = new HSSFWorkbook();
// 建立工作表
HSSFSheet sheet = workbook.createSheet(title);
// 產生表格標題行
HSSFRow rowm = sheet.createRow(0);
//建立表格標題列(需要的可以放開,這裡不使用標題列)
//HSSFCell cellTiltle = rowm.createCell(0);
// sheet樣式定義; getColumnTopStyle(); getStyle()均為自定義方法 --在下面,可延伸
// 獲取列頭樣式物件
HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
// 獲取單元格樣式物件
HSSFCellStyle style = this.getStyle(workbook);
//合併表格標題行,合併列數為列名的長度,第一個0為起始行號,第二個1為終止行號,第三個0為起始列好,第四個引數為終止列號
//合併單元格(需要的可以放開,這裡不合並單元格)
//sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
//設定標題行樣式(需要的可以放開,這裡不使用標題列)
//cellTiltle.setCellStyle(columnTopStyle);
//設定標題行值(需要的可以放開,這裡不使用標題列)
//cellTiltle.setCellValue(title);
// 定義所需列數
int columnNum = rowName.length;
// 在索引2的位置建立行(最頂端的行開始的第二行)
HSSFRow rowRowName = sheet.createRow(0);
// 將列頭設定到sheet的單元格中
for (int n = 0; n < columnNum; n++) {
// 建立列頭對應個數的單元格
HSSFCell cellRowName = rowRowName.createCell(n);
// 設定列頭單元格的資料型別
cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING);
HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
// 設定列頭單元格的值
cellRowName.setCellValue(text);
// 設定列頭單元格樣式
cellRowName.setCellStyle(columnTopStyle);
}
// 將查詢出的資料設定到sheet對應的單元格中
for (int i = 0; i < dataList.size(); i++) {
Object[] obj = dataList.get(i);
// 建立所需的行數,排除掉標題行的數量
HSSFRow row = sheet.createRow(i + 1);
for (int j = 0; j < obj.length; j++) {
// 設定單元格的資料型別
HSSFCell cell = null;
if (j == 0) {
cell = row.createCell(j, HSSFCell.CELL_TYPE_NUMERIC);
cell.setCellValue(i + 1);
} else {
cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING);
if (!"".equals(obj[j]) && obj[j] != null) {
// 設定單元格的值
cell.setCellValue(obj[j].toString());
}
}
// 設定單元格樣式
cell.setCellStyle(style);
}
}
// 讓列寬隨著匯出的列長自動適應
for (int colNum = 0; colNum < columnNum; colNum++) {
int columnWidth = sheet.getColumnWidth(colNum) / 256;
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
HSSFRow currentRow;
// 當前行未被使用過
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(colNum) != null) {
HSSFCell currentCell = currentRow.getCell(colNum);
if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
int length = currentCell.getStringCellValue()
.getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
if (colNum == 0) {
//設定寬度
sheet.setColumnWidth(colNum, (columnWidth - 2) * 256);
} else {
sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
}
}
workbook.write(out);
//檔案自定義存放位置(不寫預設在下載裡,這裡不使用)
//workbook.write(new FileOutputStream(new File("D://test"+".xls")));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 列頭單元格樣式
* @param workbook
* @return
*/
private HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
// 設定字型
HSSFFont font = workbook.createFont();
// 設定字型大小
font.setFontHeightInPoints((short) 11);
// 字型加粗
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 設定字型名字
font.setFontName("Courier New");
// 設定樣式;
HSSFCellStyle style = workbook.createCellStyle();
// 設定底邊框;
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
// 設定底邊框顏色;
style.setBottomBorderColor(HSSFColor.BLACK.index);
// 設定左邊框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
// 設定左邊框顏色;
style.setLeftBorderColor(HSSFColor.BLACK.index);
// 設定右邊框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
// 設定右邊框顏色;
style.setRightBorderColor(HSSFColor.BLACK.index);
// 設定頂邊框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 設定頂邊框顏色;
style.setTopBorderColor(HSSFColor.BLACK.index);
// 在樣式用應用設定的字型;
style.setFont(font);
// 設定自動換行;
style.setWrapText(false);
// 設定水平對齊的樣式為居中對齊;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 設定垂直對齊的樣式為居中對齊;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
/**
* 列資料資訊單元格樣式
* @param workbook
* @return
*/
private HSSFCellStyle getStyle(HSSFWorkbook workbook) {
// 設定字型
HSSFFont font = workbook.createFont();
// 設定字型大小
// font.setFontHeightInPoints((short)10);
// 字型加粗
// font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 設定字型名字
font.setFontName("Courier New");
// 設定樣式;
HSSFCellStyle style = workbook.createCellStyle();
// 設定底邊框;
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
// 設定底邊框顏色;
style.setBottomBorderColor(HSSFColor.BLACK.index);
// 設定左邊框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
// 設定左邊框顏色;
style.setLeftBorderColor(HSSFColor.BLACK.index);
// 設定右邊框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
// 設定右邊框顏色;
style.setRightBorderColor(HSSFColor.BLACK.index);
// 設定頂邊框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 設定頂邊框顏色;
style.setTopBorderColor(HSSFColor.BLACK.index);
// 在樣式用應用設定的字型;
style.setFont(font);
// 設定自動換行;
style.setWrapText(false);
// 設定水平對齊的樣式為居中對齊;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 設定垂直對齊的樣式為居中對齊;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
/**
* 關閉輸出流
* @param os
*/
private void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、使用測試
@RequestMapping("exportWordData")
public void exportExcelData(HttpServletRequest request, HttpServletResponse response){
// 定義表的標題
String title = "員工列表一覽";
//定義表的列名
String[] rowsName = new String[] { "序號", "姓名", "性別", "特長", "學歷", "入職時間", "簡歷", "照片", "部門" };
List<Object[]> dataList = new ArrayList<Object[]>();
//定義表的內容第一行
Object[] objs = new Object[9];
objs[0] = "測試";
objs[1] = 11;
objs[2] = "111";
objs[3] = "測試";
objs[4] = "測試";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(2018-12-24);
objs[5] = date;
objs[6] = "測試";
objs[7] = "測試";
objs[8] = "測試";
//定義表的內容第二行
Object[] objs1 = new Object[9];
objs1[0] = "測試";
objs1[1] = 11;
objs1[2] = "111";
objs1[3] = "測試";
objs1[4] = "測試";
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
String date1 = df1.format(2019-12-24);
objs1[5] = date1;
objs1[6] = "測試";
objs1[7] = "測試";
objs1[8] = "測試";
dataList.add(objs);
dataList.add(objs1);
// 建立ExportExcel物件
ExcelUtil excelUtil = new ExcelUtil();
try{
//生成word檔案的檔名
String fileName= new String("測試excel檔案.xlsx".getBytes("UTF-8"),"iso-8859-1");
excelUtil.exportExcel(title,rowsName,dataList,fileName,response);
System.out.println(true);
}catch(Exception e){
e.printStackTrace();
}
}
四、效果展示
匯入excel
匯入與匯出的基本步驟相似,關鍵要了解要匯入excel的結構,比如資料列、讀取資料的起始位置等,理解了匯出那麼匯入也就沒什麼難處了
一、控制層
@PostMapping("/import")
public boolean addUser(@RequestParam("file") MultipartFile file) {
boolean a = false;
String fileName = file.getOriginalFilename();
try {
a = userService.batchImport(fileName, file);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(a);
return a;
}
二、實現層
boolean batchImport(String fileName, MultipartFile file) throws Exception;
@Override
@Transactional(rollbackFor = RuntimeException.class)
public boolean batchImport(String fileName, MultipartFile file) throws Exception {
boolean notNull = false;
List<User> userList = new ArrayList<User>();
//正則驗證上傳檔案格式
if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
return false;
}
boolean isExcel = true;
if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
isExcel = false;
}
InputStream is = file.getInputStream();
Workbook wb = WorkbookFactory.create(is);
Sheet sheet = wb.getSheetAt(0);
if(sheet!=null){
notNull = true;
}
User user;
//遍歷當前頁所有行
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
Row row = sheet.getRow(r);
if (row == null){
continue;
}
user = new User();
if( row.getCell(0).getCellType() !=1){
return false;
}
String name = row.getCell(0).getStringCellValue();
if(name == null || name.isEmpty()){
return false;
}
row.getCell(1).setCellType(Cell.CELL_TYPE_STRING);
String phone = row.getCell(1).getStringCellValue();
if(phone==null || phone.isEmpty()){
return false;
}
String add = row.getCell(2).getStringCellValue();
if(add==null){
return false;
}
Date date=new Date();
if(row.getCell(3).getCellType() !=0){
return false;
}else{
date = row.getCell(3).getDateCellValue();
}
String des = row.getCell(4).getStringCellValue();
user.setName(name);
user.setPhone(phone);
user.setAddress(add);
user.setEnrolDate(date);
user.setDes(des);
userList.add(user);
}
for (User userResord : userList) {
userDao.addUser(userResord);
System.out.println(" 插入 "+userResord);
}
return notNull;
}
三、前端傳入檔案
必須使用post方式傳入
<form method="post" enctype="multipart/form-data" action="user/import" >
<input type="file" name="file"/>
<input type="submit" value="提交">
</form>
四、使用測試
匯入功能要根據具體的業務實現,為了方便小夥伴使用我整理了檔案讀取功能,儲存就需要自己實現啦!附上excel讀取工具類:
public class ImportExcelUtil {
/**
* 獲取excel資料
* 檔案字尾只能是xls、xlsx
*
* @param inputStream
* @param fileName
* @return
* @throws IOException
*/
public static List<Map<String, Object>> getExcelData(InputStream inputStream, String fileName) throws IOException {
Map<String, Object> resultMap = new HashMap<>();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
suffix = suffix.toLowerCase();
List<String> sheetNameList = new ArrayList<>();
List<Map<String, Object>> listDataMap = new ArrayList<>();
if ("xls".equals(suffix)) {
HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
HSSFSheet sheet = null;
//獲取每個Sheet表
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
sheetNameList.add(workbook.getSheetName(i));
sheet = workbook.getSheetAt(i);
List<List<String>> sheetList = new ArrayList<>();
Map<String, Object> sheetDataMap = new HashMap<>();
//獲取每行
for (int j = 1; j < sheet.getPhysicalNumberOfRows(); j++) {
HSSFRow row = sheet.getRow(j);
List<String> rowList = new ArrayList<String>();
//獲取每個單元格
for (int k = 0; k < row.getPhysicalNumberOfCells(); k++) {
rowList.add(String.valueOf(row.getCell(k)));
}
sheetList.add(rowList);
}
System.out.println(workbook.getSheetName(i) + "表資料:" + sheetList);
sheetDataMap.put("sheetName", workbook.getSheetName(i).trim());
sheetDataMap.put("data", sheetList);
listDataMap.add(sheetDataMap);
}
} else if ("xlsx".equals(suffix)) {
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
XSSFSheet sheet = null;
//獲取每個Sheet表
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
sheetNameList.add(workbook.getSheetName(i));
sheet = workbook.getSheetAt(i);
List<List<String>> sheetList = new ArrayList<>();
Map<String, Object> sheetDataMap = new HashMap<>();
//獲取每行
for (int j = 2; j < sheet.getPhysicalNumberOfRows(); j++) {
XSSFRow row = sheet.getRow(j);
List<String> rowList = new ArrayList<String>();
//獲取每個單元格
for (int k = 0; k < row.getPhysicalNumberOfCells(); k++) {
rowList.add(String.valueOf(row.getCell(k)));
}
sheetList.add(rowList);
}
sheetDataMap.put("sheetName", workbook.getSheetName(i).trim());
sheetDataMap.put("data", sheetList);
listDataMap.add(sheetDataMap);
}
System.out.println("---所有資料:" + listDataMap);
}
return listDataMap;
}
}