零基础学Excel VBA-WE005 【设置变量灵活查询】

一、简单演示和代码展示

零基础学Excel VBA-WE005 【设置变量灵活查询】

本期宏的触发方式,选择事件触发——只要B1单元格的内容有变化,就会执行宏。

沿用上期的数据库,增加了用变量去匹配数据的方式,并且保留了上期指定匹配的方式进行对比。

在采取变量去匹配的时候,好处在于进行下面的操作不需要更新宏代码:

1、随时增减需要查询的数据

2、数据源的列可以随意变化

零基础学Excel VBA-WE005 【设置变量灵活查询】

二、新对象/方法的介绍

1. 事件

之前我们介绍的宏,都是通过按一个按钮触发的。除此之外,还有 事件 触发——通俗地理解,就是这个事情发生以后,自动会触发宏代码的运行。

事件,都有固定的名字和参数,不要尝试去修改,改了就无法触发了。

我们刚开始用 VBA,不需要过于滥用 事件,先知道有这么一种存在就好,后续的视频——应该是比较后续的视频,还会有介绍,因为本人并不是特别喜欢用事件。

但如果你喜欢,觉得 事件 非常酷,可以在代码窗口右上角这里,下拉箭头这里,都是 事件,而左边这个下来箭头,则可以选择具有 事件 的对象。

零基础学Excel VBA-WE005 【设置变量灵活查询】

注意:需要把事件触发的代码,写在对应的Sheet表格下面。

2. Private / Public

如果是 Private, 除了用在 Sub,还用在 Function 和 变量。Private 表示只有本模块可以调用, Public 表示所有模块都可以调用。

事件,应该都是 Private 的。

3. 数组Array

两种定义方式:

Dim Array1(1 To 5) As Integer ' 声明数组变量。

Array2 = Array(1, 2, 3, 4, 5) ' 使用Array函数直接赋值。

4. Application.WorksheetFunction

在 Visual Basic 语句中可以使用大多数 Microsoft Excel 工作表函数。

比如常用的VLookup,SumIf,Subtotal,Sum,Match等等,我曾经无聊算过一次,总共有174个,随着Excel的更新,这个数字估计有上下浮动了。

5. Clear

清除内容和格式设置。

有个类似的ClearContents,清除内容,保留格式(跟用Rows("3:" & r1) = Null的效果一样)。

三、执行思路及过程分析

在上期的视频中说到,进行数据查询和匹配时,少量数据可以用直接指定的方式,大量数据的时候,建议用变量的方式。

在本期的例子里面,前面小半部分,是对直接指定方式的回顾,后面的部分,是用变量的方式的具体实现方法。

至于是通过 事件 触发,还是通过 按钮 触发,其实代码基本都一样的。

只是这里我们用了 Worksheet_Change 这个事件,也就是更改单元格,为了不让宏乱触发,所以往往需要加一个限制触发的条件:

就是这一句——(If Target.Count = 1 And Target.Address = "$B$1" Then)

Target,理解成发生改变的单元格就可以了。

回到执行思路——

【1】确定查询条件

表1《查库存》的 B1 是我们的查询条件,当我们输入 名称 的,想跟这个 物品 相关的所有信息都调出来,包括表2 和表3 的。

第 2 行代码,触发宏的条件就是 B1 单元格发生变化,而且发生变化的单元格数量只有 1 个。

【2】用指定的方式,提取 表2 的数据。

第 3 行算是我们的老朋友了,取最大的行号。第 4 行,是把之前的查询结果清空。注意,rmax1 已经是最大列号,为什么这里用 rmax1 + 1 呢?

如果并没有查询数据,最大行是 2,执行 Rows("3:2").Clear ,会把第 2 行的内容清除掉——这也是刚接触 VBA,使用最大行列的时候,容易出现意外的地方。

好,接着往下看——

我们需要 表2 中提取的数据有 3 列,就是灰色的这三列,2、4、5 列,当通过 If 语句匹配到名字相同时,就进行赋值。我们看这 3 行代码,左边的是当前工作表,也就是 表1,分别是 2、4、5 列,而右边的,是 表2,分别对应 4、6、7 列。其中中间这个,乘 -1,是因为 表2 的是出库的记录,后面还会进行一个存量统计的计算。

(注意:上期定义一个变量 x,完全是为了展示 select case 的使用。本期提取的数据列,根上期不同,而表2对应的列号,直接指定,并没有使用x。)

零基础学Excel VBA-WE005 【设置变量灵活查询】

