Board logo

標題: [發問] 請問VBA可以做到兩檔案比對後再產生另一檔案的比對結果嗎? [打印本頁]

作者: happycoccolin    時間: 2013-7-25 11:09     標題: 請問VBA可以做到兩檔案比對後再產生另一檔案的比對結果嗎?

請問一下大師們~

目前手邊有一近五萬筆的資料庫--A資料 我們需要將手邊的B資料與之做比對

請問VBA有沒有辦法做出一個檔案 開啟後直接載入EXCEL的A檔案 與B檔案 比對後產生C檔案呢?
C檔案以B檔案格式為主 向後多加欄位"K"
K欄位內容是A檔案的A欄位

比對內容是

A檔案的E欄位 與 B檔案的J欄位比較(可忽略"-")

A檔案的格式如下
A                 B           C                       D                         E
100-1       XXX      XXX                 XXX                   DOG
100-2       XXX      XXX                 XXX                   CAT
100-3       XXX      XXX                 XXX                   CAT-1
100-4       XXX      XXX                 XXX                   CAT-2

B檔案的格式如下
A                 B           C                       D                         E                      F                       G             H                I           J
11            XX          XX                      XX                       XX                 XX                        XX         XX            CC       DOG
12            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT
13            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT1
14            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT-1
15            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT3

比對結果希望產生C檔案
A                 B           C                       D                         E                      F                       G             H                I           J                K
11            XX          XX                      XX                       XX                 XX                        XX         XX            CC       DOG       100-1
12            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT          100-2
13            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT1        100-3
14            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT-1       100-3
15            XX          XX                      XX                       XX                 XX                        XX         XX            CC       CAT3          No Data
作者: happycoccolin    時間: 2013-7-25 11:15

忘了附檔.....稍後附上檔案~
作者: happycoccolin    時間: 2013-7-25 11:21

回復 2# happycoccolin


    :$ 若有空請大家看看是否可以達成~~~謝謝!!!!!
作者: vocolboy    時間: 2013-7-25 14:47

本帖最後由 vocolboy 於 2013-7-25 14:48 編輯

回復 1# happycoccolin

我也是剛學的不能下載付件直接從你上述的寫

Sub 比對()
Set d = CreateObject("Scripting.Dictionary")          '字典
With Workbooks("A.xls").Sheets(1)                       'with 報名名稱.工作表名稱
  For Each a In .Range(.[E2], .[E65536].End(xlUp))
   d(a & "") = Array(a.Offset(, -4).Value)
  Next
End With
With Workbooks("B.xls").Sheets(1)                                       
  For Each a In .Range(.[J2], .[J65536].End(xlUp))
    a.Offset(, 1).Resize(, 1).Value = d(a & "")
  Next
End With
End Sub


這個結果並不會產生到C新的上
他會match在B裡面
我想這只是個複製貼上小問題@@
作者: happycoccolin    時間: 2013-7-25 16:14

回復 4# vocolboy


    哈囉~~謝謝vocolboy ~

請問一下 是否可以有一個檔案 開啟以後 讓我按鈕選擇載入兩個檔案比對呢?

例如

按鈕一  請選擇檔案
按鈕二  請選擇檔案
按鈕三  開始比對
作者: GBKEE    時間: 2013-7-25 16:56

回復 4# vocolboy
  1. Option Explicit
  2. Sub Ex()
  3.     Dim d As Object, i As Variant, S  As Variant
  4.     Set d = CreateObject("scripting.dictionary")
  5.     i = 1
  6.     With Workbooks("A.xls").Sheets(1)
  7.         Do While .Cells(i, "e") <> ""
  8.             d(.Cells(i, "e").Value) = .Cells(i, "A").Value
  9.             i = i + 1
  10.         Loop
  11.     End With
  12.      i = 1
  13.     With Workbooks("B.xls").Sheets(1)
  14.         Do While .Cells(i, "J") <> ""
  15.            S = Join(Application.Transpose(Application.Transpose(.Range("A" & i & ":J" & i))), ",")
  16.            If d.Exists(.Cells(i, "J").Value) Then
  17.                 S = S & "," & d(.Cells(i, "J").Value)
  18.                 d(.Cells(i, "J").Value) = Split(S, ",")
  19.            Else
  20.                 d(.Cells(i, "J").Value) = Split(S & ",No Data", ",")
  21.                 S = d(.Cells(i, "J").Value)
  22.            
  23.            End If
  24.             i = i + 1
  25.         Loop
  26.     End With
  27.     For Each i In d.keys
  28.         If InStr(i, "-") Then If Mid(i, InStr(i, "-"), 2) <> "-1" Then d.Remove i        '可忽略"-"的步驟
  29.     Next
  30.     With Workbooks("C.xls").Sheets(1)
  31.         .Cells.Clear
  32.         S = Application.Transpose(Application.Transpose(d.ITEMS))
  33.         .[A1].Resize(UBound(S, 1), UBound(S, 2)) = S
  34.     End With
  35. End Sub
複製代碼

作者: happycoccolin    時間: 2013-7-25 18:20

回復 6# GBKEE


    謝謝版大~~~

抱歉小妹才疏學淺...... 請問一下要怎麼使用才能做比對呢?

我將語法複製到模組中 但是如何才能正確使用?

目前偵錯停在
With Workbooks("A.xls").Sheets(1)

對VBA很有興趣但是未開竅 目前腳步很慢尚停留在函數階段 也請各位大師們多多見諒我問的笨問題..
作者: GBKEE    時間: 2013-7-25 19:24

回復 7# happycoccolin
xls 是2003版活頁簿的副檔名
2007版以後的副檔名xlsx是沒有巨集的活頁簿 ,副檔名xlsm是有巨集的活頁簿.
作者: happycoccolin    時間: 2013-7-26 11:34

回復 8# GBKEE


謝謝板大~

可以再請問一下嗎~如何不指定檔名~要做到人人都可以利用此檔案來做比對

那可以怎麼處理呢?

我現在是以A.xlsx為主,sheet1我加一個按鈕直接RUN此比對

如何載入欲比對的檔案呢?
作者: GBKEE    時間: 2013-7-26 13:47

