![75c252ea211c6079f042070b91015113.png](https://i-blog.csdnimg.cn/blog_migrate/ef816e78eb22335cfe312aeacde3ddfc.jpeg)
最近在做一份实习,但大量的手动Excel操作让人窒息,被前一份实习惯坏了的我开始重操旧业——自动化。
但是我的直属上司并不太会编程,所以我现在处于自行摸索现学现卖的情况中orz,也不知道哪里来的勇气决定整理一波我的自学成果,希望能让吃瓜群众们少走一点弯路。
首先要声明的是,由于我还是初学者阶段,以下文章将会是弱智化教程的路线,请选择性跳读并且不要在评论骂我。
一、基础操作
使用VBA最重要也是最基础的一点:一定要知道如何打开VBA(微笑)
先打开一个Excel,然后按一下Alt+F11,你就打开了新世界,哦不,VBA的大门。
调试是按F8,可以看到每一行语句的输出结果,也可以监测你的程序是哪里出了问题。
当然你也可以按上面那个绿色的小箭头直接整段运行,然后看着报错的提示框开始挠头。
-------------------------------------------------------
这段。。。原本是没有的,由于我快1年没用VBA了,突然要用一下但又不太记得,我回来看了自己写的这篇文章,发现我犯了一个致命的错误ToT
对于一个完全不会,第一次打开VBA的萌新来说,你还需要知道一个事情,就是你写的代码要放在哪里才可以运行,不然后面那些语句全都是废的(手动擦汗...
你需要一个Sub把你的代码框起来:
Sub 一个随便起的名字()
[代码内容]
End Sub
举个栗子:
Sub aa()
Range("A1") = 10
End Sub
运行后就会发现你的A1单元格里被赋值了个10
恭喜你终于迈出了第一步!!!(撒花
--------------------------------------------------------------
二、表和单元格
对表的调用有两种基础的方法:
Sheets("表名")或者Application.ActiveSheet
前者指定用哪个表,后者调用当前你在使用的那个表
对单元格的调用:Range("单元格"),例如Range("A1")
Range("单元格").Value调用该单元格的真实值,Range("单元格").Text调用该单元格你看到的东西,啥都不写的话默认是Value
Example: Sheets("Input").Range("A1").Value=Application.ActiveSheet.Range("B2").Value
实现将当前使用表单元格B2的值赋给Input表的A1
三、数据类型
常见的有数值型,字符型,日期型,如果不先定义直接赋值的话,VBA会自己猜一个
Range("A1").Value=5 ->数值型
Range("A1").Value="ABC" ->字符型
Range("A1").Value="2015/9/25" ->日期型
但定义一个新变量更规范的方式是: Dim x as 数据类型
常用的有integer(整数)、single(单精度数值)、string(字符串)、date(日期)
Example:
Range("A1").Value=Format(19850216, "0000-00-00")
Range("A1").Value=Format(Range("B1").Value, "0000/00/00")
顺手提供一个将8位数值型假日期转换为真之日期的方法
四、IF......Then......语句
常用于先做条件判断再执行相应命令
简单的IF语句可以写成一行:
If a>=0 Then b="True" Else b="False"
也可以加入and或者or进行逻辑判断:
If a>0 and b>0 Then c="True" Else c="False"
If a>0 or b>0 Then c="True" Else c="False"
多层逻辑判断可用括号进行辅助:
If a>0 and (b>0 or c>0) Then d="True" Else d="False"
但让我惊讶的是,VBA似乎没有in这个运算符(或者是我打开方式不对)
Error:If a in ("Hi" "Hello" "Hey") Then b="True" <-SAS
Error:If a in ("Hi","Hello","Hey") Then b="True" <-SQL
以上两种写法均会报错,于是我写出了一个宛如智障的语句来实现以上事情:
If a="Hi" or a="Hello" or a="Hey" Then b="True"
打开写VBA的文章,还顺便看到了SAS和SQL,买一送二了嘿嘿
还有以下这件事情,亲测也是VBA做不到的
Error: If a="Hi" Then b="True" and c="True" and d="True"
Correct:
If a="Hi" Then
b="True"
c="True"
d="True"
End If
嵌套If语句可以做先后判断:
If a="Hi" Then If b="Hello" Then c="True"
实现先判断a的值是否符合要求,再判断b的值是否符合要求,最后再对c赋值
至于If......Else If......这个语句我怎么写怎么报错,跳过这个点(尴尬又不失礼貌的微笑)
五、For语句
常用于实现循环
Example:
For i= 1 To 10
Range("A" & i).Value=i
Next i
可实现将A1至A10单元格分别赋值为1到10
For i= 1 To 10
Range("A" & i).Value=Range("B"& i).Value
Next i
可实现将B1至B10单元格的值分别赋给A1至A10单元格
在我各种搜索VBA如何定义和调用宏变量无果之后,自行摸索出来一个做法:
Example:
location_test="E"
For i= 1 To 10
Range(location_test & i).Value="Hi"
Next i
在这里location_test虽然看上去是一个普通的字符变量,但可实现类似于宏变量的作用,将“Hi”赋给指定行指定列,这里是指定了E1至E10。
因为这个只是简单的片段,看上去这么做完全没有必要甚至有些无聊,但使用变量代替地址的优点在于可以一定程度上摆脱VBA程序对位置信息的依赖,有更强的适用性,当表的结构发生变动时,修改起来也更加便捷。
六、常用函数
一些Excel里的函数也可以在VBA程序里面使用,Application.FunctionName可以调用相应函数,如Application.Vlookup,Application.IfError;
除此之外,VBA自身也有大量的函数可以实现相同功能,如VBA.Left, VBA.Right, VBA.Mid,和在Excel的调用方法相同;
值得一提的是,有一些长得很像功能相同的函数在Excel中和在VBA中的参数设置会有些许区别,例如DateDIF函数和VBA.DateDIFF:
DATEDIF(开始日期,结束日期,时间单位):DATEDIF(1989/8/24,2018/9/1,"Y")=29
VBA.DATEDIFF(时间单位,开始日期,结束日期):VBA.DATEDIFF("Y",1989/8/24,2018/9/1)=29
两个函数名称相似功能相同,但参数的先后顺序不一样,这个需要注意一下。
而DATE()和VBA.DATE()虽然名字相同但是功能却不一样,DATE(Year,Month,Day)用于将输入的年月日合在一起转化为日期,而VBA.DATE()用于返回当前系统日期,与DATE()功能相同的函数是VBA.DateSerial(Year,Month,Day)。
七、一些神奇的操作
如何让你的程序变得更高zhuang级bi,这里介绍一些方法:
- 弹框输入
总有那么一些情况需要在一段代码被封装起来之后需要修改点什么,为了让宏能更加灵活地被使用,可以在一些参数输入的地方换成弹框输入,用到的是InputBox这个函数:
还是刚才那个简bai单chi的例子
Sub aa()
i = InputBox("input a number")
Range("A1") = i
End Sub
运行后便会弹出一个框让你输入一个数字,然后这个数字就会赋值给单元格A1
我之前写了一个可以将一个路径下所有csv/xlsm/xlsb等可以用excel打开的文件批量转换成xlsx的宏,就用到了上面这个东西,等我找找贴上来哈
[这里应有一个宏]
Public Sub xxxTOxlsx()
Dim FSO As Object
Dim folder As Object
Dim wb As Object
xxxPath = InputBox("Please input a path (without at the end): ")
input_format = InputBox("Please input file type (xlsm, xlsb, csv e.g.): ")
company_code = InputBox("Please input folder name (company code): ")
xlsxPath = xxxPath & "" & company_code
Set FSO = CreateObject("Scripting.FileSystemObject")
Set xxxFolder = FSO.GetFolder(xxxPath)
If FSO.FolderExists(xlsxPath) = False Then
FSO.createFolder (xlsxPath)
End If
Set xlsxFolder = FSO.GetFolder(xlsxPath)
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
For Each wb In xxxFolder.Files
If LCase(Right(wb.Name, Len(input_format))) = input_format Then
Set activeWB = Workbooks.Open(wb)
activeWB.SaveAs Filename:=xlsxPath & "" & Left(activeWB.Name, Len(activeWB.Name) - Len(input_format)) & "xlsx", FileFormat:=xlOpenXMLWorkbook
activeWB.Close True
End If
Next
With Application
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub
然后之后我会写一个VBA实现自动化报表输出的实例,就是我这几天的研究成果,当上述看似基本的东西打出一套组合拳的时候,效果还是蛮惊人的,欢迎指正指导。
如果您路过看到这一篇文章去我的主页找了VBA实例没有找到,不用担心,那就是
我还没写......
(也可能不会写了......)