vba编程基础1

  1. 在主要的编程语言中, 结构体是用大括号来表示 代码段的 范围 界定的. 但是在一些比较"老的"语言中,由于历史原因, 还是使用的 是: 关键字来进行界定代码 的 结构段, 如vba中的 语法结构:

    • if .. . then ... end if, if .... then ... else ... end if; if .... then .... elseif .... then .... elseif .... then.... end if
    • for i=1 to 10 ... exit for.... next i
    • while ..... wend
  2. 面向对象的编程 思想中 对象要与具体的/实际的操作者 相"绑定" ?

    • 作为一个类, 实例化一个类的对象时, 默认是"没有任何 指定性 意义的" , 举个例子, 比如 开一张银行卡, 它是一个对象, 但是如果这张银行卡, 没有跟任何人实际相关联, 其实它就是一张废卡. 你只有将这张卡跟 某个人相关联, 作为 某个人的银行卡了, 这时候这个对象的意义 才变得重要起来了, 卡主会给这张银行卡 设定密码, 存钱, 取钱等等操作. 也就是说, 一个对象要跟具体的 文件/数据/操作者相 关联, 那么这个时候, 对这个对象的操作/方法/成员函数, 才会/就会 作用到具体的 实物上. 才会使对象编程有实际意义和实际效果. 比如,你创建了一个 文件类 CFile file ,那么要让这个file对象 跟实际的某个文件如: E:/MyApp/myfile.txt 相关联, 那么这个时候, 对file的操作, 如open, read, write, close等操作就是对 myfile.txt 的操作了.
    • 而让类对象 跟 实际操作对象 相关联的方法, 就是 在初始化/创建 一个 类对象的时候, 传入操作对象作为参数Person p('theName', AGE) , 或者是使用类提供的方法 来建立关联,如 file.open('E:/MyApp/myfile.txt', 'a') 打开文件, 追加写内容...

  1. excel工作表和vba代码的关系: 在vba(ide界面)中, 执行代码(全局性的Sub foo() 过程:子程序), 执行的结果/输出/作用对象, 正是/就是与之关联的工作表.

1.excel本身内置了"内部预定义变量", 如:Worksheets, 表示所有工作表的集合

  1. 整数类型根据范围 ,可以为byte(0-255), long型等. 工作表 的变量类型是:
    worksheet.

  2. vba 中的字符串连接 用 &, 语句结束用 "自然的" 回车enter表示, 即一行表示一条语句,末尾不用分号

  3. vba支持中文过程名或函数名.所以你的 过程/函数/模块/类名等, 可以用中文来表示...

sub 工作表改名()
dim i as byte, sh as worksheet
i=0
for each sh in worksheets
   i=i+1
   sh.Name= chr(64+i)&"工作表"'
next sh

end sub
  1. vba中的iif: iif(exp, truepart, falsepart),实际上就是 c语言中的 ?: 三元运算符.
    注意的是, iif always evaluates both truepart and falsepart, even though it only returns one of them

  2. 数字和字母的AScii的相互关系

数字共26个字母, 数字从1,到26, 大写字母从A - Z, 小写字母从a -z,
分别是对应数字加 64或96, 正好是 32的2倍和3倍. 所以大写字母是 从 65~ 90,
小写字母是从 97 ~ 26+96=122.

vba中数字和字母字符的相互转化的函数: chr(num+64)或 chr(num+96). 字母->数字 :
code(char).

  1. 字符提取函数:
    left(text, num_char); mid(text, start, length); right(text,num_char)

  2. column()函数表示光标所在列 的地址引用, 如A1, 同理row().

  3. 注意工作表/公式中的函数, 和vba中的函数可能是不一样的! char是工作表函数, chr是vba中的函数.这两种不能换用!

  4. 单元格的地址引用, 可以为: 相对引用A1, 绝对引用R1C1(注意是行在前列在后),混合引用, 还可以使用R[-2], R,C等形式.
    单元格的引用, 更多参考: http://www.cnblogs.com/jaxu/archive/2009/05/04/1448947.html

  5. "井号name!"表示函数名称错误, "井号value!" 表示数值/数字错误. 利用公式的"求值"计算步骤可以看到一步一步的计算过程.


  1. vba的数组,语法是用小括号,而不是像c语言那样用中括号,如worksheets(1).name="工作表1"

  2. vba中有input函数 ,那是对文件的写入字符操作,类似的有read操作.
    跟c语言中的字符读写类似. 如果是输入框的话, 应该是 inputbox函数.

  3. 声明变量的四种方式:
    dim varname as type
    public varname as type: 公共变量, 多个模块都可以使用的
    private varname as type: 当前模块/过程中可以使用的变量, 跟dim var as type基本相同
    static var as type: 在整个工程级/工作簿中都有效, 只有当工作簿关闭才会消失

:::: 当用public, private ,static 来声明变量的时候, 就不要用dim了.


  1. vba是一种面向函数的语言, 任何变量, 你可以在函数/过程外部定义, 但是你不能在
    过程/函数外部进行赋值, 否则回报"编译错误: 无效的外部过程" 也就是说, 你要在 过程内部进行 变量的赋值.
    然后, 你要在另一个过程 引用这个变量的值时, 要首先 要么首先执行 "给变量赋值的那个过程", 要么在另一个过程中 调用先前赋值的那个过程! 否则无效.

  2. 三级关联列表 使用select case... case 1(表示是省, 2,表示市, 3表示县). end select.
    使用的是字典的数据结构.

  3. vba的调试, 没有 "开始调试"的按钮, 直接 按f8就可以单步调试了, 也可以按 ctrl +f8 运行到 当前光标所在处....

  4. exit sub: 可以在sub中, 使用表示直接 退出 sub 不再运行代码了. 相当于c语言中的return语句..


如何清除vim中高亮的字符串? 可以使用设置: set nohlsearch. 但是这个不是很方便, 以后再次进入 vim/gvim的时候, 该词又会高亮显示, 一个比较好的方法是: 再次搜索一个 "根本就不存在"的字符串,就好了, 那么 , 以后 你所困扰的那个高亮的字符串 就再也不会出现高亮了..... 此法甚好, 方便简单直接....


  1. for 循环结构,中间要用循环变量,不能直接就是 for 1 to 10, 而应该是for i=1
    to 10 , 因为后面要用 next i来说明循环变量.

  2. excel与外部数据库的交互,可以通过dao或 ado来交换. DAO是: data access object; ADO: activex data object

  3. excel中的按钮和控件等,可以分为窗体的按钮控件等, 和 activex控件两种. 窗体的控件主要是用来指定 运行"宏"的(宏就是过程). 任意工作表都可以使用;
    而activex控件是属于 某一个 工作表的私有的. 双击activex控件可以跳到代码编辑处, 而双击窗体控件是没有反应的.

  4. "模块"中的内容是所有工作表都可以使用的, 公用的. 而某一个工作表中的 内容对象是只供具体的某一个表来使用的.


  1. 函数和过程都可以使用, 通常来说, 如果是给变量赋值的, 就要使用函数,
    就一定要加括号. 如果不赋值的话, 就使用过程, 就不能加括号, 如果要加括号,就要使用call关键字.

  2. 冒号等号 ":=" 主要是用在 过程中参数的调用时,可以不按参数的默认顺序书写: 如:
    msgbox title:="Please Confirm" prompt:="Be certain to close?"

  3. 数组声明: dim a(), b() 数组的使用: 把数组名就作为一个普通变量来使用了: a=array(1,2,3) a=array('jack','tome') 等'

数组的声明/赋值, 一定要使用 array, 而 数组元素的引用, 要用 a(0), a(1).. 下标从0开始.

a = Array(1, 2, 3)
dt = Now()
MsgBox "today is: " & dt
MsgBox a(0) &":" & a(1) & ":" & a(2)

date()只能取到日期, now()可以取到日期和时间.

调试的几个按键都跟F8相关

F8: 逐语句
shift+F8: 逐过程
ctrl+shift+F8: 跳出过程
ctrl+F8: 运行到光标处

要注意的是, datedif是工作表 公式函数, 不能在 vba编程中使用. 注意区分: 有的函数是vb函数,可以直接调用,而有些是excel函数,不能直接用

indirect函数: 他的参数应该是一个单元格的地址, 如a1, 或者"a1". 所以如果不是单元格的地址形式的话, 就会报错: #ref! 表示参数地址引用错误. 第一,  如果参数用 引号, 则表示 引用指定单元格中的 值. 如果参数没有用引号, 则表示 引用 参数a1中的表示单元格如b2单元格中的内容.., 实际上, 是 引用了两次, 所以叫 间接引用.


choose函数和if 的区别

choose和if函数类似, 都是根据第一个参数给出的条件, 在后面的系列值中取一个值出来.

  1. if函数, 只能有两个值, 而choose可以有多个值 , 是一个系列.
  2. if中的候选值, 只能是单个的值, 如果他的值是一个范围, 会报#value! 错误: =IF(FALSE,A9,A10:A12)
    而choose的 系列值中的 每一个 值, 可以是一个 单元格单元格范围, 这样可以用来进行sum求和计算.
  3. 但是, 单元格中,不能直接返回由choose指定的单元格范围, 那样会显示 #value! 错误. 但是可以使用sum统计函数等, 如 =SUM(CHOOSE(3.6,A9,A10:A12,A9:A10, A12))

在excel中, 过程sub和函数 还是有明确的区别的. 他们采用的 关键字都不一样, 过程用sub, 函数用function. 在excel工作表工作表中只能用 函数 , 不能使用sub

为什么函数的定义 一定要使用 函数名如total = 计算公式... 这样做就是为了避免 在 单元格中, 使用公式的时候, 引起 循环引用! 即, 在引用函数的时候, 就表示 这个单元格的值就是 由 函数名 代替 返回的值.

所谓, 循环公式引用, 就是你所在的单元格 如: A1中, 输入公式, 而公式中又包含 了对A1 的引用. 这个就是 循环引用:本来你是要求 a1的值, 结果a1的值没有求出来, 你又在公式中使用/引用它. 通过 公式 审核 -> 错误检查 就能 查出循环引用.
而要避免循环, 就可以 使用过程, sub, 因为sub 不需要返回值, 直接在 sub中 就 计算结果了. 但是 sub的话, 就不能 使用在公式中 不能使用等号了, 而是直接执行 宏...


关于cells的参数引用

  1. cells的参数 是两个! 因为有s复数? 两个参数分别是: row_index, columnIndex.
  2. 在vba中, 凡是 "字符组合", 如果你不用引号括起来, 就被解释为/认为是: 一个变量, 而这个变量没有被定义时, 就会报错, 所以, 如果你要表示 "列号"的话, 凡是你没有定义为 变量的 "字符序列" 都要用双引号 括起来表示 字符串!
  3. 比如在cells中要表示A2单元格, 你可以 cells(2, 1), 或 cells(2, "A")
  4. 只有cells 属性, 没有 cell属性!

worksheets是一个集合/数组, 其中 worksheets(index/worksheets.count) 和 worksheets("工作表的标签,如worksheet1") 返回的是 worksheet对象. 他的属性有: visible =true/false. 以及 activate.等. 参考: http://www.feiesoft.com/vba/excel/xlobjSheets.htm, http://www.feiesoft.com/

cells其实是一个 属性 , 是一个 application/工作表/工作区对象的属性. 格式为 : [object]Expression. cells . 如果不指定 expression: 使用本属性时,如果不指定对象识别符,则本属性将返回代表 活动工作表中所有单元格的 Range对像

使用with, 就是对同一个对象 引用它的 多个属性进行操作的时候, 最常见的是 对单元格字体的设置: with worksheets(1). cells(1,2) .font .name="arial" .size=14 end with

默认的一个对象是 Application, 其中很多都是 application 的属性, 如 worksheets, sheets等. 这个 application对象通常会 省略.. 比如 cells 属性的对象是application, 那么可以直接使用 cells属性...而直接使用 属性, 这些 属性 返回的 可能是 对象... 注意 在 vba中, 数组也叫做 "集合". 数组 ===== 集合.... 使用方法是用 圆括号 表示..

但是要注意 很多 属性 返回的 就是 对象 , 如 返回 Range对象 .... 对vba对象 的 操作, 可以使用 属性和方法. 而且 对象的方法, 在使用时, 是不必加括号的. 这个跟c/c++ 就有些区别了!

