【问题标题】:Handling of arrays in VBA macros for Excel处理 Excel 的 VBA 宏中的数组
【发布时间】:2013-02-28 21:23:59
【问题描述】:

我正在尝试在 VB(Excel 宏)中编写一个模拟器,其中模拟的输入取自一张表中的单元格。输入将被放置在多个数组中,例如 timePerUser(10) 和 bytesPerUser(10)。然后会有一些简单的 if/for/while 东西来根据数组进行计算,最后我会将结果写回 Excel。因此,Excel 将仅用于提供输入数据和显示结果,其他一切都在宏内部发生,包括更改数组中的值。

我习惯使用 Matlab,但不能将它用于这个模拟器,所以这里是我的问题:

  1. 我可以在 Excel 宏中使用任何现有的矩阵/数组运算吗?例如,是否有一些命令可以检查数组中的最小值或下一个最小值? Excel 函数“SMALL”将是完美的,但它似乎不适用于宏。还是我只需要用 for 循环来解决这个问题?

  2. 关于如何创建数组还有其他建议吗?是有一个大矩阵,其中每一行对应于时间、数据、用户等(NxM 矩阵)更好,还是每个参数有单独的数组更好?

  3. 如何加速矩阵/数组运算?有什么一般性建议吗?

谢谢! 奥斯卡

【问题讨论】:

  • 有人能澄清为什么这个问题被否决了吗?

标签: arrays excel matlab


【解决方案1】:

Excel 确实有一些简单的数组操作 - SUMPRODUCT(Matlab 等效:A*B')、MIN、MAX、...其中大部分,包括 SMALL,需要使用 Application.WorksheetFunction.xxx 调用;例如,函数 SMALL 可以在 VBA 中调用如下:

nthSmallest = Application.WorksheetFunction.Small(r, n)

其中 r 是一个数组或范围,n 是介于 1 和 r.Cells.Count 之间的整数

我强烈建议您为每个概念变量使用一个变量,而不是试图巧妙地处理一个二维数组中的多个实体。 Speedwise 我怀疑差异很小;但是编写不可读代码的机会很重要。

至于加快速度:将变量(尤其是数组)定义为某种固定类型(而不是变体)确实很有帮助,例如:

Dim a(1 To 10) as Double
Dim ii as Integer

让所有数组使用相同的(默认)基数可能会有所帮助。由于我自己是 Matlab 迷,我经常使用从 1 开始的数组索引 - 您可以通过添加在 VBA 中强制执行此操作

Option Base 1

在模块的开头。此时,如果你声明

Dim a(10) as Double

相当于

Dim a(1 To 10) as Double

对于不精通VBA的人来说也是一种很好的做法,添加

Option Explicit

在模块的开头,因为它将确保您未声明的任何变量(或更常见的是,您拼写错误)都会产生解释器错误。

关于数组的另一件事:作为 Matlab 人员,您习惯于 Matlab 根据需要增加数组大小。在 VBA 中,可以在运行时动态更改数组大小,例如使用

ReDim Preserve a(1 To 20)

这将使数组a 大小为20 个元素。如果它更短,它将用零填充;如果它更长,它将被修剪。这可能很有用,但非常昂贵,因为通常需要将整个数组复制到新位置。当您事先不知道您的数组有多大时,最好高估(并检查界限)而不是每次需要变大时都重新调整 - 最后做一个最终的ReDim 以使其达到大小合适。

希望这足以让您开始!

【讨论】:

  • 好答案,+1。我认为 1d/2d 数组问题是相对优先的。对于 OP:请注意,VBA 支持声明多维数组(我不确定限制是什么)。此外,根据工作的计算强度,可能(未经我自己测试!)多维数组将比多个“向量”更快。如果性能很重要,您可能希望使用您的代码对此进行测试,因为有许多非常详细的考虑因素(您可能熟悉缓存一致性等)可能会影响结果。
  • @mkingston - 感谢您的投入。我刚刚运行了一些基准测试;填充 1000x1000 变体数组需要 125 毫秒,而使用 Double 或 Integer 需要 78 毫秒。这与 1000000 元素线性阵列之间没有显着差异(在测量的分辨率和可重复性范围内)。
  • 呃,我觉得自己像个白痴。需要关注的不是缓存一致性;它是由缓存算法引起的缓存未命中。您的测试很可能不会对此进行测试。这些 Wiki 页面上有一些相关内容:en.wikipedia.org/wiki/Cache_algorithmsen.wikipedia.org/wiki/Page_replacement_algorithm。只有当运行时间实际上相当长时,这个问题才可能困扰您,否则您可能不会注意到它。我只在 OP 真的 需要性能的情况下提到它。除非您确实遇到性能问题,否则我不会打扰。
  • 当然,如果 OP真的 需要性能,VBA 并不是一个很大的限制。
  • 是的 - 为了获得真正的性能,您可以考虑编译一个 dll 并在需要时从 VBA 调用它(或者可能使用像 C 这样的语言来创建一个插件)。
猜你喜欢
  • 1970-01-01
  • 2014-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-17
  • 2011-10-04
  • 2011-01-14
相关资源
最近更新 更多