【问题标题】:Convert an entire range to uppercase without looping through all the cells将整个范围转换为大写而不遍历所有单元格
【发布时间】:2013-11-27 22:47:52
【问题描述】:

现在我正在使用以下代码将股票代码列表从小写字母转换为大写字母:

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

【问题讨论】:

  • 为什么不想遍历每个单元格?
  • @Jack 我知道这很古老,但你的问题的答案是:这是一个非常非常糟糕的主意。超级慢。

标签: excel vba range uppercase


【解决方案1】:

你不能像这样在一行中做到这一点,但是你可以在给定的范围内做到这一点,例如:

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

这相当简单直观。

【讨论】:

  • 这不还是个循环吗?
  • 是的。这个解决方案很容易理解,但没有@SiddharthRout 的解决方案那么令人印象深刻。
【解决方案2】:

有没有一种方法可以将整个范围转换为一行?

是的,您可以在不循环的情况下进行转换。试试这个

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

或者,使用可变范围,试试这个:

Sub Sample()
    Dim rng As Range
    Set rng = Range("A1:A20")
    rng = Evaluate("index(upper(" & rng.Address & "),)")
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),)]

IndexUpper 是工作表函数。所以你可以使用Application.Worksheetfunction.Index(),但由于我们没有像Application.Worksheetfunction.UPPER()这样的UPPER,我们只能写成[cell] = [UPPER(cell)]

现在,我们通过该行指示VBA 返回一个数组,这就是INDEX 发挥作用的地方。 (我们知道,INDEX 函数有两种形式:数组形式和引用形式。)通过不指定数组的行或列,我们只是让 Excel知道我们想要整个数组。 (在 VBA 帮助中也提到过)所以基本上我们所做的是将[A1:A20] 中的每个单元格转换为大写

【讨论】:

  • +1,不错。我敢打赌你不能用一行来解释它是如何工作的:)。
  • @DougGlancy:赌什么? :P
  • @DougGlancy:哈哈哈。我已经超出了每日投票上限,因此不再投票不会有任何影响。但是,如果我曾经在你的镇上,那么啤酒就在你身上! :) 有时间给我,我会更新帖子。
  • 那将是我的荣幸。
  • @DougGlancy:I bet you can't explain how it works in one line顺便说一句,如果我以另一种方式看待它,我就输了;)我花了大约 14 行来解释它:P
【解决方案3】:

这是另一个“单线黑客”:

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

这假设您的所有单元格都不包含 vbBack 字符(ASCII 代码 8)。

【讨论】:

    【解决方案4】:

    关于Peter Albert 提出的优雅答案,WorksheetFunctionTranspose 函数有一些老式的限制;具体来说,可以翻转的元素上限为 65,535(最大无符号整数 -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
    

    这个过程很快。 100K 单元的数据通常需要不到半秒的时间,1M 单元可以在 4-6 秒内转换。


    这是可以从Application.Selection 属性中的单元格中受益的子过程类型。请参阅this answer 以了解在选择中处理单元格的样板框架。

    【讨论】:

    • 在通过 Row aka range("A1:AZ1") 时不起作用。使用简单的 For Each Cell In rng Cell.Value = UCase(Cell) Next Cell
    【解决方案5】:

    根据我从各种来源收集的信息:

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

    【讨论】:

      猜你喜欢
      • 2016-05-28
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 2021-02-28
      • 2016-04-20
      • 1970-01-01
      • 2018-05-11
      相关资源
      最近更新 更多