簡體   English   中英

數據文件中Excel VBA中的Error13

[英]Error13 in Excel VBA in data file

我正在以下文件中執行下面的VBA代碼:

http://www.filedropper.com/error13

我得到錯誤13類型不匹配。

這是宏

將行聚合,整理和轉置為列

當我選擇一些行時工作正常(例如id 1001或1003和1004,但當我嘗試處理更多行時,我得到錯誤13。

我正在嘗試一次處理每個id,但我有大約100個..

為了好奇和智力鍛煉,我采用了原始問題中 ZygD最初提交的數組處理方法,以克服運行時錯誤'13':在較大的數據集上輸入不匹配錯誤。

ReDim Preserve語句只能重新定義最后一個等級,同時保留已經存儲的現有值,這取決於您提高了數組維度的大小而不是縮小它。 這就是msdn.microsoft.com關於這個問題的說法:

使用Preserve調整大小 如果使用“保留”,則只能調整陣列的最后一個維度。 對於每個其他維度,您必須指定現有數組的邊界。
例如,如果您的數組只有一個維度,則可以調整該維度的大小並保留數組的所有內容,因為您要更改最后一個維度。 但是,如果您的數組具有兩個或更多維度,則在使用“保留”時,可以僅更改最后一個維度的大小。

由於數據的方向從工作表中剝離,第一個等級是與ReDim一起增長的維度,因此使用Application.Transpose,ReDim'ed和Preserve翻轉方向。 隨着陣列隨着附加記錄的增長,Application.Transpose很快達到了重新定向陣列的最大容量。 我在XL中找到了一些關於此的舊文檔:使用自動化將數組傳遞到Excel的限制但是它已經過時了。

我的解決方案是將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

兩份報告數據結果完全相同。 請注意,我在測試期間關閉了屏幕更新和事件處理。 這可能改進了工作表方法,而不是改進了數組方法,但我認為這是公平的,因為這些是提高宏效率的非常標准的技術。

定時結果:

測試環境:使用基於i5 / 8Gb商務級筆記本電腦的45,894行×2列原始數據轉換為123行×2列聚合報告數據(Win7,Excel 2010版本14.0.7145.5000(32位)

concatenate_and_transpose_to_delim_string (工作表).... 00:01.01秒¹
jpd_Transposing (內存陣列)............................................. .. 00:00.07秒¹

¹ 測試運行了幾次。 時代很典型。

結論:

好的,所以我們在工作表讀/寫時使用變量存儲器陣列幾乎整整一秒,但是將相同數據處理到相同結果的效率仍然提高了93%。 我已經將其他長時間運行的例程從工作表驅動轉換為陣列內存; 結果至少同樣可觀,並且這些結果用於大數據矩陣中更多重復的查找類型操作。

它值得嗎? 這幾乎取決於個人用戶和情況。 當然有好處,但我編寫基於工作表的代碼比基於數組的代碼快得多,所以除非每天運行幾次,否則我可能不會打擾。 項目的規模也是一個因素,因為福利會隨着工作量的增加而增加。 盡管如此,保持內存陣列方法使用的方法在頭腦中是新鮮的,並且在某些情況下,方法的混搭可能會產生最佳結果。

FWIW,轉置輔助函數中使用的VBA修剪函數不會產生任何可測量的有害影響(例如額外的時間),無論是否使用它,並且似乎是確保最終結果沒有字符串留下的尾隨空格字符的最佳位置級聯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM