+ Reply to Thread
Results 1 to 21 of 21

Improve speed on Trim function

Hybrid View

  1. #1
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Improve speed on Trim function

    Im trying to run a function that TRIM and CLEAN all cells in a range, using a worksheetfunction. However this takes forever since I loop trough all cells.
    In order to test I have set range = A1:X100000, however in actual use this range may vary, and be up to 3-4 times bigger.
    My current code now takes about 16-17 minutes, is there any better way to do what I want that improves the speed?

    Function Clean_Trim()
    
    Application.ScreenUpdating = False
    
        Dim CleanTrimRg As Range
        Dim oCell As Range
        Dim Func As WorksheetFunction
         
        Set Func = Application.WorksheetFunction
         
        On Error Resume Next
        Set CleanTrimRg = Worksheets("Import_data").Range("A1:X100000")
        If Err Then MsgBox "No data to clean and Trim!": Exit Sub
         
        For Each oCell In CleanTrimRg
            oCell = Func.Clean(Func.Trim(oCell))
        Next
    
    Application.ScreenUpdating = True
    
    End Function

  2. #2
    Forum Guru
    Join Date
    07-25-2011
    Location
    Florida
    MS-Off Ver
    Excel 2003
    Posts
    9,653

    Re: Improve speed on Trim function

    Try this...

    Function Clean_Trim()
    
    Application.ScreenUpdating = False
    
        Dim CleanTrimRg As Range
        Dim v As Variant
        Dim oCell As Variant
        Dim Func As WorksheetFunction
         
        Set Func = Application.WorksheetFunction
        On Error Resume Next
        Set CleanTrimRg = Worksheets("Import_data").Range("A1:X100000")
        If Err Then MsgBox "No data to clean and Trim!": Exit Function
         
        v = CleanTrimRg
        For Each oCell In v
            oCell = Func.Clean(Func.Trim(oCell))
        Next
        CleanTrimRg = v
    
    Application.ScreenUpdating = True
    
    End Function
    It reads the the cell range values into a variant array then clean-trims the array then writes the array back to the cells. It may seem counter-intuitive, but it is much faster than doing it one cell at a time.

    Also, technically this is not a Function. It's a procedure. Functions return a value back to the caller.

  3. #3
    Valued Forum Contributor
    Join Date
    02-12-2011
    Location
    The Netherlands
    MS-Off Ver
    365
    Posts
    860

    Re: Improve speed on Trim function

    Try specialcells.
    Set CleanTrimRg = Worksheets("Import_data").Range("A1:X100000").SpecialCells(2)
    Harry.

  4. #4
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Re: Improve speed on Trim function

    @HSV,
    What exactly does SpecialCells(2) do? It seems to improve speed a lot when there is little/no data in my range, but not a big improvement if cells contain data. Does it skip empty cells?
    Last edited by jeffreybrown; 12-08-2012 at 02:55 PM.

  5. #5
    Valued Forum Contributor
    Join Date
    02-12-2011
    Location
    The Netherlands
    MS-Off Ver
    365
    Posts
    860

    Re: Improve speed on Trim function

    Quote Originally Posted by TommyN View Post
    Does it skip empty cells?
    That's right.

  6. #6
    Forum Guru Winon's Avatar
    Join Date
    02-20-2007
    Location
    East Rand, R.S.A.
    MS-Off Ver
    2010
    Posts
    6,113

    Re: Improve speed on Trim function

    Hello TommyN,

    Welcome to the Forum.

    See if this speeds up the process:

    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    and at the end;

    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Please consider:

    Be polite. Thank those who have helped you. Then Click on the star icon in the lower left part of the contributor's post and add Reputation. Cleaning up when you're done. If you are satisfied with the help you have received, then Please do Mark your thread [SOLVED] .

  7. #7
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & 2010
    Posts
    23,259

    Re: Improve speed on Trim function

    Hello TommyN,

    The quickest way is copy the cell data into an array. This greatly reduces the overhead time by eliminating the processing to retrieve a Range object.
    Sub Clean_Trim()
    
        Dim CleanData As Variant
        Dim CleanTrimRg As Range
        Dim Item As Variant
        
         
            Set CleanTrimRg = Worksheets("Import_data").Range("A1:X100000")
         
            CleanData = CleanTrimRg.Value
            
                For Each Item In CleanTrimRg
                    Item = Trim(Item)
                Next Item
                
            CleanTrimRg.Value = CleanData
    
    End Sub
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  8. #8
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Re: Improve speed on Trim function

    @: Leith Ross and AlphaFrogs

    Both your codes made quite a big difference in performance (AlphaFrogs: 3.02 minutes, Leith Ross: 47 seconds)
    But none of your codes seems to actually TRIM or CLEAN the cells in the range, like my original code did.

  9. #9
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & 2010
    Posts
    23,259

    Re: Improve speed on Trim function

    Hello TommyN,

    In that case, you should upload a copy of the workbook for review.

  10. #10
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,834

    Re: Improve speed on Trim function

    try
    Sub test()
        [a1:x100000] = [index(trim(clean(a1:x100000)),)]
    End Sub

  11. #11
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Re: Improve speed on Trim function

    @jindon,
    How do I get this to reference to the sheet I want to trim/clean?

  12. #12
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,834

    Re: Improve speed on Trim function

    Quote Originally Posted by TommyN View Post
    @jindon,
    How do I get this to reference to the sheet I want to trim/clean?
    Something like
    Sub test()
        With Sheets("sheet1")
            .Range("a1:x100000").Value = .Evaluate("index(trim(clean(a1:x100000)),)")
        End With
    End Sub

  13. #13
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Re: Improve speed on Trim function

    @Leith Ross,

    I made a new workbook for testing purposes, with some test data and narrowed the range.
    As you can see, if you try to run the 3 different subs, only the first one will actually trim the extra spaces from the text, leaving just one space between each word and no spaces in front or at the end.
    Attached Files Attached Files

  14. #14
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Re: Improve speed on Trim function

    @jindon: thank you, this works and improves the speed at about 2 minutes compared to my original 17. Even though I don't understand what your code actually does.

    However, Im wondering if this is the most efficient way, or are there still room for improvement? Because as I said my range may be up to 4 times bigger, and I would guess that this would take 4 times longer?

    Leith Ross code took about half the time, but since it didnt' do anything I cant use it. Does someone knows whats wrong? Or know of other efficient ways?

  15. #15
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,834

    Re: Improve speed on Trim function

    Not sure if there is faster solution.

    Regarding Leith Ross code
    You can't change the elements in an array by For Each loop.

  16. #16
    Forum Guru
    Join Date
    07-25-2011
    Location
    Florida
    MS-Off Ver
    Excel 2003
    Posts
    9,653

    Re: Improve speed on Trim function

    This will loop through each element in the array.

    Sub Clean_AlphaFrog2()
        
        Dim CleanTrimRg As Range
        Dim v As Variant, i As Long, j As Long
        Dim Func As WorksheetFunction
        
        Set Func = Application.WorksheetFunction
        Set CleanTrimRg = Worksheets("Import_Data").Range("A1:D10")
        
        Application.ScreenUpdating = False
         
        v = CleanTrimRg
        For i = 1 To UBound(v, 1)
            For j = 1 To UBound(v, 2)
                v(i, j) = Func.Clean(Func.Trim(v(i, j)))
            Next j
        Next i
        CleanTrimRg = v
            
        Application.ScreenUpdating = True
        
    End Sub
    Also note; WorksheetFunction.Trim is not exactly the same as VBA function Trim.

    WorksheetFunction.Trim will trim multiple consecutive spaces within the text.
    VBA Trim will only trim leading and trailing spaces.

    Example (periods represent space characters for illustration):
    WorksheetFunction.Trim "..Test....Test.." becomes "Test.Test"
    VBA Function Trim "..Test....Test.." becomes "Test....Test"

  17. #17
    Forum Contributor
    Join Date
    07-27-2012
    Location
    California, USA
    MS-Off Ver
    Excel 2003
    Posts
    198

    Re: Improve speed on Trim function

    I am curious to know if the code below speeds up the process.
    I borrowed code from jindon. I am going on the idea that the
    more data you process at one time, the more it will impact
    computer memory and increase the time to process, possibly reaching
    a point where it takes minutes rather than seconds to complete.

    With your data in every cell from A to X in 65,500 rows, the macro
    took 8 seconds. The difference is that I break the data into
    3 blocks and the results are entered in Sheet2.
    Sub Clean_Copy()
    'copy Sheet1 data, columns A - X, trimmed and cleaned
    'of double spaces to Sheet2.
    'This experiment breaks the data into 3 blocks to see if
    'processing time can be reduced.
    Dim lastRow As Long, i As Long, biteSize As Long
    Dim j As Integer
    Dim startTime As Date, endTime As Date, elapsedTime As Date
    
        startTime = Now()
        lastRow = ActiveSheet.UsedRange.Rows.Count
        biteSize = Application.WorksheetFunction.RoundUp(lastRow / 3, 0)
            
        With Sheets("Sheet1")
            j = 1
            For i = 1 To lastRow Step biteSize
                Sheets("Sheet2").Range("a" & i & ":x" & (j * biteSize)).Value = _
                    .Evaluate("index(trim(clean(a" & i & ":x" & (j * biteSize) & ")),)")
                j = j + 1
            Next
        End With
       
        endTime = Now()
        elapsedTime = endTime - startTime
        
        MsgBox "Data copied in blocks" & vbCrLf & vbCrLf & _
            "Start time: " & Format(startTime, "HH:MM:SS") & vbCrLf & _
            "End time: " & Format(endTime, "HH:MM:SS") & vbCrLf & _
            "Elapsed time: " & Format(elapsedTime, "HH:MM:SS")
            
    End Sub
    Last edited by xLJer; 12-11-2012 at 11:54 PM.

  18. #18
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,834

    Re: Improve speed on Trim function

    See the difference.

    Only about one second on my PC.
    Sub test()
        test1
        test2
    End Sub
    
    Sub test1()
        Dim i As Long, s As Single
        s = Timer
        With Sheets("sheet1").Range("a1:x100000")
            For i = 1 To .Rows.Count Step 30000
                With .Rows(i).Resize(30000)
                    .Value = .Parent.Evaluate("index(trim(clean(" & .Address & ")),)")
                End With
            Next
        End With
        Debug.Print "test1", Format$(Timer - s, "#.00000")
    End Sub
    
    Sub test2()
        Dim s As Single
        s = Timer
        With Sheets("sheet1")
            .Range("a1:x100000").Value = .Evaluate("index(trim(clean(a1:x100000)),)")
        End With
        Debug.Print "test2", Format$(Timer - s, "#.00000")
    End Sub
    And the results

    test1 14.40625
    test2 13.01953
    test1 14.69922
    test2 13.05469

    test2 is faster.
    Last edited by jindon; 12-12-2012 at 12:07 AM.

  19. #19
    Valued Forum Contributor
    Join Date
    11-15-2008
    Location
    ph
    MS-Off Ver
    2007/2010/2016
    Posts
    479

    Re: Improve speed on Trim function

    Hi-

    For me, jindon's solution is the best but even further improved as below unless I am doing something wrong.

    jindon, would calling once the evaluate boost the speed as below?
    atleast in my PC I got the same data results and took 3.04688 seconds
    Sub test2()
        Dim s As Single
        s = Timer
        With Sheets("Sheet1 (2)")
            .Range("a1:x100000").Value = .Evaluate("index(trim(clean(a1:x1)),)")
        End With
        Debug.Print "test2", Format$(Timer - s, "#.00000")
    End Sub
    Regards,
    Event

  20. #20
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,834

    Re: Improve speed on Trim function

    .Evaluate("index(trim(clean(a1:x1)),)")

  21. #21
    Registered User
    Join Date
    11-27-2012
    Location
    Oslo, Norway
    MS-Off Ver
    Excel 2010
    Posts
    9

    Re: Improve speed on Trim function

    Thanks I went with jindons last solution where "test2" was fastest. It was far superior than anything else I tried. Still uses some time (17-18 seconds), but at least now users won't wait forever...

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1