Excel VBA(宏):添加宏

时间:2022-09-02 08:45:53
写在前面:
1、编写宏,打开VBA,双击ThisWorkbook对当前工作薄进行编写宏;双击Sheet1,对整个sheet编写宏;
或者创建模块,在模块里,编写、调试代码。
打开VBA的方法见第一讲,结合常用窗口进行编写、调试。
2、部分对象有提示,如Dim a As,敲击空格后有提示。
3、所有宏要运行,必须启动宏。(2007版启动宏,点击表格左上角 “excel选项” “信任中心” “信任中心设置” “启用宏”)
4、“无法在未启用宏的工作簿中保存以下功能”提示,选是后,宏会整个丢失。
2007版,由于VBA或者宏代码有一定的危害性,为了提高安全意识,凡是以XLSX为后缀名的文件都不能含有宏代码,需要将后缀保存为XLSM
5、vba中_表示代码连接符,注意空格
================================================================
运行excel中的VBA代码时,需要启用宏。

VBA主要操作包含触发、指定单元格:
    1.触发:选择不同的触发模式。
    2.指定单元格:指定cells和Range。
==================================================================
VBA代码调试技巧
######################################################################
第一讲:

常见错误:
1、编译错误:不正确的代码,编译工具能提示错误
2、运行时错误,执行不可能完成的错误
3、逻辑错误

打开VBA方法:
ALT+F11 == 菜单 工具 宏  == 控件 右键 查看代码 == excel visual basic

常用窗口:
    在“视图”中依次打开:
立即窗口:可输入指令运行
本地窗口:中断过程可查看中间变量值内容
查看窗口:查看运行输出结果

Debug对象:
    Debug.print ...    '打印内容
    Debug.assert ...   '暂停点,中断程序

VBA程序三种状态:设计、运行、中断模式时。

调试工具: 视图  工具栏  调试

中断程序的方法(3种):
    设置断点:调试  切换断点 == F9
    使用Debug.Assert方法
    添加监视条件:代码窗口(或监视窗口) 右键 添加监视

实例:

'VBA编辑器会根据自己提供的内容及已创建变量等自动调整大小写,建议一次写对,避免类似变量过多时引入问题
'Sub是当前页面要执行的方法,类似main函数,Function为要调用的方法
'当有多个Sub时,选择编辑框右上角选择对应demo名称
Sub Demo()
    'Dim 定义变量 As Integer(整数)
    Dim i As Integer, iSum As Integer
    'for 循环语句
    For i = 1 To 10
    '断言,每次都会被执行,开始写代码可能会用到,之后,常用断点方式调试代码
    'Debug.Assert i < 9
    iSum = iSum + add(i)
    'vbTab 表示一个table(空字符),不同变量与字符间用","号分割,"'"表示注释
    'Debug.Print vbTab, "i=", i, vbTab, "sum", iSum
    Debug.Print "i= ", i, " sum ", iSum
    Next i
End Sub
Function add(num As Integer) As Integer
add = num + num
End Function
######################################################################
第二讲:
shape对象:
    自选对象
    图片
    艺术字
    任意多边形
    OLE对象(Object Linking and Embedding对象连接于嵌入)
常用shape对象(集合)
    Shapes集合:代表文档中所有图形对象
    ShapeRange集合:代表文档中的图形对象指定的子集(图形对象的一部分)
    Shape:代表单个图形对象

实例:
'为了便于看到效果,需要在表格中插入"图形"等,设置下轮廓,不要带填充色
'包含多个Sub时,在当前编辑框右上角选择执行的demo
Sub demo1()
'选中所有的图形对象
ActiveSheet.Shapes.SelectAll
'选择第一个和第三个图像对象,没有找到图形对象时报1004错误
'代码按序执行,先选中所有,在选中1,3,最终选中效果为后者
ActiveSheet.Shapes.Range(Array(1, 3)).Select
End Sub
' 创建的图像(如:图形)最好不要带填充色,设置下轮廓即可,不然很可能看不出效果
Sub demo2()
ActiveSheet.Shapes.Range(Array(1, 2, 3)).Select
'设置背景色为红色(注意:有些图形对象没有属性Forecolor等或者写错了而找不到,报错438)
Selection.ShapeRange(1).Fill.BackColor.RGB = RGB(255, 0, 0)
End Sub

