【问题标题】:WorksheetFunction.Transpose changes data typeWorksheetFunction.Transpose 更改数据类型
【发布时间】:2020-06-25 11:11:14
【问题描述】:

我在 VBA 中使用WorksheetFunction.Transpose 将混合日期/字符串的一维数组转换为二维数组以写入工作表。

当我的 Windows 区域设置设置为 DMY 时,写回的日期会切换月/日。

【问题讨论】:

    标签: excel vba transpose worksheet-function


    【解决方案1】:

    关于DatesWorksheetFunction.Transpose 方法转换为Strings 在本论坛中已经提到。

    我对此进行了更深入的研究。

    看来WorksheetFunction.Transpose 转换了很多数据类型。转置后的结果将是BooleanDoubleString

    在 VBA 中使用此方法时需要考虑这一点。

    以下是一些演示该问题的代码:

    Option Explicit
    Option Base 1
    Sub Tester()
        Dim v, w, i As Long
        
    v = Array(CBool(-1), CBool(0), CByte(9), CDbl(1234), CDec(1234), _
                CInt(1234), CLng(1234), CLngPtr(1234), CSng(1234), _
                CCur(123456), #5/1/2015#, "1234")
                
    w = WorksheetFunction.Transpose(v)
    
    For i = 1 To UBound(v)
        Debug.Print v(i), TypeName(v(i)), w(i, 1), TypeName(w(i, 1))
    Next i
    
    
    End Sub
    

    debug.print 输出

    True          Boolean       True          Boolean
    False         Boolean       False         Boolean
     9            Byte           9            Double
     1234         Double         1234         Double
     1234         Decimal        1234         Double
     1234         Integer        1234         Double
     1234         Long           1234         Double
     1234         Long           1234         Double
     1234         Single         1234         Double
     123456       Currency      $123,456.00   String
    01-May-15     Date          01-05-2015    String
    1234          String        1234          String
    
    

    编辑WorksheetFunction.Transpose的另一个问题

    • 给定一维数组
    • 转置数组的第一个维度的上限将由公式Ubound(1D_array) mod 2^16 给出
    • 只有第一个 uBound(1D_array) mod 2^16 元素将返回到转置数组。
      • 因此,如果一维数组的 ubound 为 65537,则转置后的数组将仅包含单个项(原始数组中的第一项)
      • 不会返回任何错误消息。
        • 我认为 Excel 2013 开始缺少错误消息,并且此行为开始。我记得早期版本在这种情况下会返回错误消息。

    【讨论】:

    • 那么解决方法是什么?手动创建第二个数组并循环填充?
    • @jamheadart 如果您在主数组中使用字符串、双精度或布尔值以外的数据类型,这是我知道的唯一解决方案。不过,您可以将日期存储为双精度值,并且这些值不会在换位时更改。
    • 如果从日期范围填充初始数组,您可以尝试使用Range.Value2 而不是Range.Value。它保留了潜在价值。
    • @shrivallabha.redij 是的,正如我所写的,这会将日期存储为双精度。
    • @VBasic2008 您是否看到与我发布的内容不符的结果?
    【解决方案2】:

    您可以在内存中使用 ListBox 进行转置,而无需使用 Transpose 并且 DataTypes 保持不变:

    Option Explicit
    Option Base 1
    Sub Tester2()
        Dim v, w, i As Long
        
    v = Array(CBool(-1), CBool(0), CByte(9), CDbl(1234), CDec(1234), _
                CInt(1234), CLng(1234), CLngPtr(1234), CSng(1234), _
                CCur(123456), #5/1/2015#, "1234")
                
    w = WorksheetFunction.Transpose(v)
    
    For i = 1 To UBound(v)
        Debug.Print v(i), TypeName(v(i)), w(i, 1), TypeName(w(i, 1))
    Next i
       
        With CreateObject("New:{8BD21D20-EC42-11CE-9E0D-00AA006002F3}")
        'Listbox always Base 0
            .List = v
             w = .List 'Now 2-dim with correct typenames, use .column for transpose Row-column)
        End With
    
    For i = 1 To UBound(v)
        Debug.Print v(i), TypeName(v(i)), w(i - 1, 0), TypeName(w(i - 1, 0))
    Next i
    
    End Sub
    

    【讨论】:

    • 谢谢,但是我发布这个的原因是为了指出我遇到的问题,以便其他人知道它。有许多变通方法——但如果您不知道它可能会发生,您就不会使用它们,最终不得不处理看似莫名其妙的错误。我没有想到ListBox 方法,但它似乎有效。但是,对于 100,000 个日期的数据样本,ListBox 方法比简单循环花费的时间长 3-4 倍。 (原始数据样本也需要更长的时间)。
    猜你喜欢
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 2012-03-19
    • 2017-04-08
    • 2017-09-13
    • 1970-01-01
    相关资源
    最近更新 更多