分享

【新提醒】Excel VBA编程的工程性规划

 求知881 2017-07-25
 本帖最后由 wrove 于 2017-7-18 14:03 编辑

看过很多人写的VBA代码,一团一团的,一点规划都没有,为了VBA编程更具工程性,这里讨论一下,并列出自己的一些建议:
0.给VBA工程定义一个名字,而非直接使用默认的名称——"VBAProject",以方便以后可能要进行的跨VBA工程编码
1.定义一个命名为“O”的标准模块【拼音中“O”字母的读音,意指“我”这个字】,用于定义所有的全局对象,管理本工程的代码与数据,主要API:
    [1]About(Optional ShowDetail As Boolean = False)函数:对本工程的各方面的自述,方便查看本工程的各类信息,可以多设置一个信息开关参数,如
        这里的ShowDetail参数,比如再增加ShowCodeLinesCount参数
    [2]Public Property Get Project() As VBIDE.VBProject,对本工程的VBA工程的引用
    [3]Public Property Get VBAType() As VBAType,对本工程的VBA类型的定义,比如是在Excel,亦或是Word中,其中VBAType是自定义的Enum
    [4]Initialize()函数:初始化本工程所有需要初始化的内容
    [5]Terminate()函数:销毁所有需要销毁的
    [6]HasLib(Byval LibName As String)函数:检查本工程是否有某COM的引用,主要是检查O.Project.References集合,比如O.HasLib("Scripting"),方便
        可能需要的动态自动编码
    [7]HasModule(Byval ModuleName As String)函数:检查本工程是否存在某个模块
    [8]Property Get/Let NextErrorNumber:用于规划本工程自定义错误号,使每个错误号都是特有的,自定义错误的抛出如下:
  1. ''第二个参数是在设置Err.Source属性,形式为:VBA工程名+模块名+方法/函数/属性名,
  2. ''如果是属性,属性名后面还建议加一个后缀#Get/#Let/#Set,以示错误的更具体来源
  3. ''使用“#”而不是“_”,是因为“_”是合法的标识符字符,可能带来含义混淆
  4. Err.Raise -2147221406, "Nutix.Output.Format", "Values参数包含的值的个数与txt参数中格式化标识个数不相等"
复制代码
    [9]Bake()函数:对本工程进行备份
    [10]Move()函数:将本工程的所有代码迁移到另外一个支持VBA的文件中
    [11]Activate(Byval ModuleName As String)函数:将某模块的代码窗口打开
    [12]各种全局对象的声明,在声明中建议直接带New关键字,这样会避免掉很多Set语句,而且因为New关键字是在对应的对象变量被实际访问时,
          才真正执行对应的New操作,所以如果有必要,请在上面的Initialize()函数中,定义某些必须立即初始化的对象的初始化;集中在这个模块声明
         也能方便对应全局变量的管理与访问,比如对象变量名称很长,直接O.XXX会更方便输入,毕竟有智能成员提示嘛,而且O模块名只有一个字      
        符。另外,集中初始化与销毁,也 能避免漏操作。
    [13]常见的第三方功能对象:
          (1)Scripting.FileSystemObject对象,全局命名为FSO
          (2)VBS_RegExp_55.RegExp对象,全局命名为RE
          (3)MSForms.DataObject对象,全局命名为Clip
          (4)Shell32.Shell对象,全局命名为SH
          (5)IWshRuntimeLibrary.WshShell对象,全局命名为WSH
          (6)MSComDlg.CommonDialog对象,全局命名为CD
