Excel VBA 转大写

问题描述

有人可以告诉我以下代码是否针对 Excel VBA 进行了优化和正确,以便在单元格焦点上大写?

有时它会减慢 Excel 的速度。有没有更好的版本?

Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
Application.EnableEvents = False
 
 For Each cell In Target
     If IsEmpty(cell) Then
  
    
 ElseIf cell.HasFormula = True Then
  
       cell.Font.Name = "Arial Narrow"
    cell.Font.Size = 9
    Else

    cell = UCase(cell)
    cell.Font.Name = "Arial Narrow"
    cell.Font.Size = 9
        End If
    
    Next
    Application.EnableEvents = True
End Sub

解决方法

缩进不一致,重复的语句可以重新组织,不需要重复;不需要存在空代码块,将 Boolean 表达式与 Boolean 字面量进行比较的条件表达式是多余的,为了更清晰的代码,可以显式地进行隐式默认成员调用:

Application.EnableEvents = False
Dim cell As Range
For Each cell In Target
    If Not IsEmpty(cell.Value) Then
        If Not cell.HasFormula Then
            cell.Value = UCase(cell.Value)
        End If
        cell.Font.Name = "Arial Narrow"
        cell.Font.Size = 9
    End If
Next
Application.EnableEvents = True

Rubberduck(免费,开源;我管理项目)可以帮助缩进,它的代码检查会警告空块(并建议反转条件)和隐式默认成员调用Range (cell.Value)。

至于性能,作为 Worksheet.Change 事件处理程序意味着每次修改任何单元格时,宏都会迭代每个修改过的单元格。大部分时间都是针对单个单元格的,因此循环大部分时间只迭代一次;您可能可以通过禁用 ScreenUpdating 并将 Calculation 模式设置为 xlCalculationManual 以及将 EnableEvents 设置为 True 来获得几毫秒的时间,但 IMO 的好处是将是微不足道的。

考虑使用样式而不是设置单个单元格的 Font.NameFont.Size,但这里最有影响力的修改是测试 Target 与特定特定有趣 {{ 1}} 个工作表上的单元格 - 例如,如果您只想在 Range 位于 Target 范围内时运行该循环,您可以将此测试作为宏执行的第一件事,以当修改的单元格超出该范围时,阻止执行任何代码:

A2:C25

请注意,If Application.Intersect(Target,Me.Range("A2:C25") Is Nothing Then 'modified cell isn't in A2:C25; bail out Exit Sub End If 事件处理程序不会“针对单元格焦点”运行,而是“针对单元格值/公式修改”运行;考虑处理 Worksheet.Change,以便在单元格获取 Excel 的选择矩形时运行代码。