回復 9# happycoccolin
  1. Option Explicit
  2. Sub Ex()
  3.     Dim d As Object, i As Variant, S  As Variant, Wb As Workbook
  4.     Set d = CreateObject("scripting.dictionary")
  5.     With Application.FileDialog(msoFileDialogFilePicker) 'FileDialog :表檔案對話方, msoFileDialogFilePicker(參數):選取檔案
  6.         .AllowMultiSelect = False                        '允許使用者從檔案對話方塊選取多個檔案=False
  7.          If .Show = False Then MsgBox "沒有選擇檔案 !!!":   Exit Sub
  8.          Set Wb = Workbooks.Open(.SelectedItems(1))   '開啟指定檔案
  9.     End With
  10.     i = 1
  11.     With Workbooks("A.xlsx").Sheets(1)   '
  12.         Do While .Cells(i, "e") <> ""
  13.             d(.Cells(i, "e").Value) = .Cells(i, "A").Value
  14.             i = i + 1
  15.         Loop
  16.     End With
  17.      i = 1
  18.     With Wb.Sheets(1)
  19.         Do While .Cells(i, "J") <> ""
  20.            S = Join(Application.Transpose(Application.Transpose(.Range("A" & i & ":J" & i))), ",")
  21.            If d.Exists(.Cells(i, "J").Value) Then
  22.                 S = S & "," & d(.Cells(i, "J").Value)
  23.                 d(.Cells(i, "J").Value) = Split(S, ",")
  24.            Else
  25.                 d(.Cells(i, "J").Value) = Split(S & ",No Data", ",")
  26.                 S = d(.Cells(i, "J").Value)
  27.            
  28.            End If
  29.             i = i + 1
  30.         Loop
  31.         .Parent.Close False               '關閉指定檔案不存檔
  32.     End With
  33.    
  34.     For Each i In d.keys
  35.         If InStr(i, "-") Then If Mid(i, InStr(i, "-"), 2) <> "-1" Then d.Remove i        '可忽略"-"的步驟
  36.     Next
  37.     With Workbooks("C.xlsx").Sheets(1)
  38.         .Cells.Clear
  39.         S = Application.Transpose(Application.Transpose(d.ITEMS))
  40.         .[A1].Resize(UBound(S, 1), UBound(S, 2)) = S
  41.     End With
  42. End Sub
複製代碼

作者: happycoccolin    時間: 2013-7-26 14:19

回復 10# GBKEE


    謝謝板大!!!!!!

但是偵錯目前停在
    With Workbooks("C.xlsx").Sheets(1)

是不是若我不指定新檔案的檔名就不會有錯誤呢?

應該是說比對完成後跑出的檔案由使用者自定義名稱

抱歉問題很多

我附上檔案給您參考
ABC.xlsm為資料庫
B.xlsx為欲比對檔案
希望比對後產生一新檔案(由使用者自定義名稱另存新檔)
[attach]15585[/attach]

很高興板大願意解惑~^^
作者: GBKEE    時間: 2013-7-26 14:38

本帖最後由 GBKEE 於 2013-7-26 17:05 編輯

回復 11# happycoccolin
  1. Option Explicit
  2. Sub Ex()
  3.     Dim d As Object, i As Variant, S  As Variant, Wb As Workbook, Wb_Name As String
  4.     Set d = CreateObject("scripting.dictionary")
  5.     With Application.FileDialog(msoFileDialogFilePicker) 'FileDialog :表檔案對話方, msoFileDialogFilePicker(參數):選取檔案
  6.         .AllowMultiSelect = False                        '允許使用者從檔案對話方塊選取多個檔案=False
  7.          If .Show = False Then MsgBox "沒有選擇檔案 !!!":   Exit Sub
  8.          Set Wb = Workbooks.Open(.SelectedItems(1))   '開啟指定檔案
  9.     End With
  10.     i = 1
  11.     With Workbooks("A.xlsx").Sheets(1)   '
  12.         Do While .Cells(i, "e") <> ""
  13.             d(.Cells(i, "e").Value) = .Cells(i, "A").Value
  14.             i = i + 1
  15.         Loop
  16.     End With
  17.      i = 1
  18.     With Wb.Sheets(1)
  19.         Do While .Cells(i, "J") <> ""
  20.            S = Join(Application.Transpose(Application.Transpose(.Range("A" & i & ":J" & i))), ",")
  21.            If d.Exists(.Cells(i, "J").Value) Then
  22.                 S = S & "," & d(.Cells(i, "J").Value)
  23.                 d(.Cells(i, "J").Value) = Split(S, ",")
  24.            Else
  25.                 d(.Cells(i, "J").Value) = Split(S & ",No Data", ",")
  26.                 S = d(.Cells(i, "J").Value)
  27.            
  28.            End If
  29.             i = i + 1
  30.         Loop
  31.         .Parent.Close False               '關閉指定檔案不存檔
  32.     End With
  33.     For Each i In d.keys
  34.         If InStr(i, "-") Then If Mid(i, InStr(i, "-"), 2) <> "-1" Then d.Remove i        '可忽略"-"的步驟
  35.     Next
  36.     Do
  37.         Wb_Name = InputBox("輸入新檔名", "存檔名稱")
  38.     Loop Until Wb_Name <> ""                             '直到有輸入字串離開迴圈
  39.     Set Wb = Workbooks.Add(1)
  40.     With Wb.Sheets(1)
  41.         .Cells.Clear
  42.         S = Application.Transpose(Application.Transpose(d.ITEMS))
  43.         .[A1].Resize(UBound(S, 1), UBound(S, 2)) = S
  44.     End With
  45.     Wb.SaveAs "D:\TEST\" & Wb_Name & "XLSX"  '存檔的完整名稱
  46. End Sub
複製代碼

作者: happycoccolin    時間: 2013-7-26 15:21

回復 12# GBKEE


    感謝板大的迅速回覆~~~

請問一下目前偵錯停在
Sub Ex()

我現在要怎麼處理呢?

謝謝板大的幫忙!!!!!!!
作者: GBKEE    時間: 2013-7-26 15:27

