Java 嵌入 SPL 輕松實現(xiàn) Excel 文件合并

大多數(shù)JAVA程序猿都選擇使用POI或者HSSFWorkbook等第三方類庫來實現(xiàn)Excel自動化合并,這樣一來不僅需要噼里啪啦的敲好多代碼,費事費力,而且用起來靈活度也不高面殖,對Excel的格式要求也很嚴(yán)格。如果能有一個專用的外部數(shù)據(jù)工具哭廉,寫簡單類似SQL的腳本來實現(xiàn)脊僚,然后在JAVA中直接調(diào)用并返回結(jié)果集,就再好不過了遵绰。潤乾集算器就是這樣的機制辽幌,通過使用JDBC調(diào)用SPL腳本,使用起來方便快捷椿访,下面就來學(xué)習(xí)下具體如何使用舶衬。

SPL實現(xiàn)

常規(guī)合并:

A.??同一個 excel 中的多個Sheet表合并

下面的例子是一個包含了銷售數(shù)據(jù)的 excel 文件,其中包含了按月劃分的 3 個結(jié)構(gòu)相同的 sheet 工作表赎离,數(shù)據(jù)如下:

January_2013:


February_2013:


March_2013:

在合并3個Sheet的同時逛犹,我們還可以同時從每個sheet中篩選出字段Customer Name, Sale Amount。最后的效果如下:

SPL?腳本:

保存腳本文件oneExcel.dfx(嵌入Java會用到)

腳本說明:

A1: 打開指定的 excel 文件梁剔,創(chuàng)建一個由多個 sheet 工作表組成的序列虽画。

A2:利用 conj 函數(shù)遍歷 A1 序列中所有的成員工作表,導(dǎo)入每個工作表中指定列'Customer Name','Sale Amount'荣病,并將數(shù)據(jù)并合并码撰。其中 xlsimport 函數(shù)導(dǎo)入指定列或舞,最后一列用分號; 隔開瘩欺。 參數(shù)~.stname表示指定當(dāng)前工作表,由于在 conj 函數(shù)的循環(huán)中近上,所以就可以逐個導(dǎo)入所有工作表颊亮。同時柴梆,xlsimport 使用選項@t指明將工作表的第一行記錄作為字段名。

A3:?將序表 A2 作為一個新的工作表“merge_sheets”保存到原來的 excel 文件中终惑,同樣用選項 @t 指明首行記錄為標(biāo)題绍在。

這段腳本只有三句話,短小精干之余雹有,邏輯清晰偿渡,也比較容易理解。下面我們再看看如何合并多個文件中的多個工作表霸奕。

B.??不同 excel 中的多表合并

下面是要合并的多個 excel 文件溜宽,它們都具有和上面例子相同的表結(jié)構(gòu),每個文件記錄了當(dāng)年的數(shù)據(jù)?

SPL?腳本:

合并后的結(jié)果如下:

保存腳本文件MergeExcels.dfx(嵌入Java會用到)

腳本說明:

A1: 通過 for 循環(huán)质帅,遍歷指定目錄下的 excel 文件适揉,在 B1 到 B3 之間進行循環(huán)內(nèi)處理合武。

B1:打開目錄下的一個 excel 文件,生成序列涡扼。

B2:導(dǎo)入當(dāng)前文件中的每個 sheet 工作表中指定列'Customer Name','Sale Amount','Purchase Date'的數(shù)據(jù)盟庞,然后合并這些數(shù)據(jù)吃沪,與前面例子中的 A2 類似。

B3:將序表 B2 的數(shù)據(jù)與 @表示的本網(wǎng)格的值進行合并什猖。

A4:將序表 B3 保存到result.xlsx文件中的 merge_data 工作表中票彪。

上面程序用兩個循環(huán)就實現(xiàn)了多個 excel 文件數(shù)據(jù)合并,外循環(huán) for 遍歷了目錄下所有的 excel 文件不狮,內(nèi)循環(huán)B1.conj則合并每個excel文件中的多個sheet工作表的數(shù)據(jù)降铸。


C.??合并出大文件

前面第一個例子中的 A2、第二個例子中的 B3 都是在內(nèi)存中裝載了合并后的 Excel 的所有數(shù)據(jù)摇零,然后一次性寫出推掸。如果文件太多太大,那么對內(nèi)存的占用也會很大驻仅,甚至超出內(nèi)存允許的范圍谅畅。為此,我們可以在SPL腳本中采用流式追加的方式生成大文件噪服。

SPL腳本:

合并后的效果如下:

保存腳本文件BigExcel.dfx(嵌入Java會用到)

腳本說明:

A1:打開指定輸出的文件毡泻。

A2:遍歷目錄下需要合并的 excel 文件。