为Shape对象指定宏代码
    手工设置宏代码:鼠标有右键指定宏即可。
        vba设备宏代码:OnAction
    为shape指定多个宏,见举例一:
    使用全局变量实现相同效果,见举例二:

shape指定多个宏,举例一:
Sub Macro1()
'ActiveSheet.Shapes 获取所有的图形对象
Dim i As Integer
For Each Shape In ActiveSheet.shapes
i = i + 1
'将每一个值图形对象的值写入表格(这里表格开始位置为<0,0>)
Cells(i, 1).Value = Shape.Name
Next
'vbInformation后边是弹出框title
MsgBox "Welcome First!", vbInformation, "hello"
'通过获取的所有对象名称,点击某个已知对象
ActiveSheet.shapes("缺角矩形 8").OnAction = "Macro2"
End Sub
Sub Macro2()
MsgBox "Hello!Second!", vbInformation, "Second"
ActiveSheet.shapes("缺角矩形 8").OnAction = "Macro1"
End Sub
'创建私有方法
Private Sub CommandButton1_Click()
Dim i As Integer
For Each Shape In shapes
i = i + 1
Cells(i, 1).Value = Shape.Name
Next
End Sub

shape指定多个宏,举例二:
'设置全局变量
Public iFlag As Boolean
'对于私有方法的调用,1、右键图形对象,指定宏,将私有方法名称协商即可点击
Private Sub CommandButton1_Click()
If iFlag Then
    MsgBox "first", vbInformation, "one"
Else
    MsgBox "secondd", vbInformation, "two"
End If
iFlag = Not iFlag
End Sub
######################################################################
第三讲
制作带自杀功能的工作薄文件

自杀功能制作原因:文件保护,限制未授权的人查看

实现步骤:
    1、用VBA设置工作薄属性为只读
    2、使用VBA文件操作指令进行自删除
举例(手工点击按钮删除);
'图像对象添加这个宏之前,一定备份一份,这个方法会删除当前文件
Sub KillThisworkBook()
    With ThisWorkbook
        '设置默认保存,不提示是否保存
        .Saved = True
        '设置工作薄只读
        .ChangeFileAccess xlReadOnly
        '读写状态,写的密码,不可被访问是否提示(默认true)
        '.ChangeFileAccess(Mode,WritePassword,Notify)
        '除当前文件,Kill是自带的方法,FullName表示文件的完整路径(它们之间有个空格)
        Kill .FullName
        .Close
    End With
End Sub
举例(工作薄打开时删除,这里宏是针对ThisWorkbook的,不是写在sheet、模块里的);
'首先点击编辑框左上角,选择worksheet,然后选择open方法
Sub KillThisWorkbook()
    With ThisWorkbook
        '设置默认保存,不提示是否保存
        .Saved = True
        '设置工作薄只读
        .ChangeFileAccess xlReadOnly
        '读写状态,写的密码,不可被访问是否提示(默认true)
        '.ChangeFileAccess(Mode,WritePassword,Notify)
        '除当前文件,Kill是自带的方法,FullName表示文件的完整路径(它们之间有个空格)
        Kill .FullName
        .Close
    End With
End Sub
Private Sub Workbook_Open()
'调用删除方法
Call KillThisWorkbook
End Sub
'2007版,由于VBA或者宏代码有一定的危害性,为了提高安全意识,凡是以XLSX为
'后缀名的文件都不能含有宏代码,需要将后缀保存为XLSM,执行正确

删除条件,列:
    非指定用户,
    计算机,
    路径,
    时间,
    打开次数
        读写注册表
        读写指定文件
        读写指定单元格
        读写隐藏名称
        读写文档属性
