2016-08-24 15 views
1

我有大量存儲在一個CSV文件(約60MB)的數據,其具有鄰近名名稱和兩個日期即VBA:雙人間遍歷數據量非常大的

A1name1 B1date1 C1date2 
A2name2 B2date1 C2date2 
列表

我有有名稱的列表另一個文件:

names1 
names2 
names3 
names4 

我想舉個例子names1,通過名字的大數據庫搜索,如果names1發現返回日期1和日期2。我已經做了這個使用雙循環。僞因爲這是如下:

For i = 1 to SMLendofrow 
    for j = 1 to LRGendofrow 
     if cells(i,"A").value = lrgwkbook.wrksheet.cells(j,"A").value then 
       cells(i,"B").value =lrgwkbook.wrksheet.cells(j,"B").Value 
       cells(i,"C").value =lrgwkbook.wrksheet.cells(j,"C").Value 
      end if 
     next j 
next i 

下面這段代碼完美的作品不過那簡直是太長時間。由於具有所有名稱的大型工作簿非常大,因此需要大約10分鐘來搜索所有名稱。這是更有效的方法嗎?我已經使用python作爲替代方案,並在2分鐘內完成它,但我想要特別針對VBA。

謝謝

+2

你有沒有考慮推範圍爲數組,然後直接比較陣列而不是迭代單元格?應該更快。此外,考慮嘗試[codereview.se]這個問題,因爲這是正確的地方優化代碼已經工作... – Dave

+1

道歉不知道。我會給陣列方法一個鏡頭。 – james1395

+0

@ james1395在我的回答下面試試我的代碼,你可以使用'Match'功能並保存內部循環。讓我知道這是否幫助你在你的評論中幫助你 –

回答

2

取決於。如果第二個文件中的RAM大小和名稱數量允許,則'Id建議爲較大的文件設置一個循環,將名稱 - date1和名稱 - date2鍵值對組合爲兩個字典(或其他語言,hash表),當它完成時,一個單獨的循環(不嵌入到另一個循環中)處理另一個文件並從兩個哈希中獲取名稱。

您必須在項目中引用microsoft.scripting.runtime。

+0

Unforuntately它是超過一百萬個名字,所以它甚至不會在excel中完全打開(csv文件)。我將需要一個圍繞 – james1395

+0

的工作哦,那不太酷。你能解釋爲什麼你需要VBA嗎?我建議使用Talend,Pentaho或純SQL將它們加載到數據庫中,然後在那裏進行聚合。我覺得更容易。 –

0

將CSV文件轉換爲MDB(Access數據庫),然後連接此數據庫並執行必要的操作。它比上面的方法運行得更快。 注意:每次需要從CSV重建MDB如果以CSV所做的更改文件

0

可以使用Match功能,它會爲你節省內環(和很多寶貴的運行時間),請參閱下面的代碼(只是部分需要修改)

Dim MatchRow As Long 
Dim SearchedRng As Range 

' set the range for "Match" all active rows and columns >> modify as needed 
' I assumed "LRGendofrow" is the last row 
Set SearchedRng = lrgwkbook.wrksheet.Range("A1:C" & LRGendofrow) 

For i = 1 To SMLendofrow 
    ' For j = 1 To LRGendofrow 
    If Not IsError(Application.Match(Cells(i, "A").Value, SearchedRng, 0)) Then 
     MatchRow = Application.Match(Cells(i, "A").Value, SearchedRng, 0) 
     Cells(i, "B").Value = lrgwkbook.wrksheet.Cells(MatchRow, "B").Value 
     Cells(i, "C").Value = lrgwkbook.wrksheet.Cells(MatchRow, "C").Value 
    Else ' "names" record not found >> do something 

     ' in my example I put #NA in cells, to know it's not found 
     Cells(i, "B") = CVErr(xlErrNA) 
     Cells(i, "C") = CVErr(xlErrNA) 
    End If 

Next i 
0

避免內(和更大的)循環,您可以使用此代碼:

Option Explicit 

Sub main() 
    Dim namesRng As Range 
    Dim f As Range, cell As Range 

    With Worksheets("Names") '<-- change "Names" with actual name of your sheet with the list of names 
     Set namesRng = .Range("A1", .Cells(.Rows.Count, 1).End(xlUp)) '<--| get the list of names form cell A1 down to last non empty row 
    End With 

    With Workbooks.Open("C:\Users\...\data.csv").Worksheets(1).UsedRange.Columns(1) '<-- open your CSV file and refer to "used" cells in its column "A" 
     For Each cell In namesRng '<-- loop through names list 
      Set f = .Find(what:=cell.value, LookIn:=xlValues, lookat:=xlWhole) '<-- try finding current name in referenced range of csv file 
      If Not f Is Nothing Then cell.Offset(, 1).Resize(, 2).value = f.Offset(, 1).Resize(, 2).value '<--| if found, then write its two adjacent cells values next to current name ones 
     Next cell 
    End With 
    ActiveWorkbook.Close False 
End Sub