回復 13# happycoccolin
同一個模組中 不能有相同的程序名稱  Sub Ex()
找找看還有第2個 Sub Ex() 嗎?
作者: happycoccolin    時間: 2013-7-26 16:58

回復 14# GBKEE


    版大~~只有一個Ex~~~我有附檔~~>< 拜託幫忙撥空看一下好嗎~
感激不盡!!!

[attach]15589[/attach]
作者: GBKEE    時間: 2013-7-26 17:03

回復 15# happycoccolin
不好意思 改一下最後 Save -> SaveAs
  1. Wb.SaveAs "D:\TEST\" & Wb_Name & "XLSX"  '存檔的完整名稱
複製代碼

作者: happycoccolin    時間: 2013-7-26 18:06

回復 16# GBKEE


    謝謝版大的幫忙~~~~

再請教一下~目前偵錯停在
With Workbooks("A.xlsx").Sheets(1)   '

因為我已經將資料庫放在ABC.xlsm裡面了

那下面這段語法是否就不用針對A.xlsx做處理呢?

i = 1
    With Workbooks("A.xlsx").Sheets(1)   '
        Do While .Cells(i, "e") <> ""
            d(.Cells(i, "e").Value) = .Cells(i, "A").Value
            i = i + 1
        Loop
作者: GBKEE    時間: 2013-7-26 19:58

回復 17# happycoccolin
因為我已經將資料庫放在ABC.xlsm裡面了
    With Workbooks("A.xlsx").Sheets(1)   -改一下檔名  With Workbooks("ABC.xlsm").Sheets(1)
作者: happycoccolin    時間: 2013-7-30 10:54

回復 18# GBKEE


    報告版大~

目前偵錯停在
Wb.SaveAs "D:\TEST\" & Wb_Name & "XLSX"  '存檔的完整名稱

可是比對結果通通都是NO DATA耶~

請見附檔
[attach]15636[/attach]
作者: GBKEE    時間: 2013-7-30 14:43

回復 19# happycoccolin
可是比對結果通通都是NO DATA
問題在這裡
  1. With Workbooks("ABC.xlsm").Sheets(1)
  2.         '這Sheets(1) 是ABC.xlsm的第一個工作表 (MAIN)
  3.         '是否要改成 Sheets(2) ->  第二個工作表 (A)
  4.         Do While .Cells(i, "e") <> ""
  5.             d(.Cells(i, "e").Value) = .Cells(i, "A").Value
  6.             i = i + 1
  7.         Loop
  8.     End With
複製代碼
D:\TEST \  這資料夾是我隨意寫的,你需改為你PC中存在的資料夾
作者: happycoccolin    時間: 2013-7-30 16:16

回復 20# GBKEE


    謝謝版大~~~成功了~~

但是是否可不指定儲存位置[ D:\TEXT ] 可讓使用者自行設定儲存位置或選擇要不要存檔?

再問一下比對檔案B.XLSX 欄位由"J"向後順延為"K"

只修改以下後偵錯沒有問題
With Wb.Sheets(1)
        Do While .Cells(i, "K") <> ""
           S = Join(Application.Transpose(Application.Transpose(.Range("A" & i & ":K" & i))), ",")
           If d.Exists(.Cells(i, "K").Value) Then
                S = S & "," & d(.Cells(i, "K").Value)
                d(.Cells(i, "K").Value) = Split(S, ",")
           Else
                d(.Cells(i, "K").Value) = Split(S & ",No Data", ",")
                S = d(.Cells(i, "K").Value)
           
           End If
            i = i + 1
        Loop
        .Parent.Close False               '關閉指定檔案不存檔
    End With


但因為B.xlsx比對欄位"K"後 還有一欄"L"
新產生的檔案資料會向後順延一欄填到"M"嗎?

偵錯現在停在
S = Application.Transpose(Application.Transpose(d.ITEMS))

[attach]15641[/attach]
作者: happycoccolin    時間: 2013-7-31 12:11

回復 20# GBKEE


報告版大~前一篇描述不清楚~我重新描述一下

目前B.xlsx的比對欄位要更動到"K"

再請教是否可以將比對好的值填到最後一個欄位呢?不要做覆蓋填上的動作呢?

請見附檔~~~謝謝~
[attach]15653[/attach]

ABC.xlsx
A        B        C        D        E
100-1        XXX        XXX        XXX        DOG
100-2        XXX        XXX        XXX        CAT
100-3        XXX        XXX        XXX        CAT-1
100-4        XXX        XXX        XXX        CAT-2
                               
↑比對完畢後Show出此欄位值                ↑比對欄位


B.xlsx

A        B        C        D        E        F        G        H        I        J        K        L        希望顯示在這欄位(M)
11        XX        XX        XX        1        A1        XX        XX        XX        CC        DOG        XX       
12        XX        XX        XX        2        A2        XX        XX        XX        CC        CAT        XX       
13        XX        XX        XX        2        A3        XX        XX        XX        CC        CAT1        XX       
14        XX        XX        XX        1        A4        XX        XX        XX        CC        CAT-1        XX       
15        XX        XX        XX        1        A5        XX        XX        XX        CC        CAT3        XX       
                                                                                               
                                                                                ↑比對欄位        ↑若有多一欄位 產生的比對資料是否可向後順延到M呢?       
應該說是否可自動填在最後一欄呢?       

而且這次CAT1沒有被比對出來~~
附檔
[attach]15652[/attach]

11        XX        XX        XX        XX        XX        XX        XX        CC        DOG        100-1
12        XX        XX        XX        XX        XX        XX        XX        CC        CAT        100-2
14        XX        XX        XX        XX        XX        XX        XX        CC        CAT-1        100-3
13        XX        XX        XX        XX        XX        XX        XX        CC        CAT1        No Data
15        XX        XX        XX        XX        XX        XX        XX        CC        CAT3        No Data

請版大撥空看看好嗎~謝謝~!!!!
作者: stillfish00    時間: 2013-7-31 20:38

回復 22# happycoccolin
CAT1  資料庫原本就沒有不是嗎?
作者: happycoccolin    時間: 2013-8-1 09:06

回復 23# stillfish00


   
哈囉~因為有這一段