打开次数举例--隐藏名称:
'2003是在插入-名称-自定义
'2007使用默认快捷键(与2003一样):Ctrl+F3
'在文档中Ctrl+F3插入名称:引用名称,opentimes;位置,工作薄;引用,=0(表常量)
Sub ReadOpentimer()
    Dim OTimer As Integer
    'opentimes为表格文档中插入的名称
    'Evaluate将名称获取对应值
    OTimer = Evaluate(ThisWorkbook.Names("opentimes").RefersTo)
    OTimer = OTimer + 1
    If OTimer > 3 Then
        'Call KillThisWorkbook
        MsgBox "这里调用要执行的删除操作:KillThisWorkbook!!!"
    Else
        ThisWorkbook.Names("opentimes").RefersTo = "-" & OTimer
    End If
End Sub
Sub HideNames()
    '设置名称不可见
    'ThisWorkbook.Names("opentimes").Visible = False
    ThisWorkbook.Names("opentimes").Visible = True
End Sub
Sub AddHiddenNames()
'添加引用的名称,并且设置为0
ThisWorkbook.Names.Add Name:="opentimes", RefersTo:="=0", Visible:=flase
End Sub

'调用
Private Sub Workbook_Open()
    Call ReadOpentimer
End Sub
Sub KillThisWorkbook()
    With ThisWorkbook
        .Save = True
        .ChangeFileAccess xlReadOnly
        Kill .FullName
        .Close
    End With
End Sub

打开次数举例--文档属性:
'2003 文件 属性 自定义 名称,opentimes;取值,0
'2007 准备 属性 (左侧小三角) 高级属性 自定义 名称,opentimes;取值,0
Sub ReadOpentimer()
    Dim opentimes As Integer
    With Me
        opentimes = .CustomDocumentProperties("opentimes").Value + 1
        opentimes = opentimes + 1
        If opentimes > 3 Then
            'Call KillThisWorkbook
            MsgBox "这里调用要执行的删除操作:KillThisWorkbook!!!"
        Else
            .CustomDocumentProperties("opentimes").Value = opentimes
            .Save
        End If
    End With
End Sub
Private Sub Workbook_Open()
    Call ReadOpentimer
End Sub
Sub KillThisWorkbook()
    With ThisWorkbook
        .Saved = True
        .ChangeFileAccess xlReadOnly
        Kill .FullName
        .Close
    End With
End Sub
'代码添加文档属性
Sub AddCustomDocumentProperties()
    ThisWorkbook.CustomDocumentProperties.Add _
    Name:="opentimes_1", _
    LinkToContent:=False, _
    Type:=msoPropertyTypeNumber, _
    Value:=8888
End Sub
######################################################################
第四讲

加载宏的概念和分类

加载宏是一类程序,他们可以扩张Excel的功能,为Excel提供可用于公式
中的新的工作表函数(自定义函数)、提那家可选指令和功能

宏的加载方式3中,Excel、com加载宏和自动化加载宏

Excel加载宏:
    是Excel编写VBA编写的程序
    是Excel文档
Excel加载宏特点:
    共享性,便于扩张;
    隐藏性,运行时是隐藏的;
    不受宏安全级限制
场合:多个工作薄使用

使用步骤:
    1、制作Excel加载宏文档,结合举例看
        1.1、创建普通Excel文档
        1.2、将上步普通Excel另存为xls(加载宏的默认格式)。
        2003版,格式后缀加载宏xls;2007版后缀加载宏xla
        保存时,便于查看,最好是将宏和要使用改宏的文档放在同一目录下
    2、加载Excel加载宏文档
    3、卸载加载宏,工具 加载宏,去掉宏的选中状态
    宏不想保留,修改注册表法和删除宏文档法(立即窗口输入AddIns("文档宏名称").FullName)
加载方式步骤:
    1、手工加载: 工具 加载宏
    2、安装加载:浏览 添加自定义的宏 选中(2007 Excel选项 加载项 转到 浏览)
自动加载
    保存在特定的位置,会自动读取
举例:
'新建空文档创建宏方法
'Function xxx 括号里的是传入参数及类型,括号是返回值类型
Function CustomDefineAdd(char As Integer) As Integer
    '将最终结果返回到CustomDefineAdd
    CustomDefineAdd = char + char
End Function

定制加载宏:
    创建加载宏信息
        在创建加载宏文档时定义信息,文档属性(准备 属性) 摘要(标题 和 备注)
    修改已存在的宏信息
        需要在VBA视图修改可编辑的状态值,编辑完代码后,在改成不可编辑的
