2016-02-02 37 views
5

Poniższy skrypt działa na mniejszych zestawach danych (mniej niż 30 tys. Wierszy), ale powoduje błędy "#VALUE" dla każdej komórki w wybranym zakresie, gdy zakres jest większy.VBA i Excel: Dlaczego mój skrypt TRIM daje #VALUE na dużych zbiorach danych?

Dim FirstCell As Range, LastCell As Range, MyRange As Range 

Set LastCell = Cells(Cells.Find(What:="*", SearchOrder:=xlRows, _ 
     SearchDirection:=xlPrevious, LookIn:=xlValues).Row, _ 
     Cells.Find(What:="*", SearchOrder:=xlByColumns, _ 
     SearchDirection:=xlPrevious, LookIn:=xlValues).Column) 

Set FirstCell = Cells(Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlRows, _ 
     SearchDirection:=xlNext, LookIn:=xlValues).Row, _ 
     Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlByColumns, _ 
     SearchDirection:=xlNext, LookIn:=xlValues).Column) 

Set MyRange = Range(FirstCell, LastCell) 
     MyRange.Select 
     If MyRange Is Nothing Then Exit Sub 
     Application.ScreenUpdating = False 
     Application.Calculation = xlCalculationManual 
    With Selection 
     .Value = Evaluate("if(row(" & .Address & "),clean(trim(" & .Address & ")))") 
    End With 

    Application.ScreenUpdating = True 
    Application.Calculation = xlCalculationAutomatic 
    MsgBox "Finished trimming " & vbCrLf & "excess spaces", 64 

VBA TRIM Error

+0

Ile komórek zmieniasz za pomocą tego kodu? Właśnie przetestowałem to na ~ 1,7 miliona komórek i nie dostałem żadnych błędów w moim dokumencie ćwiczeniowym – TMH8885

+0

8,106,860 komórek. To 161,363 wiersze. –

+0

Wydaje się działać do około 70 tys. Wierszy. Za dużo więcej, po prostu ustawia wartość każdej komórki w wybranym zakresie na #VALUE. –

Odpowiedz

1

udało mi się replikować problemu, a przy użyciu tablicy wariantowej jak pokazano poniżej rozwiązuje problem dla dużych zbiorów danych

Dim FirstCell As Range, LastCell As Range, MyRange As Range 
Dim DataRange() As Variant 
Dim lRows As Long 
Dim lCols As Long 
Dim i As Long, j As Long 
Dim value As String 

Set LastCell = Cells(Cells.Find(What:="*", SearchOrder:=xlRows, _ 
     SearchDirection:=xlPrevious, LookIn:=xlValues).Row, _ 
     Cells.Find(What:="*", SearchOrder:=xlByColumns, _ 
     SearchDirection:=xlPrevious, LookIn:=xlValues).Column) 

Set FirstCell = Cells(Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlRows, _ 
     SearchDirection:=xlNext, LookIn:=xlValues).Row, _ 
     Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlByColumns, _ 
     SearchDirection:=xlNext, LookIn:=xlValues).Column) 

Set MyRange = Range(FirstCell, LastCell) 
    MyRange.Select 
    If MyRange Is Nothing Then Exit Sub 
    Application.ScreenUpdating = False 
    Application.Calculation = xlCalculationManual 
    lRows = MyRange.Rows.Count 
    lCols = MyRange.Columns.Count 
    ReDim DataRange(1 To lRows, 1 To lCols) 
    DataRange = MyRange.value 
    For j = 1 To lCols 
    For i = 1 To lRows 
     DataRange(i, j) = Trim(DataRange(i, j)) 
    Next i 
    Next j 

    MyRange.value = DataRange 

Application.ScreenUpdating = True 
Application.Calculation = xlCalculationAutomatic 
MsgBox "Finished trimming " & vbCrLf & "excess spaces", 64 

Dla porównania, kiedyś ten artykuł, aby pomóc wymyślić odpowiedź: https://blogs.office.com/2008/10/03/what-is-the-fastest-way-to-scan-a-large-range-in-excel/

+0

Linki mogą zostać zerwane w przyszłości. Skopiuj i wklej informacje potrzebne do udzielenia odpowiedzi na pytanie do postu. Użyj linku tylko jako odniesienia. – eirikdaude

+0

Mam zaktualizowaną odpowiedź, aby było bardziej zrozumiałe, że link był tylko w celach informacyjnych, odpowiedź została uwzględniona powyżej – TrtlBoy