Question

right now I'm using the following code to convert a list of ticker symbols from lowercase to upper case letters:

Dim Tickers As String
Dim n As Integer
For n = 2 To Last
    Tickers = UCase(W.Cells(n, 1).Value)
    W.Cells(n, 1).Value = Tickers
Next n

Is there a method I can use to convert the whole range in one line? something like:

Range("A1:A20").convertouppercasesomehow
Was it helpful?

Solution

Is there a method I can use to convert the whole range in one line?

Yes you can convert without looping. Try this

Sub Sample()
    [A1:A20] = [INDEX(UPPER(A1:A20),)]
End Sub

Alternatively, using a variable range, try this:

Sub Sample()
    Dim rng As Range
    Set rng = Range("A1:A20")
    rng = Evaluate("index(upper(" & rng.Address & "),)")
End Sub

As per your example

W.Range("A1:A20") = [index(upper(A1:A20),)]

Explanation

There are two parts to [A1:A20] = [INDEX(UPPER(A1:A20),)]

PART 1

As shown above, [A1:A20] is nothing but just a short way of writing Range("A1:A20")

PART 2

[INDEX(UPPER(A1:A20),)]

Index and Upper are worksheet functions. So you can use Application.Worksheetfunction.Index() but since we don't have an equivalent of UPPER like Application.Worksheetfunction.UPPER(), we can only write it as [cell] = [UPPER(cell)]

Now with that line we are instructing VBA to return an array and this is where INDEX comes into play. (As we are aware, there are two forms of the INDEX function: the array form and the reference form.) By not specifying a row or a column of the array, we are simply letting Excel know that we want the whole array. (Mentioned in VBA help as well) So basically what we are doing is converting each cell in [A1:A20] into uppercase

OTHER TIPS

You can't do it in one line like that, but you can do it for a given range like:

Sub Test()
    Dim Rng As Range
    Dim c As Range

    Set Rng = ActiveSheet.Range("A1:A20")
    For Each c In Rng
        c.Value = UCase(c.Value)
    Next c
End Sub

Which is rather simple and intuitive.

from what i gathered from various sources:

Function UcaseRangeAsArray(TargetRng As Range) As Variant()
Dim Arr()    
Arr = Evaluate("INDEX(UPPER(" & TargetRng.Address(External:=True) & "),)")    
UcaseRangeAsArray = Arr
Erase Arr
End Function

Here's another "one liner hack":

Sub UCaseRange(rng As Range)
    rng = WorksheetFunction.Transpose(Split(UCase(Join( _
        WorksheetFunction.Transpose(rng), vbBack)), vbBack))
End Sub

This assumes, that none of your cells contain the vbBack character (ASCII code 8).

With respect to the elegant answer put forth by Peter Albert, the WorksheetFunction's Transpose function has some old fashioned limits; specifically there is a ceiling of 65,535 (max unsigned integer -1) elements that can be flipped. Bulk loading a variant array, processing 'in-memory' and subsequently returning the modified values to the worksheet can overcome that limit.

Sub test()
    With Worksheets("Sheet1")
        makeUpper .Range("A2:A1000000")
    End With
End Sub

Sub makeUpper(rng As Range)
    Dim v As Long, vUPRs As Variant
    With rng
        vUPRs = .Value2
        For v = LBound(vUPRs, 1) To UBound(vUPRs, 1)
            vUPRs(v, 1) = UCase(vUPRs(v, 1))
        Next v
        .Cells = vUPRs
    End With
End Sub

This processes very quickly. 100K cells of data typically takes less than half a second and 1M cells can be converted in 4-6 seconds.


This is the type of sub procedure that can benefit from working on cells in the Application.Selection property. See this answer for boilerplate framwework to process cells within the Selection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top