ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E文精选 > Excel VBA > VBA数组学习笔记

VBA数组学习笔记

作者:绿色风 分类: 时间:2022-08-17 浏览:185
楼主
liuguansky
[友情提示:如果感觉这里的排版不堪入目,请直接下载附件,上面有DOC的良好排版。]


初识VBA数组
      

     [注:以下言论仅为笔者初学VBA几日的一些看法,如有不对之处,敬请海涵雅正。]
    从最开始接触VBA什么都不懂开始,到现在大致可以看懂一般的代码,感觉数组贯穿了笔者学习VBA的始末。
    数组以它处理问题的便捷[二维数组与工作表的行列相对应,更具直观性,处理起来能得心应手。]、高效[从内存调用变量,避免频繁调用对象而造成代码的速度迟缓;同时结合循环,可以让问题更快、更灵活的得到解决。]得到了很多高手的亲睐,希望此文能对初学者有所帮助。
     [以下说明,仅针对笔者数组学习中所困惑、不易掌握、易忽略的知识点,其他知识点请参考相关数组资料自行学习。]

说在前面:
    学习VBA,初期最重要的一点是养成编写代码的好习惯。从学代码的初期就应该严格要求自己,从优化、通用、准确着手来编写代码。
        1.定义变量类型;
         定义变量类型可能有时初学者不以为然,认为定义不定义都无所谓,为了偷懒往往不愿意花时间去定义类型,这是个很不好的习惯。

             因为有时定义一个类型可能会让你的代码的速度提升好几倍。
      2.通用可延伸性;
        有时对数组源的处理的时候,不喜欢去判断是否为””,或者不去用条件去判断区域,而直接引用一个固定的区域,还有就是喜欢用currentregion

            在数据源增加的时候容易出错的表达形式。
        又或者,union的时候不判断RNG IS NOTHING的情况,字典返回的时候不判断DIC.COUNT>0的情况等。
        再就是版本通用性的时候,比如我们取某列最后一个非空单元格的行号:
                                                 ["a65536"].end(3).row
        其实这里在07版本就不很适用,可以小改动下就可以了
                                                 Cells(rows.count,1).end(3).row
       3.循环中尽量在内存中进行取值
         有时可能循环时,可以直接引用单元格来进行处理,代码可能会简单一点,但效率却差很多,所以要养成不在循环中引用对象的习惯。
        4.区域赋值时,先清空区域,这样效率也会快很多,而且避免多次运行代码出现错误情况。


一、数组的元素。

      数组,简单的说就是用一个名称通过下标[或索引]来区分引用多个值。――>为创建循环提供便利
      数组中的元素可以是不同类型的数据,也可以是相同类型的数据。
      一般我们可能听说过,就是定义一个变量特定类型,会比不定义特定类型速度要快。对数组而言,如果所赋值元素均为统一类型,可以定义数组元素类型。如:
        Dim arr as integer '定义一维数组,后面可以不用加()
        Dim arr() as integer'定义多维动态数组,后面一定要加(),否则在动态定义redim preserve时会造成“类型不匹配错误”
        Dim arr(1 to 3) as long'直接定义静态一维数组;
        Dim arr(1 to 2,2 to 4) as string'定义静态二维数组;

                                         
 


     当未指定类型时,默认数组类型为Variant.数组大肚能容,元素可以是几乎任意东西,当然可以是数组。如果维度不同的元素数据类型不同的话,请定义为Variant类型。
     因为一般工作表的源数据会有文本,数值等,所以定义数组用来存放单元格内容的话,一般直接定义为Variant.

二、数组的下上界

      我们知道可以用Lbound,ubound来返回数组的下界与上界,也知道可以用option base0 & 1 来调整下界的默认值。这里有几点注意的地方:
             1.当我们把单元格区域赋值给一个数组的时候
         比如 arr=range(“a1:c10”),抑或 arr=range(“a1:a10”) ,甚至 arr=range(“a1:e1”)
         我们可以在本地窗口中发现,arr总是个二维的数组。行代表第一维,列代表第二维。而且下界总是从1开始的,不受option base 0 的影响。
                              
 


        从而我们也可以知道:一维数组对应工作表单元格区域是一行。那么当我们赋值给单元格时,如何把一维数组赋值给一列呢?