######################################################################
第5讲

ADO应用技巧

制作相片的学生证
    1、制作学生证常规 方法
        常规方法获取数据库中国的图片
            步骤:获取数据库中的图片资料的二进制数组
                使用open语句把二进制数组写入临时文件
                使用LoadPicture函数把图片显示在控件上
                使用kill语句删除临时文件
    2、制作学生证 api自编函数
        API(应用程序编程接口)
        将二进制数组转换为可以是Image控件接受的Picture对象
        把Picture对象显示在Image控件中
此节,需要单独了解把图片保存到数据库(mdb,ldb)以及实现步骤中用到的方法
######################################################################
第6讲
Access数据库中的链接表
    链接表:类似快捷方式
    手工创建链接表:文件|空白右键选择链接表
    代码创建链接表: 
        Catalog对象
        建立table对象
        设置ParentCatalog属性值和Properties集合的各项值
        把Table对象添加到Catalog对象的Tables集合中
略。
######################################################################
第7讲
Excel VBA类的初步应用

子类化实现控件数组
    控件数组是指具有相同名称和类型并且具有相同的事件过程的一个或者多个控件
查询窗体实例
    任务背景
    常规设计方法(处理重复的内容时,需要写很多遍,如:很多个按钮)
    子类化方法:通过使用类技术,把相同的时间过程写在一个类模块中,使
        多个相同类型的控件可以共同调用改事件的过程的方法

子类化实现控件数组
    类:类是一个模块;类是对象的模板,可以被多次调用,生成相同性质的对象
    子类化的步骤:
        1、创建类:插入 类(name:CommandWithEw)
        2、编写类代码:
        3、调用类代码
    WithEvents变量说明:
        1、withEvents变量不能是派生对象变量,即不能把它声明为
        As Object--当声明该变量时必须制定类名
        2、不能把WithEvents声明为As New,必须明确地创建事件源
        对象,并把它赋给WithEvents变量
        3、不能在标准模块中声明WithEvents变量,只能在类模块、
        窗体模块以及其他定义类的模块中声明
    类模块中的公共变量--添加类属性
        Public WithEvents cmd As MSForms.CommandButton
界面实现步骤:
    1、打开VBA,右键工作薄,创建form;修改名称:userQuery;
    2、添加组件:A,显示提示信息;ab,文本输入框;其他,将鼠标放在
    “Toolbox”上悬停,即可看到相关组件提示信息。
    界面显示大致效果:
    要查询的ID: "这里是输入框(name:txbID)"
    "按钮,显示1(name:cmd1)" "按钮,显示2(name:cmd2) ...
    "按钮,显示6(name:cmd6)" "按钮,显示7(name:cmd7)" ...
    "按钮,显示查询(name:cmdQuery)"   "按钮,显示取消(name:cmdCancel)"
    说明:通过按Ctrl+鼠标左键拖动,可复制一个或多个(选中多个拖动),
        按钮修改显示字符,先选中按钮组件,过1秒,在点击按钮一次。
常规方法举例:
'将name为cmd0组件的caption头,追加到txbID组件中
'txbID.Text = txbID.Text & cmd0.Caption
'点击运行,每点击一个按钮,输入框中都会多一个数字
Private Sub cmd0_Click()
txbID.Text = txbID.Text & cmd0.Caption
End Sub

Private Sub cmd1_Click()
txbID.Text = txbID.Text & cmd1.Caption
End Sub

Private Sub cmd2_Click()
txbID.Text = txbID.Text & cmd2.Caption
End Sub

Private Sub cmd3_Click()
txbID.Text = txbID.Text & cmd3.Caption
End Sub

Private Sub cmd4_Click()
txbID.Text = txbID.Text & cmd4.Caption
End Sub

Private Sub cmd5_Click()
txbID.Text = txbID.Text & cmd5.Caption
End Sub

Private Sub cmd6_Click()
txbID.Text = txbID.Text & cmd6.Caption
End Sub

Private Sub cmd7_Click()
txbID.Text = txbID.Text & cmd7.Caption
End Sub

