我下面執行下列文件中的VBA代碼:Error13在Excel VBA中的數據文件
http://www.filedropper.com/error13
我得到一個錯誤13類型不匹配。
這裏是宏觀
Aggregate, Collate and Transpose rows into columns
工作正常,當我選擇一些行(例如ID爲1001或1003和1004一起,但是當我嘗試處理更多行,我得到錯誤13
我試圖同時處理每個ID,但我有大約100 ..
我下面執行下列文件中的VBA代碼:Error13在Excel VBA中的數據文件
http://www.filedropper.com/error13
我得到一個錯誤13類型不匹配。
這裏是宏觀
Aggregate, Collate and Transpose rows into columns
工作正常,當我選擇一些行(例如ID爲1001或1003和1004一起,但是當我嘗試處理更多行,我得到錯誤13
我試圖同時處理每個ID,但我有大約100 ..
出於好奇心和智力活動的緣故,我花了刺傷最初由提交的陣列處理方法3210在original question與一個頭腦克服運行時錯誤'13':在較大的數據集上輸入不匹配錯誤。
ReDim Preserve statement只能重新調整最後一個等級,同時保留已存儲的現有值,這是因爲您正在提高數組維度的大小並且不縮小它。這是msdn.microsoft.com有話要說:
與保留調整大小。如果使用Preserve,則只能調整數組的最後一個維度。對於其他維度,您必須指定現有數組的邊界。
例如,如果數組只有一個維度,則可以調整該維度的大小並仍然保留數組的所有內容,因爲您正在更改最後一個維度。但是,如果陣列具有兩個或更多維度,則只有使用Preserve時,纔可以更改最後維度的大小。
由於剝離出去工作表的數據的方向,第一等級與使用ReDim能長得這麼方向與Application.Transpose翻轉,以保留ReDim'ed然後翻轉回來的尺寸。隨着陣列增加更多記錄,Application.Transpose迅速達到了重新定向陣列的最大容量。我在XL: Limitations of Passing Arrays to Excel Using Automation上發現了一些關於這方面的舊文檔,但它已經過時了。
我的解決方案是將ar1
中的值轉換爲ar2
,這樣ar2
可以在不重新定向的情況下重新調整大小。一旦處理完成,結果是錯誤的方向。爲了以正確的方向將值返回工作表,我寫了一個幫助函數,將ar2
轉換回截斷的ar1
。這種僞轉置只需要一次;就在將新的彙總值填入報告區域之前。
修改後的子代碼:
Sub jpd_Transposing()
Const sDestination As String = "D2"
Dim ar1 As Variant
Dim ar2 As Variant
Dim i As Long 'counter
With ActiveSheet
ar1 = .Range("A2:B" & .Cells(Rows.Count, 1).End(xlUp).Row).Value
ReDim ar2(1 To 2, 1 To 1)
ar2(1, 1) = ar1(1, 1): ar2(2, 1) = ar1(1, 2)
For i = 2 To UBound(ar1, 1)
If ar1(i, 1) = ar2(1, UBound(ar2, 2)) Then
ar2(2, UBound(ar2, 2)) = ar2(2, UBound(ar2, 2)) & ar1(i, 2)
ElseIf ar1(i, 1) = vbNullString Then
ar2(2, UBound(ar2, 2)) = ar2(2, UBound(ar2, 2)) & " "
Else
ReDim Preserve ar2(1 To 2, 1 To UBound(ar2, 2) + 1)
ar2(1, UBound(ar2, 2)) = ar1(i, 1)
ar2(2, UBound(ar2, 2)) = ar1(i, 2)
End If
Next
ar1 = my_2D_Transpose(ar1, ar2)
.Range(sDestination).Resize(UBound(ar1, 1), UBound(ar1, 2)) = ar1
End With
End Sub
Function my_2D_Transpose(a1 As Variant, a2 As Variant)
Dim a As Long, b As Long
ReDim a1(1 To UBound(a2, 2), 1 To UBound(a2, 1))
For a = LBound(a2, 1) To UBound(a2, 1)
For b = LBound(a2, 2) To UBound(a2, 2)
a1(b, a) = Trim(a2(a, b))
Next b
Next a
my_2D_Transpose = a1
End Function
所以,現在你可能想知道多大的改善了原有的工作基礎例行多麼有一個與陣列存儲處理。因爲這是合乎邏輯的下一步,所以我跑了兩個計時器注意開始和停止。
Sub timed()
Application.ScreenUpdating = False
Application.EnableEvents = False
Debug.Print Timer
Call concatenate_and_transpose_to_delim_string
Debug.Print Timer
Call jpd_Transposing
Debug.Print Timer
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
這兩個報告數據結果都是相同的。請注意,我在測試期間關閉了屏幕更新和事件處理。這可能改進了工作表方法,而不是改進了數組方法,但我認爲這是公平的,因爲這些是用於提高宏效率的非常標準的技術。
定時結果:
測試環境:45894行×2分使用業務類的i5聚集報告數據的列/ 8GB基於轉換成123行的原始數據的×2列膝上型(Win7的,Excel中2010版14.0.7145.5000(32位)
concatenate_and_transpose_to_delim_string(工作表).... 00:01.01seconds¹
jpd_Transposing(存儲器陣列).............. .......... ....................... 00:00.07秒¹
¹測試運行了好幾次。時代是典型的。
結論:
好了,所以我們選擇了幾乎一整秒使用一種變型存儲器陣列上的工作表的讀/寫但仍然在處理相同的效率高達93%的改善數據到相同的結果。我將其他長時間運行的例程從工作表驅動轉換爲陣列內存;結果至少是可觀的,並且這些結果致力於在大數據矩陣中進行更多重複的查找式操作。
值得嗎?這很大程度上取決於個人用戶和情況。當然,這樣做有好處,但我寫基於工作表的代碼要比基於數組的代碼快很多,所以除非每天每天運行幾次,否則我可能不會打擾。項目的規模也是一個因素,因爲隨着工作量的增加,福利會增加。儘管如此,將內存數組方法使用的方法保持在頭腦中並且在某些情況下方法混搭可能會產生最佳結果仍然很好。
FWIW,在轉輔助函數使用的VBA Trim function沒有產生可測量的不利影響是否有人使用與否,似乎以確保最終的結果並沒有尾隨空格字符左側的最佳場所(如額外的時間)來自字符串連接。
非常感謝Jeeped! – user3437823 2015-04-06 06:08:55
一個很好的調查!我非常喜歡它,謝謝! – ZygD 2015-04-08 05:22:59
@ZygD - 不用擔心。謝謝你讓我探索這條大道。我總是擔心重新使用別人的努力而不先清除它。我希望原始認證已經足夠。 – Jeeped 2015-04-08 05:42:09
我的理解是你問了一個有兩個答案的問題。你接受了其中一個答案,但正在嘗試其他失敗的答案。爲什麼要發佈一個新問題而不是發佈針對失敗答案的評論,以便宏的作者可以修復它。特別是在沒有評論的情況下,修復別人錯誤的宏很困難。 – 2015-04-04 22:59:46