【问题标题】:VBA - Create empty array [duplicate]VBA - 创建空数组[重复]
【发布时间】:2017-03-24 17:15:37
【问题描述】:

我有一个函数,它接受一个字符串数组并将每个字符串映射到一个Date 实例。该函数归结为以下代码。

Private Function ParseDates(dates() As String) As Date()
  Dim res() As Date
  Dim i As Integer

  If UBound(dates) >= 0 Then
    ReDim res(UBound(dates)) As Date
  End If


  For i = LBound(dates) To UBound(dates)
    res(i) = #01/01/2000#
  Next i
  ParseDates = res
End Function

只要参数dates 非空,该函数就可以正常工作。当dates 为空时,res 未指定维度。因此,返回的值是不可枚举的,如果在循环中枚举结果,会导致该函数的用户崩溃。

parsedDates = ParseDates(input) 
For i = 1 To UBound(parsedDates) ' Suscription out of range
  ...

当日期为空时,如何实例化并返回一个空数组?

如果您调用Split("","."),您会收到一个类型为String(0 to -1) 的对象。我需要我的函数返回Date(0 to -1) 类型的对象,因为Date() 不是实际数组。

我尝试过使用ReDim res(-1),这会导致Subscript out of range 错误。

【问题讨论】:

  • 也许你应该在调用ParseDates函数之前检查dates()是否为空?
  • 这也是一个解决方案,但我更希望ParseDates 处理正确类型的所有输入。我还认为代码中充满了所有额外的 If 语句。
  • 我最终将函数返回一个可能为空的数组声明为Variant。这允许我为空数组和我想要的类型的数组返回 Split("",",")PS。 “创建空数组”如何与“如何确定数组是否在 VB6 中初始化?”重复??

标签: arrays vba


【解决方案1】:

我以前用过类似的东西。

Public Function IS_ARRAY_EMPTY(arrInput As Variant) As Boolean

Dim lngTemp As Long

On Error GoTo eHandle

lngTemp = UBound(arrInput)

IS_ARRAY_EMPTY = False

Exit Function

eHandle:
    IS_ARRAY_EMPTY = True

End Function

【讨论】:

  • 谢谢,我已经做了一个类似的解决方法。我只是从未想过空数组会成为问题。
【解决方案2】:

这似乎可以解决问题:

Private Declare Function EmptyDateArray Lib "oleaut32" Alias "SafeArrayCreateVector" (Optional ByVal vt As VbVarType = vbDate, Optional ByVal lLow As Long = 0, Optional ByVal lCount As Long = 0) As Date()

Function emptyDate() as Date()
    emptyDate = EmptyDateArray()
End Function

基于用户 wgweto 在 VBForums 上对this question 的回答。

【讨论】:

  • 有趣的把戏,尤其是因为VbVarType 可以更改以将其扩展到其他情况,而不仅仅是Date。我不确定我是否会使用它,但很高兴知道这种可能性,所以 +1
【解决方案3】:

您特别提到了调用代码需要迭代返回值并且迭代无维数组会引发错误的问题。收藏没有这个问题。一种可能性是重构您的代码,使其返回一个集合(可能有也可能没有零元素):

Private Function ParseDates(dates() As String) As Collection
  Dim res As New Collection
  Dim i As Long

  For i = LBound(dates) To UBound(dates)
    res.Add #1/1/2000#
  Next i

  Set ParseDates = res
End Function

假设调用代码有这行:

Set C = ParseDates(dates)

即使C.Count = 0,以下循环仍然有效:

Dim d As Variant

For Each d In C
    'process d
Next d

【讨论】:

  • 这似乎是一个有效的解决方案。但是,我在尝试实现它时遇到了问题。在我的代码中,我调用了一堆期望接收Date 对象的函数,但集合由ObjectVariant 元素组成,导致程序抛出Type mismatch error。有什么好办法处理吗?
  • @Jonas 没有看到代码很难确定,但至少有 4 种可能的解决方案,2 个在被调用方,2 个在调用方:1)在接收函数只需将As Date 更改为As Variant 2) 将d As Date 之类的参数更改为ByVal d As Date,3) 保持函数不变,但在调用代码中将参数包装在CDate() 中,然后再传递它们,或者4 ) 在调用代码中有一个Date 变量,比如d,并将从集合中提取的变量分配给d,然后传递d
【解决方案4】:

试试这个:

Private Function ParseDates(dates() As String) As Date()
  Dim res() As Date
  Dim i As Integer
  Dim k%
  k=0
  If UBound(dates) >= 0 Then
    ReDim res(UBound(dates)) As Date
  End If


  For i = LBound(dates) To UBound(dates)
    if dates(i)<>"" then
       k=k+1      
    redim preserve res(k)
       end if
res(k) = #01/01/2000#
  Next i
    if k=0 then
     redim res(ubound(dates))
      end if
  ParseDates = res
End Function

【讨论】:

  • 感谢您的回复。不幸的是,这并不能解决问题,因为 res 仅在日期至少包含一个元素时才给出维度。
  • 那么你想要的是 res 有dimensión 日期是否有元素? @乔纳斯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 2010-09-17
  • 2014-09-15
  • 2016-08-15
  • 2019-02-15
相关资源
最近更新 更多