Private Sub cmd8_Click()
txbID.Text = txbID.Text & cmd8.Caption
End Sub

Private Sub cmd9_Click()
txbID.Text = txbID.Text & cmd9.Caption
End Sub

Private Sub cmdCancel_Click()
    '本节不处理
    Unload Me
End Sub

Private Sub cmdQuery_Click()
    MsgBox "这是一个测试!"
End Sub

子类化方法举例:
'创建一个类(name:CommandWithEvents)
Option Explicit
'WithEvents变量可以被公共调用,类属性cmd
Public WithEvents cmd As MSForms.CommandButton
'在对象列表(编辑框左上角)选择cmd,过程列表(编辑框右上角)选择click事件

Private Sub cmd_Click()
    '按钮被点击时,将点击内容添加都输入框
    userQuery.txbID.Text = userQuery.txbID.Text & cmd.Caption
End Sub

'在窗体userQuery中填写如下代码
'添加声明,模块级变量
Option Explicit
'与按钮组件数一致,注意arrCmd和cmdb对应的i保持一致
Dim arrCmd(0 To 9) As CommandWithEvents

Private Sub cmdCancel_Click()
    '不处理
    Unload Me
End Sub

Private Sub cmdQuery_Click()
    MsgBox "这是一个测试!"
End Sub

Private Sub UserForm_Click()

End Sub
'选择userform窗体对象后,右上角选择Initialize方法
Private Sub UserForm_Initialize()
    Dim i As Integer
    Dim cmdb As CommandWithEvents
    For i = 0 To 9
        '创建新对象
         Set cmdb = New CommandWithEvents
         Set cmdb.cmd = Me.Controls("cmd" & i)
         Set arrCmd(i) = cmdb
         '释放变量
         Set cmdb = Nothing
    Next i
End Sub


子类化方法举例--代码循环创建组件:
'将所有的组件,剪贴掉,然后添加组件frame(name:frame1),
'第一次创建默认是frame1,通过循环就不需要在关注内部按钮名称了
'添加声明,模块级变量
Option Explicit
'与按钮组件数一致,注意arrCmd和cmdb对应的i保持一致
Dim arrCmd(0 To 9) As CommandWithEvents

Private Sub cmdCancel_Click()
    '不处理
    Unload Me
End Sub

Private Sub cmdQuery_Click()
    MsgBox "这是一个测试!"
End Sub

Private Sub UserForm_Click()

End Sub
'选择userform窗体对象后,右上角选择Initialize方法
Private Sub UserForm_Initialize()
    Dim i As Integer
    Dim cmdb As CommandWithEvents
    For i = 0 To Me.Frame1.Controls.Count - 1 '9,注意取值范围
        '创建新对象
         Set cmdb = New CommandWithEvents
         Set cmdb.cmd = Me.Frame1.Controls(i) 'Me.Controls("cmd" & i)
         Set arrCmd(i) = cmdb
         '释放变量
         Set cmdb = Nothing
    Next i
End Sub
'举例测试--控件事件本身的运行,先于子类化:
'在上边代码的基础上,添加
Private Sub cmd1_Click()
MsgBox "控件事件本身的运行,先于子类化!"
End Sub
######################################################################
第八讲

控件的应用
    输入时逐步提示信息(下拉菜单等)
        作用,提供输入效率和正确率
        实现,在工作薄中建立基础数据表
            1、将中文转换为拼音首字母
            2、输入时自动转换
        使用文本框控件和列表框控件
            控件的显示和隐藏
            输入时逐步提示
            将提示信息写入工作表

步骤;
产品名称    辅助列
食品    sp
...    ...

需要方法:将中文转换为拼音首字母、输入时自动转换(发生时间,工作薄内容
发生改变时)

######################################################################
参考网址:
http://video.1kejian.com/video/?67331-0-1.html
http://www.feiesoft.com/vba/word/
其他参考:
文档打开时,工作薄最大化
'对Thisworkbook添加open时事件
Private Sub Workbook_Open()
    Application.WindowState = xlMaximized
    ActiveWindow.WindowState = xlMaximized
    Worksheets("Sheet1").Activate
    Range("A1").Select
End Sub