第7章使用Range对象处理单元格区域,怎么用python处理excel

python 4
第7章使用Range对象处理单元格区域 Range对象代表单元格区域,它是Excel对象模型中最重要且频繁使用的对象,几乎所有与单元格区域相关的操作都与Range对象有关。
本章将详细介绍使用Range对象处理单元格区域的方法,包括引用单元格和单元格区域的多种方式、在单元格区域中定位与查找、读写单元格区域中的数据。
除此之外,还将介绍与处理单元格区域中的数据相关的其他一些对象和技术,包括使用Name对象处理名称、使用Sort对象和AutoFilter对象处理排序和筛选等。
7.1理解Range对象 Range对象是Worksheet对象的子对象,它可以是一个单元格,一个单元格区域,不相邻的多个单元格区域。
本节将介绍Range对象的基本概念及其常用的属性和方法,在本章后面的内容中将会详细介绍这些属性和方法的具体应用。
7.1.1Range对象的常用属性和方法 Range对象包含很多属性和方法,表7-1和表7-2列出了其中比较常用的属性和方法。
属性AddressAreasCellsColumnColumnsColumnWidthCountCountLargeCurrentRegionEndEntireColumnEntireRowFontFormulaHeightHidden 表7-1Range对象的常用属性说明 返回Range对象中包含的单元格或单元格区域的相对或绝对引用的地址返回包含多个单元格区域的Areas集合,每一个单元格区域是一个Range对象返回单元格区域中的所有单元格返回单元格区域第一列的列号,如果有多个区域,则只返回第一个区域第一列的列号返回单元格区域中的所有列,如果有多个区域,则只返回第一个区域中的所有列返回或设置单元格区域中的所有列的列宽返回单元格区域中的所有单元格的总数返回比Count属性范围更大的单元格数量返回单元格所在的连续的数据区域,该区域与其他数据区域之间以空行和空列分隔返回数据区域末尾的单元格,该属性与Ctrl+方向键的操作具有同等效果返回单元格区域中的整列返回单元格区域中的整行返回表示单元格字体格式的Font对象返回或设置单元格中的公式,使用A1引用样式返回单元格区域的高度,以磅为单位返回或设置是否隐藏行或列 ExcelVBA编程实战宝典 属性OffsetResizeRowRowHeightRowsTextValueWidth 方法ActivateAutoFitClearContentsClearFormatsCopyCutFindFindNextFindPreviousPasteSpecialSelectSpecialCells 续表说明返回对单元格或单元格区域进行偏移后得到的单元格或单元格区域返回对单元格或单元格区域的大小进行调整后得到的单元格区域返回单元格区域第一行的行号,如果有多个区域,则只返回第一个区域第一行的行号返回或设置单元格区域中的所有行的行高返回单元格区域中的所有行,如果有多个区域,则只返回第一个区域中的所有行返回或设置单元格或单元格区域中的文本,包含格式返回或设置单元格或单元格区域中的值,不包含格式返回单元格区域的宽度,以字符为单位 表7-2Range对象的常用方法说明 激活选区内的一个单元格根据单元格中的内容多少,自动调整单元格所在行的行高或列的列宽以适应内容清除单元格区域中的内容清除单元格区域中的格式将单元格区域复制到指定的单元格区域或剪贴板中将单元格区域剪切到指定的单元格区域或剪贴板中在单元格区域中查找特定信息,不影响选区和活动单元格返回由Find方法指定的搜索条件所找到的下一个匹配单元格,不影响选区和活动单元格返回由Find方法指定的搜索条件所找到的上一个匹配单元格,不影响选区和活动单元格将单元格区域中的内容以指定格式粘贴到目标区域,与Excel中的选择性粘贴功能等效选择单元格或单元格区域返回与指定类型匹配的所有单元格,与Excel中的定位条件功能等效 7.1.2选择与激活单元格 单元格操作方面的一个比较容易混淆的概念是单元格的选择与激活。
使用Range对象的Select方法可以选择单元格或单元格区域。
下面的代码选择活动工作表中的B2:D6单元格区域: Range("B2:D6").Select 选择B2:D6单元格区域后的效果如图7-1所示,该区域被绿色边框包围起来,除了区域中的一个单元格呈白色背景外,其他单元格的背景都是灰色的。
如果在此状态下输入内容,那么会将内容输入到具有白色背景的B2单元格中,这个单元格是该选区中的活动单元格。
在保持选区不变的情况下,可以按Tab、Shift+Tab、Enter和Shift+Enter等键在选区内改变活动单元格的位置。
在VBA中,可以在选择一个单元格区域后,使用Activate方法在选区内激活任一单元格,使其成为活动单元格。
下面的代码先选择B2:D6单元格区域,然后激活其中的D5单元格,使其成为活动单元格,结果如图7-2所示。
Range("B2:D6").SelectRange("D5").Activate ·118· 第7章使用Range对象处理单元格区域 图7-1选择B2:D6单元格区域 图7-2激活选区中的D5单元格 如果使用Activate方法激活的单元格不在当前选区内,那么激活的单元格将取代原来的选区。
换句话说,激活的单元格变成活动单元格且成为当前选区,该选区只包含这个刚被激活的单元格。
7.2引用单元格和单元格区域 本节将介绍在VBA中引用单元格或单元格区域的多种方法,其中的一些方法具有相同的效果,而另一些方法则适合在不同的情况下使用。
7.2.1引用一个单元格 可以使用Range或Cells属性引用单元格。
Range属性以字符串的形式进行引用,Cells属性以数字的形式进行引用。
本节主要介绍引用一个单元格的方法,引用单元格区域的方法将在下一节介绍。

1.Range属性可以使用Application或Worksheet对象的Range属性引用工作表中的单元格。
使用Application对象的Range属性引用的是活动工作表中的单元格,使用Worksheet对象可以引用活动工作表中的单元格,也可以引用指定工作表中的单元格。
无论使用哪个对象的Range属性,要引用一个单元格都需要将表示单元格地址的文本输入到Range属性右侧的一对圆括号中,并使用双引号将单元格地址括起来。
下面的代码引用活动工作表中的A1单元格: Range("A1") 如果活动工作表是Sheet1,那么下面的代码引用Sheet2工作表中的A1单元格: Worksheets("Sheet2").Range("A1") 由于Range属性中的参数是字符串,因此可以使用变量、数字和文本的组合来作为字符串表达式提供给Range属性的参数。
案例7-1在Range属性中使用变量下面的代码在Range属性的参数中使用由变量和文本组成的表达式,变量用于存储用户输入的表示行号的数字,然后与表示列标的字母组合为单元格地址,并将作为Range属性的参数。
本例将选择位于A列某行中的单元格。
Sub在Range属性中使用变量()DimstrRowAsStringstrRow=InputBox("请输入单元格的行号:") ·119· ExcelVBA编程实战宝典 IfIsNumeric(strRow)ThenRange("A"&strRow).Select EndIfEndSub Range对象也有一个Range属性,虽然也可以引用单元格,但是在使用中容易造成混乱。
下面的代码使用了Range对象的Range属性,引用的是D4单元格。
在使用Range对象的Range属性的情况下,可以将Range对象所引用的单元格想象成工作表中左上角的A1单元格,即本例中的B2,C3则是B2向右3列并向下3行后的单元格,即D4。
Range("B2").Range("C3")
2.Cells属性引用单元格的另一种方式是使用Cells属性。
与Range属性类似,Cells属性的父对象也可以是Application、Worksheet或Range对象。
Cells属性包含两个参数,分别用于指定要引用的单元格的行号和列号。
下面的代码引用Sheet1工作表中的A2单元格。
Worksheets("Sheet1").Cells(2,1) 如果Sheet1是活动工作表,则可以省略Worksheet对象的限定,写为以下形式,这种方式等同于Application.Cells。
Cells(2,1) Cells属性的第二个参数除了可以使用数字外,还可以使用字母来表示列,如下所示: Cells(
2,"A") 虽然Cells属性包含两个参数,但是第二个参数是可选参数,这意味着可以省略第二个参数。
当只使用第一个参数时,该参数表示的是工作表或单元格区域中的单元格索引号,按先行后列的顺序计算。
下面的代码仍然引用单元格A2,但是只使用了Cells属性的第一个参数。
在Excel2007或更高版本的Excel中,列的总数是16384。
由于使用一个参数的Cells属性是按照先行后列的顺序来计算索引号的,因此下面代码中的16385相当于是16384+
1,即扫描完第一行的16384列之后,转向下一行的第一列,即A2单元格。
Worksheets("Sheet1").Cells(16385) 由于Cells属性可以使用表示行号、列号的两个数字来引用特定的单元格,因此可以很方便地在循环结构中进行处理。
案例7-2在循环结构中处理Cells属性下面的代码在A1:D6单元格区域的每一个单元格中输入一个数字,该数字是其所在单元格的行号和列号的乘积,如图7-3所示。
Sub在循环结构中处理Cells属性()DimintRowAsInteger,intColAsIntegerForintRow=1To6ForintCol=1To4Cells(intRow,intCol).Value=intRow*intColNextintColNextintRow EndSub 如果在Range对象中使用Cells属性,那么引用的将是该Range对象所表示的单元格区域中的某个单元格。
下面的代码引用活动工作表中的B2:F6单元格区域的第2行第3列的单元格,即D3单元格。
使用Range对象引用单元格区域的方法将在下一节介绍。
Range("B2:F6").Cells(2,3) ·120· 第7章使用Range对象处理单元格区域 图7-3在单元格区域中输入数字 也可以在Range对象的Cells属性中只使用一个参数,其作用与前面介绍的使用一个参数的Cells属性相同,仍然按照先行后列的方式引用单元格区域中的单元格。
如果仍要在上面的B2:F6单元格区域中引用D3单元格,则可以将Cells属性的第一个参数设置为
8。
这是因为单元格D3位于B2:F6单元格区域中的第2行第3列,该区域每行有5个单元格,因此D3单元格的索引号为1×5+3=
8。
Range("B2:F6").Cells
(8) 7.2.2引用连续或不连续的单元格区域 可以使用Range属性引用单元格区域,也可以在Range属性中使用Cells属性引用单元格区域。
如果要引用不连续的单元格区域,则可以使用Range属性或Application对象的Union方法。

1.Range属性与使用Range属性引用一个单元格的方法类似,也可以使用Range属性引用一个单元格区域,只需将表示单元格区域的地址放入Range属性右侧的一对圆括号中,并使用双引号将其括起来。
下面的代码引用活动工作表中的B2:F6单元格区域: Range("B2:F6") Range属性实际上有两个参数,在使用该属性引用单元格区域时,可以同时指定两个参数,将第一个参数指定为单元格区域左上角的单元格,将第二个参数指定为单元格区域右下角的单元格,两个参数之间以逗号分隔。
下面的代码仍然引用B2:F6单元格区域,但是同时指定了Range属性的两个参数: Range("B2","F6") 也可以将Cells属性返回的单元格作为Range属性的两个参数,以指定单元格区域的左上角单元格和右下角单元格。
下面的代码仍然引用B2:F6单元格区域,但是使用Cells属性作为Range属性的参数: Range(Cells(2,2),Cells(6,6)) 使用Range属性不仅可以引用一个单元格区域,还可以引用多个不连续的单元格或单元格区域,只需在Range属性右侧的圆括号中使用一对双引号将所有以逗号分隔的单元格或单元格区域括起来。
下面的两行代码分别引用5个单元格(A1、B3、C6、D2、E5)和3个单元格区域(A1:A6、C1:C6、E1:E6)。
Range("A1,B3,C6,D2,E5")Range("A1:A6,C1:C6,E1:E6")
2.Union方法当需要引用并处理多个区域时,可以使用Application对象的Union方法。
该方法可以将多个单元格区域引用合并为一个Range对象,其中的每个参数表示一个单元格区域引用,各参数之间以逗号分隔。
必须至少为Union方法提供两个参数。
下面的代码使用rng变量存储A1:B3 ·121· ExcelVBA编程实战宝典 和D3:E6两个单元格区域: DimrngAsRangeSetrng=Union(Range("A1:B3"),Range("D3:E6")) 7.2.3处理多个单元格区域 在使用上一节介绍的技术引用了多个单元格区域后,如果要处理这些区域,则需要使用Range对象的Areas属性。
该属性返回Range对象中包含的所有单元格区域的集合,其中的每一个区域都是一个Range对象,可以使用ForEach循环结构在Areas集合中遍历每一个区域并进行相应的处理。
案例7-3使用Areas属性处理多个区域下面的代码显示了每个单元格区域包含的单元格数量,使用rngs变量存储两个单元格区域,然后在ForEach循环结构中使用rng变量遍历每一个单元格区域,使用Range对象的Count属性统计每个单元格区域中的单元格数量,并显示在对话框中。
Sub使用Areas属性处理多个区域()DimrngAsRange,rngsAsRangeSetrngs=Union(Range("A1:B3"),Range("D3:E6"))ForEachrngInrngs.AreasMsgBoxrng.Address(0,0)&"区域中的单元格数量是:"&rng.CountNextrng EndSub 7.2.4引用多个区域的重叠部分 如果需要获取多个区域的重叠部分,则可以使用Application对象的Intersect方法。
Intersect方法包含的参数与Union方法类似,每个参数表示要获取重叠部分的单元格区域的引用,各参数之间以逗号分隔。
必须至少为Intersect方法提供两个参数。
案例7-4使用Intersect方法引用多个区域的重叠部分下面的代码显示两个单元格区域的重叠部分包含的单元格的地址,如果没有重叠部分,则向用户显示提示信息。
通过使用Is运算符将存储重叠部分的rng变量与Nothing关键字进行比较,来判断两个单元格区域是否存在重叠部分。
Sub使用Intersect方法引用多个区域的重叠部分()DimrngAsRange,rngsAsRange,strMsgAsStringSetrngs=Intersect(Range("A1:C6"),Range("B5:E8"))IfrngsIsNothingThenMsgBox"两个单元格区域没有重叠部分!"ElseForEachrngInrngsstrMsg=strMsg&vbCrLf&rng.Address(0,0)NextrngMsgBox"两个区域重叠部分的单元格包括:"&strMsgEndIf EndSub Intersect方法常被用于检测用户操作的单元格是否位于指定的区域内,由此来决定用户的操作权限或执行特殊的操作。
案例7-5检查活动单元格是否在指定区域内下面的代码判断活动单元格是否位于B3:E9单元格区域内,如果不是则向用户发出提示信 ·122· 第7章使用Range对象处理单元格区域 息,禁止当前的操作。
Sub检查活动单元格是否在指定区域内() IfIntersect(ActiveCell,Range("B3:E9"))IsMsgBox"活动单元格不在指定区域内,禁止操作!" ExitSubEndIfEndSub Nothing Then 上面的代码放在工作簿或工作表的事件中才能发挥更好的作用。
在VBA中编写事件代码的 内容将在第12章进行详细介绍。
7.2.5引用一行或多行 使用Range对象的Rows属性可以返回单元格区域中的所有行。
Range对象还有一个EntireRow属性,用于返回单元格区域中的所有整行。
这两个属性可能容易引起混淆,它们看起来具有相同的作用,但实际上不同。
下面的代码显示活动工作表中的B3:D5单元格区域中每一行的地址,这里使用的是Rows属性。
返回的结果依次为B3:D3、B4:D4、B5:D5,说明Rows属性返回的行是限定在单元格区域范围内的每一行,而不是贯穿整个工作表的一整行。
SubRows属性()DimrngAsRangeForEachrngInRange("B3:D5").RowsMsgBoxrng.Address(0,0)Nextrng EndSub 如果使用EntireRow属性替换上面代码中的Rows属性,那么返回的结果依次为3:3、4:4、5:
5,说明EntireRow属性返回的行是从单元格区域范围内的每一行延伸到贯穿整个工作表的一整行。
SubEntireRow属性()DimrngAsRangeForEachrngInRange("B3:D5").EntireRowMsgBoxrng.Address(0,0)Nextrng EndSub 可以使用索引号引用Rows属性返回的所有行中的某一行。
下面的代码引用活动工作表中的第2行: Rows
(2) 如上面的代码所示,不带对象限定符的Rows属性引用的是活动工作表中的行。
也可以使用Worksheet对象引用指定工作表中的行。
下面的代码引用Sheet2工作表中的第2行: Worksheets("Sheet2").Rows
(2) 下面的代码引用B3:D5单元格区域中的第2行(即B4:D4): Range("B3:D5").Rows
(2) 可以使用Range对象的Row属性返回对象的行号。
下面的代码返回B3:D5单元格区域中的第2行的行号,返回值为
4,因为该区域的首行从工作表的第3行开始: Range("B3:D5").Rows
(2).Row 如果将Rows属性应用于包含多个单元格区域的Range对象,则将只返回第一个区域中的所有行,因此下面的代码返回第一个单元格区域的总行数
3,而不是所有单元格区域的总行数18。
·123· ExcelVBA编程实战宝典 Range("A1:A3,C1:C6,E1:E9").Rows.Count 可以使用EntireRow属性引用某个单元格所在的一整行。
下面的代码引用单元格B5所在的整行,即工作表中的第5行: Range("B5").EntireRow 也可以使用EntireRow属性引用单元格区域所占据的所有整行。
下面的代码引用B3:D5单元格区域所占据的工作表中的第3~5行。
Range("B3:D5").EntireRow 7.2.6引用一列或多列 与上一节介绍的使用Rows和EntireRow属性引用行的方法类似,使用Range对象的Columns和EntireColumn属性可以引用工作表或单元格区域中的所有列或整列。
下面的代码引用Sheet2工作表中的第3列: Worksheets("Sheet2").Columns
(3) 下面的代码引用B3:D5单元格区域中的所有列,即B~D列: Range("B3:D5").EntireColumn 与Rows属性类似,如果将Columns属性应用于包含多个单元格区域的Range对象,则将只返回第一个区域中的所有列。
7.2.7[A1]引用方式 除了使用Range和Cells属性引用单元格和单元格区域之外,还可以使用一种更简洁的方式来引用单元格或单元格区域。
只需将要引用的单元格或单元格区域的地址放置在一对方括号中,这种方法实际上是Application对象的Evaluate方法的简写形式。
使用[A1]引用方式所引用的单元格都是绝对引用。
下面的两行代码分别引用A1单元格和B3:D5单元格区域: [A1][B3:D5] 7.2.8引用当前包含数据的独立区域 如果某个包含数据的区域与其他数据区域之间至少被一个空行和一个空列分隔开,那么就可以使用该区域内的任一单元格的CurrentRegion属性来选择这个区域。
在如图7-4所示的工作表中包含两个彼此由空列隔开的数据区域B2:D6和F2:H6。
如果希望快速选择其中的某个数据区域,则可以使用Range对象的CurrentRegion属性。
下面的代码选择B2:D6数据区域,作为Range属性的参数的单元格并非必须是B2,也可以是B2:D6数据区域中的任一单元格。
Range("B2").CurrentRegion.Select 图7-4使用CurrentRegion属性选择当前数据区域 随着数据的增加,数据区域的范围会逐渐变大。
为了在任何时候都可以正确选择完整的数 ·124· 第7章使用Range对象处理单元格区域 据区域,使用CurrentRegion属性通常是最好的选择,但是需要确保数据区域是连续的,即不能包含空行和空列。
7.2.9引用工作表中的已用区域 UsedRange属性是Worksheet对象的属性,该属性返回的是一个Range对象,表示工作表中已使用的单元格区域。
已使用的单元格区域并不仅仅是指包含数据的单元格区域,那些曾经设置过格式的单元格区域也被纳入“已使用”的范围内,即使这些单元格中没有任何内容。
一个工作表只有一个已使用的单元格区域,该区域左上角的单元格由已使用过的最小行行号和最小列列标组成,该区域右下角的单元格由已使用过的最大行行号和最大列列标组成,由这两个单元格组成的矩形区域就是工作表中已使用的单元格区域。
对于上一节工作表中的两个不连续区域而言,使用下面的代码将返回这个工作表的已使用的单元格区域B2:H6,假设这个工作表是活动工作表。
这是因为工作表中包含数据的第一个单元格是B2,包含数据的最后一个单元格是H6,因此工作表中已使用的单元格区域是B2:H6。
ActiveSheet.UsedRange 案例7-6确定已使用区域的最后一行和最后一列 下面的代码确定活动工作表中已使用区域的最后一行和最后一列的位置,其中声明了4个变量,分别表示已使用区域的第一行、第一列、总行数、总列数,然后将已使用区域的第一行、第一列、总行数、总列数赋给这4个变量,最后通过公式计算出已使用区域最后一个单元格的行号和列号,并在对话框中显示相关信息。
程序运行后的效果如图7-5所示。
Sub确定已使用区域的最后一行和最后一列()DimlngFirstRowAsLong,lngFirstColAsLongDimlngRowCountAsLong,lngColCountAsLongDimstrMsgAsStringlngFirstRow=ActiveSheet.UsedRange.RowlngFirstCol=ActiveSheet.UsedRange.ColumnlngRowCount=ActiveSheet.UsedRange.Rows.CountlngColCount=ActiveSheet.UsedRange.Columns.CountstrMsg="已使用区域的最后一行是工作表中的第"&lngRowCount+lngFirstRow-1&"行"strMsg=strMsg&vbCrLf&"已使用区域的最后一列是工作表中的第"&lngColCount+lngFirstCol-1&"列"MsgBoxstrMsg EndSub 图7-5确定已使用区域的最后一行和最后一列 ·125· ExcelVBA编程实战宝典 案例7-7删除工作表中的所有空行下面的代码删除活动工作表已使用区域中的所有空行。
在ForNext循环结构中从已使用区域的底部向顶部逐行循环,这样可以避免由上向下删除行时导致的行号错乱问题。
使用工作表函数CountA判断当前行是否为空,如果是则删除该行,否则检查下一行,直到已使用区域的第一行为止。
Sub删除工作表中的所有空行() DimlngRowCountAsLong,lngRowAsLonglngRowCount=ActiveSheet.UsedRange.Rows.CountForlngRow=lngRowCountTo1Step-
1 IfApplication.WorksheetFunction.CountA(Rows(lngRow).Cells)=0ThenRows(lngRow).Delete EndIfNextlngRowEndSub 案例7-8选择工作表中的所有合并单元格 下面的代码选择活动工作表中的所有合并单元格,如图7-6所示。
在活动工作表中的已使用区域中遍历每一个单元格,使用Range对象的MergeCells属性判断当前单元格是否是合并单元格,如果是则判断作为用于存储合并单元格的对象变量rngMerge是否为空,如果为空则将当前单元格赋值给该对象变量,如果不为空则说明该对象变量已经存储过一个合并单元格了,那么就使用Union方法将当前的合并单元格与之前的合并单元格同时存储到rngMerge对象变量中。
遍历完所有的单元格后选择rngMerge对象变量中存储的所有合并单元格。
为了避免没有合并单元格时导致运行时错误,因此在执行Select方法选择前先使用Is运算符判断rngMerge对象变量是否为空。
Sub选择工作表中的所有合并单元格() DimrngUsedAsRange,rngMergeAsRange,SetrngUsed=ActiveSheet.UsedRangeForEachrngCellInrngUsed IfrngCell.MergeCellsThenIfrngMergeIsNothingThenSetrngMerge=rngCellElseSetrngMerge=Union(rngMerge,EndIf EndIfNextrngCellIfNotrngMergeIsNothingThen rngMerge.SelectEndIfEndSub rngCellAsrngCell) Range ·126· 图7-6选择工作表中的所有合并单元格 第7章使用Range对象处理单元格区域 7.2.10通过偏移引用单元格或单元格区域 Range对象的Offset属性与Excel工作表函数OFFSET的功能类似,用于将单元格或单元格区域偏移一定的行、列位置之后获得一个新的单元格或单元格区域。
与Excel工作表函数OFFSET不同的是,Range对象的Offset属性只用于偏移,而不调整单元格区域的范围大小。
可以使用Range对象的Resize属性调整单元格区域的范围大小,Resize属性将在下一节介绍。
Offset属性包含两个可选参数,语法格式如下: Offset(RowOffset,ColumnOffset) RowOffset:可选,单元格或单元格区域向上或向下偏移的行数。
正数为向下偏移,负数为向上偏移,0为不偏移。
如果省略该参数,则其值默认为
0。
ColumnOffset:可选,单元格或单元格区域向左或向右偏移的列数。
正数为向右偏移,负数为向左偏移,0为不偏移。
如果省略该参数,则其值默认为
0。
下面的代码引用的是F7单元格。
从C5单元格开始向下偏移2行变成C7,然后从C7再向右偏移3列变成F7。
Range("C5").Offset(2,3) 如果Range对象是一个单元格区域,那么在使用Offset属性后得到的就是一个经过偏移指定行、列数后的与原区域具有相同行列数的新区域。
下面的代码引用的是E5:G8单元格区域。
这是因为原区域B3:D6包含4行3列,该区域左上角单元格B3向下偏移2行,再向右偏移3列后变成E5,因此偏移后的新区域的左上角单元格是E5。
由于区域的行列数并没有发生改变,因此新区域从E5单元格为起点,向下和向右延伸至4行3列的范围,即E5:G8单元格区域。
Range("B3:D6").Offset(2,3) 注意:由于Offset属性的两个参数都可以是负数,因此在使用Offset属性时要小心偏移后得到无效的单元格,此时会出现运行时错误。
比如在对A1单元格执行向左偏移列的操作时就会出现运行时错误,因为A1单元格的左边已经没有单元格了。
案例7-9标记销量未达标的员工姓名 下面的代码将销量不足500的员工姓名设置为黄色背景,如图7-7所示。
首先获取以A1单元格所在的连续数据区域,然后使用ForEach循环结构遍历该区域第2列中的每一个单元格,如果销量小于500,则将当前单元格左侧一列且同行的单元格的背景色设置为黄色,这个单元格就是与当前销量对应的姓名。
图7-7标记销量未达标的员工姓名 Sub标记销量未达标的员工姓名() DimrngAsRange,rngsAsRangeSetrngs=Range("A1").CurrentRegionForEachrngInrngs.Columns
(2).Cells Ifrng.Value<500Thenrng.Offset(
0,-1).Interior.Color=vbYellow EndIfNextrngEndSub ·127· ExcelVBA编程实战宝典 7.2.11调整单元格区域的引用范围 使用Range对象的Resize属性可以缩放单元格区域的范围大小。
Resize属性用于在原有单元格或单元格区域的基础上,扩大或缩小区域的范围大小。
Resize属性包含两个可选参数,语法格式如下: Resize(RowSize,ColumnSize) RowSize:可选,新区域包含的行数,省略该参数表示新区域的行数不变。
ColumnSize:可选,新区域包含的列数,省略该参数表示新区域的列数不变。
下面的代码引用A1:B3单元格区域。
缩放前只有A1单元格,使用Resize属性后,从A1单元格为起点,扩展到包含三行、两列的范围,最后得到的就是A1:B3。
Range("A1").Resize(3,2) 下面的代码由原有的A1:C3单元格区域扩展到A1:E5单元格区域: Range("A1:C3").Resize(5,5) 下面的代码由原有的A1:C3单元格区域缩小到A1:B2单元格区域: Range("A1:C3").Resize(2,2) 案例7-10标记销量未达标的员工记录下面的代码将销量不足500的员工的整行记录(包括姓名和销量)同时设置为黄色背景,如图7-8所示。
本例与上一个案例只有一个区别,就是当销量不足500时标记员工的整行数据,而不只是员工姓名。
此时需要使用Resize属性来扩展单元格的范围大小,以员工姓名所在的单元格为起点,包含一行两列的区域。
Sub标记销量未达标的员工记录()DimrngAsRange,rngsAsRangeSetrngs=Range("A1").CurrentRegionForEachrngInrngs.Columns
(2).CellsIfrng.Value<500Thenrng.Offset(
0,-1).Resize(1,2).Interior.Color=vbYellowEndIfNextrng EndSub 图7-8标记销量未达标的员工记录 7.3在单元格区域中定位与查找 Range对象提供了几个用于在工作表中定位和查找数据的属性和方法,包括End属性、SpecialCells方法和Find方法等。
本节将介绍使用以上几种技术在单元格区域中进行定位与查找的方法。
·128· 第7章使用Range对象处理单元格区域 7.3.1定位单元格区域的边界 如果在某列数据的顶部选择了一个单元格,然后按Ctrl+向下键,则会出现以下几种情况中的其中之一: 选中所选单元格的列中有空单元格,则将跳转到该列中的空单元格之前包含数据的单元格。
如果所选单元格的列中没有空单元格,则跳转到该列中包含数据的最后一个单元格。
如果所选单元格的下面一个单元格为空,则将跳转到同列中下一个包含数据的单元格。
如果所选单元格的同列下方没有任何数据,则将跳转到该列中的最后一个单元格。
除了使用Ctrl+向下键之外,还可以使用Ctrl键与其他3个方向键的组合来实现其他方向的定位操作。
在VBA中可以使用Range对象的End属性实现Ctrl+方向键的功能。
该属性包含一个参数,用于确定单元格跳转的方向,参数值由XlDirection常量提供,见表7-
3。
表7-3XlDirection常量 名称 值 说明 xlUp -4162 向上 xlDown -4121 向下 xlToLeft -4159 向左 xlToRight -4161 向右 下面的代码引用从A1单元格开始,包含连续数据的区域的最后一个单元格,如图7-9所示为A10单元格。
Range("A1").End(xlDown) 如果A1单元格为空,那么上面的代码将引用从A1单元格开始,同列中下一个包含数据的单元格,如图7-10所示为A3单元格。
图7-9A1不为空时跳转到A10 图7-10A1为空时跳转到A3 上面的代码只有在A列数据的中间不包含空单元格时才能跳转到A列包含数据的最后一个单元格。
如果A列中包含空单元格,但是又希望引用A列最后一个包含数据的单元格,那么可以使用下面的代码,从工作表底部的最后一行开始向上查找包含数据的单元格。
Range("A1048576").End(xlUp) 上面的代码可以在Excel2007或更高版本的Excel中正常运行,但是如果在Excel2007之前的Excel版本中运行则会出现运行时错误,这是因为早期版本的Excel工作表最多只有65536 ·129· ExcelVBA编程实战宝典 行。
可以使用下面的代码解决这个问题,该代码通用于Excel各个版本: Cells(Rows.Count,1).End(xlUp) 使用End属性可以实现CurrentRegion属性的功能。
假设数据区域的位置如图7-11所示,其左上角的单元格是B3,下面的代码将引用该数据区域,即B3:E9单元格区域: Range("B3",Range("B3").End(xlDown).End(xlToRight)) 图7-11使用End属性实现CurrentRegion属性的功能 7.3.2定位包含指定类型内容的单元格 如果希望快速选择包含特定类型内容的所有单元格,则可以在Excel界面中按F5键,然后单击“定位条件”按钮,在打开的“定位条件”对话框中进行设置,如图7-12所示。
图7-12“定位条件”对话框 在VBA中可以使用Range对象的SpecialCells方法实现相同的功能。
SpecialCells方法包含两个参数,语法格式如下: SpecialCells(Type,Value) Type:必选,要返回的单元格的类型,该参数的值由XlCellType常量提供,见表7-
4。
Value:可选,只有将Type参数设置为xlCellTypeConstants(常量)或xlCellTypeFormulas (公式)时,Value参数才起作用。
该参数的值由XlSpecialCellsValue常量提供,可以从表7-5的4个值中选择一个或多个来设置常量或公式包含的类型。
可以采取将不同常量值相加的方式来同时包括多个类型。
默认选择常量或公式的所有类型。
·130· 第7章使用Range对象处理单元格区域 名称xlCellTypeBlanksxlCellTypeConstantsxlCellTypeFormulasxlCellTypeCommentsxlCellTypeVisiblexlCellTypeLastCellxlCellTypeAllFormatConditionsxlCellTypeSameFormatConditionsxlCellTypeAllValidationxlCellTypeSameValidation 表7-4XlCellType常量值42 -4123-4144 1211-4172-4173-4174-4175 说明空单元格包含常量的单元格包含公式的单元格包含批注的单元格所有可见单元格已用区域中的最后一个单元格包含所有条件格式的单元格包含相同条件格式的单元格包含所有数据有效性的单元格包含相同数据有效性的单元格 表7-5XlSpecialCellsValue常量 名称 值 说明 xlNumbers
1 数字 xlTextValues
2 文本 xlLogical
4 逻辑值 xlErrors 16 错误值 使用SpecialCells方法返回与指定类型的内容匹配的所有单元格。
如果没找到匹配的单元格,则会出现运行时错误,因此在使用SpecialCells方法时应该编写防错代码。
案例7-11删除销售数据中的日期 下面的代码删除工作表中的所有日期,而保留商品名称和销量,如图7-13所示。
由于在Excel中日期也是数值的一种,因此使用SpecialCells方法会同时返回日期和销量。
为了只删除其中的日期,需要使用VBA的内置函数IsDate来判断返回的数值中哪些是日期,然后再进行删除。
Sub删除销售数据中的日期() DimrngAsRange,rngsAsRangeOnErrorResumeNextSetrngs=Cells.SpecialCells(xlCellTypeConstants,IfNotrngsIsNothingThen ForEachrngInrngsIfIsDate(rng)Thenrng.ClearContentsEndIf NextrngEndIfEndSub xlNumbers) ·131· ExcelVBA编程实战宝典 图7-13要删除日期的数据区域 使用SpecialCells方法还可以确定工作表中已使用区域的最后一个单元格,如下所示: Cells.SpecialCells(xlCellTypeLastCell) 注意:没有数据但包含格式的单元格也被看作是已使用的单元格,即使将这类单元格删除,Excel也不会自动重设已使用区域中的最后一个单元格。
只有保存工作簿或执行ActiveSheet.UsedRange代码才能重置已使用的区域。
7.3.3查找包含特定信息的单元格 在Excel工作表中要搜索特定的内容,则可以使用查找功能。
只需按Ctrl+F组合键,在打开的“查找和替换”对话框中的“查找”选项卡中进行设置即可,如图7-14所示。
图7-14“查找和替换”对话框中的“查找”选项卡 在VBA中可以使用Range对象的Find方法实现相同的功能。
Find方法包含多个参数,语法格式如下: Find(What,After,LookIn,LookAt,SearchOrder,SearchDirection,MatchCase,MatchByte,SearchFormat) What:必选,要查找的内容,可以输入任何内容或使用通配符*或?