B2:打開一個需要合并的 excel 文件粘优。

B3:如果輸出文件不存在仇味,讀取 sheet 工作表的所有數(shù)據(jù),包括標(biāo)題行雹顺;如果輸出文件已經(jīng)有了丹墨,就通過 @t 選項指明第一行是標(biāo)題,從第二行開始讀取數(shù)據(jù)嬉愧。

B4:將 B3 讀取的數(shù)據(jù)以流式追加到 A1 指定的輸出文件的 merger 工作表中带到。

通過流式逐個讀取文件數(shù)據(jù)后追加寫入,這個方式適合將大量小的 excel 文件合并成一個大的 excel 文件英染。

JAVA調(diào)用

SPL嵌入到Java應(yīng)用程序十分方便揽惹,通過JDBC調(diào)用存儲過程方法加載,用同一個excel中的多個Sheet表合并保存的文件OneExcel.dfx四康,示例調(diào)用如下:

...

Connection con =null;

Class.forName("com.esproc.jdbc.InternalDriver");

con= DriverManager.getConnection("jdbc:esproc:local://");//調(diào)用存儲過程搪搏,其中OneExcel是dfx的文件名

st =(com. esproc.jdbc.InternalCStatement)con.prepareCall("call OneExcel()");//執(zhí)行存儲過程

st.execute();//獲取結(jié)果集

ResultSet rs = st.getResultSet();

...

替換成MergeExcels.dfx/BigExcel.dfx是同樣的道理,只需call MergeExcels()或者call BigExcel()即可闪金。這里只用 Java 片段粗略解釋了如何嵌入 SPL疯溺,詳細(xì)步驟請參閱Java 如何調(diào)用 SPL 腳本?论颅,也非常簡單,不再贅述囱嫩。同時恃疯,SPL 也支持 ODBC 驅(qū)動,集成到支持 ODBC 的語言墨闲,嵌入過程類似今妄。

拓展節(jié)選

關(guān)于Excel文件的處理除了像上面講的普通合并外,還可以在SPL腳本中對匯總后的結(jié)果分組去重鸳碧,然后再將結(jié)果集導(dǎo)出盾鳞。

分組匯總

下面繼續(xù)以前面的銷售數(shù)據(jù) excel 文件為例。

A.??字段分組

根據(jù)某個字段或多個字段實現(xiàn)分組計算瞻离,SPL 腳本如下:

A3的效果:

A4的效果:

腳本說明:

A1: 打開指定的 excel 文件腾仅。

A2:讀取并合并文件中所有 sheet 工作表的數(shù)據(jù)。

A3:在合并后的數(shù)據(jù)上按字段 'Customer ID' 分組求銷售額套利、平均值推励。

A4:在合并后的數(shù)據(jù)上按字段 'Customer ID', 'Purchase Date' 分組求銷售額。

B.??按序分組

集算器在進行分組聚合時還可以和相鄰數(shù)據(jù)行對比肉迫,在原數(shù)據(jù)已經(jīng)有序時可以不再排序吹艇,從而節(jié)省時間,并保持原有的次序昂拂。假設(shè)原數(shù)據(jù)已經(jīng)按日期排序受神,我們想按月份分組統(tǒng)計時,代碼如下格侯。

SPL 腳本:

A5 分組效果:

A6 分組效果:

腳本說明:

A1至B3: 在前面的例子中已經(jīng)介紹鼻听,將同一目錄下所有相同結(jié)構(gòu)的 excel 文件的工作表進行合并。

A4:在序表 B3 的基本上重新構(gòu)造了一個序表 A4联四,將日期拆分撑碴,新增年、月字段朝墩。

A5:groups 跨年度按月分組匯總銷售額醉拓、平均值。

A6:groups@o 按年月分組匯總銷售額收苏、平均值, 帶參數(shù) @o 實現(xiàn)分組歸并處理亿卤。

其中,A4 為數(shù)據(jù)記錄明細(xì)鹿霸;A5 按月統(tǒng)計, 不區(qū)分年排吴;A6 則按年月統(tǒng)計。這三個單元格中的數(shù)據(jù)展現(xiàn)出了不同層次的合并匯總結(jié)果懦鼠。

C.??分段分組

將要統(tǒng)計的數(shù)據(jù)按條件分成幾段钻哩,統(tǒng)計各組的情況屹堰。

SPL 腳本:

分組效果:

代碼說明:

步驟A1到 B3 之間參考前面例子的說明。

A4:字段'Sale Amount'金額的范圍分成 5 段街氢,然后累計求出各段的數(shù)量及總數(shù)扯键。

不過,這樣的寫法不夠方便珊肃,如果我們想調(diào)整分段方案荣刑,就需要修改 groups 函數(shù)的參數(shù),而這個參數(shù)表達式還是比較復(fù)雜的近范。這時,我們還可以利用集算器中另一個 pseg 函數(shù)延蟹,更方便地實現(xiàn)這個功能评矩,腳本如下:

當(dāng)然,我們也可以根據(jù)需要阱飘,按不同字段不同要求進行分組斥杜,然后進行統(tǒng)計處理。例如沥匈,在統(tǒng)計班級考生成績時蔗喂,各科成績可劃分成優(yōu)、良高帖、中缰儿、差、及格的分?jǐn)?shù)區(qū)段散址,一次為條件進行統(tǒng)計乖阵。groups 用法還有很多,可以參考函數(shù)手冊中相應(yīng)的章節(jié)预麸。

D.??大數(shù)據(jù)分組

前面的例子中瞪浸,要讀取的 excel 文件都不能很大,也就是都能一次讀進內(nèi)存吏祸。手工處理大文件对蒲,也會有類似的要求,因為同時打開多個文件贡翘,意味著把這些文件都裝入內(nèi)存蹈矮,很可能會超過機器的物理內(nèi)存,而用 VBA 讀取的情況也差不多鸣驱。這時含滴,我們就需要用流式的方法讀取數(shù)據(jù),不需一次讀進內(nèi)存丐巫,而是邊讀取邊合并谈况。?

SPL 腳本:

篩選分組的效果:

代碼說明:

A1: 使用 @r 選項指明以流式打開 excel 文件勺美。

A2:遍歷 excel 中的 sheet 工作表。

B2:使用 @c 選項指明以游標(biāo)方式導(dǎo)入數(shù)據(jù)碑韵。

B3:將游標(biāo)B2匯集到B3序列中赡茸。

A4:將游標(biāo)序列B3的成員合并到一起組成新的游標(biāo)。

B4:序列A4按‘Customer ID’分組累計‘Sale Amount’祝闻。

A5:將結(jié)果保存占卧。

通過游標(biāo)以流的方式循環(huán)從大文件中讀取一段段數(shù)據(jù),實現(xiàn)對數(shù)據(jù)的分組合并联喘。

去重處理

實際數(shù)據(jù)合并過程中华蜒,往往會出現(xiàn)數(shù)據(jù)重復(fù)的現(xiàn)象,重復(fù)數(shù)據(jù)肯定會影響到我們對數(shù)據(jù)的計算分析豁遭。下面介紹使用集算器 SPL 腳本去除重復(fù)數(shù)據(jù)的幾種主要解決方法叭喜。

A.??主鍵去重

sales_2013中的數(shù)據(jù),設(shè)其主鍵為’Invoice Number’蓖谢,則根據(jù)主鍵去掉重復(fù)記錄捂蕴。

合并去重后的數(shù)據(jù):

代碼說明:

A1: 打開指定的 excel 文件。

A2:導(dǎo)入 sheet 工作表中指定列的數(shù)據(jù)闪幽。

A3:將序表 A2 按主鍵'Invoice Number'分組去重處理, 其中參數(shù) @1 表示取每一個分組的第一條記錄組成排列后返回(注意是數(shù)字 1啥辨,不是字母 l)。

A4:將結(jié)果保存盯腌。

各個 sheet> 中的數(shù)據(jù)是唯一的溉知,但合并的數(shù)據(jù)不一定是唯一的,因此采用主鍵方式去掉重復(fù)數(shù)據(jù)腕够。

B.??某字段去重

根據(jù)數(shù)據(jù)表 sales_2013 中的某字段去重處理, 查看不同姓名的雇員記錄.

代碼說明:

A1: 打開指定的 excel 文件着倾。

A2:導(dǎo)入 sheet 工作表中指定列的數(shù)據(jù)。

A3:從序表 A2 中獲取不重復(fù)姓名的記錄燕少。

A4:從序表 A2中獲取不重復(fù)姓名的記錄列表卡者。

A5:將序表 A4 另存,首行記錄為標(biāo)題客们。

A3 數(shù)據(jù)去重結(jié)果:

A4 數(shù)據(jù)去重結(jié)果:

C.??聯(lián)合多字段去重

有的記錄雖然有主鍵崇决,但判斷是否為重復(fù)的記錄,需要用其它幾個字段來確定底挫,此時用多個字段聯(lián)合來確定是否有重復(fù)記錄.

代碼說明:

A1: 導(dǎo)入指定 excel 文件的數(shù)據(jù)恒傻。

A2:同上。

A3:按字段 'Customer ID', 'Purchase Date' 合并序表 A1建邓,A2盈厘,返回序表 A3。

A4:序表 A3 按 'Customer ID', 'Purchase Date' 分組去重官边。

A5:將結(jié)果保存沸手。

