あるワークブックに現在のデータがあり、別のワークブックにアーカイブ データがあります。最近のデータ ワークブックの列 "B" には、ID 変数があります。私は言いたい:
最近のデータの列 B の ID ごとに、アーカイブされたワークブックの列 A のすべての行を反復処理します。一致する場合は、最近のデータ ワークブックのさまざまな列エントリをアーカイブ済みワークブックにコピーします。
動作するコードを書きましたが、問題は、アーカイブ データ ワークブックに 1,048,575 行あるため、一致ごとに For ループの実行が非常に遅くなることです。これについて考えるより良い方法はありますか?
これが私の現在のコードです:
Sub CopyDataLines()
Dim wb As Workbook, wb2 As Workbook
Dim ws As Worksheet
Dim vFile As Variant
Dim Filter As String
Dim FilterIndex As Integer
Dim Pupid As String
'Set source workbook
Set wb = ActiveWorkbook
Set wbSheet = ActiveSheet
'Filters for allowed files
Filter = "Excel Later Versions (*.xlsx),*.xlsx," & _
"Excel Files (*.xls),*.xls,"
FilterIndex = 1
'Open the target workbook
vFile = Application.GetOpenFilename(Filter, FilterIndex, "Select One File to Open", , False)
'if the user didn't select a file, exit sub
If TypeName(vFile) = "Boolean" Then Exit Sub
'Else open the file
Workbooks.Open vFile
'Set worbook to copy from
Set wb2 = ActiveWorkbook
Set wb2sheet = ActiveSheet
With wb2.ActiveSheet
FirstRow_book2 = 3
LastRow_book2 = .Cells(.Rows.Count, "B").End(xlUp).Row
'The contents of the tracking book
FirstRow_book1 = 3
LastRow_book1 = wbSheet.Cells(.Rows.Count, "A").End(xlUp).Row
For Lrow = LastRow_book2 To FirstRow_book2 Step -1
With .Cells(Lrow, "B")
Pupid = .Value
End With
'The For Loop Now Iterates Through All of the First WorkBook
For Lrow_book1 = LastRow_book1 To FirstRow_book1 Step -1
With wbSheet.Cells(Lrow_book1, "A")
If .Value = Pupid Then
'Reference for Date Changed Cells
wbSheet.Cells(Lrow_book1, "V") = wb2sheet.Cells(Lrow, "C")
'Reference for Date Changed Cells
wbSheet.Cells(Lrow_book1, "X") = wb2sheet.Cells(Lrow, "D")
'Prepare to copy range of multiple columns
Let secondBookRange = "I" & Lrow & ":" & "N" & Lrow
Let firstBookRange = "AI" & Lrow_book1 & ":" & "AN" & Lrow_book1
wb2sheet.Range(secondBookRange).Copy Destination:=wbSheet.Range(firstBookRange)
End If
End With
Next Lrow_book1
Next Lrow
End With
ディクショナリ/ハッシュ マップを使用した現在の実装:
Sub CopyLinesImproves()
Dim vFile As Variant
Dim Filter As String
Dim FilterIndex As Integer
Dim Pupid As Long
'Set Tracking Book
Set wb_TrackingBook = ActiveWorkbook
Set wbSheet_TrackingBook = ActiveSheet
'Set Last Row of TrackingBook
LastRow_TrackingBook = wbSheet_TrackingBook.Cells(wbSheet_TrackingBook.Rows.Count, "A").End(xlUp).Row
'Filters for allowed files
Filter = "Excel Later Versions (*.xlsx),*.xlsx," & _
"Excel Files (*.xls),*.xls,"
FilterIndex = 1
'Open the target workbook
vFile = Application.GetOpenFilename(Filter, FilterIndex, "Select One File to Open", , False)
'if the user didn't select a file, exit sub
If TypeName(vFile) = "Boolean" Then Exit Sub
'Else open the file
Set wb_NewData = Workbooks.Open(vFile)
Set wbSheet_NewData = wb_NewData.ActiveSheet
'Set First Row and Last Row of the New Data Worksheet
FirstRow_NewData = 3
LastRow_NewData = wbSheet_NewData.Cells(wbSheet_NewData.Rows.Count, "B").End(xlUp).Row
'create a lookup map using a dictionary
Set rngLookup = wbSheet_TrackingBook.Range("A1").Resize(LastRow_TrackingBook, 1)
Set d = GetMap(rngLookup)
For CurrentRow = FirstRow_NewData To LastRow_NewData Step 1
Pupid = wbSheet_NewData.Cells(CurrentRow, "B").Value
If d.exists(Pupid) Then
wbSheet_TrackingBook.Cells(d(Pupid), "V") = wbSheet_NewData.Cells(CurrentRow, "C")
wbSheet_TrackingBook.Cells(d(Pupid), "X") = wbSheet_NewData.Cells(CurrentRow, "D")
Let secondBookRange = "I" & CurrentRow & ":" & "N" & CurrentRow
Let firstBookRange = "AI" & d(Pupid) & ":" & "AN" & d(Pupid)
wbSheet_NewData.Range(secondBookRange).Copy Destination:=wbSheet_TrackingBook.Range(firstBookRange)
End If
Next CurrentRow
End Sub
Function GetMap(rng) As Object
Dim d, v, arr, ub As Long, r As Long, r1 As Long
Dim c As Range
Set d = CreateObject("scripting.dictionary")
arr = rng.Value
r1 = rng.Cells(1).Row
ub = UBound(arr, 1)
For r = 1 To ub
v = arr(r, 1)
If Len(v) > 0 Then
If d.exists(v) Then
d(v) = d(v) & "|" & r1 + (r - 1)
Else
d.Add v, r1 + (r - 1)
End If
End If
Next r
Set GetMap = d
End Function