【问题标题】:Best way to run macro for over 500K rows?为超过 500K 行运行宏的最佳方法?
【发布时间】:2020-05-15 04:07:36
【问题描述】:

我有一个包含一堆行的文件,其中包含来自不同配置的某些部件号的数据。其中一些部件号在整个文件中重复,并且在这些重复的部件号中可能包含某些数据,而有些可能不包含。我正在尝试找到确定文件中某些数据的共性的最佳方法。所以对于共性,如果一行有值而另一行是空白的,则非空白行的值将被放入空白行。如果这两行的数据不同,它会改变单元格上的字体颜色,表明这个部件号有两个不同的唯一值,应该检查。

Dim i, j, n As Long
Dim lr As Long
Dim moaf As Workbook
Dim sht As Worksheet

Application.ScreenUpdating = False

Set moaf = Workbooks("MOAF3.xlsb")
Set sht = moaf.Worksheets("Wire Data")

n = InputBox("What column # are you trying to fill in?: ")
lr = Cells(Rows.count, 2).End(xlUp).Row

For i = 2 To lr
    lkup = Cells(i, 2).Value 'sets first lookup value
    Fill = Cells(i, n).Value 'sets the first data value to compare
    If Len(Fill) > 0 Then
        For j = 2 To lr
            lkup2 = Cells(j, 2).Value 'sets the second lookup value
            Fill2 = Cells(j, n).Value 'sets the second value to compare
            If lkup2 = lkup Then 'checks to see if p/ns are same
                If Len(Fill2) = 0 Then 'checks to see if second value is blank
                    Cells(j, n).Value = Fill 'if value is blank the cell takes value of non blank     cell
                ElseIf Fill <> Fill2 Then 'checks to see if the values are non matching and non zero
                    Cells(i, n).Font.ColorIndex = 3 'changes font color of two cells
                    Cells(j, n).Font.ColorIndex = 3 'changes font color of two cells
                End If
            End If
        Next j
    End If
Next i
Application.ScreenUpdating = True
End Sub

这样做通常会冻结我的 excel,我的计算机有 32GB 的 RAM 并且是 Windows10。有没有更好的方法来解决我的问题,或者它是否可以在不使用 vba 的情况下完成?我对不使用 vba 的方法进行了一些研究,但使用 sumifs、countifs 之类的方法,但还没有真正深入研究。

【问题讨论】:

  • 您的代码在较小的数据集上工作正常吗?如果是,这个问题可能更适合codereview.stackexchange.com 也就是说,您可能希望考虑让第一个循环为i = 2 To lr - 1,第二个循环为j = i + 1 To lr
  • 你能给出一些简短的样本数据和预期的输出吗?我想知道条件格式是否可行?此外,您可以尝试使用Application.Calculation=False 关闭可能会增加速度的计算。此外,您的范围都是不合格的...您声明 sht 但从未将范围链接到它...
  • 我在开始时做了一个步骤来测试代码的每个实例并且它有效。例如:p123 有一个参数 A,p123 也存在于更下方,但没有列出该参数。它会将 A 的参数放在更下方的空白处。这样我就不必手动过滤每个查找值或部分。我知道我意识到我不使用 sht 值。我最初编写它时打开了多个工作簿,但我决定在运行它时只打开文件。
  • @brucewayne 我对关闭计算不太熟悉。当空白考虑计算时,实际上是在输入一个值。当屏幕更新重新打开时,将其关闭是否会阻止单元格被填充?

标签: excel vba large-data large-files


【解决方案1】:

内部for循环只需从i开始,即:

for j = i to lr

这应该大约是运行时间的一半。

进一步的性能增强: 使用 .Value2 而不是 .Value 属性。 或者更好的是,将整个列读入一个数组,在 VBA 中处理,然后将结果写回。

【讨论】:

  • 我这样做了,它让它变得更容易了,我不确定我什么时候开始运行,但它几乎没有通过任何代码。有没有其他方法可以实现我的目标。
  • 您也许可以通过将整个范围读入 2-dim 数组来进一步提高性能,然后进行处理,并且只有在完成后才回写。一般来说,这应该比一个一个地读取这么多单元格要快。
【解决方案2】:

所以,如果我正确理解您的问题,您可以从以下数据开始:

ID Column_header
 2             a
 3       _BLANK_
 4       _BLANK_
 5             b
 6       _BLANK_

而你想把它变成:

ID Column_header
 2             a
 3             a
 4             a
 5             b
 6             b

我知道一个非常简单的技巧(我将所有内容都放在'A'列中以供解释):

  • 选择该列中的每个单元格
  • 转到 (Ctrl+G) 特殊,空白
  • 在编辑栏中,输入=A2(您当前位于“A3”中,并且您想将其上方单元格的值复制到那里)
  • Ctrl+ENTER

您会看到“A2”被复制到“A3”中,“A3”被复制到“A4”中,“A5”被复制到“A6”中(事实上这是对 all 空白单元格,是由于Ctrl+ENTER)。

把它记录成一个宏,它会更快。

我已经看到一个问题弹出:“好的,但是我要更改的字体颜色呢?”。好吧,新填充的单元格是基于公式的,所以=FORMULATEXT() 的长度不会为零。您将其用作条件格式的基础。

祝你好运

【讨论】:

  • 是的,差不多就是这样,但是对于填充的每个空白,它们都有一个单独的列,该列具有一个共同的值,该值决定了将其放置在哪里。
  • 我不明白你的意思,但你认为你可以完成修改公式吗?
  • 索引外观参数 2 L1 a 3 L1 ? 4 L2 c n L1 ?对于 2 和 3,值取决于查找,如果它们不同,则颜色不同。
  • ?对不起,我不明白你的意思。您能否编辑您的问题,显示您的工作表的外观以及宏之后的外观?
猜你喜欢
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-16
  • 2021-09-02
  • 2015-09-21
  • 2018-08-31
  • 1970-01-01
相关资源
最近更新 更多