VB速查大全(数据库、表格及报表编程) ★ VB错误处理,ado常见错误,VB数据类型等,网上有很多教程是错的,强烈建议看此文

 ■ 学新的编程语言先仔细看该语言案例教程或从入门到精通的书。对具体语句、函数及可使用对象不了解或忘记的,可在该编程语言的“参考手册”中检索。 《如果资料为电子书时,即使不知道具体名称也能按需要的功能用关键字在手册中搜索,比如微软的MSDN中带有中/英文的索引,可以在索引/搜索页中查:如:报表report、API、分隔split、表grid/table、数组下标Array Bound、文件File、查找Find/Look/Seek、行Row列Col、左left右right中mid、顶Top底bottom 等就会显示出相关内容,当然也可以直接输入语句/函数/对象等查其用法。》


■ 多看案例,养成好的开发习惯
1、模块化开发(如读入/回写,查找、验证模块),在模块旁标注模块用途及用法,变量及重要语句后标注含义。常用值常量化(如读写的单元格位置用常量名)
2、【尽量使用局部变量和对象,因为过程嵌套调用时公用对象状态和值就无法控制,而且非局部变量调用时一般也是要赋初始值。】
3、循环或判断内的语句缩进,在结束语句标上结束哪个循环或判断。
4、过程与变量名尽量包含大写字母,这样在使用时容易看出是否书写错了名称。
5、作说明文件(主要流程,数据库结构等),统一对象/变量的命名规则(自己易记易懂)。
6、小心使用复合判断(复合判断是指含And or 等的判断),多数复合判断做成简单判断的嵌套更可靠。
7、保留模块头的Option Explicit声明,在发布软件前尽量不使用容错机制,正式发布时应使用容错机制(有些错可以忽略跳过比如:重复关闭对象或提交等无效操作)
8、程序中可以使用debug.print 在立即窗中输出表达式结果,debug不会被编译进exe。Vb调试时无错误的编译后的仍可能报错。
9、断点即执行该语句前中断程序,VB断点快捷键F9,断点或在出现错误时进入调试,都可以直接修改程序后继续运行,也可在立即窗中输入? rs!f等语句回车显示该语句结果,断点所在过程中的表达式鼠标停留即可查看当前值。
On error goto errs  '【仅在首次错误时跳转到过程,再次出错后本过程中的任何on error处理都无效(包括on error resume next)】
Errs:    '通用错误提示
If Err.Number <> 0 Then
   Dim cwts '错误提示
   cwts = Err.Description & vbCrLf & "错误代码:" & Err.Number
   If Err.Number <> -2147217887 And Err.Number <> -2147467259 Then cwts = cwts & vbCrLf & "引发错误部件:" & Err.Source
   MsgBox cwts
End If


On Error Resume Next   '错误时继续执行,▲可用于同一个过程中多次出现错误的处理,每次错误都会执行下一句,在判断语句行出错则视同该语句条件为真▲
if Err.Number<>0 then     '用在要判断是否有错误的行前
   if Err.number=10048 then 
msgbox  "端口占用"
   else
debug.print err.Number,err.Source,err.Description
   end if
   Err.number=0  '--------清除错误状态,以正确响应下次错误
   Err.Description = ""   '-------------清除错误描述(err.number=0不会清除err其他属性值,直到下一次出错时所有err属性值会被替换为新错误代码)●
else
   if winsock1.任意错误的属性=1 then
debug.print "本句会被执行"  ●
debug.print "本句会被执行"  
   else
debug.print "其他句不会被执行"
   end if
   debug.print err.number
endif
On Error GoTo errs   '在on error resume next多次偿试的错误后,仍可以使用其他错误处理结构,但在on error goto后的on error resume next无效●




■ 所有对象(含变量,方法,事件,控件,API;ActiveX dll/ocx等)都必须先注册再创建使用。
  ⊕系统及VB自带对象安装时已经注册,其他COM或ActiveX对象则必须用,win+R组合键在运行中运行命令 regsvr32 filename.dll(或ocx文件,/U卸载/s不返回成功否的提示框。) ,有些对象要用DLL自带函数注册,如sqliteodbc,注册运行命令(或批命令.bat文件)rundll32 sqlite3.dll,install (参数quiet表示无提示框, uninstall表示反注册)
 ⊕VB中静态创建:基本对象直接定义(Public|Private,Dim,Declare等),是部件的可直接拖放出来即可,扩展对象或ActiveX dll/ocx则要先在菜单中将“引用/部件”勾选,外部对象的定义dim object as classname,有些还要用set object=new classname或其自带的初始化方法进行初始化。
  ⊕VB中动态创建:先定义一个空对象,然后通过语句“如:Set Obj=CreateObject()/GetObject()”将创建并初始化后的对象装入空对象中。动态对象也有各自的堆栈和事件池等(要求该COM对象已注册)。 API函数声明必须用Declare可以在Declare前加Public。
  /*** 可用对象在Visual C/Basic...中的对象浏览器(Object Viewer)中可以查看。在"添加 引用/部件"的列表中找到并选中,在对象浏览器<所有支持库下拉列表>中的名称一般即是该对象名(有Lib等明显不是名称要素的后缀去掉)。  ★要响应Active对象的事件可以在定义对象的名称前加“withevents”关键字,这样就可以在对象下拉表中选中对象再在事件中选择相应事件。★  ***/




■VB运算符、变量、语句、函数、对象等基础 (注:VBS中只有一种变量类型即变体型,不可像VB这样定义类型)


+ 加(也是字符串拼接)
- 减(也是取负值)
*
/ 浮点数除
\ 整数除
Mod 取余数
^ 乘方
& 字符串拼接(A & B即表示AB),还有些特殊用法如&H...表示16进制数。
:       分隔两个语句,两个语句放同一行时。  也可以作为goto跳转的段落标识如Error:,段落必须放在过程中,所有段落都会被执行,因此要加以判断如:If Err.Number <> 0 Then End
_       下划线连接下一行,将一个长语句拆分为多行时用。
AddressOf 引用对象地址


< 小于
<= 小于等于
> 大于
>= 大于等于
= 等于  (【=号的两边是区分大小写的】,instr等查找比较时是可以设定是否区分大小写的,UCase函数将所有字母大写,LCase所有字母小写 )
<> 不等于
Like    字符比较(通配符"*"代表任意长度任意字符"?"任意一个字符"#"代表一个数字"!"表示非"-"在[]中表示范围。示例:"a[L-P]#[!c-e]"值ao3f则符合)
Is      两个对象比较,如果是同类对象则返回真
Eqv     数值同位比较,以二进制方式,逐位比较。


And 变量1 And 变量2 两个量均为True ,才返回True 
Or 变量1 Or 变量2 只要有一个量为True ,返回值就为True 
Xor 变量1 Xor 变量2 两个量一个为True,一个为False才返回True
Not 变量1 Not 变量2 简单地把True 变为False ,把False 变为True 


$ String 字符串
% Integer 整型-32,768 到 32,767 之间
& Long 长整型,计算精度高速度快, -2,147,483,648 到 2,147,483,647之间
@ Currency 定点精确计算(货币型),小数点左边15位,右边4位,计算精度高。  〖一般不使用 !Single型 #Double型,因为这两种变量精度不够,且相互赋值或运算时会出错,另外long=integer*integer如:x=300*200也会溢出,详见底部案例说明〗
Variant  '变体型,VB默认的通用类型,如果是数值且不含小数它会自动按整数处理;如果数值所含小数不多于4位它会按货币型处理;如果小数位大于4就按浮点数处理(也就是说小数大于4位且超过实际有效位数时用变体型和浮点型一样会产生误差)
Decimal  '整数连小数部分共28位有效数值,是VB能接受的最大数值范围,不能直接定义,只能用dim iDec as Variant:  iDec= CDec(0)来把变体实例化为Decimal型,之后iDec就是Decimal型了,用Cdec()定义时最好用比较小的整数如CDec(1)这样。
byte 字节型0-255,主要用于存储二进制内容。可以byte()="string"直接把文本存入字节数组,其他类型数组则不可以。
【未使用变量(含数组),数值类的默认值为0,非数值的(包括变体型)默认初始值为"",Boolean默认False】。
【a = "0001"  if CStr(Trim(Val(a))) = a then 'a是数值,可以避免编码如:0001当成数值。IsNumeric()可以判断0.00】
【VarType()用于判断数据类型如8204表示8192(数组)+12(变体型)即变体型数组,(类型值小于7一般是数值)。 就算变体型也不能直接赋值为整个数组、自定义型、对象型】


⊕dim a(9)或dim a$(9)或dim a(9) as Variant定义一维静态数组,其下标为0上标为9。上下标范围内的数组才可访问如:A(0)="xxx"。 
⊕dim a(9,9)定义10行10列的二维静态数组,用格式a(0,0)访问数组成员。
⊕dim VarName() as Variant  '空括号表示数组是上下标及维数可变的动态数组,Lbound取数组下标,ubound取数组上标,dim v() as byte 成员可变字节数组为特殊数组可以直接存放字节集或文本。 
⊕redim VarName(3 to 9)  清空动态数组成员,重定义上下标。【非动态数组不可redim,redim不能改变数组类型】【Preserve改变上标而不清空原数组内容,但用这个关键字时下标不可改变,多维数组的非最后一维也不可变】。
⊕如果A(1)=Barr,则Barr成为A(1)子数组,访问A(1)成员用格式A(1)(X) X是Barr数组的上下标范围。
⊕数组可以作为过程的返回值,格式为 Function returnArr(...) As Variant()。和定义数组时写法不一样,括号应在类型后且不能用简写。
⊕【判断VB数组为空不能用Ubound()或Lbound()会报错(err.Number=9,err.Description=下标越界),只能用if join(Arr,",")="" 来判断】
⊕只有同类型数组(不论上下标是否一样)才能用Aarr=Barr整组赋值,Aarr必须为动态数组,赋值后两个数组完全一样,即原数组上下标范围和内容都会被新数组代替。
⊕VB自带的collection对象有时比数组方便。首项为1,count属性为成员数量,add用于插入(设before或after参数,两个只能选一个。 key参数是用于替代index的别名只能是字符串。),remove index删除指定成员(指定成员被删除后index会自动重新从1连续排到count),成员只能x=c(i)读出而不能c(i)=x被赋值。


⊕Set obj=objx (将对象赋于对象变量,被New实例化的对象不能装入其他对象,即dim objectX as new object不能被set objectX=object) 
⊕load object/unload object 加载对象,或释放对象。
⊕if object.state=1 then object.close  适用于所有有close方法的对象,判断对象是否已经打开,如果打开就关闭。
⊕set obj = Nothing 完全清除对象
⊕【end 语句后不带任何参数,直接释放当前程序(含所有窗口),这个是真正的退出应用程序,程序不止一个窗体时很有用】
⊕Form.show 1  '带模式打开窗口(不可使用其他窗口),0为无模式窗口(其他窗口可正常用),Mdi窗体中不可以用带模式窗体(但mdi比较便于集中关闭窗口退出应用等操作),窗口关闭后show或visiable或使用窗体中的对象都会加载窗口触发Load事件。
⊕Command函数可以取本程序运行时的参数,比如命令行运行本程序 ok.exe /s,command返回"/s"


⊕【Format 函数可以用于定义或转换各种格式(如:"00000"可以将数值变为前置0的定长字符串,也可以用">"将英文全部转大写,详见VB MSDN)】
⊕len()字符个数,lenB字符字节数,instr查找字符左边首个为1(InstrRev从末尾向前查找),Replace替换count参数为-1时替换所有符合项,left取字符左边指定个数,Right取右边,Mid取中间指定个数字符。
⊕str转为字符型(会保留首位符号位,如正数则为空格,去前后空格用trim函数),Val转为数值(截取出数字直到碰到第一个非数字); 类型转换只能对具体单个变量,不能对整个数组(比如A为数组:str(a(1))可以,str(a)不可以),str("b")将出错。
⊕Ccur转为小数型,Clng转为长整型,Cdec变体转为精确小数型,Cvar...开头的转换函数仅限于转换符合最终格式的值【Cstr("b")不像str("b")会出错,但CSng("-1a")和Cdec("")将出错。  ∴转换类型用此类函数,但取数值用val()】
⊕Split分割字符返回数组(接收数组必须为字符型动态数组),Join把数组组合成字符串(判定数组为空时可以用 str=join(Array,",") 如果str=""则为空数组)
⊕Asc()函数可取字符的ASCII码,Chr函数则可将ASCII码还原成字符如:Chr(13) & Chr(10) 表示回车符加换行符。 StrConv()转码UniCode、Ansi及单双字节等转换。
⊕String()函数,string(10,"a")返回10个a。 string即是声明变量类型的关键字,也是函数。


⊕系统自带常量:Null无任何类型数据(不能用if xx=null判断,只能isnull(xx)判断) vbNullstring即""(用if xx=vbNullstring判断)  Empty可以表示0或""(用if xx=empty判断)    vbCrLf回车换行;  Nothing空对象(判断用is Nothing)。 使用Alt+→可以调出可用常量与系统对象,比如输入ad然后按组合键就会把ad开头(多数是ado常量)的常量列出来。


⊕【Static静态(再次执行Static语句也能保留变量值而不像Dim初始化变量)】、Private私有、Public公开、ByVal传值、ByRef传址(即直接引用该地址的对象) 、sub无返回值的过程、 Function可返回值的过程、 As([new] 过程作用的对象或返回值)、 Dim声明变量或对象、 Declare声明API、 Event定义事件(RaisEvent触发)、 Property <set/let/get>属性定义、赋值等过程、Type语句自定义变量结构、New关键字将外部对象实例化(外部对象必须实例化后使用,部件在被拖到窗口时即已经实例化,VB内部对象本身已经实例化所以不能NEW),【withevents声明对象带事件】,【自定义函数:Optional关键字使参数可省略并设默认值、ParamArray声明数组参数能接收的参数个数不限(只能用在最后一个参数上)、Enum在模块中定义枚举(用作参数的备选项,在调用函数时使用自定义枚举的参数可以使用该枚举,也可以使用其他值)】、Const定义常数(常数默认为其所赋值的类型而不是Variant,使用常数以后修改程序只要改常数值就可以修改所有用到该值的语句)


⊕【If..then..elseif..elseif..else..endif】●、 Do..while/until..loop、 For..to..next、For Each..in..next(遍历集合中的元素)、 Select case 表达式/对象 case..case else..end select(不支持Like比较,不支持case is >0.5 <1这样的区间范围,【Case对大小写敏感,为了使用Like和区间范围select case true后支持case a like [0-9]这样的表述】)、 Exit sub/do/for/Function(跳出)、GoSub(跳转到其他过程)、open(打开文件)。。。On Error goto/Resume Next/Exit ... (VB容错机制,Err.Number返回错误代码。)、 IIf(expression,,) 根据表达式逻辑值,返回两个参数中的一个、Choose(expression,,,...) 根据表达式整数值,返回多个参数中的对应位置的那个。


⊕模块中的函数可以直接调用且允许public declare等公开声明而类模块不允许,但类模块允许withevents的对象(调用类模块dim c as new class1:c.func()),CreateObject("工程名(不是文件名).类模块名")可以创建独立线程的类模拟多线程效果(只有在Active EXE的工程属性中选右下角的“每个对象对应一个线程”,并编译后运行才有多线程效果)


⊕“工具--菜单编辑器”--可以调出菜单编辑器制作菜单,然后可以用PopUpMenu函数在窗体中任意位置弹出菜单。


⊕在过程中常用对象可以用 with 常用对象名...end with 这样的结构,结构中该常用对象直接用 . 表示。如:with form1 后  .text1.text=""等效于form1.text1.text="",这样便于批量修改代码。


⊕VB实现拖放功能,设窗体或PictureBox等要接收拖放对象的 OLEDropMode=1 ,在OLEDragDrop事件中的Data.files(index)集合即被拖放入的文件名集合。


⊕“编辑”工具栏中的“设置注释块”“解除注释块”,可以快速在选中语句首自动添加/去除注释标记。 书签可以快速跳转到书签行(关闭即清空书签)。


⊕VB6动态创建控件,1、先把控件的Index设为0(只能在设计窗口的属性中设,在运行时为只读,设为0后事件中也会出现Index参数用于接收是哪个成员返回的事件,ubound同样可以取对象数组的上标)2、运行时load object(Index)即可创建,Index不可为已经存在的,使用时object(index).方法/属性。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


⊕Form和TextBox的BorderStyle属性在运行时是只读属性,只能使用Windows API 去修改一个Window的样式了,PictureBox等无hwnd的BorderStyle是可以在代码中设置的。


⊕有些属性在属性页是不可见的如:hwnd(对象句柄handle的一种)、Parent...这些只能些只能在对象浏览器中看,或见msdn语言参考手册等。
⊕X:\Microsoft Visual Studio\Common\Tools\Winapi 安装VB等VS Studio中的开发工具后,该目录中即有windows的常用API。


⊕“格式”菜单--顺序--移到顶层Ctrl+J、移到底层Ctrl+K,也可在“窗体编辑器”快捷工具条上点选(位置在控件对齐方式旁边)。
/*** 决定哪个控件显示在最顶端,也可在程序中使用Zorder方法设置,但注意后方置控件不可完全被放置在一个容器控件中(变成类似于子控件,这样就不可能把父控件置于子控件前)***/


⊕“外接程序”--外接程序管理器(加载/卸载外接功能,使其在菜单中出现/不出现),含VB6 ActiveX控件接口向导、VB6 资源编辑器(加载后在工具菜单下)、打包和展开向导等外置工具。




条件编译或选择编译,可以用于一个软件有不同版本,这时只要一个版本常量设定,就可以编译出不同版本软件
#Const OSVer= "WIN95"   '(or WIN98 or WINXP)
#If OSVer = "WIN95" Then 
'WIN95 Code here     '只有常量=win95,才编译
#ElseIf OSVer = "WIN98" Then 
'WIN98 Code here 
#ElseIF OSVer = "WINXP" Then 
'WINXP Code here 
#Else 
'Non-specific OS here 
#End If




VB常用内部可引用对象
  App.Path      返回程序所在路径(返回的路径最后是不带"\"的,后面要加文件名时必须自行加上)  用法例:app.path & "\..\data"  (返回程序上级目录下的data) 
  App.EXEName   可执行文件名
  App.LegalCopyright  版权信息
  App.hInstance   返回应用程序实例的句柄
  App.PrevInstance 【提示是否已经有个本程序在运行,如果已经存在返回true。可用于禁止程序重复运行。】
  ......


用Environ函数获取环境变量值 
Environ ("Windir") ' Windows目录


Environ ("ProgramFiles") 'ProgramFiles目录


Environ ("UserProfile") 'Administrator目录


Environ ("ALLUSERSPROFILE") '所有用户目录


Environ ("APPDATA") '系统默认应用程序存储数据的位置


【Environ ("COMPUTERNAME") '返回计算机的名称】


Environ ("COMSPEC") '命令行解释器可执行程序的准确路径


Environ ("HOMEDRIVE") '连接到用户主目录的本地工作站驱动器号。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。


Environ ("HOMEPATH") '返回用户主目录的完整路径。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。


Environ ("NUMBER_OF_PROCESSORS") '指定安装在计算机上的处理器的数目。


Environ ("OS") '返回操作系统的名称。Windows 2000或win7 都显示为 Windows_NT


Environ ("PATH") '指定可执行文件的搜索路径。 


Environ ("PATHEXT") '返回操作系统认为可执行的文件扩展名的列表


Environ ("PROCESSOR_ARCHITECTURE") '返回处理器的芯片体系结构。值: x86,IA64


Environ ("PROCESSOR_LEVEL") '计算机上处理器的型号


Environ ("PROCESSOR_LEVEL") '处理器的版本号


Environ ("SYSTEMDRIVE") '返回包含 Windows XP 根目录(即系统根目录)的驱动器。


Environ ("SYSTEMROOT") '返回 Windows XP 根目录的位置


Environ ("TEMP")  '返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP,而其它应用程序则需要 TMP


Environ ("USERDOMAIN") '返回包含用户帐户的域的名称。


Environ ("USERNAME") '返回当前登录的用户的名称。


  ME.  窗体本身
  ......
  Screen.MousePointer 屏幕鼠标形状
  Screen.Forms.Count  已打开窗口数量
  ......
  Printer.  打印机对象  (可通过printers打印机集合对象来设置当前打印机。)
  打印机对象与picturebox对象比较类似,也可以使用DrawText、Bitblt等用于设备场景的API。




■常用模块
  部件
  Microsoft Windows Common Controls-...     '工具条、多页夹、状态栏、进度条、树型框等
  Microsoft Common  Dialog Controls  'commondialog通用对话框,用于打开/保存文件,调用字体调色板等对话框(filename返回的是全路径)。 filter(提示|过滤,如:数据库*.*db|*.*db|全部|*.*) InitDir(默认路径) ShowOpen(打开文件)  FileName(被选中的文件名含全路径),也可以用默认的driveListBox、dirListBox、fileListBox操作(这三个列表框可以按列普通表框操作,但建议用特有属性drive、path、filename注意filename返回的是不带路径的path返回的是不带最后"\"的)
  Microsoft Tabbed dialog  controls  6 'sstab控件,替代多页夹
  Microsoft Rich Textbox control 6.0
  Microsoft Hierarchical FlexGrid Control 6.0...    '能绑定ADODB和ADODC与数据环境的表格
 Microsoft Comm Control                '串口通讯控件
 Microsoft Winsock Control 6.0        '网络编程接口
  引用
 Microsoft ActiveX Data objects 2.8 Library     'ADODB  
 Microsoft ADO Exr. 2.8 for DDl and .....      'ADO扩展
 设计器
  Data Environment 'ADO集成数据环境设计器(可直接拖放等,详见例程大全中datareport及ADO相关)
  Data Report      'VB自带报表(功能较一般,注脚没办法放余额等,明细部分不能放统计框。)
  '常用的ActiveX 引用/部件多数是以“Microsoft ”开头的,如Microsoft DataList Controls 6.0...即datalist控件
'自定义的通用的模块放一个文件里,如VB的comm.bas
'某类软件的开发可以做一个空的框架,把模块和要用的对象先配置好。






■、开发经验


    一、编程时要注意变量值可能被过程更改而不是出于设计的本意,这时要注意两点,以VB为例:1、过程声明使用Static使过程中局部变量值被保留而不会在每次调用该过程时被刷新为初始值。 (易语言局部变量勾选静态) 2、过程参数为数值或字符的应设为ByVal(传值)限定,VB默认的ByRef(传址)适用于参数为某类对象。即:传址时如果过程中更新参数值则会直接对该变量地址操作,导致调用该过程语句所提供的变量参数值被更改。3、大量循环不要频繁取对象值for i=1 to text1.text应该x=text1.text后再for i=1 to x。


  二、VB调用过程需要用到返回值时,才必须带(),否则不可带括号。


  三、dim a,b as string是将a定义为变体型,B定义为字符型。快速定义可用dim a$($表定义为字符,% integer,& long,@ Curreny)。 而VB中用#1999-01-01#表时间值,&Hxxx&表示16进制值,&Oxxx&表示8进制值。


  四、null(如读出数据库字段值为空时)赋给字符串等变量会出错,解决方法有二个,一个是用isnull()函数判断值是否为空,另一种是直接用string="" & rs(n).value,这样如果原值是null就会得到""。


  五、常用技巧
1、解决VB自带四舍五入函数不能用问题, round()不像Excel中的可以用"负号",且round(6.5)=6,round(7.5)=8的偶数原则。**************************
Public Function roundX(Num#, Optional Rx% = 0)   '自定义四舍五入函数
Num = Num / (1 / 10 ^ Rx)
Num = Format(Num, "0")
Num = Num * (1 / 10 ^ Rx)
roundX = Num
End Function
'附注:fix(-9.9)=-9对负数取整时会直接去掉小数,VB和excel中的取整Int(-9.1)=-10。
---------------------------------------------------------------------------------
2、菜单标题或按钮标题末尾加 &x 可定义相应快捷访问键。这样就可用ALT_X键访问了。 


 Label标签对象backstyle属性设为0,则背景透明,但其所框起的范围仍然响应click、dbclick等事件,可以作为自构形按钮等使用。   


VB定义快捷键几种方式:
1、设Form.KeyPreview = True '表单优先响应按键,然后keydown中if keycode=17 then ctrlPress=true '即ctrl按下, keyup事件中if keycode=17 then ctrlPress=false即放开ctrl键,最后在keypress中if KeyAsci=10 and ctrlPress then msgbox "ctrl+回车"。 也可以直接用keydown中的keycode=13 and shift=2也相当于ctrl+回车。 (keydown/keyup中keycode=16对应按下/放开shift、17ctrl、18Alt,shift=1对应shift按住、2ctrl按住、4Alt按住)  (keypress中keyascii=13回车、10ctrl+回车、27ESC,但注意没有ALT或Shift+回车对应值)  【注意:ALt/Shift/Ctrl按住时的tab键(如:sendkey "{TAB}")不会将焦点移到下一控件,只能用object.setfocus()等方法手动将焦点移到下一控件】
2、菜单中设置菜单快捷键。 3、定义操作系统全局快捷键需要用API。 
---------------------------------------------------------------------------------


3、For...nex循环的step不为整数的时候一定要注意i应为single。For i=1 to 1执行一次,For i=1 to 0不执行,For i=1 to 0 step -1执行两次,for i=1 to 1 step -1执行一次。


vba 没有控件组,可以用 枚举 
Dim c As Control
For Each c In Me.Controls
   If TypeName(c) = "TextBox" Then  'typename取除自定义类型外的所有变量或对象类型,返回字符串如:string、integer、picture
      c.Text = "..."
   End If
Next


---------------------------------------------------------------------------------
4、在窗体上回车自动将控件焦点移到下个控件上,先将窗体的Keypreview属性设为true,再
   Private Sub Form_KeyPress(KeyAscii As Integer)
   If KeyAscii = 13 Then KeyAscii = 0: SendKeys "{TAB}"
   End Sub
5、最简化的状态切换,(仅限两种状态间切换)
       Static b As Boolean
       b = Not (b)  '求反
       If b Then ...
---------------------------------------------------------------------------------
6、VB日期相关操作:
取当前月份天数
day(DateAdd("D", -1, DateAdd("M", 1, Format(sDateVal, "YYYY-MM-" & "01"))))
说明
now  函数返回当前系统日期+时间 time返回时间 date返回日期
datevalue或cdate可以把字符转为日期型
dateadd() 返回指定日期加上一定时间后的日期
datediff()   返回两个日期间的时间差,可以返回日差或月差等
DateSerial   返回该年所剩的天数
"yyyy-mm-dd hh:nn:ss" 日期时间的表示完整格式,用于Format函数中,单个字母则用在时间操作中。


Public Function c2d$(Dstr$)  '将字符串转为日期,字符串必须符合中国日期顺序如:2015815,年份必须为四位
   Select Case Len(Dstr)
      Case 5
         c2d = Format(Dstr, "####-#")
      Case 6
         c2d = Format(Dstr, "####-##")
      Case 7
         If Val(Mid(Dstr, 5, 2)) < 13 Then
            c2d = Format(Dstr, "####-##-#")
         Else
            c2d = Format(Dstr, "####-#-##")
         End If
      Case 8
         c2d = Format(Dstr, "####-##-##")
   End Select
End Function
---------------------------------------------------------------------------------
7、'shell函数可以执行外部可执行文件(如exe,bat等)
Dim port As Long
port = 445
shell "cmd /c netstat -na|find /c " & Chr(34) & ":" & CStr(port) & Chr(34) & "  >d:\ret.txt",vbHide   '查端口是否被占用,无占用返回0到ret.txt
'原DOS命令是:cmd /c netstat -na|find /c ":445"  >d:\ret.txt  chr(34)是“双引号”  vbhide是不显示执行的dos窗  任何有>或>>dos符的都要在cmd环境中
'if  shell ("explorer 目录路径",1)=0    then msgbox "成功用浏览窗打开指定文件夹"
'shell函数使用Dos内部命令,如copy,必须 shell "cmd /c copy a b"。因为cmd加载dos环境后才能用DOS内部命令,如果使用Xcopy这样的外部命令则不用cmd /c。


'用默认程序打开文件则要用API 
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
 ShellExecute Me.hwnd, "open", "要打开的文件", "可执行程序(否则为Null)", vbNull, 3                 '用默认程序打开文件
 ShellExecute vbNull, "open", "http://www.ok510.com", vbNull, vbNull, SW_SHOWNORMAL   '用默认浏览器打开网址SW_SHOWNORMAL=1,网址必须为http://开头(Shell "explorer.exe http://www.ok510.com" 可以用IE打开网址,但如果有杀软等控制,则会被改为默认浏览器打开 )
---------------------------------------------------------------------------------
8、把注册表当作软件“系统设置”的数据库,可以用 SaveSetting  和 GetSetting()  函数
---------------------------------------------------------------------------------
9、 取得指定范围内“不重复”的随机数序列(随机遍历)   
 '返回指定范围内不重复的随机数集合  ,stepV为步长                                       ****************** 功能函数一:取不重复随机数序列 ************
Public Function rndC(Optional startV = 0, Optional endV = 9, Optional stepV = 1) As Collection
    Dim iCol As New Collection  '定义一个可以加减元素的集合对象
    Dim i, index&  '这里i为变体型,用于step为非整数的循环,速度会比整数略慢!
    Dim Nums
    Randomize  '初始化随机数种子,无参数默认以当前时间为参数
    For i = startV To endV Step stepV   '将要指定的范围加入集合对象中
        iCol.Add i
    Next    
    For i = 1 To iCol.Count   '随机产生一个整数index,输出指定index并删除该index项
      If iCol.Count = 1 Then  '只有一项时就不要随机了
        Nums = iCol.Item(1)
        rndC.Add Nums
        iCol.Remove 1
      Else
        index = CInt(Rnd * (iCol.Count - 1)) + 1     'round(Rnd * (最大上限值- 最低下限值),小数位数) + 最低下限值  ,产生min-max(含最大最小本身)的随机数
        Nums = iCol.Item(index)
        rndC.Add Nums
        iCol.Remove index
      End If
    Next
    Set iCol = Nothing
End Function
'把总额按指定的小数位数和范围随机拆分,个数不定,返回上下标1-N数组。  如果Join(返回数组,",")=""则拆分失败           ********** 功能函数二 ************
Public Function RndCF(TotalV, DecimalN%, basicMin, basicMax, Optional Least = "min", Optional Most = "max") As Variant()
If Least = "min" Then Least = basicMin
If Most = "max" Then Most = basicMax
If Most < Least Or basicMin > TotalV Or basicMax > TotalV Or basicMax < basicMin Or Most < basicMax Or Least > basicMin Then Exit Function
If DecimalN > 4 Then  '小数多于四位,将变体设为精确小数型
  basicMin = CDec(basicMin)
  basicMax = CDec(basicMax)
  Least = CDec(Least)
  Most = CDec(Most)
  TotalV = CDec(TotalV)
End If
Randomize
Dim jxcf As Boolean, TryTime%, IiI& '继续拆分,偿试次数
jxcf = True
Dim CIndex&, Jrnd As New Collection, temV, temSum, viodC As New Collection  '随机数,临时变量,临时合计和临时集合


For IiI = 1 To 10
If jxcf = False Then Exit For
temV = CDec(0)
temSum = CDec(0)
'Set temC = viodC '将空集合赋给temC以清空它的方法是无效的,所以只能先set c=noting再dim 才能清
Dim temC As New Collection
Debug.Print "清空后temc.count" & temC.Count & "  viodc.count" & viodC.Count
TryTime = TryTime + 1


Do While jxcf
   temV = RoundX(Rnd * (basicMax - basicMin) + basicMin, DecimalN)    '__________********必须配合自定义roundX函数使用********__________
   If temSum + temV <= TotalV Then  '如果本次与之前累加后不超过总额
      temC.Add temV
      temSum = temSum + temV
      If temSum = TotalV Then jxcf = False
   Else  '累加超过总额
      temV = TotalV - temSum  '超过总额了,就把余值作为最后一次值
      If temV >= Least And temV <= Most Then '剩余值如果不低于最小约定且不大于最大约定 , 将剩余值作为最后一次值
         temC.Add temV
         jxcf = False '退出拆分
      Else  '剩余值不足最低约定  ,将剩余值随机并入前值(并入后不超过最大限制)
         Set Jrnd = RndC(1, temC.Count)     '__________********必须配合自定义Rndc取不重复随机序列函数使用********________
         For CIndex = 1 To Jrnd.Count
             If temC(Jrnd(CIndex)) + temV <= Most Then
                temC.Add temC(Jrnd(CIndex)) + temV
                temC.Remove Jrnd(CIndex)
                jxcf = False
                Exit For
             End If
         Next CIndex
      End If   '处理最后剩余值结束
      If jxcf = True Then Set temC = Nothing
      Exit Do
   End If
Loop


Next IiI '如果已经取得正确值就不循环
Debug.Print "偿试次数:" & TryTime


If  jxcf = False Then  '分拆完成,偿试10次内得到正确值,将集合写入数组并返回
  Dim Temp()
  ReDim Temp(1 To temC.Count)
  For IiI = 1 To temC.Count
     Temp(IiI) = CDec(temC.Item(IiI))
  Next IiI
  RndCF = Temp
End If
End Function
---------------------------------------------------------------------------------
10、大量的运算或需要刷新调用DoEvents()方法,可以响应外部事件,以便继续运行后面程序。
'示例:等待几秒后继续运行后面程序,等待过程可以用timer控件或dateadd函数,要精确的可用API计步空循环,循环中必须DoEvents,否则程序假死。
Public Sub Delay(DelayTime As Single) '参数等待时间单位为秒,可以有小数点。
    Dim BeginTime, EndTime, acrossDays&, acrossed As Boolean
    BeginTime = Timer
    EndTime = BeginTime + DelayTime    'Timer是VB本身的函数,取0点到当前经过的秒数,精度到1%秒。
       While Timer + (86400 * acrossDays) < EndTime
            If Timer - BeginTime < -0.01 And acrossed = False Then    '跨0点timer从0开始,所以跨越天数+1
               acrossDays = acrossDays + 1     
               acrossed = True
            Else
                If Timer - BeginTime >= 0 Then acrossed = False
            End If
            DoEvents
       Wend
End Sub
---------------------------------------------------------------------------------
11、窗体的Active、DeActive、GotFocus、LostFocus事件只在APP自身窗口间切换时有效,外部窗口和程序中的窗口切换无效。
---------------------------------------------------------------------------------
12、数组排序,SortArr 要排序的数组,Ascending是否按升序排列,调用本过程后作参数的数组就已经排序好了。
Sub SortArr(ByRef Arr(), Optional Ascending As Boolean = True)
  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值