11

I am using the code below to trim some "blank cells" that contain a space. The thing is it takes too much time, as is looping to every cell. What I want is to remove the spaces(the ones in the beginning and end, not middle), of all the cells.

Is there any easier way that I can apply all at once?

For a = 1 To ScenarioTableLastRow
    For f = 1 To ScenarioTableLastColumn

       If Cells(a, f) <> "" Then
            Cells(a, f) = Excel.Application.Trim(Cells(a, f))
       End If

    Next f
Next a
Community
  • 1
  • 1
Leandro Moreira
  • 215
  • 4
  • 17
  • Are you setting `Application.ScreenUpdating = False` before you run this? That can drastically speed up VBA code. Just don't forget to set `Application.ScreenUpdating = True` at the end of your code. – TylerH Feb 09 '17 at 22:19
  • 2
    @TylerH the main bottleneck here is reading and writing individual cells, but if you're going to start changing `ScreenUpdating`, you should at least restore it to whatever it *was* before your procedure hijacked it. – ThunderFrame Feb 09 '17 at 22:25
  • 1
    @ThunderFrame Yes, hence why I said set it back to true at the end of your code. – TylerH Feb 09 '17 at 22:39
  • @TylerH But what if it wasn't True when *entering* the procedure? Explicitly setting it to `True` at the end of your code might create unexpected results for procedures that call this procedure. – ThunderFrame Feb 09 '17 at 22:48
  • Application.ScreenUpdating yes, i always applied that. – Leandro Moreira Feb 09 '17 at 23:30
  • 1
    @ThunderFrame My comment is intended to be read in its entirety. So clearly the context is that you would set screen updating to true to reverse the setting of screen updating to false before the relevant code runs. Context is key. – TylerH Feb 09 '17 at 23:39
  • @TylerH I see, I read " at the end of your code" as if you meant "at the end of the *current* procedure". – ThunderFrame Feb 09 '17 at 23:58
  • By the way, VBA's `Trim` and excel's `Application.Trim` (aka `WorksheetFunction.Trim` do not do the same trimming. The former trim only trailing spaces (at beginning and end), and the latter trims also inside the string, removing any multiple spaces and keeping only one space... which makes the two answers different on more aspects than we thought... – A.S.H Feb 15 '17 at 02:21

3 Answers3

12

You'll get much better performance copying the data into an array, and working on the array, then placing the data back into the range.

Also, don't use Excel.Application.Trim. That's Excel 95 syntax, and a late-bound call with unexpected error handling. VBA has a Trim function built-in - it's about 10 times faster and it provides Intellisense.

Sub test()

    'Assuming ScenarioTable is a range
    Dim ScenarioTable As Range
    Set ScenarioTable = Range("ScenarioTable")

    'I assume your range might have some formulas, so...
    'Get the formulas into an array
    Dim v As Variant
    v = ScenarioTable.Formula

    Dim a As Long
    Dim f As Long
    'Then loop over the array
    For a = LBound(v, 1) To UBound(v, 1)
        For f = LBound(v, 2) To UBound(v, 2)
            If Not IsEmpty(v(a, f)) Then
                v(a, f) = VBA.Trim(v(a, f))
            End If
        Next f
    Next a
    'Insert the results
    ScenarioTable.Formula = v
End Sub
ThunderFrame
  • 9,352
  • 2
  • 29
  • 60
8

Do it on the whole range at once using the array version of Excel's Trim:

myRange.Value = Application.Trim(myRange.Value)

Using the only variables visible in your code, it would be:

With Range(Cells(1,1), Cells(ScenarioTableLastRow, ScenarioTableLastColumn))
     .Value = Application.Trim(.Value)
End With
A.S.H
  • 29,101
  • 5
  • 23
  • 50
  • 3
    This is faster than my answer, and in the event that the range contains formulas, you could substitute the instances of `.Value` for `.Formula`, and preserve the formulas. – ThunderFrame Feb 09 '17 at 22:56
0

For some reason Worksheetfunction.Trim does not remove the spaces, maybe because it has CRLF in it. In those cases Application.Clean function is the best method to choose.

Attila
  • 118
  • 1
  • 8