當(dāng)然外遇,也可以根據(jù)需要,參考更多的字段進行分組合并契吉,去掉重復(fù)記錄跳仿。

D.??記錄級去重

解決要合并的每個文件中的記錄本身是不重復(fù)的,但合并后可能存在重復(fù)記錄捐晶。

代碼說明:

A1: 導(dǎo)入 excel 文件的數(shù)據(jù)菲语。

B1:根據(jù)字段'Invoice Number'去掉序表 A1中的重復(fù)數(shù)據(jù)。

A2惑灵、B2:同上

A3:合并序表 B1山上,B2 的數(shù)據(jù),并去掉重復(fù)數(shù)據(jù)記錄返回序表 A3英支。選項 @u 表示序表成員按順序合并到一起組成新的序表, 去掉重復(fù)的記錄佩憾。

B3:查看合并后的數(shù)據(jù)記錄數(shù)。

merge@u適合對多序表合并處理, 其中序表內(nèi)部有序且無重復(fù)數(shù)據(jù)潭辈。

總結(jié)

使用SPL處理同構(gòu)/異構(gòu)excel 多文件合并鸯屿、分組匯總數(shù)據(jù)及數(shù)據(jù)去重時澈吨,都是只要把需要合并的字段讀成集算器的集合對象就可以了把敢。學(xué)會了用這種專業(yè)數(shù)據(jù)處理工具,不僅能合并 Excel 文件, 合并其他文本數(shù)據(jù)方法也是一致的谅辣,再也不用擔(dān)心合并數(shù)據(jù)中的多文件修赞、大文件和結(jié)構(gòu)差異問題了。

SPL優(yōu)勢

有庫寫 SQL桑阶,沒庫寫 SPL

用Java程序直接匯總計算數(shù)據(jù)柏副,還是比較累的,代碼很長蚣录,并且不可復(fù)用割择,很多情況數(shù)據(jù)也不在數(shù)據(jù)庫里,有了SPL萎河,就能像在Java中用SQL一樣了荔泳,十分方便。

常用無憂虐杯,不花錢就能取得終身使用權(quán)的入門版

如果要分析的數(shù)據(jù)是一次性或臨時性的玛歌,潤乾集算器每個月都提供免費試用授權(quán),可以循環(huán)免費使用擎椰。但要和Java應(yīng)用程序集成起來部署到服務(wù)器上長期使用支子,定期更換試用授權(quán)還是比較麻煩,潤乾提供了有終身使用權(quán)的入門版达舒,解決了這個后顧之憂值朋,獲得方式參考?如何免費使用潤乾集算器叹侄?

技術(shù)文檔和社區(qū)支持

官方提供的集算器技術(shù)文檔本身就有很多現(xiàn)成的例子,常規(guī)問題從文檔里都能找到解決方法吞歼。如果獲得了入門版圈膏,不僅能夠使用SPL的常規(guī)功能,碰到任何問題都可以去乾學(xué)院上去咨詢篙骡,官方通過該社區(qū)對入門版用戶提供免費的技術(shù)支持稽坤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市糯俗,隨后出現(xiàn)的幾起案子尿褪,更是在濱河造成了極大的恐慌,老刑警劉巖得湘,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杖玲,死亡現(xiàn)場離奇詭異,居然都是意外死亡淘正,警方通過查閱死者的電腦和手機摆马,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸿吆,“玉大人囤采,你說我怎么就攤上這事〕痛荆” “怎么了蕉毯?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長思犁。 經(jīng)常有香客問我代虾,道長,這世上最難降的妖魔是什么激蹲? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任棉磨,我火速辦了婚禮,結(jié)果婚禮上学辱,老公的妹妹穿的比我還像新娘乘瓤。我一直安慰自己,他們只是感情好项郊,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布馅扣。 她就那樣靜靜地躺著,像睡著了一般着降。 火紅的嫁衣襯著肌膚如雪差油。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音蓄喇,去河邊找鬼发侵。 笑死,一個胖子當(dāng)著我的面吹牛妆偏,可吹牛的內(nèi)容都是我干的刃鳄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼钱骂,長吁一口氣:“原來是場噩夢啊……” “哼叔锐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起见秽,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤愉烙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后解取,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體步责,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年禀苦,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔓肯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡振乏,死狀恐怖蔗包,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昆码,我是刑警寧澤气忠,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布邻储,位于F島的核電站赋咽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吨娜。R本人自食惡果不足惜脓匿,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宦赠。 院中可真熱鬧陪毡,春花似錦、人聲如沸勾扭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妙色。三九已至桅滋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丐谋。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工芍碧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人号俐。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓泌豆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吏饿。 傳聞我的和親對象是個殘疾皇子踪危,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容