三、赋值单元格区域

      当我们把一维数组赋值给一列时,因为维度的不对应性,可以用工作表函数transpose来进行转置后赋值给单元格。如
              Dim arr as integer '定义一维数组
              Dim I% '定义变量,用于循环给数组元素赋值
              ReDim arr(1 To 30000) '定义数组下界,上界
              For i=1 to 10 '循环赋值

                 Arr(i)=i^2 '因为设定数组下界从1开始              Next i

              Cells(1,1).resize(10,1)=application.worksheetfunction.transpose(arr)'转置赋值给单元格区域
      先用循环赋值给变量,再一次性把对象赋值给单元格对象。

      这是最简单的一个代码优化思想:在循环中尽量避免引用对象,因为引用对象会浪费很多的时间。
         请看下面代码的测试结果:

  1. Sub 变量赋值与单元格对象直接赋值对比()
  2.   Dim arr, i&, t1, t2, str1$
  3.   t1 = Timer
  4.   ReDim arr(1 To 30000)
  5.   For i = 1 To 30000
  6.     arr(i) = i ^ 2
  7.   Next i
  8.   Cells(1, 1).Resize(30000, 1) = Application.Transpose(arr)
  9.   t2 = Timer
  10.   str1 = "变量赋值用时" & t2 - t1 & vbCrLf
  11.   t1 = Timer
  12.   For i = 1 To 30000
  13.     Cells(i, 2) = i ^ 2
  14.   Next i
  15.   t2 = Timer
  16.   str1 = str1 & "引用单元格对象用时" & t2 - t1
  17.   MsgBox str1
  18.   Stop
  19. End Sub

                                          
 

          一般我们要在一个单元格区域返回值,可以定义一个与单元格区域相符合大小的数组来存放结果,再一次性的返回给单元格区域。
              主要是避免在循环中引用单元格对象。


          下面这里是另外一个优化技巧:

              就是在赋值单元格区域时,先清空区域,可以提升速度。同时也可以避免多次运行代码产生错误结果。
四、数组元素赋值与运算相关函数


      下面说明一些数组赋值与运算中经常会用到的函数与技巧:
             1.判断是否为数组:isarray()
            2.返回下界,上界:lbound(数组arr,N维度)ubound(数组arr,N维度)
           可以用于循环的初末值设定、返回数组的元素个数等
             3.Join函数:返回一个字符串,该字符串是通过连接某个数组中的多个子字符串而创建的。[仅针对一维数组有效][对多维数组的思考:用INDEX返回一维后再JOIN]
             例:
  1. Sub JOIN实例()
  2.   Dim arr, arrre, str1$
  3.   arr = Cells(1, 1).CurrentRegion.Value
  4.   ReDim arrre(1 To UBound(arr, 2))
  5.   For i = 1 To UBound(arr, 2) '选用二维循环,循环次数少
  6.     arrre(i) = Join(Application.Transpose(Application.Index(arr, , i)), ",")
  7.     '此时要把INDEX生成的一列转置成一维数组进行JOIN
  8.   Next i
  9.   For i = 1 To UBound(arrre)
  10.     str1 = str1 & "," & arrre(i)
  11.   Next i
  12.   MsgBox Mid(str1, 2)
  13.   Stop
  14. End Sub

                  这里只是提供一种思路,有兴趣的朋友可以比较下JOIN这样的连接方式与一次循环的速度。
        说明:
                             1.JOIN只针对一维数组,非一维数组的使用,要进行转换为一维,或用其它思维进行。
                             2.用于字符串组合生成的时候可以考虑。[优先考虑]
             4.Filter函数:返回一个下标从零开始的数组,该数组包含基于指定筛选条件的一个字符串数组的子集。
                 Filter([, include[, compare]])

免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap