Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 精品国产91,特黄日韩免费一区二区三区,色聚网久久综合

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          程序員接私活利器 玩轉(zhuǎn)excel導(dǎo)入導(dǎo)出

          程序員接私活利器 玩轉(zhuǎn)excel導(dǎo)入導(dǎo)出

          什么會寫Easypoi

          以前的以前(歲月真TMD的快)我雖然寫了不少代碼但還是很少寫poi,然后跳到一家公司之后就和業(yè)務(wù)人員聊上了,來這個(gè)需要個(gè)報(bào)表,這個(gè)報(bào)表樣式是這樣的,這個(gè)表頭是這樣的,就這樣我寫了大量的poi代碼,每次都是大量的篇幅,copy to copy,無聊的一逼,然后加入了jeecg,jeecg中有一個(gè)小的工具類,雖然我也不知道是誰寫的,然是可以用注解搞定最簡單的導(dǎo)出,突然豁然開朗,我可以完善,讓我從報(bào)表的苦海當(dāng)中脫離出來,這樣我花了一周的時(shí)間做了第一個(gè)版本支持導(dǎo)入導(dǎo)出放到了jeecg,發(fā)現(xiàn)還是不錯(cuò)的,慢慢的用的人越來越多,我就把這塊獨(dú)立出來了,再然后有人提出了模板,然后就加入了模板功能,提出了word的需求,加入了word的功能,后來工作忙了雖然沒再參與jeecg,但還是一直維持這easypoi的更新,根據(jù)見識的增長也不斷的重構(gòu)這代碼,直到現(xiàn)在

          獨(dú)特的功能

          • 基于注解的導(dǎo)入導(dǎo)出,修改注解就可以修改Excel
          • 支持常用的樣式自定義
          • 基于map可以靈活定義的表頭字段
          • 支持一堆多的導(dǎo)出,導(dǎo)入
          • 支持模板的導(dǎo)出,一些常見的標(biāo)簽,自定義標(biāo)簽
          • 支持HTML/Excel轉(zhuǎn)換,如果模板還不能滿足用戶的變態(tài)需求,請用這個(gè)功能
          • 支持word的導(dǎo)出,支持圖片,Excel

          小白如何開始

          • 下載demo運(yùn)行看看,基本上常見的用用法都在里面easypoi-test
          • 查看幾個(gè)*Util的用法,Easypoi的主要輸出就是這個(gè)
          • 看看注解的意思
          • 看看模板的標(biāo)簽用法
          • 可以出師了

          Easypoi 為誰而開發(fā)

          • 不太熟悉poi的
          • 不想寫太多重復(fù)太多的
          • 只是簡單的導(dǎo)入導(dǎo)出的
          • 喜歡使用模板的

          都可以使用easypoi

          Easypoi的目標(biāo)是什么

          Easypoi的目標(biāo)不是替代poi,而是讓一個(gè)不懂導(dǎo)入導(dǎo)出的快速使用poi完成Excel和word的各種操作,而不是看很多api才可以完成這樣工作

          1.3 使用

          • 1.easypoi 父包--作用大家都懂得
          • 2.easypoi-annotation 基礎(chǔ)注解包,作用與實(shí)體對象上,拆分后方便maven多工程的依賴管理
          • 3.easypoi-base 導(dǎo)入導(dǎo)出的工具包,可以完成Excel導(dǎo)出,導(dǎo)入,Word的導(dǎo)出,Excel的導(dǎo)出功能
          • 4.easypoi-web 耦合了spring-mvc 基于AbstractView,極大的簡化spring-mvc下的導(dǎo)出功能
          • 5.sax 導(dǎo)入使用xercesImpl這個(gè)包(這個(gè)包可能造成奇怪的問題哈),word導(dǎo)出使用poi-scratchpad,都作為可選包了

          如果不使用spring mvc的便捷福利,直接引入easypoi-base 就可以了,easypoi-annotation

          1.4 測試項(xiàng)目

          測試這個(gè)事情真不是個(gè)容易的事情

          測試項(xiàng)目包括兩塊 Junit 的常見測試和spring 的view測試

          1.spring view測試

          運(yùn)行application就可以了,訪問界面,然后看到界面

          對應(yīng)的代碼在view下面

          2.Junit的測試目錄結(jié)構(gòu)如下

          • tohtml html預(yù)覽測試
          • view 導(dǎo)出的view測試
          • cache 自定義緩存測試
          • html html互轉(zhuǎn)測試
          • test
          • excel
          • read 讀取Excel測試
          • check 導(dǎo)入檢查測試
          • hanlder 導(dǎo)入數(shù)據(jù)處理
          • img 含圖片導(dǎo)入測試
          • styler 導(dǎo)出樣式自定義測試
          • template 模板導(dǎo)出測試
          • sum 導(dǎo)出含統(tǒng)計(jì)測試
          • test 導(dǎo)出測試
          • groupname groupname 屬性測試
          • img 導(dǎo)出圖片測試
          • pdf pdf測試
          • word word導(dǎo)出測試
          • util util 內(nèi)部測試

          目前的測試覆蓋率

          2. Excel 注解版

          2.1 Excel導(dǎo)入導(dǎo)出

          Excel的導(dǎo)入導(dǎo)出是Easypoi的核心功能,前期基本也是圍繞這個(gè)打造的,主要分為三種方式的處理,其中模板和Html目前只支持導(dǎo)出,因?yàn)橹С諱ap.class其實(shí)導(dǎo)入應(yīng)該是怎樣都支持的

          • 注解方式,注解變種方式
          • 模板方式
          • Html方式

          下面分別就這三種方式進(jìn)行講解

          2.2 注解

          注解介紹

          easypoi起因就是Excel的導(dǎo)入導(dǎo)出,最初的模板是實(shí)體和Excel的對應(yīng),model--row,filed--col 這樣利用注解我們可以和容易做到excel到導(dǎo)入導(dǎo)出

          經(jīng)過一段時(shí)間發(fā)展,現(xiàn)在注解有5個(gè)類分別是

          • @Excel 作用到filed上面,是對Excel一列的一個(gè)描述
          • @ExcelCollection 表示一個(gè)集合,主要針對一對多的導(dǎo)出,比如一個(gè)老師對應(yīng)多個(gè)科目,科目就可以用集合表示
          • @ExcelEntity 表示一個(gè)繼續(xù)深入導(dǎo)出的實(shí)體,但他沒有太多的實(shí)際意義,只是告訴系統(tǒng)這個(gè)對象里面同樣有導(dǎo)出的字段
          • @ExcelIgnore 和名字一樣表示這個(gè)字段被忽略跳過這個(gè)導(dǎo)導(dǎo)出
          • @ExcelTarget 這個(gè)是作用于最外層的對象,描述這個(gè)對象的id,以便支持一個(gè)對象可以針對不同導(dǎo)出做出不同處理

          注解中的ID的用法

          這個(gè)ID算是一個(gè)比較獨(dú)特的例子,比如

          @ExcelTarget("teacherEntity")
          public class TeacherEntity implements java.io.Serializable {
           /** name */
           @Excel(name="主講老師_teacherEntity,代課老師_absent", orderNum="1", mergeVertical=true,needMerge=true,isImportField="true_major,true_absent")
           private String name;
          

          這里的@ExcelTarget 表示使用teacherEntity這個(gè)對象是可以針對不同字段做不同處理

          同樣的ExcelEntity 和ExcelCollection 都支持這種方式

          當(dāng)導(dǎo)出這對象時(shí),name這一列對應(yīng)的是主講老師,而不是代課老師還有很多字段都支持這種做法

          @Excel

          這個(gè)是必須使用的注解,如果需求簡單只使用這一個(gè)注解也是可以的,涵蓋了常用的Excel需求,需要大家熟悉這個(gè)功能,主要分為基礎(chǔ),圖片處理,時(shí)間處理,合并處理幾塊,name_id是上面講的id用法,這里就不累言了

          屬性類型默認(rèn)值功能name

          String

          null

          列名,支持name_id

          needMerge

          boolean

          fasle

          是否需要縱向合并單元格(用于含有l(wèi)ist中,單個(gè)的單元格,合并list創(chuàng)建的多個(gè)row)

          orderNum

          String

          "0"

          列的排序,支持name_id

          replace

          String[]

          {}

          值得替換 導(dǎo)出是{a_id,b_id} 導(dǎo)入反過來

          savePath

          String

          "upload"

          導(dǎo)入文件保存路徑,如果是圖片可以填寫,默認(rèn)是upload/className/ IconEntity這個(gè)類對應(yīng)的就是upload/Icon/

          type

          int

          1

          導(dǎo)出類型 1 是文本 2 是圖片,3 是函數(shù),10 是數(shù)字 默認(rèn)是文本

          width

          double

          10

          列寬

          height

          double

          10

          列高,后期打算統(tǒng)一使用@ExcelTarget的height,這個(gè)會被廢棄,注意

          isStatistics

          boolean

          fasle

          自動統(tǒng)計(jì)數(shù)據(jù),在追加一行統(tǒng)計(jì),把所有數(shù)據(jù)都和輸出

          這個(gè)處理會吞沒異常,請注意這一點(diǎn)

          isHyperlink

          boolean

          false

          超鏈接,如果是需要實(shí)現(xiàn)接口返回對象

          isImportField

          boolean

          true

          校驗(yàn)字段,看看這個(gè)字段是不是導(dǎo)入的Excel中有,如果沒有說明是錯(cuò)誤的Excel,讀取失敗,支持name_id

          exportFormat

          String

          ""

          導(dǎo)出的時(shí)間格式,以這個(gè)是否為空來判斷是否需要格式化日期

          importFormat

          String

          ""

          導(dǎo)入的時(shí)間格式,以這個(gè)是否為空來判斷是否需要格式化日期

          format

          String

          ""

          時(shí)間格式,相當(dāng)于同時(shí)設(shè)置了exportFormat 和 importFormat

          databaseFormat

          String

          "yyyyMMddHHmmss"

          導(dǎo)出時(shí)間設(shè)置,如果字段是Date類型則不需要設(shè)置 數(shù)據(jù)庫如果是string 類型,這個(gè)需要設(shè)置這個(gè)數(shù)據(jù)庫格式,用以轉(zhuǎn)換時(shí)間格式輸出

          numFormat

          String

          ""

          數(shù)字格式化,參數(shù)是Pattern,使用的對象是DecimalFormat

          imageType

          int

          1

          導(dǎo)出類型 1 從file讀取 2 是從數(shù)據(jù)庫中讀取 默認(rèn)是文件 同樣導(dǎo)入也是一樣的

          suffix

          String

          ""

          文字后綴,如% 90 變成90%

          isWrap

          boolean

          true

          是否換行 即支持\n

          mergeRely

          int[]

          {}

          合并單元格依賴關(guān)系,比如第二列合并是基于第一列 則{0}就可以了

          mergeVertical

          boolean

          fasle

          縱向合并內(nèi)容相同的單元格

          fixedIndex

          int

          -1

          對應(yīng)excel的列,忽略名字

          isColumnHidden

          boolean

          false

          導(dǎo)出隱藏列

          @ExcelTarget

          限定一個(gè)到處實(shí)體的注解,以及一些通用設(shè)置,作用于最外面的實(shí)體

          屬性類型默認(rèn)值功能value

          String

          null

          定義ID

          height

          double

          10

          設(shè)置行高

          fontSize

          short

          11

          設(shè)置文字大小

          @ExcelEntity

          標(biāo)記是不是導(dǎo)出excel 標(biāo)記為實(shí)體類,一遍是一個(gè)內(nèi)部屬性類,標(biāo)記是否繼續(xù)穿透,可以自定義內(nèi)部id

          屬性類型默認(rèn)值功能id

          String

          null

          定義ID

          @ExcelCollection

          一對多的集合注解,用以標(biāo)記集合是否被數(shù)據(jù)以及集合的整體排序

          屬性類型默認(rèn)值功能id

          String

          null

          定義ID

          name

          String

          null

          定義集合列名,支持nanm_id

          orderNum

          int

          0

          排序,支持name_id

          type

          Class<?>

          ArrayList.class

          導(dǎo)入時(shí)創(chuàng)建對象使用

          @ExcelIgnore

          忽略這個(gè)屬性,多使用需循環(huán)引用中,無需多解釋吧^^

          2.3 注解導(dǎo)出,導(dǎo)入

          2.3.1 對象定義

          注解介紹了這么多,大家基本上也了解我們的注解是如何定義Excel的了吧,下面我們來跟著路飛實(shí)戰(zhàn)吧

          這天老師吧路飛叫到了辦公室,讓給給老師實(shí)現(xiàn)一個(gè)報(bào)表的需求,就是從教育平臺把某個(gè)班級的人員導(dǎo)出來

          需求是,導(dǎo)出我們班的所有學(xué)生的姓名,性別,出生日期,進(jìn)校日期

          正巧路飛剛看到Easypo,就打算用Easypoi來實(shí)現(xiàn),實(shí)現(xiàn)方法如下:

          首先定義一個(gè)我們導(dǎo)出的對象,為了節(jié)省篇幅,統(tǒng)一忽略getter,setter

           public class StudentEntity implements java.io.Serializable {
           /**
           * id
           */
           private String id;
           /**
           * 學(xué)生姓名
           */
           @Excel(name="學(xué)生姓名", height=20, width=30, isImportField="true_st")
           private String name;
           /**
           * 學(xué)生性別
           */
           @Excel(name="學(xué)生性別", replace={ "男_1", "女_2" }, suffix="生", isImportField="true_st")
           private int sex;
           @Excel(name="出生日期", databaseFormat="yyyyMMddHHmmss", format="yyyy-MM-dd", isImportField="true_st", width=20)
           private Date birthday;
           @Excel(name="進(jìn)校日期", databaseFormat="yyyyMMddHHmmss", format="yyyy-MM-dd")
           private Date registrationDate;
           }
          

          這里設(shè)置我們的4列分別是學(xué)生姓名,學(xué)生性別,出生日期,進(jìn)校日期

          其中學(xué)生姓名定義了我們的列的行高,學(xué)生性別因?yàn)槲覀兓旧隙际谴嬖跀?shù)據(jù)庫都是數(shù)字所以我們轉(zhuǎn)換下,兩個(gè)日期我們都是進(jìn)行了格式化輸出了,這樣我們就完成了業(yè)務(wù)對我們Excel的樣式需求,后面只有把這個(gè)學(xué)生列表輸出就可以了

          生成Excel代碼如下

           Workbook workbook=ExcelExportUtil.exportExcel(new ExportParams("計(jì)算機(jī)一班學(xué)生","學(xué)生"),
           StudentEntity .class, list);
          

          這樣我們就得到的一個(gè)java中的Excel,然后把這個(gè)輸出就得到我們的Excel了https://static.oschina.net/uploads/space/2017/0622/212811_uh7e_1157922.png

          2.3.2 集合定義

          路飛很快的完成了老師的任務(wù),花了也就是喝杯茶的時(shí)間,就交差了,但過了一會就又被老師叫去了,讓他給出一個(gè)某個(gè)班級選擇選擇某些課的學(xué)生以及對應(yīng)的老師

          路飛又很快的想到了Easypoi,其中有一對多的導(dǎo)出,這不正是一對多的體現(xiàn)嗎,然后他繼續(xù)定義實(shí)體:

          一個(gè)課程對應(yīng)一個(gè)老師

          一個(gè)課程對應(yīng)N個(gè)學(xué)生

          課程的實(shí)體

           @ExcelTarget("courseEntity")
           public class CourseEntity implements java.io.Serializable {
           /** 主鍵 */
           private String id;
           /** 課程名稱 */
           @Excel(name="課程名稱", orderNum="1", width=25)
           private String name;
           /** 老師主鍵 */
           @ExcelEntity(id="absent")
           private TeacherEntity mathTeacher;
           @ExcelCollection(name="學(xué)生", orderNum="4")
           private List<StudentEntity> students;
           }
          

          教師的實(shí)體

          @ExcelTarget("teacherEntity")
          public class TeacherEntity implements java.io.Serializable {
           private String id;
           /** name */
           @Excel(name="主講老師_major,代課老師_absent", orderNum="1", isImportField="true_major,true_absent")
           private String name;
          

          這里在課程這個(gè)實(shí)體里面就完成了一堆多的導(dǎo)出,達(dá)到了我們基礎(chǔ)需求,同時(shí)使用了orderNum對我們的列進(jìn)行了排序,滿足老師的需求,導(dǎo)出代碼如下

           Workbook workbook=ExcelExportUtil.exportExcel(new ExportParams("2412312", "測試", "測試"),
           CourseEntity.class, list);
          

          這樣我們就完成了老師的需求,效果如圖2.3.2-1

          但是課程名和代課老師沒有合并,不太美觀

          路飛又果斷給課程名稱和代課老師加了needMerge=true的屬性,就可以完成單元格的合并

           /** 課程名稱 */
           @Excel(name="課程名稱", orderNum="1", width=25,needMerge=true)
           private String name;
           //--------------------------------
           /** name */
           @Excel(name="主講老師_major,代課老師_absent", orderNum="1",needMerge=true, isImportField="true_major,true_absent")
          

          效果如圖2.3.2-2

          到這里,路飛就完美的完成了老師的任務(wù),快樂的去交差了

          圖2.3.2-1

          圖2.3.2-2

          2.3.3 圖片的導(dǎo)出

          在日常運(yùn)作中不可避免的會遇到圖片的導(dǎo)入導(dǎo)出,這里提供了兩種類型的圖片導(dǎo)出方式

          @Excel(name="公司LOGO", type=2 ,width=40 , height=20,imageType=1)
           private String companyLogo;
          
          1. 表示type=2 該字段類型為圖片,imageType=1 (默認(rèn)可以不填),表示從file讀取,字段類型是個(gè)字符串類型 可以用相對路徑也可以用絕對路徑,絕對路徑優(yōu)先依次獲取
          @Excel(name="公司LOGO", type=2 ,width=40 , height=20,imageType=1)
           private byte[] companyLogo;
          
          1. 2.表示type=2 該字段類型為圖片,imageType=2 ,表示從數(shù)據(jù)庫或者已經(jīng)讀取完畢,字段類型是個(gè)字節(jié)數(shù)組 直接使用 同時(shí),image 類型的cell最好設(shè)置好寬和高,會百分百縮放到cell那么大,不是原尺寸,這里注意下

          效果如下

          List<CompanyHasImgModel> list;
           @Before
           public void initData() {
           list=new ArrayList<CompanyHasImgModel>();
           list.add(new CompanyHasImgModel("百度", "imgs/company/baidu.png", "北京市海淀區(qū)西北旺東路10號院百度科技園1號樓"));
           list.add(new CompanyHasImgModel("阿里巴巴", "imgs/company/ali.png", "北京市海淀區(qū)西北旺東路10號院百度科技園1號樓"));
           list.add(new CompanyHasImgModel("Lemur", "imgs/company/lemur.png", "亞馬遜熱帶雨林"));
           list.add(new CompanyHasImgModel("一眾", "imgs/company/one.png", "山東濟(jì)寧俺家"));
           }
           @Test
           public void exportCompanyImg() throws Exception {
           File savefile=new File("D:/excel/");
           if (!savefile.exists()) {
           savefile.mkdirs();
           }
           Workbook workbook=ExcelExportUtil.exportExcel(new ExportParams(), CompanyHasImgModel.class, list);
           FileOutputStream fos=new FileOutputStream("D:/excel/ExcelExportHasImgTest.exportCompanyImg.xls");
           workbook.write(fos);
           fos.close();
           }
          

          運(yùn)行效果

          2.3.3 -1

          2.3.4 Excel導(dǎo)入介紹

          有導(dǎo)出就有導(dǎo)入,基于注解的導(dǎo)入導(dǎo)出,配置配置上是一樣的,只是方式反過來而已,比如類型的替換 導(dǎo)出的時(shí)候是1替換成男,2替換成女,導(dǎo)入的時(shí)候則反過來,男變成1 ,女變成2,時(shí)間也是類似

          導(dǎo)出的時(shí)候date被格式化成 2017-8-25 ,導(dǎo)入的時(shí)候2017-8-25被格式成date類型

          下面說下導(dǎo)入的基本代碼,注解啥的都是上面講過了,這里就不累贅了

           @Test
           public void test2() {
           ImportParams params=new ImportParams();
           params.setTitleRows(1);
           params.setHeadRows(1);
           long start=new Date().getTime();
           List<MsgClient> list=ExcelImportUtil.importExcel(
           new File(PoiPublicUtil.getWebRootPath("import/ExcelExportMsgClient.xlsx")),
           MsgClient.class, params);
           System.out.println(new Date().getTime() - start);
           System.out.println(list.size());
           System.out.println(ReflectionToStringBuilder.toString(list.get(0)));
           }
          

          基本是寫法也很簡單,ImportParams 參數(shù)介紹下

          屬性類型默認(rèn)值功能titleRows

          int

          0

          表格標(biāo)題行數(shù),默認(rèn)0

          headRows

          int

          1

          表頭行數(shù),默認(rèn)1

          startRows

          int

          0

          字段真正值和列標(biāo)題之間的距離 默認(rèn)0

          keyIndex

          int

          0

          主鍵設(shè)置,如何這個(gè)cell沒有值,就跳過 或者認(rèn)為這個(gè)是list的下面的值

          這一列必須有值,不然認(rèn)為這列為無效數(shù)據(jù)

          startSheetIndex

          int

          0

          開始讀取的sheet位置,默認(rèn)為0

          sheetNum

          int

          1

          上傳表格需要讀取的sheet 數(shù)量,默認(rèn)為1

          needSave

          boolean

          false

          是否需要保存上傳的Excel

          needVerfiy

          boolean

          false

          是否需要校驗(yàn)上傳的Excel

          saveUrl

          String

          "upload/excelUpload"

          保存上傳的Excel目錄,默認(rèn)是 如 TestEntity這個(gè)類保存路徑就是

          upload/excelUpload/Test/yyyyMMddHHmss* 保存名稱上傳時(shí)間五位隨機(jī)數(shù)

          verifyHanlder

          IExcelVerifyHandler

          null

          校驗(yàn)處理接口,自定義校驗(yàn)

          lastOfInvalidRow

          int

          0

          最后的無效行數(shù),不讀的行數(shù)

          readRows

          int

          0

          手動控制讀取的行數(shù)

          importFields

          String[]

          null

          導(dǎo)入時(shí)校驗(yàn)數(shù)據(jù)模板,是不是正確的Excel

          keyMark

          String

          ":"

          Key-Value 讀取標(biāo)記,以這個(gè)為Key,后面一個(gè)Cell 為Value,多個(gè)改為ArrayList

          readSingleCell

          boolean

          false

          按照Key-Value 規(guī)則讀取全局掃描Excel,但是跳過List讀取范圍提升性能

          僅僅支持titleRows + headRows + startRows 以及 lastOfInvalidRow

          dataHanlder

          IExcelDataHandler

          null

          數(shù)據(jù)處理接口,以此為主,replace,format都在這后面

          2.3.5 Excel導(dǎo)入小功能

          1. 讀取指定的sheet
          2. 比如要讀取上傳得第二個(gè)sheet 那么需要把startSheetIndex=1 就可以了
          3. 讀取幾個(gè)sheet
          4. 比如讀取前2個(gè)sheet,那么 sheetNum=2 就可以了
          5. 讀取第二個(gè)到第五個(gè)sheet
          6. 設(shè)置 startSheetIndex=1 然后sheetNum=4
          7. 讀取全部的sheet
          8. sheetNum 設(shè)置大點(diǎn)就可以了
          9. 保存Excel
          10. 設(shè)置 needVerfiy=true,默認(rèn)保存的路徑為upload/excelUpload/Test/yyyyMMddHHmss* 保存名稱上傳時(shí)間五位隨機(jī)數(shù)
          11. 如果自定義路徑 修改下saveUrl 就可以了,同時(shí)saveUrl也是圖片上傳時(shí)候的保存的路徑
          12. 判斷一個(gè)Excel是不是合法的Excel
          13. importFields 設(shè)置下值,就是表示表頭必須至少包含的字段,如果缺一個(gè)就是不合法的excel,不導(dǎo)入

          2.3.6 圖片的導(dǎo)入

          有圖片的導(dǎo)出就有圖片的導(dǎo)入,導(dǎo)入的配置和導(dǎo)出是一樣的,但是需要設(shè)置保存路徑

          1.設(shè)置保存路徑saveUrl 默認(rèn)為"upload/excelUpload"

          可以手動修改 ImportParams 修改下就可以了

           @Test
           public void test() {
           try {
           ImportParams params=new ImportParams();
           params.setNeedSave(true);
           List<CompanyHasImgModel> result=ExcelImportUtil.importExcel(
           new File(PoiPublicUtil.getWebRootPath("import/imgexcel.xls")),
           CompanyHasImgModel.class, params);
           for (int i=0; i < result.size(); i++) {
           System.out.println(ReflectionToStringBuilder.toString(result.get(i)));
           }
           Assert.assertTrue(result.size()==4);
           } catch (Exception e) {
           e.printStackTrace();
           }
           }
          }
          

          導(dǎo)入日志

          16:35:43.081 [main] DEBUG c.a.e.e.imports.ExcelImportServer - Excel import start ,class is class cn.afterturn.easypoi.test.entity.img.CompanyHasImgModel
          16:35:43.323 [main] DEBUG c.a.e.e.imports.ExcelImportServer - start to read excel by is ,startTime is 1503650143323
          16:35:43.344 [main] DEBUG c.a.e.e.imports.ExcelImportServer - end to read excel by is ,endTime is 1503650143344
          16:35:43.429 [main] DEBUG c.a.e.e.imports.ExcelImportServer - end to read excel list by pos ,endTime is 1503650143429
          cn.afterturn.easypoi.test.entity.img.CompanyHasImgModel@1b083826[companyName=百度,companyLogo=upload/CompanyHasImgModel/pic88273295062.PNG,companyAddr=北京市海淀區(qū)西北旺東路10號院百度科技園1號樓]
          cn.afterturn.easypoi.test.entity.img.CompanyHasImgModel@105fece7[companyName=阿里巴巴,companyLogo=upload/CompanyHasImgModel/pic22507938183.PNG,companyAddr=北京市海淀區(qū)西北旺東路10號院百度科技園1號樓]
          cn.afterturn.easypoi.test.entity.img.CompanyHasImgModel@3ec300f1[companyName=Lemur,companyLogo=upload/CompanyHasImgModel/pic86390457892.PNG,companyAddr=亞馬遜熱帶雨林]
          cn.afterturn.easypoi.test.entity.img.CompanyHasImgModel@482cd91f[companyName=一眾,companyLogo=upload/CompanyHasImgModel/pic69566571093.PNG,companyAddr=山東濟(jì)寧俺家]
          

          2.3.5-1

          2.3.7 Excel多Sheet導(dǎo)出

          目前單Sheet和單Class的方式比較多,對于多Sheet的方式還是一片空白,這里做一下說明:

          導(dǎo)出基本采用ExportParams 這個(gè)對象,進(jìn)行參數(shù)配置;

          我們需要進(jìn)行多Sheet導(dǎo)出,那么就需要定義一個(gè)基礎(chǔ)配置對象

          public class ExportView {
           public ExportView(){
           }
           private ExportParams exportParams;
           private List<?> dataList;
           private Class<?> cls;
           public ExportParams getExportParams() {
           return exportParams;
           }
           public void setExportParams(ExportParams exportParams) {
           this.exportParams=exportParams;
           }
           public Class<?> getCls() {
           return cls;
           }
           public void setCls(Class<?> cls) {
           this.cls=cls;
           }
           public List<?> getDataList() {
           return dataList;
           }
           public void setDataList(List<?> dataList) {
           this.dataList=dataList;
           }
           public ExportView(Builder builder) {
           this.exportParams=builder.exportParams;
           this.dataList=builder.dataList;
           this.cls=builder.cls;
           }
           public static class Builder {
           private ExportParams exportParams=null;
           private List<?> dataList=null;
           private Class<?> cls=null;
           public Builder() {
           }
           public Builder exportParams(ExportParams exportParams) {
           this.exportParams=exportParams;
           return this;
           }
           public Builder dataList(List<?> dataList) {
           this.dataList=dataList;
           return this;
           }
           public Builder cls(Class<?> cls) {
           this.cls=cls;
           return this;
           }
           public ExportView create() {
           return new ExportView(this);
           }
           }
          }
          

          對象主要有三個(gè)屬性:

          // 該注解配置的導(dǎo)出屬性

          1. ExportParams exportParams // 對應(yīng)注解 class 實(shí)例對象的數(shù)據(jù)集合
          2. List<?> dataList // 對應(yīng)注解的 class
          3. Class<?> cls

          這里沒有用泛型,因?yàn)槎郤heet導(dǎo)出時(shí),會引用到不同的注解對象;

          定義基礎(chǔ)配置的集合

          public class ExportMoreView {
           private List<ExportView> moreViewList=Lists.newArrayList();
           public List<ExportView> getMoreViewList() {
           return moreViewList;
           }
           public void setMoreViewList(List<ExportView> moreViewList) {
           this.moreViewList=moreViewList;
           }
          }
          

          最后在實(shí)現(xiàn)調(diào)用的方法中,對整個(gè)集合進(jìn)行配置和解析

          List<Map<String, Object>> exportParamList=Lists.newArrayList();
           //該行主要用于獲取業(yè)務(wù)數(shù)據(jù),請根據(jù)具體的情況進(jìn)行修改和調(diào)整 
          ExportMoreView moreView=this.getBaseTransferService().mergeExportView(templateTypeCode);
           //迭代導(dǎo)出對象,將對應(yīng)的配置信息寫入到實(shí)際的配置中
           for(ExportView view:moreView.getMoreViewList()){
           Map<String, Object> valueMap=Maps.newHashMap();
           valueMap.put(NormalExcelConstants.PARAMS,view.getExportParams());
           valueMap.put(NormalExcelConstants.DATA_LIST,view.getDataList());
           valueMap.put(NormalExcelConstants.CLASS,view.getCls());
           exportParamList.add(valueMap);
           }
           //實(shí)現(xiàn)導(dǎo)出配置
           modelMap.put(NormalExcelConstants.FILE_NAME,new DateTime().toString("yyyyMMddHHmmss"));
           //將轉(zhuǎn)換完成的配置接入到導(dǎo)出中
           modelMap.put(NormalExcelConstants.MAP_LIST,exportParamList);
           return NormalExcelConstants.JEECG_EXCEL_VIEW;
          

          如果不是采用的MVC的方式,請將轉(zhuǎn)換的配置采用以下的方式實(shí)現(xiàn):

          參見ExcelExportUtil

          2.4 注解變種-更自由的導(dǎo)出

          這天老師又把路飛喊道的辦公室,要求路飛導(dǎo)出班級學(xué)生的整體信息

           @Excel(name="學(xué)生姓名", height=20, width=30, isImportField="true_st")
           private String name;
           @Excel(name="學(xué)生性別", replace={ "男_1", "女_2" }, suffix="生", isImportField="true_st")
           private int sex;
           @Excel(name="出生日期", databaseFormat="yyyyMMddHHmmss", format="yyyy-MM-dd", isImportField="true_st", width=20)
           private Date birthday;
           @Excel(name="進(jìn)校日期", databaseFormat="yyyyMMddHHmmss", format="yyyy-MM-dd")
           private Date registrationDate;
          

          路飛飛快的用到上面的學(xué)到的知識搞定了,這這時(shí)有一個(gè)老師把路飛叫去,說想要導(dǎo)出一個(gè)不要出生日期的Excel,感覺用戶需求很無奈,路飛又造兩個(gè)一個(gè)bean,把這個(gè)注解去掉了,來導(dǎo)出

           @Excel(name="學(xué)生姓名", height=20, width=30, isImportField="true_st")
           private String name;
           @Excel(name="學(xué)生性別", replace={ "男_1", "女_2" }, suffix="生", isImportField="true_st")
           private int sex;
           @Excel(name="進(jìn)校日期", databaseFormat="yyyyMMddHHmmss", format="yyyy-MM-dd")
           private Date registrationDate;
          

          雖然解決了老師的需求,但這個(gè)并不是一個(gè)完美的解決方案,下面介紹一個(gè)更自由的解決方案

          注解的導(dǎo)出,規(guī)定我們必須把model寫好,并且注解寫好,每次導(dǎo)出的Excel都是固定的,無法動態(tài)控制導(dǎo)出的列,雖然可以通過id來處理一個(gè)案例,但是自由度遠(yuǎn)遠(yuǎn)不夠,這里介紹個(gè)變種支持,基本支持注解所有的功能

          基于List<ExcelExportEntity> 的導(dǎo)出,ExcelExportEntity是注解經(jīng)過處理翻譯成的實(shí)體類,兩者幾乎是一對的,所以如果我們要?jiǎng)討B(tài)自定義導(dǎo)出列,我們只要?jiǎng)討B(tài)拼裝ExcelExportEntity就可以了

          下面我們看下這個(gè)類

          /**
           * 如果是MAP導(dǎo)出,這個(gè)是map的key
           */
           private Object key;
           private double width=10;
           private double height=10;
           /**
           * 圖片的類型,1是文件,2是數(shù)據(jù)庫
           */
           private int exportImageType=0;
           /**
           * 排序順序
           */
           private int orderNum=0;
           /**
           * 是否支持換行
           */
           private boolean isWrap;
           /**
           * 是否需要合并
           */
           private boolean needMerge;
           /**
           * 單元格縱向合并
           */
           private boolean mergeVertical;
           /**
           * 合并依賴
           */
           private int[] mergeRely;
           /**
           * 后綴
           */
           private String suffix;
           /**
           * 統(tǒng)計(jì)
           */
           private boolean isStatistics;
           private String numFormat;
           private List<ExcelExportEntity> list;
          

          基本上是和注解對應(yīng)的, List<ExcelExportEntity> list 這個(gè)是對應(yīng)的一對多的導(dǎo)出,相當(dāng)于集合,其他基本上都是和注解保持一致

          下面給出正常的demo

          public void test() {
           try {
           List<ExcelExportEntity> entity=new ArrayList<ExcelExportEntity>();
          //構(gòu)造對象等同于@Excel
           ExcelExportEntity excelentity=new ExcelExportEntity("姓名", "name");
           excelentity.setNeedMerge(true);
           entity.add(excelentity);
           entity.add(new ExcelExportEntity("性別", "sex"));
           excelentity=new ExcelExportEntity(null, "students");
           List<ExcelExportEntity> temp=new ArrayList<ExcelExportEntity>();
           temp.add(new ExcelExportEntity("姓名", "name"));
           temp.add(new ExcelExportEntity("性別", "sex"));
          //構(gòu)造List等同于@ExcelCollection 
           excelentity.setList(temp);
           entity.add(excelentity);
           List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
          //把我們構(gòu)造好的bean對象放到params就可以了
           Workbook workbook=ExcelExportUtil.exportExcel(new ExportParams("測試", "測試"), entity,
           list);
           FileOutputStream fos=new FileOutputStream("D:/excel/ExcelExportForMap.tt.xls");
           workbook.write(fos);
           fos.close();
           } catch (FileNotFoundException e) {
           e.printStackTrace();
           } catch (IOException e) {
           e.printStackTrace();
           }
           }
          

          路飛想到了這個(gè)方案,并且用上面做了測試可以完美解決所以他把之前的代碼改為了(代碼有刪減,基本上都是和注解對應(yīng)的)

          List<ExcelExportEntity> beanList=new ArrayList<ExcelExportEntity>();
          beanList .add(new ExcelExportEntity(new ExcelExportEntity("學(xué)生姓名", "name"));
          beanList .add(new ExcelExportEntity("學(xué)生性別", "sex"));
          beanList .add(new ExcelExportEntity("進(jìn)校日期", "registrationDate"));
          if(needBirthday()){
           beanList .add(new ExcelExportEntity("出生日期", "birthday"));
          }
           Workbook workbook=ExcelExportUtil.exportExcel(new ExportParams("測試", "測試"), beanList ,
           list);
          

          用同一套代買完美了支持了老師的需求,心滿意足的回宿舍了^^

          2.5 Map導(dǎo)入,自由發(fā)揮

          這天,老師把路飛叫到辦公室,總是被叫,能者的悲哀啊,讓他臨時(shí)導(dǎo)入一批數(shù)據(jù),到數(shù)據(jù)庫,但是中間需要處理一些字段邏輯沒辦法直接導(dǎo)入到數(shù)據(jù)庫,

          這時(shí)路飛首先想到構(gòu)造一個(gè)bean然后標(biāo)記注解,導(dǎo)入處理對象,但是想想一次的對象太過于浪費(fèi),不如用map試試,獲取map處理map也是一樣的

          導(dǎo)入的邏輯就變成了

           ImportParams params=new ImportParams();
           params.setDataHanlder(new MapImportHanlder());
           long start=new Date().getTime();
           List<Map<String, Object>> list=ExcelImportUtil.importExcel(
           new File(PoiPublicUtil.getWebRootPath("import/check.xls")), Map.class, params);
          

          導(dǎo)入后,處理每個(gè)map,然后入庫完美的解決了老師的需求,簡單更快捷,和bean導(dǎo)入基礎(chǔ)沒有區(qū)別,省去了bean的構(gòu)造時(shí)間

          PS:這個(gè)作者也只是在臨時(shí)方案中或者一次性活當(dāng)中使用,一般還是推薦注解這種方式,擁有更高的代碼閱讀性

          !!!測試了時(shí)間的,最好導(dǎo)入使用文本格式,可以獲取時(shí)間格式可能無法獲取

          2.6 Excel的樣式自定義

          "路飛,來辦公室一趟",就這樣路飛又被叫到了辦公室,這次老師的需求是,想要一個(gè)漂亮點(diǎn)的Excel,希望路飛可以點(diǎn)綴下Excel,思來想去還是需要用poi的style來解決,但是如果每個(gè)都寫style是不是太麻煩,而且Excel的styler數(shù)量是有限制的,這里就需要盡量復(fù)用已經(jīng)創(chuàng)造的style,看看之前的Excel表格,大體上可以分為[標(biāo)題,表頭,表體],那可以說的就是創(chuàng)建一個(gè)接口每次調(diào)用這三個(gè)接口就可以了不說干就干

          public interface IExcelExportStyler {
           /**
           * 列表頭樣式
           * @param headerColor
           * @return
           */
           public CellStyle getHeaderStyle(short headerColor);
           /**
           * 標(biāo)題樣式
           * @param color
           * @return
           */
           public CellStyle getTitleStyle(short color);
           /**
           * 獲取樣式方法
           * @param Parity
           * @param entity
           * @return
           */
           public CellStyle getStyles(boolean Parity, ExcelExportEntity entity);
          }
          

          實(shí)現(xiàn)類盡量復(fù)用已經(jīng)創(chuàng)建的Styler,切記

          這樣路飛先造了一個(gè)帶邊框的styler ,ExcelExportStylerBorderImpl

          效果如下

          然后路飛又手癢寫了個(gè)帶換行顏色的 ExcelExportStylerColorImpl

          效果如下

          客官看到這里應(yīng)該就大體理解了我們的實(shí)現(xiàn)方法了吧,

          最后路飛實(shí)現(xiàn)了一個(gè)復(fù)雜的按照老師要求的樣式交差了


          styler接口用法

          上面兩個(gè)表頭和標(biāo)題樣式不用解釋

          后面這個(gè)是傳入當(dāng)前列的以及奇偶行,用戶可以根據(jù)需求實(shí)現(xiàn)業(yè)務(wù),包括去掉Excel的小箭頭(也就是設(shè)置數(shù)字為數(shù)字格式的Cell),完成居中,字體等等各式各樣的需求

          但是這里無法實(shí)現(xiàn)特別沒的Excel,如果有這種需求可以使用模板來實(shí)現(xiàn),在Excel點(diǎn)點(diǎn)就可以完美實(shí)現(xiàn)

          獲取源碼方式 轉(zhuǎn)發(fā)+【關(guān)注】,私信回復(fù)【eypoi】,即可免費(fèi)獲取源碼地址

          家好,接下來幾篇文章我將分享基于SSM整合POI實(shí)現(xiàn)Excel的導(dǎo)入導(dǎo)出,并介紹如何采用MVC三層模式體驗(yàn)企業(yè)級JavaWeb應(yīng)用的開發(fā)流程。而這些功能我進(jìn)行了整理并錄制了一套完整的視頻教程,具體的功能列表如下:

          1、SSM的整合流程;

          2、POI導(dǎo)入導(dǎo)出Excel;

          3、增加、刪除、修改、搜索功能。

          其中,我對整個(gè)項(xiàng)目進(jìn)行了兩種方式的整合:第一種是采用傳統(tǒng)的往lib目錄丟jar包;第二種是采用maven的方式進(jìn)行整合;而視頻教程中采用的是第一種方式。當(dāng)然啦,這兩種方式的源碼我這里都有!感興趣的童鞋可以私聊!

          大家也可以搜索“程序員實(shí)戰(zhàn)基地”,關(guān)于poi實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出介紹視頻鏈接如下:

          http://list.youku.com/albumlist/show/id_51818026.html

          asyPOI 與 SpringMVC

          在開發(fā)前端這塊大多使用 SpringMVC,EasyPOI 也提供了 對 SpringMVC 的支持;

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

          EasypoiMapExcelView map 列表導(dǎo)出

          EasypoiPDFTemplateView pdf導(dǎo)出

          EasypoiSingleExcelView 注解導(dǎo)出

          EasypoiTemplateExcelView 模板導(dǎo)出

          EasypoiTemplateWordView word模板導(dǎo)出

          MapGraphExcelView 圖表導(dǎo)出


          導(dǎo)入頁面

          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <html>
          <head>
              <title>Title</title>
              <%@include file="/WEB-INF/views/head.jsp" %>
          </head>
          <body>
          
          <span style="color: red">${count}</span>
          <!-- 上傳請配置enctype -->
          <form action="/import/xlsx" method="post" enctype="multipart/form-data">
              <input class="easyui-filebox" name="xlsxFile" data-options="prompt:'選擇一個(gè)文件...'" style="width:80%">
              <button class="easyui-linkbutton" type="submit">確定</button>
          </form>
          </body>
          </html>

          Controller

          @Controller
          @RequestMapping("/import")
          public class ImportController extends BaseController {
          
              @Autowired
              private IEmployeeService employeeService;
              @Autowired
              private IDepartmentService departmentService;
          
              //跳轉(zhuǎn)到導(dǎo)入頁面
              @RequestMapping("/index")
              public String index(){
                  return "import";
              }
          
              //跳轉(zhuǎn)到導(dǎo)入頁面
              @RequestMapping("/xlsx")
              public String importXlsx(MultipartFile xlsxFile, HttpServletRequest request, HttpServletResponse response) throws Exception{
          
                  ImportParams params=new ImportParams();
                  params.setTitleRows(1); //注意:這里有兩個(gè)表頭
                  List<Employee> list=ExcelImportUtil.importExcel(
                         xlsxFile.getInputStream(),
                          Employee.class, params);
                  for (Employee employee : list) {
                      employee.setPassword("123"); //默認(rèn)密碼123
                      if(employee.getDepartment()!=null) {
                          Department department=departmentService.findByName(employee.getDepartment().getName());
                          employee.setDepartment(department);
                      }
                      employeeService.save(employee);
                  }
                  return "import";
              }
          }

          自定義驗(yàn)證(用戶名重復(fù))

          自定義驗(yàn)證需要實(shí)現(xiàn)IExcelVerifyHandler接口


          主站蜘蛛池模板: 亚洲一区二区影院| 国产一区二区三区乱码网站| 99精品国产一区二区三区不卡| 熟妇人妻一区二区三区四区| 国产波霸爆乳一区二区| 日本夜爽爽一区二区三区| 亚洲制服中文字幕第一区| 国产MD视频一区二区三区| 日韩精品中文字幕视频一区| 日韩好片一区二区在线看| 自慰无码一区二区三区| 中文无码AV一区二区三区| 久久精品国产一区| 国产在线不卡一区二区三区| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 欧洲无码一区二区三区在线观看| 日韩AV在线不卡一区二区三区 | 国产精品视频分类一区| 无码人妻精品一区二区三区在线| 亚洲一区AV无码少妇电影☆| 亚洲高清偷拍一区二区三区| 国产一区二区三区乱码在线观看| 国产精品成人免费一区二区| 国产精品成人免费一区二区| 日本一区高清视频| 精品久久久久一区二区三区| 精品一区中文字幕| 国产aⅴ精品一区二区三区久久| 国产精品一区二区久久沈樵| 色系一区二区三区四区五区| 一区在线免费观看| 日韩人妻无码一区二区三区久久99 | 精品国产乱码一区二区三区 | 国产av一区二区三区日韩| 成人毛片无码一区二区| 国产剧情一区二区| 婷婷国产成人精品一区二| 中文字幕精品一区| av无码免费一区二区三区| 国产拳头交一区二区| 狠狠色婷婷久久一区二区三区|