Java操作Excel并导出
生活随笔
收集整理的這篇文章主要介紹了
Java操作Excel并导出
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Java導出Excel表格
提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔
文章目錄
- Java導出Excel表格
- 前言
- 一、企業excel項目導出演示
- 二、使用步驟
- 1.引入Maven倉庫
- 2.引入Java操作Excel工具類
- 3.引入Controller層相關代碼
- 4.Application.yml文件
- 5.實體類代碼
- 6.具體操作截圖(Postman調用接口)
- 總結
前言
在企業實際開發中,經常會遇到使用Java操作Excel表格并導出,其實這個功能不管是前端Vue還是后端Java,實現起來都是非常簡單的,相信看完本文的你一定會有所收獲,干貨滿滿.以下是本篇文章正文內容,下面是個人企業開發的真實案例:可供參考
一、企業excel項目導出演示
下面就來聊聊具體實現吧。
二、使用步驟
1.引入Maven倉庫
代碼如下(示例):
<!--excel相關依賴--><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17-beta1</version></dependency>2.引入Java操作Excel工具類
代碼如下(示例):
public class ExcelExportUtils {public static List<List<String>> myReadExcel(File file){List<List<String>> resultList = new ArrayList<>();String path = file.getName();Workbook wb = null;Short rowLen = 0;Integer columnLen = 0;try {if (path.endsWith("xls")) {FileInputStream fis = new FileInputStream(file);wb = new HSSFWorkbook(fis);} else if (path.endsWith("xlsx")) {wb = new XSSFWorkbook(file);}} catch (Exception e) {e.printStackTrace();}Sheet firstSheet = wb.getSheetAt(0);if (firstSheet != null)columnLen = firstSheet.getLastRowNum();for (int i = 0; i < columnLen; i++) {Row row = firstSheet.getRow(i);if (row != null) {List<String> rowData = new ArrayList<>();resultList.add(rowData);if (rowLen == 0)rowLen = row.getLastCellNum();for (int i2 = 0; i2 < rowLen; i2++) {Cell cell = row.getCell(i2);if (cell != null)rowData.add(cell.toString());else rowData.add("");}}}return resultList;}/*** 這是一個通用的方法,利用了JAVA的反射機制,可以將放置在JAVA集合中并且符號一定條件的數據以EXCEL 的形式輸出到指定IO設備上** @param title 表格標題名* @param headers 表格屬性列名數組* @param dataset 需要顯示的數據集合,集合中一定要放置符合javabean風格的類的對象。此方法支持的* javabean屬性的數據類型有基本數據類型及String,Date,byte[](圖片數據)* @param out 與輸出設備關聯的流對象,可以將EXCEL文檔導出到本地文件或者網絡中* @param pattern 如果有時間數據,設定輸出格式。默認為"yyy-MM-dd"*/public static <T> void exportExcelList(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern, String[]... args) {// 聲明一個工作薄HSSFWorkbook workbook = new HSSFWorkbook();// 生成一個表格HSSFSheet sheet = workbook.createSheet(title);// 設置表格默認列寬度為15個字節sheet.setDefaultColumnWidth((short) 15);// 生成一個樣式HSSFCellStyle style = workbook.createCellStyle();// 設置這些樣式//設置表頭的背景顏色(excel的第一行)style.setFillForegroundColor(HSSFColor.WHITE.index);//SKY_BLUEstyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);style.setBorderBottom(HSSFCellStyle.BORDER_THIN);style.setBorderLeft(HSSFCellStyle.BORDER_THIN);style.setBorderRight(HSSFCellStyle.BORDER_THIN);style.setBorderTop(HSSFCellStyle.BORDER_THIN);style.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 生成一個字體HSSFFont font = workbook.createFont();//設置表頭的字體顏色font.setColor(HSSFColor.BLACK.index);//VIOLETfont.setFontHeightInPoints((short) 12);font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 把字體應用到當前的樣式style.setFont(font);// 生成并設置另一個樣式HSSFCellStyle style2 = workbook.createCellStyle();//設置表體的背景顏色(除了表頭)style2.setFillForegroundColor(HSSFColor.WHITE.index);//LIGHT_YELLOWstyle2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);style2.setBorderRight(HSSFCellStyle.BORDER_THIN);style2.setBorderTop(HSSFCellStyle.BORDER_THIN);style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 生成另一個字體HSSFFont font2 = workbook.createFont();font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);// 把字體應用到當前的樣式style2.setFont(font2);// 聲明一個畫圖的頂級管理器HSSFPatriarch patriarch = sheet.createDrawingPatriarch();// 定義注釋的大小和位置,詳見文檔HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));// 設置注釋內容comment.setString(new HSSFRichTextString("可以在POI中添加注釋!"));// 設置注釋作者,當鼠標移動到單元格上是可以在狀態欄中看到該內容.comment.setAuthor("leno");for (int i = 0; i < args.length - 1; i = i + 2) {//下拉框的位置CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 1, Integer.valueOf(args[i + 1][0]), Integer.valueOf(args[i + 1][0]));//下拉框準備的數據DVConstraint constraint = DVConstraint.createExplicitListConstraint(args[i]);HSSFDataValidation dataValidation = new HSSFDataValidation(cellRangeAddressList, constraint);sheet.addValidationData(dataValidation);}// 產生表格標題行HSSFRow row = sheet.createRow(0);for (short i = 0; i < headers.length; i++) {HSSFCell cell = row.createCell(i);cell.setCellStyle(style);HSSFRichTextString text = new HSSFRichTextString(headers[i]);cell.setCellValue(text);}// 遍歷集合數據,產生數據行Iterator<T> it = dataset.iterator();int index = 0;while (it.hasNext()) {index++;row = sheet.createRow(index);T t = it.next();// 利用反射,根據javabean屬性的先后順序,動態調用getXxx()方法得到屬性值Field[] fields = t.getClass().getDeclaredFields();int i = 0;for (short j = 0; j < fields.length; j++, i++) {Field field = fields[j];String fieldName = field.getName();if (fieldName.equals("serialVersionUID")) {i = -1;continue;}HSSFCell cell = row.createCell(i);cell.setCellStyle(style2);String getMethodName ="get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);try {Class tCls = t.getClass();Method getMethod = tCls.getMethod(getMethodName, new Class[]{});Object value = getMethod.invoke(t, new Object[]{});if (value == null) continue;// 判斷值的類型后進行強制類型轉換String textValue = null;if (value instanceof Boolean) {boolean bValue = (Boolean) value;textValue = "男";if (!bValue) {textValue = "女";}} else if (value instanceof Date) {Date date = (Date) value;SimpleDateFormat sdf = new SimpleDateFormat(pattern);textValue = sdf.format(date);} else if (value instanceof byte[]) {// 有圖片時,設置行高為60px;row.setHeightInPoints(60);// 設置圖片所在列寬度為80px,注意這里單位的一個換算sheet.setColumnWidth(i, (short) (35.7 * 80));// sheet.autoSizeColumn(i);byte[] bsValue = (byte[]) value;HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) 6,index, (short) 6, index);anchor.setAnchorType(2);patriarch.createPicture(anchor,workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));} else {// 其它數據類型都當作字符串簡單處理textValue = value.toString();}// 如果不是圖片數據,就利用正則表達式判斷textValue是否全部由數字組成if (textValue != null) {Pattern p = Pattern.compile("^//d+(//.//d+)?$");Matcher matcher = p.matcher(textValue);if (matcher.matches()) {// 是數字當作double處理cell.setCellValue(Double.parseDouble(textValue));} else {HSSFRichTextString richString = new HSSFRichTextString(textValue);HSSFFont font3 = workbook.createFont();//設置數據的字體顏色(除了第一行)font3.setColor(HSSFColor.BLACK.index);//BLUErichString.applyFont(font3);cell.setCellValue(richString);}}} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} finally {// 清理資源}}}try {workbook.write(out);} catch (IOException e) {e.printStackTrace();}} }工具類代碼直接復制即可。
3.引入Controller層相關代碼
代碼如下(示例):
@RestController @RequestMapping("/excel") public class ExcelController {/*** 從配置文件中讀取值,加: 可以保證配置文件中沒有該值的時候不會報錯,* 正常這些值是直接從數據庫中查詢出來,這里為了減少數據操作層才這么做*/@Value("#{'${test.value1:}'.empty ? null : '${test.value1:}'.split(',')}")private List listValue1;@Value("#{'${test.value2:}'.empty ? null : '${test.value2:}'.split(',')}")private List listValue2;@Value("#{'${test.value3:}'.empty ? null : '${test.value3:}'.split(',')}")private List listValue3;@Value("#{'${test.value4:}'.empty ? null : '${test.value4:}'.split(',')}")private List listValue4;/*** 該導出方法最后操作是流,所以不需要返回值,使用void,相反如果寫了return是會報錯的,不信的可以試試* @param name* @param response*/@GetMapping("/export_list/{name}")public void exportConsumList(@PathVariable("name") String name, HttpServletResponse response){System.out.println("接收到來自前端的參數name :" + name);List<ExcelConsumListResp> exportList = new ArrayList<>();/*** 下面給 exportList 賦值*/setValue(exportList);/*** 下面就是具體的導出方法*/exportNewModel(exportList,response);}private void exportNewModel(List<ExcelConsumListResp> exportList, HttpServletResponse response) {OutputStream bos = null;String fileName = "場館測試.xls";try{bos = new BufferedOutputStream(response.getOutputStream());response.setHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-excel");/*** 這里的表頭,需要與前面定義的 ExcelConsumListResp 類中的屬性名保持一致,并且順序和數量也需要一致*/String[] atrArray = {"序號","場館名稱","場館地址","服務項目","加入日期"};//調用工具類中的方法,進行導出ExcelExportUtils.exportExcelList(fileName, atrArray, exportList, bos, "yyy-MM-dd");//寫出流ResponseEntity.ok().body(bos);bos.close();}catch(Exception e){e.getMessage();}}private void setValue(List<ExcelConsumListResp> resp){List<List<String>> list = new ArrayList<>();list.add(listValue1);list.add(listValue2);list.add(listValue3);list.add(listValue4);list.stream().forEach(p->{int i = 0;ExcelConsumListResp vo = new ExcelConsumListResp();vo.setIndex(p.get(i++)).setStaName(p.get(i++)).setAddress(p.get(i++)).setProjectName(p.get(i++)).setCreateTime(p.get(i));resp.add(vo);});}}4.Application.yml文件
代碼如下(示例):
server:port: 8088# 定義具體導出的數據,正常通過數據庫查詢即可 test:value1: 1,體育館1,武漢,羽毛球,2021-11-01value2: 2,體育館2,北京,籃球,2021-11-02value3: 3,體育館3,上海,乒乓球,2021-11-03value4: 4,體育館4,深圳,足球,2021-11-045.實體類代碼
代碼如下(示例):
@Data public class ExcelConsumListResp {/*** 序號*/private String index;/*** 場館名稱*/private String staName;/*** 場館地址*/private String address;/*** 服務項目*/private String projectName;/*** 加入日期*/private String createTime;}6.具體操作截圖(Postman調用接口)
調用寫好的接口試試:
發現接口已經調用進來,放開端點:
由于后端返回的是流,所以可以看到這里的postman返回值,這個是不可以直接使用的,前端vue自然有辦法將流轉換為excel文件,那么到這一步可以算是成功了
那么如何查看這個流正不正確呢,其實postman可以這樣做:
在調用接口的時候就保存
點擊之后會讓我們選擇保存位置,保存到桌面
打開看看:
總結
提示:這里對文章進行總結:
以上就是今天要講的內容,一步一步的講解了java操作excel導出的步驟,如果你是新手小白,可以關注我的微信公眾號,即可領取此項目的源碼哦,感謝支持,每周分享一些干貨給你們 Thanks。
總結
以上是生活随笔為你收集整理的Java操作Excel并导出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UE_Visibility Buffer
- 下一篇: kafka send方法详解 (同步异步