2.定义一个命名为Enums标准模块,存放所有的自定义Enum
3.定义一个命名为Types标准模块,存放所有的自定义Type结构体
4.定义一个命名为Constants标准模块,存放所有自定义的常数
5.定义一个命名为API标准模块,存放所有对Windows API声明及扩展
6.定义一个命名为Main标准模块,作为本工程的工作模块,所有的编码,在本模块测试,通用的测试也存放在本模块,以方便查阅,来了解VBA的特性,尤其是不常用的对象,你可能某一时候学会了使用它的API,但长久不用,就又忘了,如果将当初的试验代码,很好的命名,并保存于此模块,也会方便你再次熟悉这种对象。
7.定义一系列X_XXX类模块,用于对VBA的标准类型,或引用的第三方类型,或VBA固有的对象,进行功能性增强
    [1]比如对Collection/Array/Dictionary/VB(这里指的是VBA库,因为VBA与VB的相似性,这里写成VB而非VBA)/VBE(你写VBA代码的那个窗口)
        /Designer(VBE的窗体设计器)/Math/String/RegExp/ErrObject/FileSystemObject类型或对象的增强,分别定义如X_Collection/X_Array
       /X_Dictionary/X_VB/X_VBE/X_Designer/X_Math/X_String/X_RegExp/X_ErrObject/X_FileSystemObject的类模块;
    [2]在O模块中分别定义一个全局的该类模块的实例对象,分别命名为xCollection/xArray/xDictionary/xVB/xVBE/xDesigner/xMath/xString/xRegExp
        /xErrObject/xFileSystemObject
    [3]当要使用对应的对象时,统一通过O.XXX的形式来引用,尤其是对象名很长时。
    [4]虽然只需要一个这样的对象,但是还是建议使用类模块,而非标准模块,这是为了避免命名污染,因为定义太多的标准模块的全局函数,会将命名
        弄得一团糟,有时会出现相互遮蔽的现象;而且如TypeName这种VBA标准中已使用了的命名,如果在标准模块中重定义了,那么它会被遮蔽,造
        成功能混乱,明明想调用VBA.TypeName却调用了某标准模块的自定义TypeName成员
8.定义一系列的Tool_XXX类模块,用于对支持VBA的文件进行功能扩展
    [1]比如.doc/.xls/.mdb/.dwg/.ppt,则可对应的定义Tool_DOC/Tool_XLS/Tool_MDB/Tool_DWG/Tool_PPT类模块,来封装对Word/Excel/Access      
         /AutoCAD/PowerPoint文件的功能代码的设计。
    [2]仍然只在O模块中定义一个这些类型的全局对象,并分别命名为tDOC/tXLS/tMDB/tDWG/tPPT,方便访问
    [3]Property Get/Set App属性:用于定义对应的VBA宿主对象,即Application对象,根据O.VBAType属性来决定是新建对象,还是直接引用现成对象,
        比如你要调用O.tXLS.App属性,而当前文档是一个Word文档,那么对其进行访问,就需要新建Application对象,而如果本来就是Excel文档,就
        可以直接设置为当前的Application对象
    [4]Property Get/Set Doc属性:用于定义对应的文档对象,Word的是Document类型,Excel的是Workbook,……
    [5]其它的功能代码
9.定义一个命名为TXTData的标准模块,来存放本VBA工程的工程数据,比如上面的O.NextErrorNumber的数据,以XML文本的形式保存,你可以借用ThsiWorkbook.VBProject.VBComponent.CodeModule.Lines()/AddFromString()/ReplaceLine()/InsertLines()/DeleteLines() 等API来完成数据的读写
10.定义一个命名为Checker的类模块,用来存放本VBA工程中所有的通用的判断式API
    [1]返回值总是Boolean,成员建议命名为IsXXX形式,仍然只在全局定义一个这样的对象实例,命名为Chk,可能经常要用到的功能如下
    [2]IsAllInType(Obj As Object,Byval TypeName As String)方法:检查如数组/集合这种包含很多元素的对象的每一个元素类型是否是某类型
    [3]IsAllInTypes(Obj As Object,ParamArray TypeNames() As Variant)方法:检查如数组/集合这种包含很多元素的对象的每一个元素类型是否是某几个
        类型中的一个
    [4]IsInTypes(Obj As Object, ParamArray TypeNames() As Variant)方法:用于检查某个变量,是否是某几个类型中的一个
    [5]HasAttr(Obj As Object, Byval ProcName As String)方法:用于检验某对象是否存在某成员
    [6]IsAllTrue(ParamArray Values() As Variant)方法:用于检验某些变量,是否全为True,如果只传递一个变量,将把该变量当作一个多元素变量,并对
        其所有元素执行该操作
    [8]IsAnyTrue(ParamArray Values() As Variant)方法:用于检验某些变量,是否存有一个为True,如果只传递一个变量,将把该变量当作一个多元素变
        量,并对其所有元素执行该操作
    [9]IsSubSet(Items1 As Variant, Items2 As Variant)方法:用于检验前者是否是后者的子集
    [10]IsIn(Item As Variant, ParamArray Items() As Variant)方法:用于检验前者是否是后者中的一项,如果只传递一个变量,将把该变量当作一个多元素
          变量,并在该变量的元素中检验Item是否是其中之一
11.定义一个命名为Createor的类模块,封装所有的NewXXX操作,方便初始化对象
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为Crt
    [2]实现某些标准或者第三方的类型对象的实例化,及初始化,比如新建一个ErrObject对象
    [3]实现某些第二方类型(就是你自己的自定义类型)对象的实例化,及初始化,比如某些Type结构体,或者某些自定义类
12.定义一个命名为Convertor的类模块,封装所有的转化操作
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为Cvt
    [2]各种对象的字符串格式化方法,命名为str_+TypeName,方便对对象的格式化
13.定义一个命名为Caller的类模块,封装所有的集群调用,能一定程度上实现函数式编程,封装好了,可以减少使用循环语句
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为Cal
    [2]ForEach(Objs As Variant, ByVal ProcName As String, ByVal CallType As VbCallType, ParamArray Args() As Variant)方法:对Objs中每一个对象访问对
        应的成员
    [3]Filtrate(Objs As Variant, ByVal ProcName As String, ByVal CallType As VbCallType,  CompareTo As Variant, ByVal GetWhenEqual As Boolean,  _
        ParamArray Args() As Variant)方法:从Objs对象集中筛选对象
14.定义一个命名为Dialogs的类模块,用于封装可能用到的对话框
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为Dlgs
    [2]GetColor(Optional dlgTitle As String)方法:调用MSComDlg库的功能,实现颜色的选取
    [3]GetFont(Optional Min As Integer = -1, Optional Max As Integer = -1,  Optional dlgTitle As String) As Nutix.MSComDlgFont方法:调用MSComDlg库的
        功能,实现对字体的设置,其中Nutix.MSComDlgFont为自定义的Type结构体类型,因为你是没办法直接New出一个Font对象的
    [4]GetSaveFileName(Optional Filter As String = "所有多件 (*.*)",  Optional FilterIndex As Integer = 1, Optional DefaultExt As String, _
         Optional InitDir As String, Optional dlgTitle As String)方法:调用MSComDlg库的功能,获取要保存的文件名与路径
    [5]GetOpenFileName(Optional Filter As String = "所有多件 (*.*)",  Optional FilterIndex As Integer = 1, Optional DefaultExt As String, _
        Optional MultiSelect As Boolean = False, Optional InitDir As String,  Optional dlgTitle As String)方法:调用MSComDlg库的功能,获取要打开的文件名
        与路径
15.定义一个命名为System的类型模块,用于对封装本操作系统的功能操作
    [1] 仍然只在全局定义一个这样的对象实例,全局变量名为Sys
    [2]HasTaskNamed(ByVal Name As String)方法:调用WbemScripting库(WMI)的相关功能,检验操作系统上是否已经运行了某名称的进程
    [3]GetClipText()方法:调用MSForms.DataObject的功能,实现对系统剪贴板的文本的读取
    [4]SetClipText()方法:调用MSForms.DataObject的功能,实现对系统剪贴板的内容进行设置

16.定义一个命名为VBS/JS的类模块,用于封装对VBS/JS代码的调用,借助MSScriptControl库来实现
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为VBS/JS
    [2]代码保存在上面所说的本VBA工程的数据模块,即TXTData模块中
    [3]Property Get This() As MSScriptControl属性:用于向外公开内部的中心对象,因为所有功能是构建在MSScriptControl对象上的,故如此说
    [4]AddCode(Byval Code As String)方法:用于向This中添加代码,代码数据也会被同步存入TXTData模块中
17.定义一个命名为Output的类模块,用于封装常用的各种字符串格式化操作
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为Out
    [2]WriteLine(Byval Line As String)方法:定义当前类的写操作,所有其它写操作是基于这个方法的;内部提供向立即窗口/文本文件两种方向的写操作
    [3]SingleSepLine(Optional Length As Integer)方法:输出指定长度的“-”(减号),即输出一个单分割线
    [4]DoubleSepLine(Optional Length As Integer)方法:输出指定长度的“=”(等号),即输出一个双分割线
    [5]NamedSepLine(ByVal Name As String, Optional ByVal Char As String = "*", Optional Length As Integer)方法:输出一个命名居中的,指定长度的, 
        由Char字符串构成的行
    [6]FileName属性:用于改变输出方向到一个文本文件
    [7]ObjectName属性:用于定义对象输出时的对象名,与下面联合完成对象格式化
    [8]PObjSelf(Obj As Variant)方法:用于输出对象本身,对象名由7定义,输出形式是:ObjectName + " = " +Object的字符串
    [9]PObjCall(Obj As Object, ByVal ProcName As String, ByVal CallType As VBA.VbCallType, ParamArray Args() As Variant)方法:用于输出对象的某个
        成员,输出形式是:ObjectName + "." + ProcName + " = " + Object.Proc的值
    [10]PObjProperties(Obj As Object, ParamArray ProcNames() As Variant)方法:用于输出对象的多个属性,输出形式如上,每一个属性,对应一个等式
          输出行
    [11]PTypeValue(Obj As Variant)方法:输出变量的类型和值,输出形式:ObjTypeName + " => " + ObjValue的字符串
18.定义命名为frmXXXTool的系列窗体模块,封装对各种支持VBA的文件的有界面操作
    [1]对应于.doc/.xls/.mdb/.dwg/.ppt,窗体模块的命名分别为frmDOCTool/frmXLSTool/frmMDBTool/frmDWGTool/frmPPTTool
    [2]不用定义全局以上窗体对象,因为VBA系统默认已经创建了一个这样的对象,其命名与窗体模块名相同
19.定义命名为Coder的类模块,用于封装对本VBA工程的对象编码功能
    [1]仍然只在全局定义一个这样的对象实例,全局变量名为Cod
    [2]引用管理功能
    [3]代码统计功能
    [4]代码增删替换的功能
    [5]基于固定模式的动态编程功能

20.最后加一段代码,作为Main模块的主要工作代码块【主要是预先声明了大量的可能用到的变量和数组,避免每次重新声明】
  1. Public Sub AAA_00000000_AAA()
  2.     ''[VBA]数据类型变量声明
  3.     Dim Byt As Byte, Byt1 As Byte, Byt2 As Byte, Byt3 As Byte
  4.     Dim Bln As Boolean, Bln1 As Boolean, Bln2 As Boolean, Bln3 As Boolean
  5.     Dim Itg As Integer, Itg1 As Integer, Itg2 As Integer, Itg3 As Integer
  6.     Dim Lng As Long, Lng1 As Long, Lng2 As Long, Lng3 As Long
  7.     Dim Sng As Single, Sng1 As Single, Sng2 As Single, Sng3 As Single
  8.     Dim Dbl As Double, Dbl1 As Double, Dbl2 As Double, Dbl3 As Double
  9.     Dim Str As String, str1 As String, str2 As String, Str3 As String
  10.     Dim Dt As Date, Dt1 As Date, Dt2 As Date, Dt3 As Date
  11.     Dim Var As Variant, Var1 As Variant, Var2 As Variant, Var3 As Variant
  12.     Dim Obj As Object, Obj1 As Object, Obj2 As Object, Obj3 As Object
  13.     ReDim byts(0) As Byte, blns(0) As Boolean, itgs(0) As Integer, lngs(0) As Long
  14.     ReDim sngs(0) As Single, dbls(0) As Double, Strs(0) As String
  15.     ReDim Dts(0) As Date, Vars(0) As Variant, Objs(0) As Object
  16.     Dim i As Long, j As Long, k As Long, RE As New VBScript_RegExp_55.RegExp
  17.     Dim c As New Collection, c1 As New Collection, c2 As New Collection, c3 As New Collection
  18.     ''[Scripting]数据类型变量声明
  19.     Dim d As New Scripting.Dictionary, d1 As New Scripting.Dictionary, d2 As New Scripting.Dictionary
  20.     Dim Key As Variant, Key1 As Variant, Key2 As Variant
  21.     ''[VBScript_RegExp_55]数据类型变量声明
  22.     Dim m As VBScript_RegExp_55.Match, ms As VBScript_RegExp_55.MatchCollection
  23.     ''[VBIDE]数据类型变量声明
  24.     Dim vbc As vbide.VBComponent, cp As vbide.CodePane, cm As vbide.CodeModule
  25.     ''[Excel]数据类型变量声明
  26.     Dim rng As Excel.Range, rng1 As Excel.Range, rng2 As Excel.Range, rng3 As Excel.Range
  27.     Dim sht As Excel.Worksheet, sht1 As Excel.Worksheet, sht2 As Excel.Worksheet, sht3 As Excel.Range
  28.     Dim wb As Excel.Workbook, wb1 As Excel.Workbook, wb2 As Excel.Workbook, wb3 As Excel.Workbook
  29.     Dim shp As Excel.Shape, Ole As Excel.OLEObject
  30.     ''[Word]数据类型变量声明
  31.     Dim Doc As New MSXML2.DOMDocument60, e As MSXML2.IXMLDOMElement, a As MSXML2.IXMLDOMAttribute
  32.     ''[MSXML2]数据类型变量声明
  33.     Dim CData As MSXML2.IXMLDOMCDATASection, NL As MSXML2.IXMLDOMNodeList, N As MSXML2.IXMLDOMNode
  34.     ''MSForms相关变量声明
  35.     Dim win As MSForms.UserForm, grp As MSForms.Frame
  36.     Dim ctls As MSForms.Control, ctl As MSForms.Control
  37.     Dim btn As MSForms.CommandButton, rbtn As MSForms.OptionButton
  38.     Dim sbtn As MSForms.SpinButton, tbtn As MSForms.ToggleButton
  39.     Dim cbb As MSForms.ComboBox, lst As MSForms.ListBox
  40.     Dim ckb As MSForms.CheckBox, img As MSForms.Image
  41.     Dim lbl As MSForms.Label, txt As MSForms.TextBox
  42.     Dim mp As MSForms.MultiPage, pg As MSForms.Page
  43.     Dim ts As MSForms.TabStrip, tb As MSForms.Tab
  44.     Dim scb As MSForms.ScrollBar
  45.     ''<AAA_00000000_AAA_WorkingCode>
  46.    
  47.     ''</AAA_00000000_AAA_WorkingCode>
  48. End Sub
复制代码
================================================================================
如上是我的VBA工程——“VBA工具集.xlsm"的编码规划,共享于此,希望能够给予各位爱好VBA的坛友以帮助。
如果觉得我的规划有功能性划分或组织不合理的地方,请给出您的建议。

关于各数据类型的Array的初始化写很多语句是不是很烦人,定义X_Array类如下成员

本帖最后由 wrove 于 2017-7-19 08:34 编辑
  1. Public Function NewBooleans(ParamArray Values() As Variant) As Boolean()
  2.     Dim blns() As Boolean, Value As Variant
  3.     ReDim blns(0)
  4.     For Each Value In Values
  5.         blns(UBound(blns)) = Value
  6.         ReDim Preserve blns(UBound(blns) + 1)
  7.     Next
  8.     If UBound(blns) <> 0 Then
  9.         ReDim Preserve blns(UBound(blns) - 1)
  10.     Else
  11.         Err.Raise -2147221322, "Nutix.X_Array.NewBooleans", "至少应有一个数据"
  12.     End If
  13.     NewBooleans = blns
  14. End Function

  15. Public Function NewBooleansInLength(ByVal Length As Long, ParamArray Values() As Variant) As Boolean()
  16.     Dim blns() As Boolean, Value As Variant, lNow As Long
  17.     ReDim blns(0)
  18.     For Each Value In Values
  19.         blns(UBound(blns)) = Value
  20.         ReDim Preserve blns(UBound(blns) + 1)
  21.     Next
  22.     If UBound(blns) <> 0 Then
  23.         lNow = UBound(blns) - LBound(blns) + 1
  24.         Select Case lNow
  25.             Case Is = Length
  26.                 ''Already Exists, Do Nothing
  27.             Case Is > Length
  28.                 Err.Raise -2147221323, "Nutix.X_Array.NewBooleansInLength", "太多数据"
  29.             Case Is < Length
  30.                 ReDim Preserve blns(Length)
  31.         End Select
  32.     End If
  33.     NewBooleansInLength = blns
  34. End Function

  35. Public Function NewBytes(ParamArray Values() As Variant) As Byte()
  36.     Dim byts() As Byte, Value As Variant
  37.     ReDim byts(0)
  38.     For Each Value In Values
  39.         byts(UBound(byts)) = Value
  40.         ReDim Preserve byts(UBound(byts) + 1)
  41.     Next
  42.     If UBound(byts) <> 0 Then
  43.         ReDim Preserve byts(UBound(byts) - 1)
  44.     Else
  45.         Err.Raise -2147221322, "Nutix.X_Array.NewBytes", "至少应有一个数据"
  46.     End If
  47.     NewBytes = byts
  48. End Function

  49. Public Function NewBytesInLength(ByVal Length As Long, ParamArray Values() As Variant) As Byte()
  50.     Dim byts() As Byte, Value As Variant, lNow As Long
  51.     ReDim byts(0)
  52.     For Each Value In Values
  53.         byts(UBound(byts)) = Value
  54.         ReDim Preserve byts(UBound(byts) + 1)
  55.     Next
  56.     If UBound(byts) <> 0 Then
  57.         lNow = UBound(byts) - LBound(byts) + 1
  58.         Select Case lNow
  59.             Case Is = Length
  60.                 ''Already Exists, Do Nothing
  61.             Case Is > Length
  62.                 Err.Raise -2147221323, "Nutix.X_Array.NewBytesInLength", "太多数据"
  63.             Case Is < Length
  64.                 ReDim Preserve byts(Length)
  65.         End Select
  66.     End If
  67.     NewBytesInLength = byts
  68. End Function

  69. Public Function NewDates(ParamArray Values() As Variant) As Date()
  70.     Dim Dts() As Date, Value As Variant
  71.     ReDim Dts(0)
  72.     For Each Value In Values
  73.         Dts(UBound(Dts)) = Value
  74.         ReDim Preserve Dts(UBound(Dts) + 1)
  75.     Next
  76.     If UBound(Dts) <> 0 Then
  77.         ReDim Preserve Dts(UBound(Dts) - 1)
  78.     Else
  79.         Err.Raise -2147221322, "Nutix.X_Array.NewDates", "至少应有一个数据"
  80.     End If
  81.     NewDates = Dts
  82. End Function

  83. Public Function NewDatesInLength(ByVal Length As Long, ParamArray Values() As Variant) As Date()
  84.     Dim Dts() As Date, Value As Variant, lNow As Long
  85.     ReDim Dts(0)
  86.     For Each Value In Values
  87.         Dts(UBound(Dts)) = Value
  88.         ReDim Preserve Dts(UBound(Dts) + 1)
  89.     Next
  90.     If UBound(Dts) <> 0 Then
  91.         lNow = UBound(Dts) - LBound(Dts) + 1
  92.         Select Case lNow
  93.             Case Is = Length
  94.                 ''Already Exists, Do Nothing
  95.             Case Is > Length
  96.                 Err.Raise -2147221323, "Nutix.X_Array.NewDatesInLength", "太多数据"
  97.             Case Is < Length
  98.                 ReDim Preserve Dts(Length)
  99.         End Select
  100.     End If
  101.     NewDatesInLength = Dts
  102. End Function

  103. Public Function NewDoubles(ParamArray Values() As Variant) As Double()
  104.     Dim dbls() As Double, Value As Variant
  105.     ReDim dbls(0)
  106.     For Each Value In Values
  107.         dbls(UBound(dbls)) = Value
  108.         ReDim Preserve dbls(UBound(dbls) + 1)
  109.     Next
  110.     If UBound(dbls) <> 0 Then
  111.         ReDim Preserve dbls(UBound(dbls) - 1)
  112.     Else
  113.         Err.Raise -2147221322, "Nutix.X_Array.NewDoubles", "至少应有一个数据"
  114.     End If
  115.     NewDoubles = dbls
  116. End Function

  117. Public Function NewDoublesInLength(ByVal Length As Long, ParamArray Values() As Variant) As Double()
  118.     Dim dbls() As Double, Value As Variant, lNow As Long
  119.     ReDim dbls(0)
  120.     For Each Value In Values
  121.         dbls(UBound(dbls)) = Value
  122.         ReDim Preserve dbls(UBound(dbls) + 1)
  123.     Next
  124.     If UBound(dbls) <> 0 Then
  125.         lNow = UBound(dbls) - LBound(dbls) + 1
  126.         Select Case lNow
  127.             Case Is = Length
  128.                 ''Already Exists, Do Nothing
  129.             Case Is > Length
  130.                 Err.Raise -2147221323, "Nutix.X_Array.NewDoublesInLength", "太多数据"
  131.             Case Is < Length
  132.                 ReDim Preserve dbls(Length)
  133.         End Select
  134.     End If
  135.     NewDoublesInLength = dbls
  136. End Function

  137. Public Function NewIntegers(ParamArray Values() As Variant) As Integer()
  138.     Dim itgs() As Integer, Value As Variant
  139.     ReDim itgs(0)
  140.     For Each Value In Values
  141.         itgs(UBound(itgs)) = Value
  142.         ReDim Preserve itgs(UBound(itgs) + 1)
  143.     Next
  144.     If UBound(itgs) <> 0 Then
  145.         ReDim Preserve itgs(UBound(itgs) - 1)
  146.     Else
  147.         Err.Raise -2147221322, "Nutix.X_Array.NewIntegers", "至少应有一个数据"
  148.     End If
  149.     NewIntegers = itgs
  150. End Function

  151. Public Function NewIntegersInLength(ByVal Length As Long, ParamArray Values() As Variant) As Integer()
  152.     Dim itgs() As Integer, Value As Variant, lNow As Long
  153.     ReDim itgs(0)
  154.     For Each Value In Values
  155.         itgs(UBound(itgs)) = Value
  156.         ReDim Preserve itgs(UBound(itgs) + 1)
  157.     Next
  158.     If UBound(itgs) <> 0 Then
  159.         lNow = UBound(itgs) - LBound(itgs) + 1
  160.         Select Case lNow
  161.             Case Is = Length
  162.                 ''Already Exists, Do Nothing
  163.             Case Is > Length
  164.                 Err.Raise -2147221323, "Nutix.X_Array.NewIntegersInLength", "太多数据"
  165.             Case Is < Length
  166.                 ReDim Preserve itgs(Length)
  167.         End Select
  168.     End If
  169.     NewIntegersInLength = itgs
  170. End Function

  171. Public Function NewLongs(ParamArray Values() As Variant) As Long()
  172.     Dim lngs() As Long, Value As Variant
  173.     ReDim lngs(0)
  174.     For Each Value In Values
  175.         lngs(UBound(lngs)) = Value
  176.         ReDim Preserve lngs(UBound(lngs) + 1)
  177.     Next
  178.     If UBound(lngs) <> 0 Then
  179.         ReDim Preserve lngs(UBound(lngs) - 1)
  180.     Else
  181.         Err.Raise -2147221322, "Nutix.X_Array.NewLongs", "至少应有一个数据"
  182.     End If
  183.     NewLongs = lngs
  184. End Function

  185. Public Function NewLongsInLength(ByVal Length As Long, ParamArray Values() As Variant) As Long()
  186.     Dim lngs() As Long, Value As Variant, lNow As Long
  187.     ReDim lngs(0)
  188.     For Each Value In Values
  189.         lngs(UBound(lngs)) = Value
  190.         ReDim Preserve lngs(UBound(lngs) + 1)
  191.     Next
  192.     If UBound(lngs) <> 0 Then
  193.         lNow = UBound(lngs) - LBound(lngs) + 1
  194.         Select Case lNow
  195.             Case Is = Length
  196.                 ''Already Exists, Do Nothing
  197.             Case Is > Length
  198.                 Err.Raise -2147221323, "Nutix.X_Array.NewLongsInLength", "太多数据"
  199.             Case Is < Length
  200.                 ReDim Preserve lngs(Length)
  201.         End Select
  202.     End If
  203.     NewLongsInLength = lngs
  204. End Function

  205. Public Function NewSingles(ParamArray Values() As Variant) As Single()
  206.     Dim sngs() As Single, Value As Variant
  207.     ReDim sngs(0)
  208.     For Each Value In Values
  209.         sngs(UBound(sngs)) = Value
  210.         ReDim Preserve sngs(UBound(sngs) + 1)
  211.     Next
  212.     If UBound(sngs) <> 0 Then
  213.         ReDim Preserve sngs(UBound(sngs) - 1)
  214.     Else
  215.         Err.Raise -2147221322, "Nutix.X_Array.NewSingles", "至少应有一个数据"
  216.     End If
  217.     NewSingles = sngs
  218. End Function

  219. Public Function NewSinglesInLength(ByVal Length As Long, ParamArray Values() As Variant) As Single()
  220.     Dim sngs() As Single, Value As Variant, lNow As Long
  221.     ReDim sngs(0)
  222.     For Each Value In Values
  223.         sngs(UBound(sngs)) = Value
  224.         ReDim Preserve sngs(UBound(sngs) + 1)
  225.     Next
  226.     If UBound(sngs) <> 0 Then
  227.         lNow = UBound(sngs) - LBound(sngs) + 1
  228.         Select Case lNow
  229.             Case Is = Length
  230.                 ''Already Exists, Do Nothing
  231.             Case Is > Length
  232.                 Err.Raise -2147221323, "Nutix.X_Array.NewSinglesInLength", "太多数据"
  233.             Case Is < Length
  234.                 ReDim Preserve sngs(Length)
  235.         End Select
  236.     End If
  237.     NewSinglesInLength = sngs
  238. End Function

  239. Public Function NewStrings(ParamArray Values() As Variant) As String()
  240.     Dim Strs() As String, Value As Variant
  241.     ReDim Strs(0)
  242.     For Each Value In Values
  243.         Strs(UBound(Strs)) = Value
  244.         ReDim Preserve Strs(UBound(Strs) + 1)
  245.     Next
  246.     If UBound(Strs) <> 0 Then
  247.         ReDim Preserve Strs(UBound(Strs) - 1)
  248.     Else
  249.         Err.Raise -2147221322, "Nutix.X_Array.NewStrings", "至少应有一个数据"
  250.     End If
  251.     NewStrings = Strs
  252. End Function

  253. Public Function NewStringsInLength(ByVal Length As Long, ParamArray Values() As Variant) As String()
  254.     Dim Strs() As String, Value As Variant, lNow As Long
  255.     ReDim Strs(0)
  256.     For Each Value In Values
  257.         Strs(UBound(Strs)) = Value
  258.         ReDim Preserve Strs(UBound(Strs) + 1)
  259.     Next
  260.     If UBound(Strs) <> 0 Then
  261.         lNow = UBound(Strs) - LBound(Strs) + 1
  262.         Select Case lNow
  263.             Case Is = Length
  264.                 ''Already Exists, Do Nothing
  265.             Case Is > Length
  266.                 Err.Raise -2147221323, "Nutix.X_Array.NewStringsInLength", "太多数据"
  267.             Case Is < Length
  268.                 ReDim Preserve Strs(Length)
  269.         End Select
  270.     End If
  271.     NewStringsInLength = Strs
  272. End Function