比較(可忽略"-")

If InStr(i, "-") Then If Mid(i, InStr(i, "-"), 2) <> "-1" Then d.Remove i        '可忽略"-"的步驟

所以應該要判斷成"100-3".....
作者: stillfish00    時間: 2013-8-1 10:01

回復 24# happycoccolin
1.  所以你希望的是   有含 "-"和沒含"-"的兩個是對應到相同結果?

2.  0730的檔案不含標頭,0731的含標頭哪個才是正確的資料?

3.  選擇比對的資料表欄位不固定,但是要比對的都是最後一欄?
作者: happycoccolin    時間: 2013-8-1 11:42

回復 25# stillfish00


    哈囉~~~

1.  所以你希望的是   有含 "-"和沒含"-"的兩個是對應到相同結果?
      YES

2.  0730的檔案不含標頭,0731的含標頭哪個才是正確的資料?
      0730是原本請版主幫忙的 ,而0731含標頭是後來發現比對的欄位有向後移一欄 因此FINAL是希望參考0731的樣子

3.  選擇比對的資料表欄位不固定,但是要比對的都是最後一欄?
      比對的欄位是固定的 資料庫ABC.xlsx中的"E"欄位 與 待比對檔案B.xlsx的"K'欄位比較
      希望將比對後的結果(ABC.xlsx的"A"欄位資料)填入一個跟B.xlsx相同的新檔案最後一欄位(目前是"M"欄)
      現在的寫法若填入資料是會覆蓋原本的欄位 希望能夠產生一新欄位 而不是用覆蓋寫入
作者: stillfish00    時間: 2013-8-1 12:17

本帖最後由 stillfish00 於 2013-8-1 12:26 編輯

回復 26# happycoccolin
先將 B_0731.xlsx "希望顯示在這欄位" 字樣刪掉儲存關閉後,再執行。
  1. Sub TEST()
  2.   Const DATABASE_NAME = "A" '資料庫工作表名稱
  3.   Const DATABASE_COL = 5  'E欄
  4.   Const COMPARE_COL = 11  'K欄
  5.   
  6.   Dim d, ar, filein, fileout, s, i As Long
  7.   
  8.   Set d = CreateObject("scripting.dictionary")
  9.   ar = Sheets(DATABASE_NAME).[A1].CurrentRegion.Value
  10.   For i = 2 To UBound(ar)
  11.     d(Replace(ar(i, DATABASE_COL), "-", "")) = ar(i, 1)
  12.   Next
  13.   
  14.   filein = Application.GetOpenFilename(Title:="選擇要比對的檔案")
  15.   If Not TypeName(filein) = "String" Then Exit Sub '取消則結束
  16.       
  17.   Application.ScreenUpdating = False
  18.   With Workbooks.Open(filein)
  19.     ar = .Sheets(1).[A1].CurrentRegion.Value
  20.     .Close False
  21.   End With
  22.   Application.ScreenUpdating = True
  23.   
  24.   ReDim Preserve ar(LBound(ar) To UBound(ar), LBound(ar, 2) To UBound(ar, 2) + 1)
  25.   For i = LBound(ar) + 1 To UBound(ar)
  26.     s = Replace(ar(i, COMPARE_COL), "-", "")
  27.     If d.exists(s) Then
  28.       ar(i, UBound(ar, 2)) = d(s)
  29.     Else
  30.       ar(i, UBound(ar, 2)) = "No Data"
  31.     End If
  32.   Next
  33.   
  34.   fileout = Application.GetSaveAsFilename(Title:="另存為新檔")
  35.   If Not TypeName(fileout) = "String" Then Exit Sub '取消則結束
  36.   
  37.   With Workbooks.Add.Sheets(1)
  38.     .[A1].Resize(UBound(ar), UBound(ar, 2)).Value = ar
  39.     .Parent.SaveAs fileout
  40.   End With

  41. End Sub
複製代碼

作者: happycoccolin    時間: 2013-8-1 12:52

回復 27# stillfish00


    謝謝stillfish00~~~~

我來run一下~感恩您的幫忙~~
作者: happycoccolin    時間: 2013-8-1 16:21

回復 27# stillfish00


    哈囉~~stillfish00 ~~^^

剛剛試過OK~

但是有幾個問題

1.若資料庫中有空白行,就會停止比對 導致B.xlsx最後一個與資料庫對應的欄位下一行皆變成NO DATA
(目前資料庫預計有50000行左右的資料) 剛剛有先放進去比對發現結果通通都是NO DATA

[attach]15666[/attach]

2.是否可以讓user選擇存檔與否 不要直接先跳出存檔的視窗呢?
p.s.目前儲存的檔案是沒有檔案類型的

3.是否可讓比對好的檔案資料有格線及自動調整欄寬?可設定字型與大小嗎?


抱歉問題很多~拜託拜託~~~~~~~
作者: stillfish00    時間: 2013-8-2 10:12

回復 29# happycoccolin
  1. Sub TEST()
  2.   Const DATABASE_NAME = "A" '資料庫工作表名稱
  3.   Const DATABASE_COL = 5  'E欄
  4.   Const COMPARE_COL = 11  'K欄
  5.   
  6.   Dim d, ar, filein, fileout, s, i As Long
  7.   
  8.   Set d = CreateObject("scripting.dictionary")
  9.   With Sheets(DATABASE_NAME)
  10.     ar = .[A1].CurrentRegion.Resize(.Cells(.Rows.Count, "A").End(xlUp).Row).Value
  11.   End With
  12.   For i = 2 To UBound(ar)
  13.     d(Replace(ar(i, DATABASE_COL), "-", "")) = ar(i, 1)
  14.   Next
  15.   
  16.   filein = Application.GetOpenFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="選擇要比對的檔案")
  17.   If Not TypeName(filein) = "String" Then Exit Sub '取消則結束
  18.       
  19.   Application.ScreenUpdating = False
  20.   With Workbooks.Open(filein).Sheets(1)
  21.     ar = .[A1].CurrentRegion.Resize(.Cells(.Rows.Count, "A").End(xlUp).Row).Value
  22.     .Parent.Close False
  23.   End With
  24.   Application.ScreenUpdating = True
  25.   
  26.   ReDim Preserve ar(LBound(ar) To UBound(ar), LBound(ar, 2) To UBound(ar, 2) + 1)
  27.   For i = LBound(ar) + 1 To UBound(ar)
  28.     s = Replace(ar(i, COMPARE_COL), "-", "")
  29.     If d.exists(s) Then
  30.       ar(i, UBound(ar, 2)) = d(s)
  31.     Else
  32.       ar(i, UBound(ar, 2)) = "No Data"
  33.     End If
  34.   Next
  35.   
  36.   With Workbooks.Add
  37.     Application.ScreenUpdating = False
  38.     With .Sheets(1).[A1].Resize(UBound(ar), UBound(ar, 2))
  39.       .Value = ar
  40.       .Font.Name = "Verdana"  '字體名稱
  41.       .Font.Size = 14 '字體大小
  42.       .Borders.LineStyle = xlContinuous '框線
  43.       .EntireColumn.AutoFit '調整欄寬
  44.       
  45.       .Rows(1).Interior.Color = 12567966  '標頭顏色
  46.       .Rows(1).Font.Bold = True  '標頭粗體字
  47.     End With
  48.     Application.ScreenUpdating = True
  49.    
  50.     If MsgBox("是否要儲存檔案?", vbYesNo) = vbYes Then
  51.       fileout = Application.GetSaveAsFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="另存為新檔")
  52.       If Not TypeName(fileout) = "String" Then Exit Sub '取消則結束
  53.       .SaveAs fileout, FileFormat:=xlWorkbookDefault
  54.     End If
  55.   End With
  56. End Sub
複製代碼

作者: happycoccolin    時間: 2013-8-2 11:05

回復 30# stillfish00


    哈囉~stillfish00

太棒了~~^^ 太感恩~

只是還有兩個小問題~
1.目前若是空白的欄位他也會做判斷

若B.xlsx的"K"欄是空白的

他會去讀取資料庫的"E"欄空白位置第一個的對應值 寫在新檔案裡面 但是其實那欄應該要是空白

2.若是資料庫的"E"欄位 同時在"A"欄位有兩筆以上對應 那怎麼比對出來?
   目前跟VLOOKUP一樣只能一對一 VBA可做出一對多嗎?

   而本次比對結果出來不是對應到第一筆 而是空白行後的第一筆(請見附檔Book21.xlsx)

[attach]15671[/attach]


謝謝謝謝!!!!持續研讀中
作者: stillfish00    時間: 2013-8-2 11:45

回復 31# happycoccolin
上傳的例子,盡量保留原本資料的特性(如:是否含標頭、是否有空白、是否會有重複項等等),才會比較符合實際想要的結果。
  1. Sub TEST()
  2.   Const DATABASE_NAME = "A" '資料庫工作表名稱
  3.   Const DATABASE_COL = 5  'E欄
  4.   Const COMPARE_COL = 11  'K欄
  5.   
  6.   Dim d, ar, filein, fileout, s As String, i As Long
  7.   
  8.   Set d = CreateObject("scripting.dictionary")
  9.   With Sheets(DATABASE_NAME)
  10.     ar = .[A1].CurrentRegion.Resize(.Cells(.Rows.Count, "A").End(xlUp).Row).Value
  11.   End With
  12.   For i = 2 To UBound(ar)
  13.     s = Replace(ar(i, DATABASE_COL), "-", "")
  14.     If s <> "" Then
  15.       If d.exists(s) Then
  16.         d(s) = d(s) & "," & ar(i, 1)
  17.       Else
  18.         d(s) = ar(i, 1)
  19.       End If
  20.     End If
  21.   Next
  22.   
  23.   filein = Application.GetOpenFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="選擇要比對的檔案")
  24.   If Not TypeName(filein) = "String" Then Exit Sub '取消則結束
  25.       
  26.   Application.ScreenUpdating = False
  27.   With Workbooks.Open(filein).Sheets(1)
  28.     ar = .[A1].CurrentRegion.Resize(.Cells(.Rows.Count, "A").End(xlUp).Row).Value
  29.     .Parent.Close False
  30.   End With
  31.   Application.ScreenUpdating = True
  32.   
  33.   ReDim Preserve ar(LBound(ar) To UBound(ar), LBound(ar, 2) To UBound(ar, 2) + 1)
  34.   For i = LBound(ar) + 1 To UBound(ar)
  35.     If ar(i, COMPARE_COL) <> "" Then
  36.       s = Replace(ar(i, COMPARE_COL), "-", "")
  37.       If d.exists(s) Then
  38.         ar(i, UBound(ar, 2)) = d(s)
  39.       Else
  40.         ar(i, UBound(ar, 2)) = "No Data"
  41.       End If
  42.     End If
  43.   Next
  44.   
  45.   With Workbooks.Add
  46.     Application.ScreenUpdating = False
  47.     With .Sheets(1).[A1].Resize(UBound(ar), UBound(ar, 2))
  48.       .Value = ar
  49.       .Font.Name = "Verdana"  '字體名稱
  50.       .Font.Size = 14 '字體大小
  51.       .Borders.LineStyle = xlContinuous '框線
  52.       .EntireColumn.AutoFit '調整欄寬
  53.       
  54.       .Rows(1).Interior.Color = 12567966  '標頭顏色
  55.       .Rows(1).Font.Bold = True  '標頭粗體字
  56.     End With
  57.     Application.ScreenUpdating = True
  58.    
  59.     If MsgBox("是否要儲存檔案?", vbYesNo) = vbYes Then
  60.       fileout = Application.GetSaveAsFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="另存為新檔")
  61.       If Not TypeName(fileout) = "String" Then Exit Sub '取消則結束
  62.       .SaveAs fileout, FileFormat:=xlWorkbookDefault
  63.     End If
  64.   End With
  65. End Sub
複製代碼

作者: happycoccolin    時間: 2013-8-2 12:36

回復 32# stillfish00


    哈囉~~stillfish00

也太快速了~~抱歉忙中有錯~練習的檔案太多搞混了~

感謝幫忙解答~~~

再問一個問題

一對多重複的資料中是否可以只取不重複的並在同一欄位內做換行動作呢?

還有若是產生的檔案其中一欄位太寬大可以用VBA處理讓他最大只到欄寬50(並自動換列)這一類的設定嗎?

抱歉小妹這初學者問的問題都很莫名其妙 也謝謝你們能夠耐心解答

再次謝謝謝謝∼~~~~
作者: happycoccolin    時間: 2013-8-2 12:53

回復 32# stillfish00


    哈囉∼stillfish00

我知道了 下次會注意 感謝大大的耐心解答
作者: stillfish00    時間: 2013-8-2 13:42

回復 33# happycoccolin
若是產生的檔案其中一欄位太寬大可以用VBA處理讓他最大只到欄寬50(並自動換列)

你指的對象是指自動調整欄寬後的所有欄都檢查,還是只要單一欄(哪一欄?)
作者: happycoccolin    時間: 2013-8-2 13:58

回復 35# stillfish00


   HELLO~stillfish00

目前是"K"欄與"M"欄,因為資料量比較多 所以都會拉到欄寬250左右~
作者: happycoccolin    時間: 2013-8-2 14:05

回復 35# stillfish00


    HELLO~~~SORRY~~~剛剛寫錯了~~~

目前是"F"欄與"M"欄,因為資料量比較多 所以都會拉到欄寬250左右~
作者: stillfish00    時間: 2013-8-2 14:11

本帖最後由 stillfish00 於 2013-8-2 14:13 編輯

回復 33# happycoccolin
一對多重複的資料中是否可以只取不重複的並在同一欄位內做換行動作呢?
還有若是產生的檔案其中一欄位太寬大可以用VBA處理讓他最大只到欄寬50(並自動換列)這一類的設定嗎?
  1. Sub TEST()
  2.   Const DATABASE_NAME = "A" '資料庫工作表名稱
  3.   Const DATABASE_COL = 5  'E欄
  4.   Const COMPARE_COL = 11  'K欄
  5.   
  6.   
  7.   Dim d, ar, filein, fileout, s As String, i As Long
  8.   
  9.   Set d = CreateObject("scripting.dictionary")
  10.   With Sheets(DATABASE_NAME)
  11.     ar = .[A1].CurrentRegion.Resize(.Cells(.Rows.Count, "A").End(xlUp).Row).Value
  12.   End With
  13.   For i = 2 To UBound(ar)
  14.     s = Replace(ar(i, DATABASE_COL), "-", "")
  15.     If s <> "" Then
  16.       If Not d.exists(s) Then Set d(s) = CreateObject("scripting.dictionary")
  17.       d(s)(ar(i, 1)) = ""   '第二層字典,用來篩選掉重複的A欄值
  18.     End If
  19.   Next
  20.   
  21.   filein = Application.GetOpenFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="選擇要比對的檔案")
  22.   If Not TypeName(filein) = "String" Then Exit Sub '取消則結束
  23.       
  24.   Application.ScreenUpdating = False
  25.   With Workbooks.Open(filein).Sheets(1)
  26.     ar = .[A1].CurrentRegion.Resize(.Cells(.Rows.Count, "A").End(xlUp).Row).Value
  27.     .Parent.Close False
  28.   End With
  29.   Application.ScreenUpdating = True
  30.   
  31.   ReDim Preserve ar(LBound(ar) To UBound(ar), LBound(ar, 2) To UBound(ar, 2) + 1)
  32.   For i = LBound(ar) + 1 To UBound(ar)
  33.     If ar(i, COMPARE_COL) <> "" Then
  34.       s = Replace(ar(i, COMPARE_COL), "-", "")
  35.       If d.exists(s) Then
  36.         ar(i, UBound(ar, 2)) = Join(d(s).keys, vbLf)
  37.       Else
  38.         ar(i, UBound(ar, 2)) = "No Data"
  39.       End If
  40.     End If
  41.   Next
  42.   
  43.   With Workbooks.Add
  44.     Application.ScreenUpdating = False
  45.     With .Sheets(1).[A1].Resize(UBound(ar), UBound(ar, 2))
  46.       .Value = ar
  47.       .Font.Name = "Verdana"  '字體名稱
  48.       .Font.Size = 14 '字體大小
  49.       .Borders.LineStyle = xlContinuous '框線
  50.       .EntireColumn.AutoFit '調整欄寬
  51.       
  52.       .Rows(1).Interior.Color = 12567966  '標頭顏色
  53.       .Rows(1).Font.Bold = True  '標頭粗體字
  54.       
  55.       '欄寬限制及自動換行
  56.       With .Columns("F")
  57.         If .Width > 250 Then
  58.           .Width = 250
  59.           .WrapText = True
  60.         End If
  61.       End With
  62.       With .Columns("M")
  63.         If .Width > 250 Then
  64.           .Width = 250
  65.           .WrapText = True
  66.         End If
  67.       End With
  68.     End With
  69.     Application.ScreenUpdating = True
  70.    
  71.     If MsgBox("是否要儲存檔案?", vbYesNo) = vbYes Then
  72.       fileout = Application.GetSaveAsFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="另存為新檔")
  73.       If Not TypeName(fileout) = "String" Then Exit Sub '取消則結束
  74.       .SaveAs fileout, FileFormat:=xlWorkbookDefault
  75.     End If
  76.   End With
  77. End Sub
複製代碼

作者: happycoccolin    時間: 2013-8-2 14:29

本帖最後由 happycoccolin 於 2013-8-2 14:32 編輯

回復 38# stillfish00


    哈囉~~~~~~~請問一下~~目前狀況如下

With .Columns("F")
        If .Width > 250 Then
          .Width = 250 (偵錯停在這一行)
          .WrapText = True
        End If
      End With
      With .Columns("M")
        If .Width > 250 Then
          .Width = 250
          .WrapText = True
        End If

"F"欄可不用逐筆資料自動換列 只要調整欄寬就好
作者: stillfish00    時間: 2013-8-2 14:50

回復 39# happycoccolin
抱歉,請將 .Width 都改為 .ColumnWidth,250改為適合的欄寬(非像素)
作者: happycoccolin    時間: 2013-8-2 15:07

回復 38# stillfish00


哈囉 stillfish00 大大

謝謝您的耐心溝通與協助!
成功了!!!!!放煙火~

也謝謝在這版幫助過我的版大與版友們

真的很感激大家的耐心解惑

也希望有朝一日我也能成為幫助人的角色
作者: happycoccolin    時間: 2013-8-15 11:46

回復 40# stillfish00


    S大~不好意思想請教一下~如何將資料填入表頭呢?

我現在需要用到將某份資料轉檔,就差表頭名稱及欄位不同,也不用比對

我使用最笨的方法錄製巨集 但是表頭資料不知如何輸入~可以幫忙看看嗎~謝謝

Sub Macro1()
'
' Macro1 Macro
'

'
    Rows("1:1").Select
    ActiveSheet.Paste
    Range("B6").Select
    Workbooks.Open Filename:="C:\Users\Documents\VB\2\A_0814.xlsx"
    Range("A6:A50000").Select
    Application.CutCopyMode = False
    Selection.Copy
    Windows("Book2").Activate
    ActiveWindow.SmallScroll Down:=-3
    Range("B2").Select
    ActiveSheet.Paste
    Windows("A_0814.xlsx").Activate
    Range("B6:B50000").Select
    Application.CutCopyMode = False
    Selection.Copy
    Windows("Book2").Activate
    Range("D2").Select
    ActiveSheet.Paste
End Sub
作者: stillfish00    時間: 2013-8-15 13:15

回復 42# happycoccolin
不明白你的意思,
要連表頭貼過去? 複製時一起選就好啦

能否上傳檔案再說明清點?
作者: happycoccolin    時間: 2013-8-15 13:40

回復 43# stillfish00


    S大~~~我有另開一個提問~在以下路徑~

http://forum.twbts.com/thread-10164-1-1.html

因為目前需要將一個檔案中 特定幾欄的資料取出(不用比對) 並產生一新檔案填入特定欄位

兩個檔案的表頭及欄位是不同的

而且目前A.xlsx是不固定的 需要由User自行選擇載入

有試著用之前的檔案修改 但是語法不純熟尚在學習中 所以想請教S大~~~

謝謝S大的回覆~~
作者: stillfish00    時間: 2013-8-15 15:32

回復 44# happycoccolin
  1. Sub TEST()
  2.   Dim ar, r As Long, i As Long
  3.   Dim cIndexOld, cIndexNew, arNewHeader
  4.   Dim f
  5.   
  6.   cIndexOld = Array(2, 3, 4, 5, 7, 8)   'A檔案中要搬動的欄
  7.   cIndexNew = Array(2, 4, 21, 24, 43, 44)   '搬到B檔位置(欄號)
  8.   arNewHeader = Array("W", "R", "X", "B", "JJ", "KK") 'B檔標題名稱
  9.   
  10.   f = Application.GetOpenFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="選擇來源檔案")
  11.   If Not TypeName(f) = "String" Then Exit Sub '取消則結束
  12.   
  13.   Application.ScreenUpdating = False
  14.   With Workbooks.Open(f)
  15.     With .Sheets(1)
  16.       ar = .Range("A5:H" & .[A5].CurrentRegion.Rows.Count).Value
  17.     End With
  18.     .Close False
  19.   End With
  20.   Application.ScreenUpdating = True
  21.   
  22.   r = UBound(ar)
  23.   With Workbooks.Add
  24.     With .Sheets(1)
  25.       For i = LBound(cIndexOld) To UBound(cIndexOld)
  26.         .Cells(1, cIndexNew(i)).Resize(r).Value = Application.WorksheetFunction.Index(ar, 0, cIndexOld(i))
  27.         .Cells(1, cIndexNew(i)).Value = arNewHeader(i)
  28.       Next
  29.     End With
  30.    
  31.     If MsgBox("是否要儲存檔案?", vbYesNo) = vbYes Then
  32.       f = Application.GetSaveAsFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="另存為新檔")
  33.       If Not TypeName(f) = "String" Then Exit Sub '取消則結束
  34.       .SaveAs f, FileFormat:=xlWorkbookDefault
  35.     End If
  36.   End With
  37. End Sub
複製代碼

作者: happycoccolin    時間: 2013-8-15 15:44

本帖最後由 happycoccolin 於 2013-8-15 15:54 編輯

回復 43# stillfish00


    S大~若有的檔案是B5欄開始有的是B6欄開始 可以怎麼判斷?

還有若是新表格所有欄位都要有TITLE 可以都填上嗎~

謝謝Stillfish00大大!
作者: happycoccolin    時間: 2013-8-15 16:11

回復 45# stillfish00


    S大~~~可以再請教一下這一段是在描述甚麼動作嗎~

Application.ScreenUpdating = False
  With Workbooks.Open(f)  這應該是指新開的資料檔嗎?
    With .Sheets(1)
      ar = .Range("A5:H" & .[A5].CurrentRegion.Rows.Count).Value 這句不懂甚麼意思
    End With
    .Close False
  End With
  Application.ScreenUpdating = True
  
  r = UBound(ar)
  With Workbooks.Add
    With .Sheets(1)
      For i = LBound(cIndexOld) To UBound(cIndexOld)
        .Cells(1, cIndexNew(i)).Resize(r).Value = Application.WorksheetFunction.Index(ar, 0, cIndexOld(i))
        .Cells(1, cIndexNew(i)).Value = arNewHeader(i)
      Next
    End With
作者: stillfish00    時間: 2013-8-15 17:46

本帖最後由 stillfish00 於 2013-8-15 17:49 編輯

回復 46# happycoccolin
若有的檔案是B5欄開始有的是B6欄開始 可以怎麼判斷?

不知道,
而且你的A_0814.xlsx檔案挺怪的!
[A4]儲存格明明沒文字(也沒有不可見字元),卻又不是空白儲存格(尋找>特殊目標>空白,不會找到)
用Ctrl+上下也都會跳過。

第一次遇到這種情形~

若是新表格所有欄位都要有TITLE 可以都填上嗎~

改一下
  1.   arNewHeader = Array("Q", "W", "E", "R", "T", "Y", "U", "I") '自己填上全部新標題名稱
複製代碼
還有這邊
  1.     With .Sheets(1)
  2.       For i = LBound(cIndexOld) To UBound(cIndexOld)
  3.         .Cells(1, cIndexNew(i)).Resize(r).Value = Application.WorksheetFunction.Index(ar, 0, cIndexOld(i))
  4.       Next
  5.       .[A1].Resize(, UBound(arNewHeader) + 1).Value = arNewHeader
  6.     End With
複製代碼

作者: happycoccolin    時間: 2013-8-16 10:15

回復 48# stillfish00


    哈囉S大~我試過了~~~感激不盡~

想請問一下若是我要跑資料從B5開始的 是要修改哪邊呢?

還是可以用判斷TITLE這種方式處理嗎?

EX:若TITLE(B4)是"Item"就從下一格(B5)開始取資料 一類的

不好意思..又以一般人的想法來提問~@@

謝謝S大的耐心與幫忙
作者: stillfish00    時間: 2013-8-16 11:26

回復 49# happycoccolin
  1. Sub TEST()
  2.   Dim ar, r As Long, i As Long
  3.   Dim cIndexOld, cIndexNew, arNewHeader
  4.   Dim f, findTitle
  5.   
  6.   cIndexOld = Array(2, 3, 4, 5, 7, 8)   'A檔案中要搬動的欄
  7.   cIndexNew = Array(2, 4, 21, 24, 43, 44)   '搬到B檔位置
  8.   arNewHeader = Array("Q", "W", "E", "R", "T", "Y", "U", "I") '自己填全部B檔標題名稱
  9.   
  10.   f = Application.GetOpenFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="選擇來源檔案")
  11.   If Not TypeName(f) = "String" Then Exit Sub '取消則結束
  12.   
  13.   Application.ScreenUpdating = False
  14.   With Workbooks.Open(f)
  15.     With .Sheets(1)
  16.       Set findTitle = .Cells.Find("Item", , xlValues, xlWhole, xlByRows, xlNext)  '找標題 Item
  17.       If findTitle Is Nothing Then MsgBox "找不到標題": Exit Sub
  18.       
  19.       With findTitle.CurrentRegion
  20.         ar = .Parent.Range(findTitle, .Cells(.Rows.Count, .Columns.Count)).Value
  21.       End With
  22.     End With
  23.     .Close False
  24.   End With
  25.   Application.ScreenUpdating = True
  26.   
  27.   r = UBound(ar)
  28.   With Workbooks.Add
  29.     With .Sheets(1)
  30.       For i = LBound(cIndexOld) To UBound(cIndexOld)
  31.         .Cells(1, cIndexNew(i)).Resize(r).Value = Application.WorksheetFunction.Index(ar, 0, cIndexOld(i))
  32.       Next
  33.       .[A1].Resize(, UBound(arNewHeader) + 1).Value = arNewHeader
  34.     End With
  35.    
  36.     If MsgBox("是否要儲存檔案?", vbYesNo) = vbYes Then
  37.       f = Application.GetSaveAsFilename(FileFilter:="Excel 活頁簿 (*.xlsx),*.xlsx", Title:="另存為新檔")
  38.       If Not TypeName(f) = "String" Then Exit Sub '取消則結束
  39.       .SaveAs f, FileFormat:=xlWorkbookDefault
  40.     End If
  41.   End With
  42. End Sub
複製代碼

作者: happycoccolin    時間: 2013-8-16 12:12

回復 50# stillfish00


    謝S大的超快速解答~

我來多跑幾個檔案試試看~

目前有一段會有問題 我再多RUN幾個檔案看格式哪邊有不同~

.Cells(1, cIndexNew(i)).Resize(r).Value = Application.WorksheetFunction.Index(ar, 0, cIndexOld(i))

謝Stillfish00大~^________^
作者: happycoccolin    時間: 2013-8-16 14:04

回復 50# stillfish00


    S大~~我想加入這兩行~但是一直有錯可以幫忙看一下嗎~~~謝謝~~~~
With Workbooks.Add
       With .Sheets(1)
      .Font.Name = "Tahoma"  '字體名稱
      .Font.Size = 10 '字體大小
       End With
End With
作者: stillfish00    時間: 2013-8-16 14:39

回復 52# happycoccolin
要給儲存格範圍,如
With Workbooks.Add
       With .Sheets(1)
          .[A1:H1].Font.Name = "Tahoma"  '字體名稱
          .[A1:H1].Font.Size = 10 '字體大小
       End With
End With
作者: happycoccolin    時間: 2013-8-16 15:13

回復 53# stillfish00


    瞭解了~~~~S大~^_____^

那若是整個sheet都要設定可以怎麼改~

我現在是這樣寫

      .[A1:AV10000].Font.Name = "Tahoma"  '字體名稱
      .[A1:AV10000].Font.Size = 10 '字體大小
作者: stillfish00    時間: 2013-8-16 15:23

回復 54# happycoccolin
.Cells 就代表工作表中的所有儲存格了
  1. With Workbooks.Add
  2.        With .Sheets(1).Cells
  3.           .Font.Name = "Tahoma"  '字體名稱
  4.           .Font.Size = 10 '字體大小
  5.        End With
  6. End With
複製代碼

作者: happycoccolin    時間: 2013-8-16 15:36

回復 55# stillfish00


    謝謝S大~~~~~~~~~^^

只是若要跟程式結合我還是有問題~~~@@

加錯地方整個程式RUN出來是空白的.........

  r = UBound(ar)
  With Workbooks.Add
       With .Sheets(1)
      For i = LBound(cIndexOld) To UBound(cIndexOld)
        .Cells(1, cIndexNew(i)).Resize(r).Value = Application.WorksheetFunction.Index(ar, 0, cIndexOld(i))
      Next
      .[A1].Resize(, UBound(arNewHeader) + 1).Value = arNewHeader
      .[A1:AV10000].Font.Name = "Arial"  '字體名稱
      .[A1:AV10000].Font.Size = 10 '字體大小
      
    End With




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)