After:可选,查找操作从该参数指定的单元格之后开始,直到绕回到该单元格时才查找 该单元格中的内容。
该参数必须是单个单元格,不能指定为单元格区域。
如果省略该参数,则将从指定区域的左上角单元格之后开始查找。
LookIn:可选,查找的内容类型,可以是值、公式或批注,该参数的值由XlFindLookIn常量提供,见表7-
6。
按值查找是按照单元格中显示的内容进行查找,按公式查找是按照编辑栏中显示的公式本身内容进行查找。
LookAt:可选,精确查找或模糊查找,精确查找是指单元格中的内容与查找的内容完全匹配,模糊查找是指单元格中的部分内容与查找的内容匹配。
该参数的值由XlLookAt ·132· 第7章使用Range对象处理单元格区域 常量提供,只有xlWhole和xlPart两个值,xlWhole表示精确查找,xlPart表示模糊查找。
SearchOrder:可选,按行或按列查找,该参数的值由XlSearchOrder常量提供,只有 xlByRows和xlByColumns两个值,xlByRows表示按行查找,xlByColumns表示按列查找。
SearchDirection:可选,查找的方向,该参数的值由XlSearchDirection常量提供,只有 xlNext和xlPrevious两个值,xlNext表示查找下一个匹配值,xlPrevious表示查找上一个匹配值。
MatchCase:可选,查找时是否完全匹配英文大小写。
如果为True则区分英文大小写,如果为False则不区分英文大小写。
MatchByte:可选,只在已经选择或安装了双字节语言支持时适用。
如果为True则双字节字符只与双字节字符匹配,如果为False则双字节字符可与其对等的单字节字符匹配。
SearchFormat:可选,设置查找的格式。
表7-6XlFindLookIn常量 名称 值 说明 xlValues -4163 值 xlFormulas -4123 公式 xlComments -4144 批注 Find方法返回一个Range对象,表示查找到的第一个符合条件的单元格。
如果没找到符合条件的单元格,该方法将返回Nothing,因此可以在IfThen结构中判断是否找到了符合条件的单元格。
每次使用Find方法后,LookIn、LookAt、SearchOrder和MatchByte这4个参数的设置结果都会被保存下来。
如果在下次执行Find方法时不指定这几个参数的值,则会自动使用上一次保存的设置结果。
为了避免在查找中出现意料之外的问题,最好在每次使用Find方法时都显式设置这几个参数的值。
如果要按照相同的条件进行重复查找,则可以使用FindNext和FindPrevious方法。
案例7-12查找特定商品所在的单元格地址 下面的代码在对话框中显示名称为“电视”的商品出现在哪些单元格中。
由于商品名称位 于A列,因此在查找时将SearchOrder参数指定为xlByColumns(按列)可以节省逐行扫描的 时间。
为了避免一直重复进行查找,在找到第一个符合条件的单元格时,使用变量存储该单元 格的地址,将之后找到的每个符合条件的单元格的地址都与其作比较,以此判断是否已经查找 完所有的数据,如果是则结束查找。
使用FindNext方法可以在找到一个符合条件的单元格后, 以相同的条件继续查找。
Sub查找特定商品所在的单元格地址()DimrngFindAsRange,rngFoundAsRangeDimstrFirstAddressAsString,strMsgAsStringSetrngFind=Range("A1").CurrentRegionSetrngFound=rngFind.Find("电视",,xlValues,xlWhole,xlByColumns)IfrngFoundIsNothingThenExitSubstrFirstAddress=rngFound.AddressDostrMsg=strMsg&vbCrLf&rngFound.Address(0,0)SetrngFound=rngFind.FindNext(rngFound)LoopUntilrngFoundIsNothingOrrngFound.Address=strFirstAddress ·133· ExcelVBA编程实战宝典 MsgBox"电视所在的单元格是:"&strMsgEndSub 案例7-13确定包含数据的区域的最后一个单元格下面的代码可以确定数据区域的最后一个单元格。
将Find方法的第一个参数设置为“*”表示按通配符对任何字符进行模糊查找。
由于将SearchDirection参数设置为xlPrevious,因此将从A1单元格向上绕到工作表的底部开始查找。
为了找到包含数据的最后一行和最后一列,将两次查找中的SearchOrder参数分别设置为xlByRows(按行)和xlByColumns(按列)。
在按行查找中,从工作表底部的最后一行开始逐行向上查找包含数据的单元格,如果找到则返回该单元格的引用,然后使用Range对象的Row属性获取该单元格所在的行号。
同理,在按列查找中,从工作表的最后一列开始逐列向左查找包含数据的单元格。
找到后使用Range对象的Column属性返回包含数据的单元格的列号。
Sub确定数据区域的最后一个单元格()DimlngLastRowAsLong,lngLastColAsLonglngLastRow=Cells.Find("*",Range("A1"),xlFormulas,,xlByRows,xlPrevious).RowlngLastCol=Cells.Find("*",Range("A1"),xlFormulas,,xlByColumns,xlPrevious).ColumnMsgBox"数据区域的最后一个单元格是:"&Cells(lngLastRow,lngLastCol).Address(0,0) EndSub 7.4读取和写入单元格区域中的数据 使用VBA处理工作表的主要操作就是在单元格区域中读取和写入数据。
本节将介绍使用不同技术与单元格区域交换数据的方法,还介绍了对数据进行选择性粘贴的方法。
7.4.1通过循环遍历每个单元格读写数据 在单元格区域中读取和写入数据的最基本技术是使用ForNext或ForEach循环结构。
ForNext循环结构的优点是可以指定区域中某个特定行、特定列位置上的单元格,而ForEach循环结构的优点是不管单元格区域中包含多少个单元格,它都会依次进行遍历,直到区域中的最后一个单元格为止。
案例7-14使用行号和列号遍历区域中的每个单元格下面的代码将A1:C5单元格区域中的每个值都加
6,如图7-15所示。
将该单元格区域赋值给一个Range类型的对象变量,使用两个Long数据类型的变量分别存储该区域的总行数和总列数。
之后使用嵌套的ForNext循环结构遍历区域中的每个单元格,外层循环负责控制行号,内层循环负责控制列号,通过行号和列号定位区域中的每个单元格。
使用Range对象的Value属性获取单元格中的原有数据,并将计算后的结果再赋值给该属性。
循环结束的标志是到达单元格区域的最后一个单元格,它由Range对象的总行数和总列数决定。
Sub使用行号和列号遍历区域中的每个单元格()DimrngAsRange,lngRowAsLong,lngColAsLongSetrng=Range("A1:C5")ForlngRow=1Torng.Rows.CountForlngCol=1Torng.Columns.Countrng.Cells(lngRow,lngCol).Value=rng.Cells(lngRow,lngCol).Value+6NextlngColNextlngRow EndSub ·134· 第7章使用Range对象处理单元格区域 图7-15代码运行前后的效果 案例7-15使用一个索引号遍历区域中的每个单元格下面的代码与上一个案例的效果相同,但是在遍历区域中的单元格时只使用了一个索引号。
通过在Range对象的Cells属性中使用该索引号来引用区域中的每个单元格,并使用Range对象的Value属性获取单元格中的原有值,然后将求和后的结果再赋值给Value属性。
循环结束的标志是到达单元格区域的最后一个单元格,它由Range对象的Count属性决定。
Sub使用一个索引号遍历区域中的每个单元格()DimrngAsRange,lngIndexAsLongSetrng=Range("A1:C5")ForlngIndex=1Torng.Countrng.Cells(lngIndex).Value=rng.Cells(lngIndex).Value+6NextlngIndex EndSub 案例7-16使用ForEach循环结构遍历区域中的每个单元格还可以使用ForEach循环结构遍历区域中的每个单元格来读写数据,这种方法比前两种方法更简洁。
Sub使用ForEach循环结构遍历区域中的每个单元格()DimrngAsRangeForEachrngInRange("A1:C5")rng.Value=rng.Value+6Nextrng EndSub 7.4.2使用数组与单元格区域交换数据 上一节介绍的在单元格区域中读取和写入数据的方法并不是最高效的,这是因为这些方法都要在循环结构中不断遍历每个单元格并进行相应的处理。
更好的方法是将单元格区域中的数据赋值给一个数组,然后在数组中对数据进行所需的处理,最后将数组中包含的数据写入到单元格区域中。
这样可以减少程序运行期间对Range对象的操作次数,加快程序的处理速度。
如果要将单元格区域中的数据赋值给一个数组,那么该数组必须是一个Variant数据类型的变量,然后可以直接将单元格区域中的数据一次性赋值给Variant变量。
这与使用VBA的内置函数Array赋值一个数组的方法类似。
下面的代码将A1:C5单元格区域中的数据赋值给avarNumbers变量,该变量被声明为Variant数据类型: DimavarNumbersAsVariantavarNumbers=Range("A1:C5").Value 注意:将单元格区域中的数据赋值给一个Variant类型的变量,与将单元格区域作为Range对象赋值给一个对象变量完全不同。
前者是创建了一个Variant类型的数组,后者则是创建了一个Range类型的对象变量。
将单元格区域中的数据赋值给一个Variant变量后,相当于创建了一个二维数组。
第一维表示单元格区域中的行,第二维表示单元格区域中的列,因此可以使用行号和列号来访问数组中 ·135· ExcelVBA编程实战宝典 的特定元素。
下面的代码将数组中第2行第3列的数组元素的值赋值给intNumber变量: intNumber=avarNumbers(2,3) 即使单元格区域只有一行或一列,赋值后创建的数组仍然是二维的。
下面的代码通过将A1:A6单元格区域中的数据赋值给一个Variant变量而创建了一个二维数组,该数组包含6行1列,数组中的第一个元素是avarNumbers(1,1),最后一个元素是avarNumbers(6,1)。
avarNumbers=Range("A1:A6").Value 无论模块顶部的声明部分是否包含OptionBase语句,将单元格区域中的数据赋值给变量所创建的数组的任何一维的下界都总是
1。
可以使用VBA的内置函数LBound和UBound确定赋值后所创建的数组每一维的下界和上界。
由于每一维的下界总是
1,因此每一维的上界就是该维度的大小。
比如使用A1:C5单元格区域中的值创建一个数组后,该数组第一维的上界是
5,第二维的上界是
3。
假设赋值后创建名为avarNumbers的数组,可以使用UBound函数自动获取该数组每一维的上界,UBound函数的第一个参数指定数组名称,第二个参数指定数组的维度,如下所示: UBound(avarNumbers,1)UBound(avarNumbers,2) 案例7-17使用数组读写单元格区域中的数据下面的代码重写了上一节中的案例,使用数组代替原先在区域中循环遍历每一个单元格的方法。
Sub使用数组读写单元格区域中的数据()DimavarNumbersAsVariant,lngRowAsLong,lngColAsLongavarNumbers=Range("A1:C5")ForlngRow=1ToUBound(avarNumbers,1)ForlngCol=1ToUBound(avarNumbers,2)avarNumbers(lngRow,lngCol)=avarNumbers(lngRow,lngCol)+6NextlngColNextlngRowRange("A1:C5")=avarNumbers EndSub 也可以利用Range对象的Resize属性将计算结果放置在其他任意指定的单元格区域中,这 样可以避免覆盖原始区域中的数据。
新区域的左上角单元格由用户指定,新区域所需的行数是 数组第一维的上界,新区域所需的列数是数组第二维的上界。
案例7-18将数据的计算结果放置在指定区域中 下面的代码可以将对单元格区域中每个单元格的计算结果放置在一个指定的区域中,新区域的左上角单元格由用户在对话框中指定。
为了避免用户输入无效的单元格地址,或指定的单元格位于原始数据区域中,因此加入了防错代码。
代码的运行效果如图7-16所示。
Sub将数据的计算结果放置在指定的区域中() DimavarNumbersAsVariant,strAddressAsStringDimlngRowAsLong,lngColAsLong,rngNewAsRangestrAddress=InputBox("请输入新区域左上角单元格的地址:") OnErrorResumeNextSetrngNew=Range(strAddress)IfrngNewIsNothingThen MsgBox"输入了无效的单元格地址!" ExitSubElse IfNotIntersect(rngNew,Range("A1:C5"))IsNothingMsgBox"不能使用数据区域中的单元格!" Then ·136· 第7章使用Range对象处理单元格区域 ExitSubEndIfEndIfavarNumbers=Range("A1:C5")ForlngRow=1ToUBound(avarNumbers,1)ForlngCol=1ToUBound(avarNumbers,2) avarNumbers(lngRow,lngCol)=avarNumbers(lngRow,lngCol)+6NextlngColNextlngRowRange(strAddress).Resize(UBound(avarNumbers,1),UBound(avarNumbers,2)).Value=avarNumbersEndSub 图7-16将数据的计算结果放置在指定的区域中 7.4.3使用选择性粘贴 将工作表中的数据复制到剪贴板之后,右击某个单元格,在右键菜单中选择“选择性粘贴”命令,将打开如图7-17所示的“选择性粘贴”对话框,从中可以选择数据的粘贴方式。
如果目标单元格中包含数据,那么还可以选择粘贴时与目标单元格进行的运算方式,包括加、减、乘、除4种。
图7-17“选择性粘贴”对话框 ·137· ExcelVBA编程实战宝典 在VBA中可以使用Range对象的PasteSpecial方法实现“选择性粘贴”对话框中的相同功能。
PasteSpecial方法包含4个参数,语法格式如下: PasteSpecial(Paste,Operation,SkipBlanks,Transpose) Paste:可选,粘贴到目标单元格中的数据的格式,该参数的值由XlPasteType常量提供,见表7-
7。
Operation:可选,粘贴时与目标单元格进行的运算方式,该参数的值由XlPasteSpecialOperation常量提供,见表7-
8。
SkipBlanks:可选,如果复制的单元格区域中存在空单元格,则可以选择粘贴时是否忽略这些空单元格。
如果为True则忽略空单元格,如果为False则不忽略空单元格。
如果省略该参数,则其值默认为False。
Transpose:可选,粘贴数据时是否转换数据区域中的行列位置。
如果为True则转换行列位置,如果为False则不转换行列位置。
如果省略该参数,则其值默认为False。
名称xlPasteAllxlPasteAllExceptBordersxlPasteAllMergingConditionalFormatsxlPasteAllUsingSourceThemexlPasteColumnWidthsxlPasteCommentsxlPasteFormatsxlPasteFormulasxlPasteFormulasAndNumberFormatsxlPasteValidationxlPasteValuesxlPasteValuesAndNumberFormats 表7-
7 XlPasteType常量 值 说明 -4104714138 -4144-4122-4123 116-416312 粘贴全部内容粘贴除边框外的全部内容将粘贴所有内容,并且将合并条件格式使用源主题粘贴全部内容粘贴复制的列宽粘贴批注粘贴复制的源格式粘贴公式粘贴公式和数字格式粘贴有效性粘贴值粘贴值和数字格式 表7-8XlPasteSpecialOperation常量 名称 值 说明 xlPasteSpecialOperationAddxlPasteSpecialOperationSubtractxlPasteSpecialOperationMultiplyxlPasteSpecialOperationDividexlPasteSpecialOperationNone 2345-4142 复制的数据与目标单元格中的值相加复制的数据与目标单元格中的值相减复制的数据与目标单元格中的值相乘复制的数据与目标单元格中的值相除粘贴数据时不执行任何计算 假设C1单元格包含如下公式: =$A$1+$A$
2 下面的代码将C1单元格中的公式复制到剪贴板,然后以值的形式粘贴到B1单元格中,并计算与B1单元格中的数字之和。
完成粘贴操作后,为了关闭剪切复制模式,需要将Application对象的CutCopyMode属性设置为False,否则执行剪切或复制操作时的虚线框会停留在工作表中。
·138· 第7章使用Range对象处理单元格区域 Sub选择性粘贴() Range("C1").CopyRange("B1").PasteSpecialxlPasteValues,Application.CutCopyMode=FalseEndSub xlPasteSpecialOperationAdd 7.5创建与使用名称 在Excel中可以为单元格或单元格区域创建名称,然后可以在公式中使用名称代替相应的单元格或单元格区域,既可以简化单元格地址的输入,又可以使公式各个部分的含义更易于理解。
实际上还可以为数字、文本或公式创建名称,从而可以在名称中存储一些难以记忆或输入的内容。
在VBA中,可以使用Excel对象模型中的Names集合和Name对象来执行与名称相关的操作。
7.5.1Excel中的预定义名称 Excel已经为某些功能预先创建好了一些名称。
例如,用户在工作表中选择一个单元格区域,然后在功能区“页面布局”选项卡中单击“打印区域”按钮,然后在弹出的菜单中选择“设置打印区域”命令,Excel将会自动创建工作表级的名称Print_Area。
如果重新设置打印区域,新定义的区域范围将会覆盖Print_Area名称中的原有范围。
在设置打印标题时,Excel将会自动创建工作表级的名称Print_Titles。
Excel包含以下一些预定义名称:Criteria、Database、Extract、Print_Area、Print_Titles。
为了避免出现错误,在创建名称时最好不要与Excel中的预定义名称同名。
7.5.2命名单元格区域 根据名称的作用范围,可以将名称分为工作簿级名称和工作表级名称。
在VBA中,Workbook对象的Names属性返回一个Names集合,它表示在特定工作簿中创建的所有工作簿级名称。
Worksheet对象也有一个Names属性,该属性返回的Names集合表示在特定工作表中创建的所有工作表级名称。
Application对象的Names属性返回的Names集合表示活动工作簿中的所有名称。
在VBA中可以使用Names集合的Add方法创建名称。
Add方法包含多个参数,前3个参数Name、RefersTo和Visible比较常用。
Name:可选,用于描述名称的文本。
RefersTo:可选,名称引用的单元格区域。
Visible:可选,名称是否隐藏,如果为True则显示名称,如果为False则隐藏名称。
如 果省略该参数,则其值默认为True。
在设置名称引用的单元格区域时,应该使用美元符号($)将单元格引用限定为绝对引用,否则该名称将引用定义该名称时相对于活动单元格的相对单元格地址,而且还需要在单元格区域的左侧包含一个等号。
下面的代码为活动工作簿中的Sheet1工作表中的C2:C9单元格区域创建一个工作簿级的名称“数量”: Application.Names.Add"数量","=Sheet1!
$C$2:$C$9" 注意:如果存在同名的名称,那么创建的名称中定义的区域范围会自动覆盖原名称中的区域范围,并且不会显示任何提示信息。
·139· ExcelVBA编程实战宝典 由于是为活动工作簿创建名称,因此可以省略Application对象的限定,如下所示: Names.Add"数量","=Sheet1!
$C$2:$C$9" 如果在指定名称引用的单元格区域时不包含工作表的名称,则将引用活动工作表中的单元格区域,如下所示: Names.Add"数量","=$C$2:$C$9" 如果要为当前打开的某个特定的工作簿创建名称,但是该工作簿不是活动工作簿,则需要在Names属性前添加对该特定工作簿的Workbook对象的引用。
下面的代码为当前打开的名为“一季度”的工作簿创建工作簿级的名称“数量”。
Workbooks("一季度").Names.Add"数量","=Sheet1!
$C$2:$C$9" 如果要创建工作表级的名称,则需要在名称前添加工作表的名称和一个叹号。
下面的代码在Sheet1工作表中创建名称“数量”: Names.Add"Sheet1!
数量","=Sheet1!
$C$2:$C$9" 如果使用Worksheet对象的Names属性返回的Names集合来创建工作表级的名称,则不需要在名称前添加工作表的名称和叹号,因为当前的Names集合就是该工作表的名称集合。
下面的代码创建的名称与上面的代码完全相同,在Names集合前添加了Worksheet对象的限定: Worksheets("Sheet1").Names.Add"数量","=Sheet1!
$C$2:$C$9" 还可以使用Range对象的Name属性为该Range对象创建名称,此时创建的名称是工作簿级的名称,可用于工作簿中的任意一个工作表。
下面的代码为Sheet1工作表中的C2:C9单元格区域创建名称“数量”。
Worksheets("Sheet1").Range("C2:C9").Name="数量" 如果要创建工作表级的名称,则需要在名称前添加工作表名称和一个叹号,如下所示: Worksheets("Sheet1").Range("C2:C9").Name="Sheet1!
数量" 虽然使用Range对象的Name属性创建名称更加简单直观,但是Names集合的Add方法是为数字、文本和公式创建名称的唯一方法。
7.5.3Name对象和Name属性 如果使用Range对象Name属性为该Range对象所代表的单元格区域创建了名称,那么可能希望以后查看为该区域定义的名称,于是运行下面的代码。
运行结果如图7-18所示,其中显示的是名称引用的单元格区域,而不是名称自身的名字。
MsgBoxRange("C2:C9").Name 图7-18使用Range对象的Name属性显示的是名称引用的单元格区域 Range对象和Name对象都包含Name属性,Range对象的Name属性返回一个Name对象,Name对象的Name属性返回名称自身的名字。
因此如果想要显示单元格区域的名称本身,则需 ·140· 第7章使用Range对象处理单元格区域 要使用Name对象的Name属性。
可以将上面的代码改为以下形式: MsgBoxRange("C2:C9").Name.Name 7.5.4使用名称 创建名称后,可以在代码中使用名称来引用相应的单元格区域。
如果所使用的名称不存在,则会出现运行时错误,因此在使用名称前应该先检查名称是否存在。
案例7-19使用名称将新增数据添加到数据区域的底部如图7-19所示,将A3:C3单元格区域命名为“输入区”,新的销售数据在该区域中输入。
将从A6单元格开始的连续数据区域命名为“存储区”,用于放置所有的销售数据。
每次在输入区中输入的新数据会被添加到存储区中所有数据的底部,并删除输入区中的数据,同时更新在存储区中定义的区域范围,从而可以包含新增的数据行。
为此需要使用Range对象的Resize属性扩展到新数据的位置,并通过为Range对象的Name属性赋值来重新定义存储区的名称。
Sub使用名称将新增数据添加到数据区域的底部()DimlngRowCountAsLongRange("A3").Resize(1,3).Name="输入区"Range("A6").CurrentRegion.Name="存储区"IfApplication.WorksheetFunction.CountA(Range("输入区"))<>3ThenMsgBox"新增数据不完整!"ExitSubEndIfWithRange("存储区")lngRowCount=.Rows.Count+1Range("输入区").Cut.Cells(lngRowCount,1).Resize(lngRowCount).Name="存储区"EndWith EndSub 图7-19将输入区中的数据添加到存储区的底部 7.5.5在名称中存储值 可以为经常使用且难以记忆和输入的数字或文本创建名称,之后可以使用名称代替这些数字或文本。
当创建引用数字或文本的名称时,需要在设置Add方法的第二个参数RefersTo时,直接输入要创建名称的数字或文本,但不能包含等号。
案例7-20使用名称代替实际值下面的代码创建了两个名称,将圆周率3.14存储在“圆周率”名称中,将文本“计算圆面 ·141· ExcelVBA编程实战宝典 积”存储在“标题”名称中。
然后使用这两个名称中存储的值计算圆的面积,并将计算结果显示在对话框中,如图7-20所示。
Sub使用名称代替实际值()Names.Add"圆周率",3.14Names.Add"标题","计算圆的面积"MsgBoxInputBox("请输入半径:")^2*[圆周率],,[标题] EndSub 图7-20使用名称代替实际值 可以使用[A1]饮用方式获取名称中存储的值,下面的代码显示“圆周率”名称中存储的值: MsgBox[圆周率] 7.5.6在名称中存储公式 与为单元格区域创建名称的方法类似,也可以为公式创建名称,从而可以在工作表公式或VBA中使用名称代替公式。
案例7-21使用名称代替公式下面的代码为B列的销量数据创建名称“总销量”,其中存储使用SUM函数计算的所有销量之和,然后在“总销量”文字右侧的单元格中放置计算结果,如图7-21所示。
如果改变了包含“总销量”文字的单元格,计算结果仍然会被输入到“总销量”文字的右侧,这是因为使用Range对象的Find方法查找包含“总销量”文字的单元格,然后使用Offset属性引用该单元格右侧一列的单元格。
Sub使用名称代替公式()Names.Add"总销量","=SUM($B:$B)"Cells.Find("总销量",Range("A1"),xlValues,xlWhole,xlByRows).Offset(0,1).Value=[总销量] EndSub 图7-21使用名称代替公式 7.5.7在名称中存储数组 与在名称中存储数字和文本的方法类似,也可以在名称中存储数组包含的值。
下面的代码创建一个数组aintNumbers并为其赋值,然后将该数组中的所有值保存到新建的名称“数组” ·142· 第7章使用Range对象处理单元格区域 中,最后在对话框中显示数组中的元素总数。
Sub在名称中存储数组()DimaintNumbers(1To6)AsInteger,intIndexAsIntegerForintIndex=LBound(aintNumbers)ToUBound(aintNumbers)aintNumbers(intIndex)=intIndexNextintIndexNames.Add"数组",aintNumbersMsgBoxApplication.WorksheetFunction.Count(aintNumbers) EndSub 7.5.8隐藏名称 有时可能希望将一些存储背景数据并且不希望让用户看到的名称隐藏起来,以免这些名称被误用和误删。
在VBA中可以将创建的名称隐藏起来,隐藏的名称不会显示在“名称管理器”对话框中,但是可以在工作表或VBA中使用这些名称。
可以使用两种方法隐藏名称,一种方法是在创建名称的同时隐藏该名称,只需将Names集合的Add方法的第三个参数设置为False,如下所示: Names.Add"数量","=Sheet1!
$C$2:$C$9",False 另一种方法是在创建名称后,将Name对象的Visible属性设置为False来隐藏名称,如下所示: Names.Add"数量","=Sheet1!
$C$2:$C$9",FalseNames("数量").Visible=False 7.5.9删除名称 使用Name对象的Delete方法可以删除不需要的名称。
下面的代码删除工作簿级的名称“数量”,如果该名称不存在,则将出现运行时错误,因此需要在执行删除操作之前加入防错语句。
OnErrorResumeNextNames("数量").Delete 如果希望删除工作簿中的所有名称,无论它是工作簿级还是工作表级的名称,可以使用下面的代码,它将删除活动工作簿中的所有名称。
Sub删除工作簿中的所有名称()DimnamAsNameForEachnamInNamesnam.DeleteNextnam EndSub 7.6排序和筛选数据 排序和筛选是比较常用且易于操作的数据分析工具,通过排序可以快速对比数值的大小,还可以对相同名称的内容进行视觉上的分组排列。
通过筛选可以快速找出符合特定条件的数据。
本节将介绍在VBA中排序和筛选数据的方法。
7.6.1排序数据 在开始排序和筛选数据前,需要正确组织工作表中的数据,每一列数据的顶部应该包含标 ·143· ExcelVBA编程实战宝典 题作为该列的字段名称,数据区域顶部由各列标题组成的行称为标题行,标题下方的每一行数据称为数据记录。
在Excel2007或更高版本的Excel中,可以使用SortFields集合和Sort对象对数据进行排序。
SortFields集合用于存储排序状态,该集合的Add方法用于添加排序字段,该集合的Clear方法用于清除以前已经定义好的排序字段。
Sort对象的属性用于设置与排序相关的选项,该对象的Apply方法用于执行排序操作。
SortFields集合的Add方法包含5个参数,语法格式如下: Add(Key,SortOn,Order,CustomOrder,DataOption) Key:必选,要排序的字段。
SortOn:可选,数据的排序方式,该参数的值由XlSortOn常量提供,见表7-
9。
Order:可选,数据的排序顺序,包括升序和降序两种,该参数的值由XlSortOrder常量 提供,见表7-10。
CustomOrder:可选,是否使用自定义排序。
DataOption:可选,对数据区域进行文本排序的方式,该参数的值由XlSortDataOption 常量提供,见表7-11。
名称SortOnValuesSortOnCellColorSortOnFontColorSortOnIcon 表7-9XlSortOn常量 值 说明
0
1 单元格颜色
2 字体颜色
3 图标 名称xlAscendingxlDescending 表7-10XlSortOrder常量 值 说明
1 按升序对指定字段排序
2 按降序对指定字段排序 表7-11XlSortDataOption常量 名称 值 说明 xlSortNormal
0 分别对数字和文本进行排序 xlSortTextAsNumbers
1 将文本作为数字型数据进行排序 除了使用SortFields集合的Add方法添加排序字段之外,还需要使用Sort对象的一些属性和方法设置排序选项并执行排序操作,具体如下: SetRange方法:要进行排序的数据区域。
如果是按列排序,则在指定的数据区域中不需要包含区域顶部的标题行;如果是按行排序,则应该在指定的数据区域中包含标题行。
Header属性:排序时数据区域的第一行是否作为标题行。
如果将第一行指定为标题行,则在排序时第一行不参与排序,否则第一行参与排序。
该参数的值由XlYesNoGuess常量提供,见表7-12。
如果省略该参数,则其值默认为xlNo。
·144· 第7章使用Range对象处理单元格区域 MatchCase属性:排序时是否按英文字母的大小写进行排序,如果为True则按英文字母的大小写排序,如果为False则不按英文字母的大小写排序。
如果省略该参数,则其值默认为False。
Orientation属性:排序的方向,可按列或按行排序,该参数的值由XlSortOrientation常量提供,见表7-13。
如果省略该参数,则其值默认为xlSortRows。
SortMethod属性:中文排序的方法,可按拼音或笔画排序,该参数的值由XlSortMethod常量提供,见表7-14。
如果省略该参数,则其值默认为xlPinYin。
Apply方法:按照设置好的排序字段和排序选项执行排序操作。
名称xlGuessxlYesxlNo 表7-12XlYesNoGuess常量 值 说明
0 让Excel自己判断区域是否包含标题行
1 数据区域顶部的标题行不参与排序
2 数据区域顶部的标题行参与排序 名称xlSortColumnsxlSortRows 表7-13XlSortOrientation常量 值
1 按列排序
2 按行排序 说明 表7-14XlSortMethod常量 名称xlPinYinxlStroke 值 说明
1 按字符的拼音顺序排序
2 按字符的笔画数排序 案例7-22对销售数据按销量从高到低进行排序 下面的代码对如图7-22所示的销售数据按C列中的销量从高到低进行排序,假设该数据区域位于名为“销售数据”的工作表中。
首先使用SortFields集合的Clear方法清除之前的排序状态,然后使用该集合的Add方法设置排序字段为“销量”,然后通过指定Sort对象的相关属性设置排序选项,最后使用Sort对象的Apply方法执行排序操作。
Sub对销售数据按销量从高到低进行排序() WithWorksheets("销售数据").Sort .SortFields.Clear.SortFields.AddKey:=Range("C1"), DataOption:=xlSortNormal.SetRangeRange("A1:C15").Header=xlNo.MatchCase=False.Orientation=xlSortColumns.SortMethod=xlPinYin.ApplyEndWithEndSub SortOn:=xlSortOnValues, Order:=xlDescending, 如果指定多个排序字段,则可以实现多列排序。
根据要同时进行排序的列的数量,多次使用SortFields集合的Add方法设置多个排序字段。
除此之外,与前面介绍的只有一个排序字段 ·145· 的单列排序没有太大区别。
ExcelVBA编程实战宝典 图7-22对销售数据按销量从高到低进行排序 7.6.2自动筛选 使用自动筛选可以快速从数据区域中找到符合特定条件的数据。
在数据区域中单击任意一个单元格,然后在功能区“数据”选项卡中单击“筛选”按钮,进入自动筛选模式,区域顶部的标题行中的每个字段右侧会显示一个下拉按钮,如图7-23所示。
可以单击字段右侧的下拉按钮,然后在打开的列表中选择字段中包含的项目,从而指定筛选条件。
图7-23在自动筛选模式下对数据进行筛选 每个工作表只能有一个数据区域开启自动筛选模式。
如果工作表包含两个数据区域,且其中一个数据区域处于自动筛选模式,那么在对另一个数据区域开启自动筛选模式后,之前的那个数据区域将会自动退出自动筛选模式。
在VBA中,可以使用AutoFilter对象获取自动筛选的相关信息。
如果自动筛选位于Excel表中,那么AutoFilter对象的父对象是ListObject对象,否则AutoFilter对象的父对象是Worksheet对象。
·146· 第7章使用Range对象处理单元格区域 AutoFilter对象存在于自动筛选模式开启期间。
如果当前没有开启自动筛选模式,则可以使用Range对象的AutoFilter方法开启。
使用Worksheet对象的AutoFilterMode属性可以检查当前是否开启了自动筛选模式,该属性返回一个Boolean类型的值,如果为True则表示已开启自动筛选模式,如果为False则表示未开启自动筛选模式。
下面的代码检查活动工作表中是否开启了自动筛选模式,如果已开启则向用户发出已开启 的提示信息,如果未开启则在已使用区域中开启自动筛选模式。
Sub检查是否开启了自动筛选模式()SelectCaseActiveSheet.AutoFilterModeCaseTrueMsgBox"当前已开启自动筛选模式!"CaseFalseActiveSheet.UsedRange.AutoFilterEndSelect EndSub 如果工作表中包含多个不相邻的数据区域,则可以为指定的区域开启自动筛选模式。
下面的代码为A1:C10单元格区域开启自动筛选模式。
Range("A1:C10").AutoFilter 不带参数的AutoFilter方法相当于一个开启和关闭自动筛选模式的开关。
如果工作表中已经开启了自动筛选模式,那么使用AutoFilter方法会将其关闭。
下面的代码关闭处于开启状态的自动筛选模式,其中使用由ActiveSheet.AutoFilter返回的AutoFilter对象的Range属性引用开启筛选模式的数据区域,然后使用该Range对象的AutoFilter方法关闭筛选模式。
Sub关闭自动筛选模式()IfActiveSheet.AutoFilterModeThenActiveSheet.AutoFilter.Range.AutoFilterEndIf EndSub 如果希望对数据执行筛选操作,则需要使用带有参数的AutoFilter方法,该方法包含5个参数,语法格式如下: AutoFilter(Field,Criteria1,Operator,Criteria2,VisibleDropDown) Field:可选,要进行筛选的字段编号。
数据区域最左侧的第一列的编号为
1,第二列的编号为
2,以此类推。
Criteria1:可选,第一个筛选条件,根据Operator参数中指定的筛选类型来进行设置。
Operator:可选,筛选类型,该参数的值由XlAutoFilterOperator常量提供,见表7-15。
Criteria2:可选,第二个筛选条件,根据第一个筛选条件以及Operator参数中指定的筛 选类型来进行设置。
VisibleDropDown:可选,字段右侧是否显示下拉按钮。
如果为True则显示,如果为False 则不显示。
如果省略该参数,则其值默认为True。
名称xlAndxlOrxlTop10ItemsxlBottom10Items 表7-15 XlAutoFilterOperator常量 值 说明
1 条件1和条件2的逻辑与
2 条件1和条件2的逻辑或
3 显示最高值项(条件1中指定的项数)
4 显示最低值项(条件1中指定的项数) ·147· ExcelVBA编程实战宝典 名称xlTop10PercentxlBottom10PercentxlFilterValuesxlFilterCellColorxlFilterFontColorxlFilterIconxlFilterDynamic 续表 值 说明
5 显示最高值项(条件1中指定的百分数)
6 显示最低值项(条件1中指定的百分数)
7 筛选值
8 单元格颜色
9 字体颜色 10 筛选图标 11 动态筛选 案例7-23筛选指定商品的销量情况下面的代码对A1:C15单元格区域中的第1列(商品)进行筛选,希望显示酒水和饮料的销量情况,并且只显示“商品”列的下拉按钮,隐藏其他列的筛选下拉按钮,如图7-24所示。
图7-24筛选指定列中的数据 Sub筛选指定商品的销量情况()DimrngFilterAsRange,intIndexAsIntegerSetrngFilter=Range("A1:C10")IfNotActiveSheet.AutoFilterModeThenrngFilter.AutoFilterEndIfForintIndex=1TorngFilter.Columns.CountrngFilter.AutoFilterField:=intIndex,VisibleDropDown:=FalseNextintIndexrngFilter.AutoFilter1,"酒水",xlOr,"饮料",True EndSub 每一列的筛选信息存储在与该列对应的Filter对象中,所有的Filter对象组成了Filters集合,表示数据区域中的所有列的筛选信息。
在Filters集合中可以使用索引号引用指定的筛选列。
案例7-24显式指定列中的第一个筛选条件下面的代码显示数据区域第1列中设置的第一个筛选值。
首先判断工作表是否开启了筛选模式,如果是则判断数据区域中的第1列是否设置了筛选条件,Filter对象的On属性用于检测字段是否执行了筛选操作,如果是则返回True,否则返回False。
如果On属性返回True,则在对话框中显示第1列设置的筛选条件。
Sub显式指定列中的第一个筛选条件() ·148· 第7章使用Range对象处理单元格区域 IfActiveSheet.AutoFilterModeThenIfActiveSheet.AutoFilter.Filters
(1).OnThenMsgBoxActiveSheet.AutoFilter.Filters
(1).Criteria1EndIf EndIfEndSub 注意:无法使用Filter对象设置筛选信息,而需要使用Range对象的AutoFilter方法设置筛选信息。
如果要筛选多个值而不是前面案例中的两个值,那么可以使用Array函数创建包含所有筛选值的数组,将其指定为AutoFilter方法中的第二个参数的值。
同时还要将Operator参数的值设置为xlFilterValues,以允许使用多个筛选值。
下面的代码是对案例7-23修改后的版本,它将筛选出酒水、饮料、大米3种商品的销量情况。
Sub设置多个筛选值()DimrngFilterAsRange,intIndexAsIntegerSetrngFilter=Range("A1:C10")IfNotActiveSheet.AutoFilterModeThenrngFilter.AutoFilterEndIfForintIndex=1TorngFilter.Columns.CountrngFilter.AutoFilterField:=intIndex,VisibleDropDown:=FalseNextintIndexrngFilter.AutoFilter1,Array("酒水","饮料","大米"),xlFilterValues,,True EndSub 7.6.3高级筛选 使用高级筛选也可以获取符合条件的数据并显示出来,而且可以将筛选结果提取到其他指定的位置上,这样可以不影响原始数据的显示。
提取的目标位置可以是同一个工作表,也可以是同一个工作簿的其他工作表,还可以是其他工作簿。
高级筛选还可以将筛选结果中的重复值删除。
使用高级筛选时,需要先在单元格区域中输入筛选条件,然后在高级筛选中将筛选条件指定为该单元格区域。
可以将放置筛选条件的单元格区域称为条件区域。
条件区域的顶部需要包含筛选字段的标题,然后在标题下方的单元格中输入具体的筛选条件。
筛选条件及其输入方式分为以下三种。
如果要在同一个字段中设置满足两个条件之一的筛选条件,则需要将筛选条件放置在条件区域的同列多行中。
如图7-25所示的条件区域表示希望筛选出酒水或饮料的销量数据。
如果要在不同字段中设置同时满足多个条件的筛选条件,则需要将筛选条件放置在条件区域的同行多列中。
如图7-26所示的条件区域表示希望筛选出北京地区酒水的销售数据。
如果要在不同字段中设置满足两个条件之一的筛选条件,则需要将这两个条件放置在条件区域的不同列和不同行中。
如图7-27所示表示筛选出酒水的销售数据,或者筛选出北京地区的销售数据。
图7-25第一种筛选条件 图7-26第二种筛选条件 图7-27第三种筛选条件 我们还可以使用返回逻辑值True或False的公式作为筛选条件,此时在条件区域中的第一行不能包含筛选字段的标题,或者包含的标题不能与待筛选的数据区域中的标题相同。
·149· ExcelVBA编程实战宝典 在VBA中可以使用Range对象的AdvancedFilter方法对数据执行高级筛选的操作,该方法包含4个参数,语法格式如下: AdvancedFilter(Action,CriteriaRange,CopyToRange,Unique) Action:必选,在数据区域的原始位置进行筛选,还是将筛选结果复制到其他位置,该参数的值由XlFilterAction常量提供,见表7-16。
CriteriaRange:可选,高级筛选的条件区域。
CopyToRange:可选,将筛选结果复制到的单元格区域。
Unique:可选,是否提取不重复值。
如果为True则在筛选后删除重复值,如果为False 则不删除重复值。
如果省略该参数,则其值默认为False。
名称xlFilterInPlacexlFilterCopy 表7-16 XlFilterAction常量值12 说明在数据的原始位置显示筛选结果将筛选结果复制到其他位置 案例7-25对数据进行高级筛选下面的代码对A1:C15单元格区域中的数据进行高级筛选,F1:G2是高级筛选中的条件区域。
将筛选结果放置在新建工作表的指定区域中,该区域的左上角单元格是A1,如图7-28所示。
图7-28对数据进行高级筛选 Sub对数据进行高级筛选()DimrngOldAsRange,rngNewAsRange,rngCriteriaAsRangeSetrngOld=Range("A1:C15")SetrngCriteria=Range("F1:G2")SetrngNew=Worksheets.Add.Range("A1")rngOld.AdvancedFilterxlFilterCopy,rngCriteria,rngNew EndSub ·150·

标签: #网页 #看图 #密码 #cpc #creo #马自达 #比例 #cadxy