Преобразуйте весь диапазон в верхний регистр без цикла через все ячейки

прямо сейчас я использую следующий код, чтобы преобразовать список тикер символы из нижнего регистра в верхний регистр:

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

есть ли метод, который я могу использовать для преобразования всего диапазона в одну строку? что-то вроде:

Range("A1:A20").convertouppercasesomehow

5 ответов


есть ли метод, который я могу использовать для преобразования всего диапазона в одну строку?

Да, вы можете конвертировать без цикла. Попробуйте это

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

согласно вашему примеру

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

объяснение

есть две части [A1:A20] = [INDEX(UPPER(A1:A20),)]

часть 1

как показано выше, [A1:A20] это не что иное, как короткий способ написания Range("A1:A20")

часть 2

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

Index и Upper функции листа. Таким образом, вы можете использовать Application.Worksheetfunction.Index() но поскольку у нас нет эквивалента UPPER как Application.Worksheetfunction.UPPER(), мы можем только написать его как [cell] = [UPPER(cell)]

теперь с этой строкой мы инструктируем VBA чтобы вернуть массив, и это где INDEX вступает в игру. (как мы знаем, есть две формы INDEX функция: форма массива и форма справки.) не указывая строку или столбец массива, мы просто сообщаем Excel, что нам нужен весь массив. (упоминается в справке VBA, а также) так что в основном то, что мы делаем, это преобразование каждой ячейки в [A1:A20] в верхнем регистре


вы не можете сделать это в одну строку, но вы можете сделать это для данного диапазона, например:

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

что довольно просто и интуитивно.


вот еще один "один лайнер hack":

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

это предполагает, что ни одна из ваших ячеек не содержит символ vbBack (код ASCII 8).


в отношении элегантного ответа, выдвинутого Питер Альберт на WorksheetFunction ' s транспонировать функция имеет некоторые старомодные ограничения; в частности, есть потолок из 65,535 (max unsigned integer -1) элементов, которые можно перевернуть. Массовая загрузка массива вариантов, обработка "в памяти" и последующее возвращение измененных значений на лист могут преодолеть это ограничение.

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

это происходит очень быстро. 100к ячейки данных обычно занимают менее половины секунды, а ячейки 1M могут быть преобразованы за 4-6 секунд.


это тип sub процедуры, которая может извлечь выгоду из работы с ячейками в приложение.Выбор собственность. См.ответ для шаблона framwework для обработки ячеек в пределах выбора.


из того, что я собрал из различных источников:

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