2016-12-02 218 views
1

这是一个函数,用于检查B列和C列中的单元格,并根据特定测试应用Proper函数。Excel VBA在特定范围内使用Proper的功能性能

Sub proper_function() 

    Dim rng, cell As Range 

    Set rng = Range("B:B", "C:C") 

    For Each cell In rng 
     If Not cell.HasFormula Then 
      cell.Value = WorksheetFunction.Proper(cell.Value) 
     End If 
    Next cell 

End Sub 

这需要很长时间来处理,并且有时会使Excel崩溃。

我宁愿它通过与文本而不是整列的单元格,我认为我需要稍微修改for循环,但不能得到它的工作,什么是最好的方式来写这个,所以它不会减慢表单的速度?

感谢

+0

如何多行数据,你呢? – Brian

+0

我们需要知道你的工作表是什么样的。一旦你达到了数据的结尾,你就想让循环中断,但是你还没有给我们一个方法来确定它在哪里。 – Fritz

回答

1

尝试这种变化(未测试):

Sub proper_function() 

Dim rng as Range 
Dim cell As Variant 

Set rng = Range("B:B", "C:C") 
For Each cell In ActiveSheet.Range(rng.Address).SpecialCells(xlCellTypeConstants)  
    cell.Value = WorksheetFunction.Proper(cell.Value) 
Next cell 

End Sub 

但我也发现最后一排,在另一个答案建议,并设置rng只对使用范围。另外,正如Thomas指出的那样,如果您将常量单元格作为先例,将挥发性函数或函数添加到其中,则需要添加Application.ScreenUpdating.Calculation。这也可能是提高速度的关键。

+0

感谢您的支持。很好奇,看看是否可以通过将Proper更改为Lower来对Lower函数使用相同的代码,但它不起作用? – Pete

+0

@Pete更改'WorksheetFunction.Proper(cell.Value) ''到LCASE(cell.Value)'(或'UCase'为大写)。另外,如果我的代码解决了您的问题,请用绿色复选标记标记。 :-) – Brian

0

你可能会,如果你通过每一个细胞中的.xlsx或.XLSM文件尝试循环遇到的问题,因为他们有1,048,576行,你这样做的两倍!无论你做什么,它都会导致放缓。

与其使用B:B和C:C的一揽子范围,您可以将其限制在可能包含数据的范围内。没有看到你的表,我不能肯定地说做到这一点的最好办法,但总的来说尝试这样的事:

Sub Properiser() 
    Dim rngAll As Range 
    Dim rngCell As Range 
    Dim lngLast As Long 

    lngLast = Range("B" & Rows.Count).End(xlUp).Row 

    If Range("C" & Rows.Count).End(xlUp).Row > lngLast Then 
     lngLast = Range("C" & Rows.Count).End(xlUp).Row 
    End If 

    Set rngAll = Range("B1", "C" & lngLast) 

    For Each rngCell In rngAll 
     If Not rngCell.HasFormula Then 
      rngCell.Value = WorksheetFunction.Proper(rngCell.Value) 
     End If 
    Next rngCell 
End Sub 

这会发现B列中最后使用的列,然后在C列,并使用较大者作为范围的终点。

我们还可以使用其他方法,例如使用UsedRange属性来查找文件中实际使用了多少行和列,但是如果没有看到数据,很难说这些数据中的哪一个可能对您更好或不。

编辑以展开:

现在,你提到你宁愿过程只看包含文本的单元格;有几种方法可以做到这一点。

选项1:检查空单元

如果你怀疑你经历了很多空单元格的弹跳,你可以简单地在你的。如果条件检查单元格内容。

if len(rngCell.value) <> 0 then 
    'Function 
end if 

选项2:检查非文本值

不幸的是,我们没有能够检查字母数字文本的简单,功能单一;我们需要走一条消除的道路。因此:

if len(rngCell.value) <> 0 then 
    if isnumeric(rngcell.value) = False AND _ 
     iserror(rngcell.value) = false then 
     'Assume it's text and perform our function 
    End if 
End if 

...等等。您可以根据需要在IF循环中堆叠尽可能多的检查。

1

我不是工作表功能Proper的粉丝,因为它没有正确地大写收缩(例如can't, doesn't, I'll变成Can'T, Doesn'T, I'Ll)。我对Proper Case with extra rules in Excel的回答有我自己的功能TitleCase正确的大写收缩。

Target范围仅包含具有恒定值(无公式)

Set Target = Intersect(.Range("B:C"), .UsedRange).SpecialCells(xlCellTypeConstants) 

关闭ScreenUpdatingCalculation大大提高了性能的非空白单元格。 Application.ScreenUpdating =假 Application.Calculation = xlCalculationManual


Sub proper_function() 
    Dim Target As Range, cell As Range 
    With Worksheets("Sheet1") 
     On Error Resume Next 
     Set Target = Intersect(.Range("B:C"), .UsedRange).SpecialCells(xlCellTypeConstants) 
     On Error GoTo 0 
    End With 


    If Not Target Is Nothing Then 
     Application.ScreenUpdating = False 
     Application.Calculation = xlCalculationManual 
     For Each cell In Target 
      If Not cell.HasFormula Then 
       cell.Value = WorksheetFunction.Proper(cell.Value) 
      End If 
     Next cell 
     Application.Calculation = xlCalculationAutomatic 
     Application.ScreenUpdating = False 
    End If 
End Sub 
+1

也许我不完全理解,但为什么你测试'如果不是cell.HasFormula',如果Range'Target'只是'xlCellTypeConstants'? – Brian