【3】用变量的方式,提取 表3 的数据

首先,定义一个数组变量 myitem 。这里定义了 100 个元素,但实际上,我们只用了不到 10 个。

cmax,取的是第 2 行的最大列号,我们实际使用的数组元素个数也是由 cmax 决定。

下面的一个 For 循环,用到了 Excel 的一个公式 Match ,引用的命令就是 Application.WorksheetFunction.Match ,紧跟着的括号的内容,跟 Excel 的用法是一样,不同在于对单元格的引用,要遵循 VBA 的规则,像 Cells(2, i) 和 Range("1:1") 都是。

这个 For 循环,通过 Match 公式,其实就实现了 表1 第 2 行的查询内容,在表3 中表头对应的位置,这一步很简单,却是理解后面赋值语句的关键。

注意:Match公式的应用,限制了表1 第 2 行表头跟表3 的表头,取名必须一致。

下一句 namec 获取的是 物料名称 在表3 中表头的列号。

现在有了 myitem(i) 和 namec,就把 查询条件,以及 查询内容 都用变量表示了。这样做的好处,就是不管表3 的列如何调整或者新增一些列,宏都不需要修改。

前面做了那么多,都是为最后的两层 For 循环做准备的。

外层的 For 循环,跟前面 表2 的数据获取一样,对 表3 进行逐行匹配。

内层的 For 循环,就是名字匹配以后,对 表1 进行逐列赋值。如果对这个赋值看得迷惘的话,需要回顾一下之前的那个 For 循环。

最后两个命令行,是对 D 列的数量进行求和,结果写在 rmax+1 行。

【4】变化查询条件验证结果

有兴趣的朋友,可以试试调整 表3 的列和 表1 的一些查询条件,看看宏是不是仍能正常运行。

1. 变更表3 的列

包括变更原来列的位置,任意新增列等。

2. 调整表1 种查询列的顺序,但灰色这几个一旦调整,是会影响第【2】点数据的获取的。

【5】重点需要理解的内容

本期的宏代码,第一次看,估计有点绕,重点是下面两个语句:

1、确定变量对应关系:

myitem(i) = Application.WorksheetFunction.Match(Cells(2, i), Worksheets("库存记录").Range("1:1"), 0)

2、完成赋值:

Cells(rmax1 + 1, i) = Worksheets("库存记录").Cells(j, myitem(i))

左边是 i 列,右边是 myitem(i) 列,只要把这对应关系想通了,就能明朗了。

四、本期宏完整展示

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count = 1 And Target.Address = "$B$1" Then
rmax1 = [A1].CurrentRegion.Rows.Count()
Rows("3:" & rmax1 + 1).Clear

rmax2 = Worksheets(2).[A1].CurrentRegion.Rows.Count()
For j = 1 To rmax2
If Worksheets(2).Cells(j, 5) = [B1] Then
rmax1 = [A1].CurrentRegion.Rows.Count()
Cells(rmax1 + 1, 2) = Worksheets(2).Cells(j, 4)
Cells(rmax1 + 1, 4) = Worksheets(2).Cells(j, 6) * (-1)
Cells(rmax1 + 1, 5) = Worksheets(2).Cells(j, 7)
End If
Next

Dim myitem(1 To 100) As Integer
cmax = [AAA2].End(xlToLeft).Column
For i = 1 To cmax
myitem(i) = Application.WorksheetFunction.Match(Cells(2, i), Worksheets("库存记录").Range("1:1"), 0)
Next
namec = Application.WorksheetFunction.Match([A1], Worksheets("库存记录").Range("1:1"), 0)
rmax3 = Worksheets("库存记录").[A1].CurrentRegion.Rows.Count()
For j = 1 To rmax3
If Worksheets("库存记录").Cells(j, namec) = [B1] Then
rmax1 = [A1].CurrentRegion.Rows.Count()
For i = 1 To cmax
Cells(rmax1 + 1, i) = Worksheets("库存记录").Cells(j, myitem(i))
Next

End If
Next

If [B1] <> "" Then
rmax1 = [A1].CurrentRegion.Rows.Count()
Range("D" & rmax1 + 1).FormulaR1C1 = "=sum(R3C:R[-1]C)"
End If
End If
End Sub

五、后话

由于视频版制作非常耗时间,而且关注的朋友很少,暂停视频版的更新,见谅。

零基础学Excel VBA-WE005 【设置变量灵活查询】


分享到:


相關文章: