朱虎平,艾迪
(九江職業(yè)技術(shù)學(xué)院,江西九江 332007)
隨著信息化辦公的不斷普及,大量日常生產(chǎn)和管理過程中產(chǎn)生的數(shù)據(jù)都會(huì)通過各種應(yīng)用軟件來管理,這極大地提高了工作效率。但在應(yīng)用軟件需要從外部批量導(dǎo)入或向外部批量導(dǎo)出數(shù)據(jù)時(shí),若采用人工方式進(jìn)行逐條操作,則工作煩瑣、效率低下又容易出錯(cuò),而如果能借助Excel辦公軟件,憑借其強(qiáng)大的數(shù)據(jù)處理能力,則能獲得事半功倍的效果。
在Java應(yīng)用軟件中,要對(duì)Excel文件進(jìn)行操作,常用的開源工具有JexcelAPI〔1〕(簡稱jxl)類庫。長期以來,各類文獻(xiàn)及應(yīng)用軟件,針對(duì)Jxl的Excel文件讀寫操作都是以Jxl的API接口為實(shí)現(xiàn)方法,直接根據(jù)應(yīng)用軟件的業(yè)務(wù)規(guī)則定制編寫Excel讀寫的模塊,從而實(shí)現(xiàn)Java應(yīng)用軟件與外部Excel文件進(jìn)行數(shù)據(jù)批量導(dǎo)入導(dǎo)出的操作。這種緊耦合的集成方法只能夠?qū)崿F(xiàn)對(duì)固定業(yè)務(wù)的需求,而對(duì)于不同業(yè)務(wù)間的需求變化只能通過代碼重構(gòu)才能實(shí)現(xiàn)。由于業(yè)務(wù)規(guī)則與Excel讀寫操作摻雜在一起,形成了一定的相互依賴,致使軟件代碼可維護(hù)性和擴(kuò)展性變得更加困難,并且難以及時(shí)適應(yīng)新的需求變化。
因此,在數(shù)據(jù)已成為各種應(yīng)用軟件的核心情況下,基于jxl工具類庫,研究并實(shí)現(xiàn)一種針對(duì)Java應(yīng)用軟件與Excel文件進(jìn)行數(shù)據(jù)交互的松耦合編程方法,就顯得尤為有價(jià)值和意義了。
Jxl是一款優(yōu)秀的開源Java API, 通過它Java研發(fā)人員可以較為方便、快捷地讀取和新建Excel文件。簡單常用的方法和接口有Workbook、Sheet、Cell、Label、WritableWorkbook、WritableSheet、WritableCell等。讀寫具體步驟如下。
第一步:InputStream is = new FileInputStream(ExcelFile);
第二步:Workbook readBook = Workbook.getWorkbook(is);
第三步:Sheet readSheet = readBook.getSheet(index);
第四步:Cell cell = readSheet.getCell(row,col);
第五步:String content = cell.getContents();
第六步:is.close()、readBook.close()。
第一步:OutputStram os = new FileOutputStream(ExcelFile);
第二步:WritableWorkbook writeBook=Workbook.createWorkbook(os);
第三步:WritableSheet writeSheet = writeBook.createSheet (“SheetName”, index);
第四步:Label label = new Label(row, col,“Label cell”);
第五步:writeSheet.addCell(label);
第六步:writeBook.write();
第七步:os.close()、writeBook.close()。
圖1 Jxl API讀取Excel文件操作
圖2 Jxl API寫入Excel文件操作
以上兩種基于Jxl API直接讀取和創(chuàng)建Excel文件的操作方法,長期以來,一直是各類文獻(xiàn)及Java應(yīng)用軟件根據(jù)業(yè)務(wù)規(guī)則定制實(shí)現(xiàn)Excel文件讀寫操作的最終解決方案。該方案雖然有效解決了Java應(yīng)用軟件與Excel文件間的數(shù)據(jù)交互問題,但卻是通過在應(yīng)用軟件中直接控制Excel文件中每一個(gè)Cell單元格讀寫操作實(shí)現(xiàn)的。這種Excel文件底層具體讀寫過程與應(yīng)用軟件高度耦合的編程方式,是計(jì)算機(jī)軟件工程思想所不推崇的解決方案。
基于上述傳統(tǒng)方案的優(yōu)缺點(diǎn),本文在Jxl API直接讀取和創(chuàng)建Excel文件的基礎(chǔ)上,結(jié)合Java注解和Java反射機(jī)制〔2〕,利用面向?qū)ο缶幊碳夹g(shù),提出了一種全新的將Java應(yīng)用軟件業(yè)務(wù)規(guī)則與Excel文件底層讀寫操作分離的松耦合編程思想,并成功實(shí)現(xiàn)了Java應(yīng)用軟件與Excel文件底層讀寫操作分離的松耦合編程設(shè)計(jì)。
注解也叫元數(shù)據(jù),是JDK1.5版本開始引入的一個(gè)特性,其為用戶提供了@Retention、@Target、@Inherited等元注解和@interface自定義注解方法,可對(duì)代碼中的package、types(類、接口、枚舉)、類型成員(構(gòu)造方法、方法、成員變量)、方法參數(shù)等進(jìn)行注解〔3〕。通過@interface自定義注解方法,用戶編寫代碼時(shí)可依據(jù)業(yè)務(wù)規(guī)則靈活自定義注解,并利用@Retention、@Target、@Inherited等元注解對(duì)自定義注解進(jìn)行注解;再根據(jù)自定義注解與Java反射機(jī)制有機(jī)結(jié)合,可實(shí)現(xiàn)在程序動(dòng)態(tài)運(yùn)行時(shí)通過元數(shù)據(jù)動(dòng)態(tài)處理〔4〕,為注解所在class實(shí)時(shí)反射注入class實(shí)例。
Java反射機(jī)制是Java被視為動(dòng)態(tài)語言的一個(gè)關(guān)鍵性質(zhì),該機(jī)制允許Java程序在運(yùn)行時(shí)透過Reflection APIs取得任何一個(gè)在運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的classes的內(nèi)部信息〔5〕,可在程序運(yùn)行時(shí)動(dòng)態(tài)生成class對(duì)象實(shí)體,并可于運(yùn)行時(shí)改變其fields內(nèi)容或喚起methods。
2.1.1 用@interface自定義注解MyAnnotation
2.1.2 創(chuàng)建JavaBean類
① 屬性字段聲明:字符串類型,且命名與Excel文件中的待讀取/待寫入列一一對(duì)應(yīng);
② 屬性字段注解:用自定義注解MyAnnotation對(duì)屬性進(jìn)行注解,注解賦值與Excel文件中待讀取/待寫入列的列名相同。
圖3 JavaBean類
圖4 自定義MyAnnotation注解
2.2.1 讀取Excel文件中指定Sheet工作表內(nèi)容的操作
創(chuàng)建Excel文件讀取類ExcelReadHandle,通過構(gòu)造方法參數(shù)傳入JavaBean.class、待讀取的Excel文件以及Sheet工作表編號(hào)。該類采用注解和反射機(jī)制封裝Excel文件的底層讀取操作,將從Excel文件Sheet工作表中讀取到的選定列數(shù)據(jù)封裝成JavaBean對(duì)象,并以List
(1)采用注解機(jī)制獲取Excel文件指定Sheet工作表中待讀取列的列名及列號(hào)。
1)讀取Excel文件,獲得指定Sheet工作表所有列的列名,并將其逐一存入字符串?dāng)?shù)組titles[]中;
2)采用注解機(jī)制,運(yùn)態(tài)獲取JavaBean.class中各屬性的MyAnnotation注解,并將每個(gè)屬性的MyAnnotation注解值定義為Key、屬性對(duì)應(yīng)的setter方法名定義為Value,然后逐一存入Map(Key,Value)類型的map對(duì)象,再將map對(duì)象添加到List
3)遍歷titles[]和list數(shù)組,將titles[]中的列名與list中map對(duì)象的注解值Key進(jìn)行匹配,相等時(shí)的列名即為Excel文件Sheet工作表中待讀取的列,并將該列名在titles[]中對(duì)應(yīng)的下標(biāo)號(hào)index和map對(duì)象中對(duì)應(yīng)的setter方法名存入List
(2)采用反射機(jī)制,動(dòng)態(tài)生成JavaBean.class實(shí)例對(duì)象obj,然后逐行讀取Excel文件中指定Sheet工作表的列字段信息,并賦值給實(shí)例對(duì)象obj的相應(yīng)屬性。
1)讀取Excel文件,逐行獲得指定Sheet工作表的列字段信息,并將每一行的列字段信息保存到字符串?dāng)?shù)組contents[]中;
2)利用反射機(jī)制,動(dòng)態(tài)生成JavaBean.class實(shí)例對(duì)象obj,并添加到List
3)逐一讀取數(shù)組cols[{index,setter}]中下標(biāo)值index和setter方法名,然后根據(jù)index獲取contents[]中的值content,并采用反射機(jī)制JavaBean.getMethod(setter,String.class).invoke(obj,content)進(jìn)行動(dòng)態(tài)賦值,即將讀取到的Excel文件Sheet工作表內(nèi)容逐一賦值給JavaBean對(duì)象的相應(yīng)屬性;
4)循環(huán)執(zhí)行步驟1)2)3),直到Excel文件中指定的Sheet工作表所有行都讀取完畢,最后向應(yīng)用程序返回List
圖5 ExcelReadHandle類讀取Excel文件時(shí)序圖
2.2.2 寫入Excel文件中指定Sheet工作表的操作
創(chuàng)建Excel文件寫入類ExcelWriteHandle,通過構(gòu)造方法參數(shù)傳入JavaBean.class、待寫入的List
(1)從JavaBean.class屬性注解獲取待寫入Excel文件中指定Sheet工作表列名及屬性對(duì)應(yīng)的getter方法名。采用注解機(jī)制,運(yùn)態(tài)獲取JavaBean.class中各屬性的MyAnnotation注解,并將每個(gè)屬性的MyAnnotation注解值定義為Key、屬性對(duì)應(yīng)的getter方法名定義為Value,然后逐一存入Map(Key,Value)類型的map對(duì)象,再將map對(duì)象添加到List
(2)遍歷list數(shù)組,將list中map對(duì)象的注解值Key,寫入Excel文件中,生成Excel文件中指定Sheet工作表的列名。
(3)讀取List
(4)重復(fù)執(zhí)行步驟(3),直到List
圖6 ExcelWriteHandle類寫入Excel文件時(shí)序圖
第一步:用@interface自定義注解MyAnnotation;
第二步:根據(jù)Excel文件中指定Sheet工作表的待讀取列,創(chuàng)建與Sheet列名相對(duì)應(yīng)的JavaBean類,并用Sheet中待讀取列名對(duì)JavaBean屬性進(jìn)行MyAnnotation注解;
第三步:調(diào)用public ExcelReadHandle(Class
第一步:用@interface自定義注解MyAnnotation;
第二步:根據(jù)Excel文件中指定Sheet工作表的待寫入列,創(chuàng)建與Sheet列名相對(duì)應(yīng)的JavaBean類,并用Sheet中待寫入列名對(duì)JavaBean屬性進(jìn)行MyAnnotation注解;
第三步:調(diào)用public ExcelWriteHandle(Class
通過以上讀寫操作步驟,可以發(fā)現(xiàn)基于Java注解與反射機(jī)制的改進(jìn)型Excel文件讀寫操作方法,對(duì)于Excel文件的讀寫操作,只需根據(jù)應(yīng)用軟件業(yè)務(wù)規(guī)則創(chuàng)建注解、JavaBean類,然后分別調(diào)用ExcelReadHandle或ExcelWriteHandle,即可實(shí)現(xiàn)讀寫操作。該方法完全不用關(guān)心底層的Jxl API工作方式,成功實(shí)現(xiàn)了應(yīng)用軟件中Excel導(dǎo)入導(dǎo)出操作與Jxl API具體讀寫過程的高度解耦。
圖7 基于Java注解與反射機(jī)制的改進(jìn)型Excel文件讀寫操作步驟
基于Java注解與反射機(jī)制的改進(jìn)型Excel文件讀寫操作方法,使得應(yīng)用軟件在讀取Excel文件時(shí)完全不用了解底層Jxl API的工作方式,實(shí)現(xiàn)了應(yīng)用軟件中Excel導(dǎo)入導(dǎo)出操作與Jxl API具體讀寫操作的高度解耦。該方法操作方便、簡單易用,針對(duì)當(dāng)今大量應(yīng)用系統(tǒng)都需要從外部Excel文件中批量導(dǎo)入或?qū)С鰯?shù)據(jù)的實(shí)現(xiàn)方式,無疑將是一項(xiàng)具有積極意義的技術(shù)革新,也必將給軟件研發(fā)和維護(hù)人員在Excel讀取方面帶來極大的方便。
九江職業(yè)技術(shù)學(xué)院學(xué)報(bào)2020年1期