10 行程式碼提取複雜 Excel 資料
10行程式碼提取複雜Excel資料
把Excel檔案匯入關係資料庫是資料分析業務中經常要做的事情,但許多Excel檔案的格式並不規整,需要事先將其中的資料結構化後再用SQL語句寫入資料庫。而一般情況下,結構化的工作量會比較大,而且很難通用,每次都要針對檔案格式進行分析後再進行開發。因此,如果有一個工具軟體能夠便捷地完成這個分析開發工作,將能夠極大地助力業務工作,提高業務效率。本文介紹的集算器就是這樣一款高效、靈活的工具,能夠輕鬆讀取excel資料,然後結構化成“序表”後匯入資料庫。
下面我們將分情況討論如何利用集算器將Excel資料進行結構化。文中用到的函式請參看集算器文件《函式參考》。
1. 普通行式
先看最簡單的情況:如下圖所示,Excel檔案中第一行是列標題,從第二行開始,每行是一條資料記錄。
集算器處理這種檔案也非常簡單:
A |
|
1 |
=file( "學生成績表.xlsx" )[email protected]() |
2 |
=connect("demo") |
3 |
=A2.update(A1,xscj) |
A1 開啟“學生成績表.xlsx”檔案並匯入成序表,選項@t表示檔案第一行是列標題
A2 連線demo資料庫
A3 將A1中的序表存入到demo資料庫的xscj表中,由於表中的列名和序表中的欄位名一樣,所以只需指定資料表名即可。update函式的更詳細用法請查閱函式文件。
A1中得到的序表如下圖所示:
A2、A3兩步連線資料庫和將序表存入資料庫的方法是通用的,所以後面的例子中將不再寫這兩步,只關注於如何把Excel中的資料結構化成序表。
2. 多行表頭行式
大多數時候,Excel檔案都不會象上例那麼簡單,表頭往往比較複雜,有表名、專案名、頁碼、填表人、填寫日期等等。比如這個樣子:
對於這種表,我們在讀取時就要跳過表頭,直接從資料行開始讀。
A |
|
1 |
=file( "措施專案清單與計價表.xlsx" ).xlsimport(;1,5) |
2 |
=A1.rename(#1:序號,#2: 專案編碼,#3: 專案名稱,#4: 計量單位,#5: 數量,#6: 單價,#7: 合價 ) |
A1 開啟檔案並匯入資料成序表,引數“1,5”表示讀第一個 sheet,從第 5 行開始讀,一直讀到檔案結尾
A2 將 A1 中讀到的序表列名依次改為“序號、專案編碼、專案名稱、計量單位、數量、單價、合價”,即要存入的資料表的列名。
執行後 A2 中的序表如下:
3. 自由格式
有時Excel檔案的資料並不是網格式的規則表,而是欄位名後緊跟著欄位值的自由格式,如下圖的僱員資訊表:
每個僱員資訊佔據9行,依次往下排列。對這種檔案,該怎麼結構化呢?請看:
A |
B |
C |
|
1 |
=create(僱員 ID, 姓名, 性別, 職位, 生日, 電話, 地址, 郵編 ) |
||
2 |
=file("僱員資訊表.xlsx").xlsopen() |
||
3 |
[C,C,F,C,C,D,C,C] |
[1,2,2,3,4,5,7,8] |
|
4 |
for |
=A3.(~/B3(#)).(eval($[A2.xlscell(]/~/")")) |
|
5 |
if len(B4(1))==0 |
break |
|
6 |
>A1.record(B4) |
||
7 |
>B3=B3.(~+9) |
A1 建立列名為“僱員 ID, 姓名, 性別, 職位, 生日, 電話, 地址, 郵編”的空序表
A2 開啟 Excel 資料檔案
A3 定義僱員資訊所在單元格列號序列
B3 定義僱員資訊所在單元格行號序列
A4 用 for 迴圈讀取每個僱員資訊
B4 A3.(~/B3(#))先算出當前僱員單元格編號序列, 再讀出這些單元格值組成僱員資訊序列。第一次迴圈時為 [C1,C2,F2,C3,C4,D5,C7,C8],第二次迴圈時為[C10,C11,F11,C12,C13,D14,C16,C17]……每次行號加 9。$[A2.xlscell(] 與 "A2.xlscell(" 相同,都是表示一個字串,它的好處是在 IDE 中編寫程式時,如果 A2 單元格的編號發生了變化,$[A2.xlscell(]中的 A2 會自動變化,比如在 A2 前插入了一行,這個表示式就會變成 $[A3.xlscell(],而用引號的話,就不會自動變了。
B5 判斷僱員 ID 值是否為空,為空則退出迴圈,結束執行
B6 將一條僱員資訊存入 A1 序表尾
B7 讓僱員資訊的行號序列都加上 9,讀取下一條僱員資訊
執行後得到的 A1 序表如下:
4. 交叉表
Excel中還有交叉表格式的資料,如下圖:
資料結構化程式如下:
A |
|
1 |
=file("交叉表.xlsx")[email protected](;1,2) |
2 |
=A1.rename(#1:運貨商) |
3 |
[email protected](運貨商;貨主地區,訂單數量) |
A1 開啟檔案並匯入資料成序表,引數“1,2”表示讀第一個 sheet,從第 2 行開始讀,一直讀到檔案結尾。選項 @t 表示開始行是列標題。
A2 由於第二行第一個單元格是圖片,讀的資料為 null,第一列沒有列標題,所以將第一列列名改為運貨商。
A3 以運貨商為分組,對序表資料進行行列轉換,選項 @r 表示將列資料轉換為行資料,轉換後新的列名分別為“貨主地區”、“訂單數量”。
執行後得到的 A3 序表如下:
5. 主子表
在下圖所示的員工資訊登記表中,除了有員工本人的資訊外,還有他的家庭成員資訊。每個 sheet 儲存一個員工的相關資訊,所以有多少員工,就有多少個 sheet。
對這種主子表結構的資料,需要建立兩個序表分別儲存主表和子表的資料,集算器程式如下:
A |
B |
C |
|
1 |
=create(身份證號,姓名,性別,出生日期,民族,手機號,部門,家庭地址,婚姻狀況,入職時間) |
||
2 |
=create(身份證號,姓名,關係,工作單位,聯絡電話) |
||
3 |
[B4,B3,D3,F3,H3,F4,H4,B5,F5,H5] |
||
4 |
=file("員工資訊表.xlsx").xlsopen() |
||
5 |
for A4 |
||
6 |
=A3.(eval($[A4.xlscell(]/~/",\""/A5.頁名/"\")")) |
>A1.record(B6) |
|
7 |
[email protected](家庭成員,姓名,關係,工作單位,聯絡電話;A5.頁名,6) |
||
8 |
=B7.rename(家庭成員:身份證號) |
>B8.run(身份證號=B6(1)) |
|
9 |
>[email protected](0:B8) |
A1 建立列名為“身份證號, 姓名, 性別, 出生日期, 民族, 手機號, 部門, 家庭地址, 婚姻狀況, 入職時間”的空序表,用於儲存主表員工資訊
A2 建立列名為“身份證號, 姓名, 關係, 工作單位, 聯絡電話”的空序表,用於儲存子表員工家庭成員資訊
A3 定義主表員工資訊所在單元格序列
A4 開啟 Excel 資料檔案
A5 迴圈讀取 Excel 檔案各 sheet 資料
B6 讀取員工資訊序列
C6 將 B6 讀取的員工資訊儲存到序表 A1
B7 從第 6 行開始讀取員工家庭成員資訊,只讀指定的“家庭成員, 姓名, 關係, 工作單位, 聯絡電話”5 列
B8 將 B7 序表的家庭成員列改名為身份證號
C8 為 B8 序表的身份證號列賦值為員工資訊中的身份證號
B9 將 B8 中的員工家庭成員資訊儲存到序表 A2
程式執行後,序表 A1 如下圖所示:
序表 A2 如下圖所示:
上面這些情況基本羅列了常見的 Excel 資料格式,如果遇到更復雜的檔案,也可以靈活使用例子中的技巧予以應對。簡單總結一下,集算器提供了非常靈活的在 excel 檔案中定位和讀取資料的功能,既可以成片讀取網格資料,也可以精確定位單元格進行讀取。再結合特有的“序表”物件,以往需要編寫數千行程式碼才能完成的 Excel 資料結構化入庫工作,現在只需要不到 10 行程式碼就可以勝任,簡單情況下甚至只需要 2、3 行程式碼!
作者:sjr
連結:http://c.raqsoft.com.cn/article/1541129604470
來源:乾學院
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。