对vba对象 的 操作, 可以使用 属性和方法. 而且 对象的方法, 在使用时, 是不必加括号的. 这个跟c/c++ 就有些区别了! 比如: worksheets(1). select. 使用对象和属性, 可以采用 "见名知义"等...更重要的是, 在vba的编辑器中, 当你 输入点号的时候, 会自动弹出 提示 该对象的方法和属性!!!


range中 如何表示 可变的单元格? 使用 range("c"& row) 因为range的参数是一个 字符串, 只要给他一个字符串 就可以符合 要求, 字符串就可以用 引号加& 加 变量的方式!

杂项

  1. 如果使用的是application的属性, 则这个 application可以不写 . sub 子过程 + function函数 统称 为 "过程"!!!

  2. 通常来说, vba中的函数(库 ) 跟工作表中的 函数(库) 是两套 独立的 , 有时不能互用. 所以 ,如果你确实 要在 vba中 使用 工作表中 的函数, 那么就用 : application.worksheetFunction. 工作表函数(....) 的方式 来引用.

  3. 变量/属性/对象的默认 属性是 value, 所以 cells(1,1).value = cells(1,1) 不过 有 前辈提示 , 最好不用默认的/缺省 属性, 为了程序的性能!

  4. 对象Range等 变量的赋值/初始化, 必须用set! 否则, 如果不用set 直接就是 : range1 = range("a1") 就会报错: 对象变量或with块变量 未设置!

Private Sub CommandButton1_Click()
Dim rg As Range

Set rg = Range("c2")

rg.Value = rg.Offset(0, -2).Value * Cells(2, 2)

End Sub
  1. offset( rowoffset, columnoffset) 两个参数,指定 当前单元格 的行偏移/列偏移 后的单元格...

  2. vba中的循环语句, 有三种: for ...next i, do ..... loop untile i>10 . while ... wend for语句, 如果有数字规律的, 就直接用 for i =1 to n .... 如果要处理的单元格没有数字规律就用 for each rg in range("单元格区域1", "a1:a10", "单元格区域3",,,,,). 比如:

Private Sub CommandButton1_Click()
Dim rg As Range

For Each rg In Range("a2:c9")
    If rg <> 0 Then
        rg.Value = 1#
        End If

Next

With Range("a2:c7").Font
    .name = "微软雅黑"
    .Size = 14
    .Color = RGB(red:=100, green:=10, blue:=120)   // 如果 参数使用 冒号等号 这种格式的话,  就要使全部参数都 使用 这种格式, 不能 交叉/混合, 否则会报 "语法错误!"
End With

End Sub
  1. do 和 loop 一定要成对使用, 即: 最后有loop , 前面一定要有do , 如同 next 前面一定要有for. do ....loop 的形式有几种:

    • do ....loop (后面不能那个加do) 之间 没有任何其他关键字, 没有 while , until限定条件, 如果没有if exit do 将构成无限循环
    • do while ... loop 使用while来限定循环次数
    • do ... loop until ... 来限定循环次数, 注意while和until的条件是相反的
  2. **如何在while循环的中间 次数 退出 while? **
    首先, 不能使用break, 或 exit while 语句, 会报错
    其次, 可以 使用 三种方法 : : goto flag 标号语言; 使用 exit sub(退出当前sub) , 或 application.quit(这个有副作用, 会退出整个excel应用程序); 或改用 do while ... exit do ...loop

============================================

使用对象浏览器, 可以查看给我们提供的有哪些类/方法等 , 在 编程中, 如果不知道/ 查询 一个 对象的 方法/属性等时, 就可以使用 对象browser

  1. 对象 /类 是在 库文件(其实是一些文件, 如在安装目录, system32中的一些dll文件, (这些dll文件中, 就是 ms已经预定义 写好的 类/ 函数/ 枚举: enum , 结构体struct 等数据类型.) 如 excel的exe文件, vba/office/msform的dll文件) 文件中定义 和提供的. 当然这些dll是保密的,不可读的.
  2. 库里面 可能包含 枚举类型的 成员.
  3. 类的成员 包括: 属性Property (不同的属性有不同的类型, 有的是string, 有的是boolean, 有的是object).. , 子过程sub, 函数function, 和事件 event.

代表单元格的 对象 是 Range , 而不是cell,cells!

cells和range的区别?

  1. 都可以表示 单个 的单元格, 但是要表示 区域 - 多个单元格的话, 就只能 使用 range
  2. 在速度和性能上, cells 最快, range其次, 方括号最慢. 一般都不用
  3. 子对象: range("a1: c5").range("a2") 是指 在第一个对象的基础上进行 寻找..
  4. 要表示变量 , 最方便的还是 cells. cells(row, column) 中, 通常使用数字, 但是 当 列数比较大 ,不便于计算的时候, 如"BK" 的时候, 就直接 使用 字母来表示 .
    range中也可以使用变量, 或 使用cells来表示变量
  5. 什么时候必须加 value属性? : 当 赋值 语句 两边的对象 的默认处理的 数据类型 不兼容的 时候 , 就一定要使用 value.

vba中的强制数据类型转换? c表示 convert . 转换.

都有对应的函数进行 转换, 如: Cbool, CLng, Cdec, cint, cstr, ccur, cdate
cstr 和 str : 区别是 str 有正负 前导符, 而 Cstr没有正负前导符...

**vba中本身 并没有 给 字符串 什么属性和方法, 所以 计算 字符串的长度 使用的是 len全局函数. 而不是 str.len属性. 这种 "混合编程(既有函数 又有对象的思想)" 的思想 跟 java 之类的完全 面向对象编程的 思想不同. **
如: msgbox len(str) , 而不是: msgbox str.len

简洁的数据类型声明后缀是: 整数%, 长整数&, 单精度! 双精度# , 字符串用$ . 这是常见的几个. 但是数据类型是很多的: byte: 1个字节; integer: 2个字节; logn:4个字节; boolean类型的 2个字节. single单精度4个字节, double双精度8个字节. 对象object 4个字节. 隐式声明的都是 variant. 可以存储任意类型的数据.


数组区域的转置?

transpose 转置, 即行和列对调, 比如原区域是 m行n列, 那么 选则 n行m列的区域 (比如: 原来是 5行2列, 转置后, 就是 2行 5列). 要转置时, 输入: transpose(a2:b6), 然后按 ctrl+shift+enter, 在原来的输入上 会自动 添加 大括号, 表示 数组功能. 但是, 不能 手动/自己去 输入 大括号, 那样是无效 的, 只会 看成是 字符串.

**联想笔记本功能键, F8 上面有几个方块的, 是" 切换多任务" , 但并不是 切换 窗口. 这个 在 linux下看得比较明显, 会在当前窗口和 "activities" 之间 切换. 因为他认为有两个任务: 一个是当前窗口(是一个任务! ), 一个是 左上角的 activities... wins下没有什么效果. **

vba声明变量 并初始化变量?

声明变量时 只能有两种 可能, 一种是 直接说明 变量的类型type, 另一种是 用new 一个对象, 做为 "先期对象绑定", 如果变量声明后, 再赋值,叫后期绑定.

dim dict  as new Dictionary  // 先期绑定

如: dim  dict as object
set dict = createObject("scripting.dictionary")  // 后期绑定, 就不先前声明  , 当然也可以声明, 凡是 对象 变量, 都可以声明为 object

dict(key) = item  一个条目包括:  key -> 对应的 item 条目

vba中的字典的方法, 只有 6个: dict.add, remove, removeall, | keys, items, exists.

Private Sub CommandButton1_Click()

Dim dict As Object
Dim arrKeys()

Set dict = CreateObject("scripting.dictionary")

dict(1) = "abc"
dict(2) = "123"
dict(3) = "100"
dict("name") = 200
dict(5) = True

arrKeys = dict.keys

MsgBox arrKeys(3)

End Sub

with 块中, 可以是任意代码, 不一定 总是以 点号 开头 的语句, 只是说 , 在with 语句块中, 凡是 以点号开头的 该对象的 方法或属性, 可以用在 任何的 语句中,包括语句的开头, 中间 , 或结尾 都可以!

原文地址:https://www.cnblogs.com/bkylee/p/7447044.html