【问题标题】:VBA and Excel: Why does my TRIM script results in #VALUE on large data sets?VBA 和 Excel:为什么我的 TRIM 脚本会在大型数据集上产生 #VALUE?
【发布时间】:2016-05-11 20:02:42
【问题描述】:

以下脚本适用于较小的数据集(少于 30k 行左右),但当范围大于该范围时,所选范围内的每个单元格都会出现“#VALUE”错误。

Dim FirstCell As Range, LastCell As Range, MyRange As Range

Set LastCell = Cells(Cells.Find(What:="*", SearchOrder:=xlRows, _
      SearchDirection:=xlPrevious, LookIn:=xlValues).Row, _
      Cells.Find(What:="*", SearchOrder:=xlByColumns, _
      SearchDirection:=xlPrevious, LookIn:=xlValues).Column)

Set FirstCell = Cells(Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlRows, _
      SearchDirection:=xlNext, LookIn:=xlValues).Row, _
      Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlByColumns, _
      SearchDirection:=xlNext, LookIn:=xlValues).Column)

Set MyRange = Range(FirstCell, LastCell)
      MyRange.Select
      If MyRange Is Nothing Then Exit Sub
      Application.ScreenUpdating = False
      Application.Calculation = xlCalculationManual
    With Selection
        .Value = Evaluate("if(row(" & .Address & "),clean(trim(" & .Address & ")))")
    End With

    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    MsgBox "Finished trimming " & vbCrLf & "excess spaces", 64

VBA TRIM Error

【问题讨论】:

  • 你用这段代码改变了多少个单元格?我刚刚在大约 170 万个单元上进行了测试,没有出现任何错误
  • 我的练习文档中有 8,106,860 个单元格。那是 161,363 行。
  • 它似乎可以处理大约 70k 行。不仅如此,它只是将所选范围内每个单元格的值设置为#VALUE。
  • 如何将范围(或至少部分)复制到基于内存的数组中,执行修剪,然后将该块复制回电子表格?可能也会更快。
  • 我还尝试设置 MyRange = Selection(我选择与 FirstCell 到 LastCell 相同的范围),它的工作时间大约有一半没有给我同样的错误。

标签: vba excel trim


【解决方案1】:

我设法复制了您的问题,并使用如下所示的变体数组克服了大型数据集的问题

Dim FirstCell As Range, LastCell As Range, MyRange As Range
Dim DataRange() As Variant
Dim lRows As Long
Dim lCols As Long
Dim i As Long, j As Long
Dim value As String

Set LastCell = Cells(Cells.Find(What:="*", SearchOrder:=xlRows, _
      SearchDirection:=xlPrevious, LookIn:=xlValues).Row, _
      Cells.Find(What:="*", SearchOrder:=xlByColumns, _
      SearchDirection:=xlPrevious, LookIn:=xlValues).Column)

Set FirstCell = Cells(Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlRows, _
      SearchDirection:=xlNext, LookIn:=xlValues).Row, _
      Cells.Find(What:="*", After:=LastCell, SearchOrder:=xlByColumns, _
      SearchDirection:=xlNext, LookIn:=xlValues).Column)

Set MyRange = Range(FirstCell, LastCell)
  MyRange.Select
  If MyRange Is Nothing Then Exit Sub
  Application.ScreenUpdating = False
  Application.Calculation = xlCalculationManual
  lRows = MyRange.Rows.Count
  lCols = MyRange.Columns.Count
  ReDim DataRange(1 To lRows, 1 To lCols)
  DataRange = MyRange.value
  For j = 1 To lCols
    For i = 1 To lRows
      DataRange(i, j) = Trim(DataRange(i, j))
    Next i
  Next j

  MyRange.value = DataRange

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Finished trimming " & vbCrLf & "excess spaces", 64

作为参考,我用这篇文章来帮助想出答案:https://blogs.office.com/2008/10/03/what-is-the-fastest-way-to-scan-a-large-range-in-excel/

【讨论】:

  • 链接将来可能会被破坏。请将回答问题所需的信息复制粘贴到您的帖子中。仅将链接用作参考。
  • 我已经更新了答案,更清楚地表明该链接仅供参考,答案已包含在上面
猜你喜欢
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 2023-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
相关资源
最近更新 更多