解決excel兩表之間數據關聯關係,知道這幾招就夠了

  用過SAP的憑證批量錄入模板(Excel文件)的都知道,一個憑證由【擡頭】和多個【行項目】組成,這是一個關於excel兩表信息關聯的典型場景。

  這裏頭蘊藏着一個麻煩:當我們需要一次性錄入多個憑證時,如何將每個憑證的擡頭與行項目關聯起來呢?

假定這是一個SAP憑證的excel錄入模板,包含多個待錄入的憑證:

【擡頭】表:

號碼 憑證日期 憑證類型 公司代碼 記賬日期 貨幣 匯率 參考憑證號 擡頭文本
1 20220113 RE CN10 20200113 CNY     這是一個僅用於測試的憑證1
2 20220113 RE CN10 20200113 CNY     這是一個僅用於測試的憑證2

 

 

 

 

【行項目】表:

號碼 記賬碼 科目賬戶 特別總賬標識 憑證貨幣金額 稅碼 成本中心 訂單 文本 基準日 分配 原因代碼 貿易伙伴
1 40 1001010000   123.25       這是一個用於測試的憑證1   20210106 A11  
1 19 1066322 A 123.25       這是一個用於測試的憑證1   20210106    
2 40 1001010000   427.86       這是一個用於測試的憑證2   20210108 A11  
2 19 1066323 A 427.86       這是一個用於測試的憑證2   20210108    
                         

 

 

 

 

 

 

 

   看了表結構,如果實際業務中【擡頭】文本跟【行項目】文本要求有一定差異,那麼能將兩張表關聯起來的就剩【號碼】字段了。此處【擡頭】號碼1跟【行項目】號碼1說的都是第1個待錄入憑證。

當我們第一層循環是遍歷【擡頭】表的每一行時,第二層內循環便是遍歷該憑證行項目對應的每一行。進一步分解需求,比如號碼1,我們需要動態計算號碼1在【行項目】的起始和終止行號。小爬能想到的思路有以下三個。

  ①利用excel公式來動態計算;

  ②利用兩個字典分別存儲某個號碼在【行項目】中的首尾行號;

  ③建立個臨時表temp,利用sql或Excel自帶篩選功能快速篩選出號碼等於特定數字(比如1)的數據,寫入臨時表。

 

先說方法一:使用match結合countif分別得到首尾行號。

如下圖所示:

 

 

接着說說方法二:使用字典來得到某個憑證行項目的首尾行號

  我們從上至下遍歷【行項目】每一行,用字典(key,value)分別存儲號碼和對應的行號,由於字典【key】的唯一性和可覆蓋性,我們永遠key對應【號碼】,則value永遠對應的該key最後一次出現的位置(行號),因爲該key第一次存入字典的value(起始行號),隨着逐行往下遍歷,被不停用新的value(行號)覆蓋。

此時我們只需要掌握一個trick,先定義個字典,從上至下遍歷,最終存儲key(號碼)和value(結束行號);緊接着再定義個字典,從下至上遍歷,便可存儲key(號碼)和value(起始行號),你get到這一點了嗎?

  完整實現的代碼示例(VBA)如下:

 1 Sub voucherEntry()
 2 Dim headerSht As Worksheet, itemSht As Worksheet, numberStr As String, startNum As Integer, endNum As Integer, headerMaxRow As Long, itemMaxRow As Long, i As Integer, j As Integer
 3 Dim startDic As Object, endDic As Object
 4 Set startDic = CreateObject("scripting.dictionary")
 5 Set endDic = CreateObject("scripting.dictionary")
 6 
 7 Set headerSht = ThisWorkbook.Sheets("擡頭")
 8 Set itemSht = ThisWorkbook.Sheets("行項目")
 9 headerMaxRow = headerSht.Cells(Rows.Count, 1).End(xlUp) '[擡頭]表的最後一行行號
10 itemMaxRow = itemSht.Cells(Rows.Count, 1).End(xlUp) '[行項目]表的最後一行行號
11 For i = 2 To itemMaxRow
12     endDic.Add CStr(itemSht.Range("A" & i).Value), i '將號碼與對應行號的關係存入字典,思考下,爲啥要轉爲字符串格式
13 Next
14 
15 For i = itemMaxRow To 2 Step -1
16     startDic.Add CStr(itemSht.Range("A" & i).Value), i '將號碼與對應行號的關係存入字典,思考下,爲啥要轉爲字符串格式
17 Next
18 
19 For i = 2 To headerMaxRow '遍歷【擡頭】表每一個擡頭行
20     numberStr = CStr(headerSht.Range("A" & i).Value) '【號碼】,思考下,爲啥要轉爲字符串格式
21     startNum = startDic(numberStr) '憑證對應的起始行號
22     endNum = endDic(numberStr) '憑證對應的結束行號
23     For j = startNum To endNum '遍歷該憑證行項目的每一行
24         此處維護核心【代碼塊】
25     Next
26 
27 Next
28 
29 End Sub

至於方法三,小爬就暫時不對此進行具體實現了,感興趣的同學不妨自己動手嘗試一波~

 

快來掃碼關注我的公衆號 獲取更多爬蟲、數據分析的知識!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章