【问题标题】:Writing an array to a range. Only getting first value of array将数组写入范围。只获取数组的第一个值
【发布时间】:2015-10-16 01:58:40
【问题描述】:

我正在尝试将一个数组写入一个范围,我尝试了多种方法,但无论如何,我总是一遍又一遍地只得到数组的第一个值。

代码如下:

Option Explicit

Sub test()

    ActiveWorkbook.Worksheets("Sheet1").Cells.Clear

    Dim arrayData() As Variant
    arrayData = Array("A", "B", "C", "D", "E")

    Dim rngTarget As Range
    Set rngTarget = ActiveWorkbook.Worksheets("Sheet1").Range("A1")

    'this doesn't work
    rngTarget.Resize(UBound(arrayData, 1), 1).Value = arrayData

    Dim rngTarget2 As Range
    Set rngTarget2 = ActiveWorkbook.Worksheets("Sheet1").Range(Cells(1, 5), Cells(UBound(arrayData, 1), 5))
    'this doesn't work either
    rngTarget2.Value = arrayData

End Sub

我希望看到的是:

(Col A)     (Col E)
A           A
B           B
C           C
D           D
E           E

我实际看到的是:

(Col A)     (Col E)
A           A
A           A
A           A
A           A
A           A

我在这里做错了什么?

我尝试遵循 Chip Pearson 的建议,如发现 HERE

但没有运气......

好的,所以添加这个问题的第二部分:

我有一个包含 8,061 个元素的一维数组,我将其传递给以下函数:

Call writeArrayData7(strTabName, arrayBucketData, 7)

Sub writeArrayData7(strSheetName As String, arrayData As Variant, intColToStart As Integer)

    Dim lngNextRow As Long
    lngNextRow = 1 ' hard-coded b/c in this instance we are just using row 1

    ' Select range for data
    Dim rngData As Range
    Set rngData = Sheets(strSheetName).Range(Cells(lngNextRow, intColToStart), Cells(lngNextRow - 1 + UBound(arrayData, 1), intColToStart))

    ' Save data to range
    Dim arrayDataTransposed As Variant
    arrayDataTransposed = Application.Transpose(arrayData)
    rngData = arrayDataTransposed

End Sub

所以当我运行它时,转置函数正确转换为:

Array(1 to 8061, 1 to 1)

该范围似乎是一列,在 G 列中有 8,061 个单元格。

但我收到以下错误:

Run-time error '1004':
Application-defined or object-defined error

以下行引发错误:

rngData = arrayDataTransposed

--- 更新 ---

所以我在示例代码中遗漏的一件事(老实说,我认为这并不重要)是我的数组的内容实际上是公式。这是我在实际实时代码中使用的行:

arrayData(i) = "=IFERROR(VLOOKUP($D" + CStr(i) + "," + strSheetName + "!$D:$F,3,FALSE),"")"

好吧,我发现(在 Excel Hero 的帮助下)上面的语句没有字符串所需的双引号,所以我不得不改为:

arrayBucketData(i) = "=IFERROR(VLOOKUP($D" + CStr(i) + "," + strSheetName + "!$D:$F,3,FALSE),"""")"

我可以把它归结为深夜的白痴编码。

但是,我学到的另一件事是,当我返回运行完整代码时,需要 FOREVER 将数组粘贴到范围。这通常是一项非常简单的任务,而且发生得很快,所以我真的很困惑。

经过多次调试,我发现问题归结为我关闭了所有警报/计算/等,当我粘贴这些公式时,strSheetName 表还没有 b/c 我'正在开发与主文件分开的代码。显然,当您粘贴代码时,它会弹出一个对话框,但是如果您关闭了所有这些东西,您将看不到它,但它确实会减慢一切。如果这些选项卡不存在,则粘贴范围大约需要 6 分钟,如果存在则需要几秒钟(可能更少)。无论如何,为了进一步完善代码,我只是添加了一个函数来检查所需的工作表,如果它不存在,它将选项卡添加为占位符,这样整个过程就不会慢到爬行。

感谢大家的帮助!我希望这可以帮助其他人。

【问题讨论】:

  • 您的 1004 发生在这里:Set rngData = Sheets(strSheetName).,因为您尚未将 Cells 对象限定为工作表。因此,要么在 With 块中完成所有操作,要么在 Cells(lngNextRow, intColToStart).Address 中完成所有操作(使用 .Address 属性和对 Cells 类的 all 调用。
  • 你能按照大卫的建议去做吗?
  • @DavidZemens - 这实际上不是我得到 1004 的地方。我在这里得到它:rngData = arrayDataTransposed - 我将你提到的行更改为:Set rngData = Sheets(strSheetName).Range(Cells(lngNextRow, intColToStart).Address, Cells(lngNextRow - 1 + UBound(arrayData, 1), intColToStart).Address),但我仍然得到错误在上面一行。
  • @gotmike 数组中是否有任何元素的文本长度超过 255 个字符?
  • 有没有机会给我发一份有问题的小样本工作簿?我可以快速排序。我的电子邮件地址是:daniel.ferry@gmail.com

标签: arrays vba excel


【解决方案1】:

这样做:

arrayData = Array("A", "B", "C", "D", "E")

[a1].Resize(UBound(arrayData) + 1) = Application.Transpose(arrayData)

重要的是 Transpose() 函数。

但如果您打算将二维数组写入工作表,最好从一开始就使用它们。只要将它们定义为第一行中的行和第二行中的列,就不需要转置。

【讨论】:

  • 啊...从技术上讲,一维数组真的是单行多列?哇,这很奇怪,我会想,因为它只是一个维度,并且二维数组中的第一个维度是行,它会是相反的方式......
  • 是的,VBA 中的一维数组是水平的。
  • 是的,VBA 中的二维数组是行主要的。
  • @DavidZemens 我的回答旨在通过简化其他所有内容来引起人们对 Transpose() 函数的注意。当然,可以适当地限定范围引用。我使用 Resize 没有任何问题。
  • @Excel Hero 请问这个代码部分 ~[a1].Resize(UBound(arrayData))~ 不会在工作表上只打印四个值。不应该是 ~[a1].Resize(UBound(arrayData) +1)~ 在工作表上打印所有 5 个值。
【解决方案2】:

这个:

Sub test()

    ActiveWorkbook.Worksheets("Sheet1").Cells.Clear

    Dim arrayData(1 To 5, 1 To 1) As Variant
    arrayData(1, 1) = "A"
    arrayData(2, 1) = "B"
    arrayData(3, 1) = "C"
    arrayData(4, 1) = "D"
    arrayData(5, 1) = "E"

    Dim rngTarget As Range
    Set rngTarget = ActiveWorkbook.Worksheets("Sheet1").Range("A1:A5")
    rngTarget = arrayData

End Sub

将产生:

【讨论】:

  • 我遇到了与问题相同的问题,但此解决方案对我有用。这是因为在电子表格的上下文中,第一个维度是行,第二个维度是列,就像矩阵一样?
【解决方案3】:

如果我可以扩展接受的答案,我建议:

[a1].Resize(UBound(arrayData) - LBound(arrayData) + 1) = Application.Transpose(arrayData)

那将是安全的方式。无论您是否将数组变量声明为:

Dim arrayData(0 to 2) 

Dim arrayData(1 to 3) 

接受的答案仅适用于第二种情况。

如果数组的大小未知并且您将 arrayData 声明为:

Dim arrayData()

【讨论】:

  • 对不起,你错了。我的答案在这两种情况下都有效。
  • @ExcelHero 我可能遗漏了一些东西,但你的答案对这两种情况都不起作用。Dim arrayData(0 To 2) Dim arrayData2(1 To 3) Debug.Print UBound(arrayData) & " " & LBound(arrayData) Debug.Print UBound(arrayData2) & " " & LBound(arrayData2)
猜你喜欢
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多