【问题标题】:What is the "correct" way to copy-paste data in VBA?在 VBA 中复制粘贴数据的“正确”方法是什么?
【发布时间】:2019-01-20 10:50:19
【问题描述】:

在 Excel 中复制粘贴 VBA 数据的“正确”方法是什么?

现在,至少据我所知,这三个是唯一可用的方法:

  1. (Range) .Copy([Destination]) 方法
  2. (Worksheet) .Paste([Destination, Link]) 方法
  3. (Range) .PasteSpecial([Paste], [Operation], [SkipBlanks], [Transpose]) 方法

现在,我进行了研究,这些是 .Copy([Destination]).Paste([Destination, Link]) 方法的优缺点,至少那些,我能想到的:

优点:

  • 允许我们将数据粘贴到与复制相同的表达式中(我猜是代码可读性..?)

缺点:

  • 单元格引用是完全不行的!
  • 您的格式和公式可能会搞砸
  • 如果范围重叠,它将显示一个提示,有效地阻止宏死在其轨道上(这是一个巨大的麻烦,特别是如果你试图自动化某些东西)
  • 更糟糕的是,如果您在提示符下按Cancel,它会抛出一个Error**(除非已处理)

硬币的另一面,.PasteSpecial()

优点:

  • PasteSpecial() 允许我们粘贴范围的特定部分!
  • 它允许我们指定我们想要做的粘贴类型
  • 具有内置的skipBlankstranspose 功能
  • 不是“如此”Error-prone!

我很难想出任何办法,但是:

缺点:

  • 还要写一些字符吗?

现在,这让我相信,.Copy() 方法的 Destination 参数本质上应该被忽略,而应该始终使用 PasteSpecial()

是否有过使用它比.PasteSpecial() 更可取的情况?还是 PasteSpecial() 应该成为每个复制粘贴操作的标准?

【问题讨论】:

  • 你忘记了直接赋值:Range().Value = Range().Value
  • 你不忽略Worksheet.Paste Method吗?
  • “一劳永逸地解决讨论” - 嗯......祝你好运!如果符合需要,我认为 .Copy() 没有任何问题。
  • 我不得不承认,想一想我过去在哪里/何时使用过任何一个,答案是,我很少使用任何一个。我通常只是将范围复制到一个变体,处理数据并将其转储回来。如果我需要格式化,我会在之后进行,但要整体进行。
  • @DavidZemens “没有什么能比得上直接赋值的表现” 我也这么认为,但后来我最近是proven otherwise;鉴于 非常大 的数据集,我惊讶地发现直接分配实际上被剪贴板打败了。

标签: excel vba performance copy-paste


【解决方案1】:

这与可读性或您输入的字符数无关。这是关于你需要实现什么

换句话说,它绝对不是主观的或基于意见的,并且与编程中的几乎所有其他东西一样......

#ItDepends.

如果您使用 Excel 并复制粘贴单元格,您是否 Ctrl+CCtrl+V 或使用特殊粘贴

取决于你需要做什么。

  • 如果您的意思是复制一个单元格,它的值、格式、数据验证、边框等;那么.Paste [Destination] 是你最好的朋友。这是 Ctrl+C/Ctrl+V... 等价于 PasteSpecial/All,在这种情况下,.Paste [Destination] 已经完成了您需要它做的所有事情。

    单元格引用完全不行!

    当然。硬编码的单元格引用是不好的。 .Paste [Destination] 无论如何都不会强迫你这样做,所以这一点没有实际意义。

    如果范围重叠,它将显示一个提示,有效地阻止宏死在其轨道上

    复制和粘贴范围不能重叠,句号。您也可以通过.PasteSpecial 获得该提示。

  • 如果您要复制单元格的Value而不是其格式、数据验证、边框等;那么.PasteSpecial 绝对是一个更好的主意,因为这相当于粘贴特殊/值的程序化 - 除了将单元格的Value 分配给你想要的东西可能更有效(不需要往返剪贴板); OTOH,如果您确实想要粘贴格式、数据验证或诸如此类,那么这可能是最简单的方法。

Paste 不会“搞乱”格式。它完全按照它的意思去做。 PastePasteSpecial等价物。为工作使用正确的工具。它们实际上分别是“粘贴”和“特殊粘贴”的程序等效项 - 如果您在 Excel 中并系统地进行“特殊粘贴”,您将完成您的工作。但是每次你这样做是为了“粘贴所有”,你就比你需要的更努力。

PasteSpecial 看起来像一把不错的锤子,但并非所有东西都是钉子。当您可以避免剪贴板写入时,通常最好避免它......但话又说回来,if you're dealing with huge data sets(想想 100K+ 单元格),它的性能可能比仅仅分配值更好。

也就是说:

@ScottCraner 我确实考虑过,但这并不是真正的复制粘贴,而是更多典型的指针引用,因此我决定不在我的问题中包含它。我不想打开一本书来讨论“什么算作复制粘贴”。

这是错误的。 .Range(foo).Value = .Range(bar).Value 不是“典型的指针引用”。它实际上是将foo 的值放入2D 变量数组,并将该2D 变量数组转储到bar,覆盖之前保存的值。因此,它绝对是点击剪贴板的完全有效的替代方案 - 但您需要测试并与 Copy+PasteSpecial 进行比较,看看这是否是适合您情况的最佳(/最有效)解决方案:

Testing with 1500000 cells (100000 rows)
Pasting from clipboard, single operation: 324.21875ms
Setting cell values, single operation:    1496.09375ms


Testing with 150 cells (10 rows)
Pasting from clipboard, single operation: 11.71875ms
Setting cell values, single operation:    3.90625ms
Pasting from clipboard, iterative:        1773.4375ms
Setting cell values, iterative:           105.46875ms

【讨论】:

  • 对我来说,It Depends 是答案,表明这个问题不适合这个论坛。您是正确的,将其归类为意见可能是错误的,但对于本论坛而言,它的主题过于广泛。再说一次,这是我的看法。但我喜欢这个答案。
  • 正是我在答案中寻找的。我也很高兴你在基于意见的问题上分享相同的推理 - 尽管我应该在原始问题中解释得更好。希望我能在这里多次投票!
猜你喜欢
  • 1970-01-01
  • 2019-09-06
  • 2017-06-14
  • 2020-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多