复制代码
  1. Public Function NewVariants(ParamArray Values() As Variant) As Variant()
  2.     Dim Vars() As Variant, Value As Variant
  3.     ReDim Vars(0)
  4.     For Each Value In Values
  5.         Vars(UBound(Vars)) = Value
  6.         ReDim Preserve Vars(UBound(Vars) + 1)
  7.     Next
  8.     If UBound(Vars) <> 0 Then
  9.         ReDim Preserve Vars(UBound(Vars) - 1)
  10.     Else
  11.         Err.Raise -2147221322, "Nutix.X_Array.NewVariants", "至少应有一个数据"
  12.     End If
  13.     NewVariants = Vars
  14. End Function

  15. Public Function NewVariantsInLength(ByVal Length As Long, ParamArray Values() As Variant) As Variant()
  16.     Dim Vars() As Variant, Value As Variant, lNow As Long
  17.     ReDim Vars(0)
  18.     For Each Value In Values
  19.         Vars(UBound(Vars)) = Value
  20.         ReDim Preserve Vars(UBound(Vars) + 1)
  21.     Next
  22.     If UBound(Vars) <> 0 Then
  23.         lNow = UBound(Vars) - LBound(Vars) + 1
  24.         Select Case lNow
  25.             Case Is = Length
  26.                 ''Already Exists, Do Nothing
  27.             Case Is > Length
  28.                 Err.Raise -2147221323, "Nutix.X_Array.NewVariantsInLength", "太多数据"
  29.             Case Is < Length
  30.                 ReDim Preserve Vars(Length)
  31.         End Select
  32.     End If
  33.     NewVariantsInLength = Vars
  34. End Function
复制代码
看下面场景:
  1. Public Sub AAA()
  2.     BBB Split("good hello smile")
  3. End Sub

  4. Public Sub BBB(Values() As String)
  5.     Dim Value
  6.     For Each Value In Values
  7.         Debug.Print Value
  8.     Next
  9. End Sub
复制代码
报错如图

如果有上面的API,就可以这样调用,BBB NewStrings("good","hello","smile")
C:\Users\nutix\Desktop\捕获.png

捕获.PNG (12.32 KB, 下载次数: 0)

捕获.PNG

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多