<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          注解+反射優(yōu)雅的實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出(通用版)

          共 17061字,需瀏覽 35分鐘

           ·

          2021-08-15 18:32

          相關(guān)閱讀:一個(gè)90后員工猝死的全過程

          來源:blog.csdn.net/youzi1394046585/

          article/details/86670203

          日常在做后臺(tái)系統(tǒng)的時(shí)候會(huì)很頻繁的遇到Excel導(dǎo)入導(dǎo)出的問題,正好這次在做一個(gè)后臺(tái)系統(tǒng),就想著寫一個(gè)公用工具來進(jìn)行Excel的導(dǎo)入導(dǎo)出。

          一般我們?cè)趯?dǎo)出的時(shí)候都是導(dǎo)出的前端表格,而前端表格同時(shí)也會(huì)對(duì)應(yīng)的在后臺(tái)有一個(gè)映射類。

          所以在寫這個(gè)工具的時(shí)候我們先理一下我們需要實(shí)現(xiàn)的效果:

          實(shí)現(xiàn)過程:

          首先需要?jiǎng)?chuàng)建三個(gè)注解

          一個(gè)是EnableExport ,必須有這個(gè)注解才能導(dǎo)出

          /**
           * 設(shè)置允許導(dǎo)出
           */

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface EnableExport {
               String fileName();

          }

          然后就是EnableExportField,有這個(gè)注解的字段才會(huì)導(dǎo)出到Excel里面,并且可以設(shè)置列寬

          /**
           * 設(shè)置該字段允許導(dǎo)出
           * 并且可以設(shè)置寬度
           */

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface EnableExportField {
               int colWidth() default  100;
               String colName();
          }

          再就是ImportIndex,導(dǎo)入的時(shí)候設(shè)置Excel中的列對(duì)應(yīng)的序號(hào)

          /**
           * 導(dǎo)入時(shí)索引
           */

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface ImportIndex {
               int index() ;

          }

          注解使用示例

          三個(gè)注解創(chuàng)建好之后就需要開始操作Excel了

          首先,導(dǎo)入方法。在后臺(tái)接收到前端上傳的Excel文件之后,使用poi來讀取Excel文件

          我們根據(jù)傳入的類型上面的字段注解的順序來分別為不同的字段賦值,然后存入集合中,再返回

          代碼如下:


          /**
           * 將Excel轉(zhuǎn)換為對(duì)象集合
           * @param excel Excel 文件
           * @param clazz pojo類型
           * @return
           */

          public static List<Object> parseExcelToList(File excel,Class clazz){
              List<Object> res = new ArrayList<>();
              // 創(chuàng)建輸入流,讀取Excel
              InputStream is = null;
              Sheet sheet = null;
              try {
                  is = new FileInputStream(excel.getAbsolutePath());
                  if (is != null) {
                      Workbook workbook = WorkbookFactory.create(is);
                      //默認(rèn)只獲取第一個(gè)工作表
                      sheet = workbook.getSheetAt(0);
                      if (sheet != null) {
                       //前兩行是標(biāo)題
                          int i = 2;
                          String values[] ;
                          Row row = sheet.getRow(i);
                          while (row != null) {
                              //獲取單元格數(shù)目
                              int cellNum = row.getPhysicalNumberOfCells();
                              values = new String[cellNum];
                              for (int j = 0; j <= cellNum; j++) {
                                  Cell cell =   row.getCell(j);
                                  if (cell != null) {
                                      //設(shè)置單元格內(nèi)容類型
                                      cell.setCellType(Cell.CELL_TYPE_STRING );
                                      //獲取單元格值
                                      String value = cell.getStringCellValue() == null ? null : cell.getStringCellValue();
                                      values[j]=value;
                                  }
                              }
                              Field[] fields = clazz.getDeclaredFields();
                              Object obj = clazz.newInstance();
                              for(Field f : fields){
                                  if(f.isAnnotationPresent(ImportIndex.class)){
                                      ImportIndex annotation = f.getDeclaredAnnotation(ImportIndex.class);
                                      int index = annotation.index();
                                      f.setAccessible(true);
                                      //此處使用了阿里巴巴的fastjson包里面的一個(gè)類型轉(zhuǎn)換工具類
                                      Object val =TypeUtils.cast(values[index],f.getType(),null);
                                      f.set(obj,val);
                                  }
                              }
                              res.add(obj);
                              i++;
                              row=sheet.getRow(i);
                          }

                      }
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return res;
          }

          接下來就是導(dǎo)出方法。另外,關(guān)注互聯(lián)網(wǎng)架構(gòu)師公眾號(hào),回復(fù)“2T”,送你一份面試題寶典!

          導(dǎo)出分為幾個(gè)步驟:

          1. 建立一個(gè)工作簿,也就是類型新建一個(gè)Excel文件

          1. 建立一張sheet表
          1. 設(shè)置標(biāo)的行高和列寬
          1. 繪制標(biāo)題和表頭

          這兩個(gè)方法是自定義方法,代碼會(huì)貼在后面

          1. 寫入數(shù)據(jù)到Excel
          1. 創(chuàng)建下拉列表
          1. 寫入文件到response

          到這里導(dǎo)出工作就完成了

          下面是一些自定義方法的代碼

          /**
           * 獲取一個(gè)基本的帶邊框的單元格
           * @param workbook
           * @return
           */

          private static HSSFCellStyle getBasicCellStyle(HSSFWorkbook workbook){
              HSSFCellStyle hssfcellstyle = workbook.createCellStyle();
              hssfcellstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
              hssfcellstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
              hssfcellstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
              hssfcellstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
              hssfcellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
              hssfcellstyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
              hssfcellstyle.setWrapText(true);
              return hssfcellstyle;
          }

          /**
           * 獲取帶有背景色的標(biāo)題單元格
           * @param workbook
           * @return
           */

          private static HSSFCellStyle getTitleCellStyle(HSSFWorkbook workbook){
              HSSFCellStyle hssfcellstyle =  getBasicCellStyle(workbook);
              hssfcellstyle.setFillForegroundColor((short) HSSFColor.CORNFLOWER_BLUE.index); // 設(shè)置背景色
              hssfcellstyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
              return hssfcellstyle;
          }

          /**
           * 創(chuàng)建一個(gè)跨列的標(biāo)題行
           * @param workbook
           * @param hssfRow
           * @param hssfcell
           * @param hssfsheet
           * @param allColNum
           * @param title
           */

          private static void createTitle(HSSFWorkbook workbook, HSSFRow hssfRow , HSSFCell hssfcell, HSSFSheet hssfsheet,int allColNum,String title){
              //在sheet里增加合并單元格
              CellRangeAddress cra = new CellRangeAddress(000, allColNum);
              hssfsheet.addMergedRegion(cra);
              // 使用RegionUtil類為合并后的單元格添加邊框
              RegionUtil.setBorderBottom(1, cra, hssfsheet, workbook); // 下邊框
              RegionUtil.setBorderLeft(1, cra, hssfsheet, workbook); // 左邊框
              RegionUtil.setBorderRight(1, cra, hssfsheet, workbook); // 有邊框
              RegionUtil.setBorderTop(1, cra, hssfsheet, workbook); // 上邊框

              //設(shè)置表頭
              hssfRow = hssfsheet.getRow(0);
              hssfcell = hssfRow.getCell(0);
              hssfcell.setCellStyle( getTitleCellStyle(workbook));
              hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
              hssfcell.setCellValue(title);
          }

          /**
           * 設(shè)置表頭標(biāo)題欄以及表格高度
           * @param workbook
           * @param hssfRow
           * @param hssfcell
           * @param hssfsheet
           * @param colNames
           */

          private static void createHeadRow(HSSFWorkbook workbook,HSSFRow hssfRow , HSSFCell hssfcell,HSSFSheet hssfsheet,List<String> colNames){
              //插入標(biāo)題行
              hssfRow = hssfsheet.createRow(1);
              for (int i = 0; i < colNames.size(); i++) {
                  hssfcell = hssfRow.createCell(i);
                  hssfcell.setCellStyle(getTitleCellStyle(workbook));
                  hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
                  hssfcell.setCellValue(colNames.get(i));
              }
          }
          /**
           * excel添加下拉數(shù)據(jù)校驗(yàn)
           * @param sheet 哪個(gè) sheet 頁添加校驗(yàn)
           * @return
           */

          public static void createDataValidation(Sheet sheet,Map<Integer,String[]> selectListMap) {
              if(selectListMap!=null) {
                  selectListMap.forEach(
                          // 第幾列校驗(yàn)(0開始)key 數(shù)據(jù)源數(shù)組value
                          (key, value) -> {
                              if(value.length>0) {
                                  CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(265535, key, key);
                                  DataValidationHelper helper = sheet.getDataValidationHelper();
                                  DataValidationConstraint constraint = helper.createExplicitListConstraint(value);
                                  DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
                                  //處理Excel兼容性問題
                                  if (dataValidation instanceof XSSFDataValidation) {
                                      dataValidation.setSuppressDropDownArrow(true);
                                      dataValidation.setShowErrorBox(true);
                                  } else {
                                      dataValidation.setSuppressDropDownArrow(false);
                                  }
                                  dataValidation.setEmptyCellAllowed(true);
                                  dataValidation.setShowPromptBox(true);
                                  dataValidation.createPromptBox("提示""只能選擇下拉框里面的數(shù)據(jù)");
                                  sheet.addValidationData(dataValidation);
                              }
                          }
                  );
              }
          }
          使用實(shí)例

          導(dǎo)出數(shù)據(jù)

          導(dǎo)入數(shù)據(jù)(返回對(duì)象List)

          源碼地址:

          https://github.com/xyz0101/excelutils




          1、滴滴、滿幫、Boss直聘都被調(diào)查,為啥知乎美國上市沒被查?

          2、字節(jié)跳動(dòng)重大宣布:取消!員工炸了:直接降薪1

          3、再見了,Teamviewer!

          4、人臉識(shí)別的時(shí)候,一定要穿上衣服啊!

          5、程序員被公司辭退12天,前領(lǐng)導(dǎo)要求回公司講清楚代碼,結(jié)果懵了

          瀏覽 57
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码视频在线免费观看 | 亚洲无码高清在线观看 | 精品无人国产偷自产在线 | 射一身成人影视 | 中文字幕亚洲美 |