ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
12
返回列表 发新帖
楼主: jz_l

[原创] VB/VBA数组Transpose转置DLL,32位/64位均可用

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-10 11:44 | 显示全部楼层
wodewan 发表于 2023-7-10 11:31
,本来也想搞个类似的,无奈初学,看的出来大佬对C/C++和VB的数据转换,内存结构很精通啊,有没啥学习 ...

熟悉点SAFEARRAY安全数组结构就行了,知道了数组描述结构位置、数据位置,其它的都好操作了

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-16 15:37 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
230716更新,修复了1个Bug,增加了使用示例。

TA的精华主题

TA的得分主题

发表于 2023-7-16 21:06 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
原地转置,用临时变量变换数据位置,再调整SAFEARRAY中的SAFEARRAYBOUND,应该是这样操作吧?速度会慢点,省内存

TA的精华主题

TA的得分主题

发表于 2023-7-17 07:47 | 显示全部楼层
jz_l 发表于 2023-7-9 15:37
DLL及使用示例。。
230716更新,修复了1个Bug。

怎么转为64位的呢,且附件也没有引用dll。能告诉一下怎么使用吗

TA的精华主题

TA的得分主题

发表于 2023-7-17 13:44 | 显示全部楼层
在vba中经常会用到动态数组redim preserve,一般都是二维的,归集好数据后,要把二维动态数组转置,excel内置的转置功能,在vba里用application.transpose时会有很多bug,比方说行数,列数的限制等,所以我自己用vba写了一个简单的转置函数来替代application.transpose.Function Transpose2(Arr) '自制转置函数,系统函数有缺陷,将二维数组行列转置
    Dim Brr, L1, U1, L2, U2, i&, j&
    L1 = LBound(Arr, 1): U1 = UBound(Arr, 1)
    L2 = LBound(Arr, 2): U2 = UBound(Arr, 2)
    ReDim Brr(L2 To U2, L1 To U1)
    For i = L1 To U1
        For j = L2 To U2
            Brr(j, i) = IIf(IsNull(Arr(i, j)), 0, Arr(i, j))
        Next
    Next
    Transpose2 = Brr
End Function

TA的精华主题

TA的得分主题

发表于 2023-7-17 13:48 | 显示全部楼层
Function Transpose2(Arr)
    Dim Brr, L1, U1, L2, U2, i&, j&
    L1 = LBound(Arr, 1): U1 = UBound(Arr, 1)
    L2 = LBound(Arr, 2): U2 = UBound(Arr, 2)
    ReDim Brr(L2 To U2, L1 To U1)
    For i = L1 To U1
        For j = L2 To U2
            Brr(j, i) = IIf(IsNull(Arr(i, j)), 0, Arr(i, j))
        Next
    Next
    Transpose2 = Brr
End Function
在vba里经常会用到动态数组来归集相应数据,一般是二维数组,归集完后,一般要转置来展示数据等,内置的转置功能,在vba中用application.transpose来处理时,会有很多bug,比方说行数,列数的限制,以致数据展示不全(错误),所以自己写了一个转置功能的函数。简单易用,好理解。

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-17 15:33 | 显示全部楼层
leolee82 发表于 2023-7-16 21:06
原地转置,用临时变量变换数据位置,再调整SAFEARRAY中的SAFEARRAYBOUND,应该是这样操作吧?速度会慢点, ...

基本上是这样
有时候可用内存不够了,只能原地转置,会慢不少

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-17 15:52 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 jz_l 于 2023-7-17 15:55 编辑
386026398 发表于 2023-7-17 07:47
怎么转为64位的呢,且附件也没有引用dll。能告诉一下怎么使用吗

打开附件的工作簿文件,Alt+F11打开VBA编辑器,查看示例源代码。
使用:
1、复制API声明部分
  1. #If Win64 Then 'Win64 + VBA7
  2.     Private Declare PtrSafe Function ArrayPtrV Lib "vbaEx64.dll" (ByRef vAry As Variant) As LongPtr
  3.     Private Declare PtrSafe Function Transpose Lib "vbaEx64.dll" (ByRef ary() As Any) As Boolean
  4.     Private Declare PtrSafe Function TransposePtr Lib "vbaEx64.dll" Alias "Transpose" _
  5.                         (ByVal pAry As LongPtr) As Boolean
  6. #Else 'Win32 + VBA7 Or Win32 + VBA6
  7.     Private Declare Function ArrayPtrV Lib "vbaEx32.dll" (ByRef vAry As Variant) As Long
  8.     Private Declare Function Transpose Lib "vbaEx32.dll" (ByRef ary() As Any) As Boolean
  9.     Private Declare Function TransposePtr Lib "vbaEx32.dll" Alias "Transpose" _
  10.                         (ByVal pAry As Long) As Boolean
  11. #End If
复制代码

2、设置原数组的值,如:


  1. Dim ary() As Long, l as Long

  2. ReDim ary(1 To 3, 2 To 10)
  3. For c = 2 To 10
  4.     For r = 1 To 3
  5.         l = l + 1
  6.         ary(r, c) = l
  7.     Next
  8. Next
复制代码


3、调用转置API

  1. If Transpose(ary()) Then '转置成功
  2.     'Do Something
  3. End If
复制代码
对于String数组、包含数组的Variant,调用方式参见附件示例。

若提示DLL文件未找到,可
1、在调用API前,调用(将对应源码复制到你的工作簿源码中):
  1. Call SetCurDir
复制代码
2、或者使用DLL绝对路径,如DLL在【D:\ABC\】文件夹中,API声明如下:

  1. #If Win64 Then 'Win64 + VBA7
  2.     Private Declare PtrSafe Function ArrayPtrV Lib "D:\ABC\vbaEx64.dll" (ByRef vAry As Variant) As LongPtr
  3.     Private Declare PtrSafe Function Transpose Lib "D:\ABC\vbaEx64.dll" (ByRef ary() As Any) As Boolean
  4.     Private Declare PtrSafe Function TransposePtr Lib "vbaEx64.dll" Alias "Transpose" _
  5.                         (ByVal pAry As LongPtr) As Boolean
  6. #Else 'Win32 + VBA7 Or Win32 + VBA6
  7.     Private Declare Function ArrayPtrV Lib "D:\ABC\vbaEx32.dll" (ByRef vAry As Variant) As Long
  8.     Private Declare Function Transpose Lib "D:\ABC\vbaEx32.dll" (ByRef ary() As Any) As Boolean
  9.     Private Declare Function TransposePtr Lib "vbaEx32.dll" Alias "Transpose" _
  10.                         (ByVal pAry As Long) As Boolean
  11. #End If
复制代码


TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-17 16:13 | 显示全部楼层
gjj136138139 发表于 2023-7-17 13:48
Function Transpose2(Arr)
    Dim Brr, L1, U1, L2, U2, i&, j&
    L1 = LBound(Arr, 1): U1 = UBound ...

对于简单的类型如Long、Single、Currency、Date等来说,统一的一个自定义函数除了损失点效率,也没啥可说的
对于包装类型Variant来说,数组元素里如果还包含数组、对象,自定义函数处理起来要复杂些,而Application.Transpose已经处理不了了
用于用户定义类型(UDT)来说,自定义函数需要对每种UDT专门1对1处理,Application.Transpose则不支持
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-22 23:31 , Processed in 0.042851 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表