【转】excel之range和cells

上一篇 / 下一篇  2014-05-18 16:29:17 / 个人分类:测试相关

1. 如下面代码,假设 i 是一个可以从1~10循环变化的值(变量),而我需要定义“Bi”单元格,然后给“Bi”单元格分别输入1~ 10,
    也就是让循环的时候,Bi 相当于B1、B2、B3、B4.....B9、B10单元格,这个“Bi”单元格,在VBA代码中,都有哪些写法呢?
     For i = 1 to  10 
          Bi = i
      Next

2. Range和Cells都能表达单元格的位置,那么,为什么要设置两个不同的属性及表达方式呢?对二者你有什么看法?

3. 请测试下面代码所指的单元格分别是哪个,你有发现其中的规律吗?或者,你知道当中的取向规则吗?有的话,请简要阐述一下。
   ① Range("C4")(2,3)                  ② Range("C5")(-2,1)                     ③   Cells(2,3)(2.5)            ④   Cells(2,3)(3.5)      
   ⑤ Range("A1:A5").Item(2)       ⑥ Range("B2:B5").Range("A2")

----------
附加题:
4. 在对单元格赋值(输入)时,如我们要在A1单元格输入3.14159,下面两种代码的写法都可以达到同样的结果,
    那么,你了解什么情况下可以省略.Value,什么时候却一定不可以呢,有的话试举例子?
   代码1:Range("A1") = 3.14159
   代码2:Range("A1").Value = 3.14159
   
1. Bi 的写法,主要有以下几种:
   Range("B" & i )               Cells( i , 2 )              Cells( i , "B") (当列号较大、不易计算时,如“H"、”AD",我们可以直接用双引号加列标作为第二参数)

    使用Range、Cells是比较常用的写法,方便,易记,规律性较好!
    另外,如5楼chunlin1wang同学,找到更多等效的写法,简单的如: [B1]( i ) 大家可以借鉴学习

P.S:
    对单元格访问,速度最快的的是 Cells(1,1) ,其次是 Range("A1"), 最慢是 [A1]
    Cells() 快于 Range()  快于 []
    因此多循环中建议使用 Cells()。  〖权威出处有待考证〗

2. Range、Cells都可以表达单元格/区域,但二者也有很明显的区别:
    Range 中文意思是“区域”,Cells 中文意思是“单元(格)”,所以,大家可以试想一下,你用Cells()可以表达一个单元格区域吗?
    比如说,我们想表示A2:D3这个区域,用Cells()可以实现吗?那么,用Range()呢?
    因此,单独用Cells()只能表示某个单元格,而不能表示一个区域。

    显然,Range是可以兼容Cells的表达方式,但Range更倾向于区域有“固定”因素时使用,当代码里要使用行、列参数都是变量的单元格时,
    直接用Range来表达的话,就显得有心有力了……   而Cells()在这时候,就是最好的选择。

    所以我们要适时选择其一,或者用Range(Cells(),Cells())的联合方式,总之让自己方便,让代码高效……

3. 各个代码所表示的单元格:
    ① Range("C4")(2,3)  = E5                   ② Range("C5")(-2,1)    =C2
    ③   Cells(2,3)(2.5)     = C3                   ④   Cells(2,3)(3.5)         =C5
    ⑤ Range("A1:A5").Item(2)  =A2        ⑥ Range("B2:B5").Range("A2")     = B3

P.S:
    如果不知道规则,那可以用VBA代码测试,比如说我们可以用Range("C4")(2,3).Select 根据运行后选择的单元格来判断结果,
    也可以用Debug.Print Range("C4").Item(2, 3).Address(0, 0)来获得地址,Address后面的参数省略的话可以得到绝对地址,是一样的。

   3.1 为什么会有像Range("C4")(2,3)这种表达方式呢,表示的又是什么意思呢?
        上面的代码,其实就是Range("C4").Item(2, 3)简化掉中间的“Item”得到的,指的就是以C4单元格为中心,按一定偏移量所得到的单元格,
         我们看一下帮助文件的说法:表达式.Item(RowIndex, ColumnIndex)  而表达式 就是指一个代表 Range 对象的变量。
         如果 RowIndex 指定为 1,则返回区域内第一行中的单元格,而非工作表的第一行。
        例如,如果选定区域为单元格 C3,则 Selection.Cells(2, 2) 返回单元格 D4(使用 Item 属性可在原始区域之外进行索引)。

        即:表达式前面指定的单元格,将作为偏移原点,而原点的坐标是(1,1),跟我们日常接触的(0,0)有所差别,具体坐标如下图所示,
        因为坐标原点不是0,所以计算时比较容易搞混,因此这种方法较少用,通常都会使用OFFSET(),因为OFFSET()的偏移量是按增量,容易计算。

   3.2 为什么Cells(2,3)(2.5) 跟 Cells(2,3)(3.5) 一个是C3、一个是C5相差2个单元格之多?
         首先,2.5与3.5,会由内部先取整,然后再如上面的偏移方式进行计算,但VBA内部,默认的取整方式,跟我们通常意义的四舍五入有点差别,
         跟VB一样,这里是遵循“四舍六入、五取偶”的方式,也称为“四舍六入,逢五奇进偶舍”,即当进位的下一位为5时,则统一向偶数靠拢。
         比如说2.5,取整则为2(舍),3.5取整为4(进),所以上面的两个Cells会相差两个单元格,VBA里的Round()函数也是遵循这一规则,跟Excel
         函数Round()也是有区别的……大家注意。

   3.3  Range.Range、Range.Cells等的理解。
         上面的第一个Range指的是一块区域,我们可以称为“母对象”,第二个Range指的是一块区域里的第几个单元格,可以理解为“子对象”;
         我们日常用的Range、Cells其实也有一个母对象,那就是“全部单元格”,如果这个理解了,那上面的也就比较容易掌握。
         如Range("B2:B5").Range("A2"),就是指B2:B5单元格区域里第1列,第2行的那个单元格,即(B3);

P.S:
    这种单元格表达方式比较不常用,因为计算方法也比较复杂,所以较少用得上,即使是区域循环,也会用For Each in ... Next 来解决,
    因此,大家理解及了解有这种表达方式即可。:DDD

4. 『附加题』什么时候可以省略.Value,什么时候不可以呢?
     很多人都说,其实.Value是Range的默认属性,所以可以省略,但当我们有时候省略时,又会出错,这是怎么一回事呢?
      可以这么说,即使Range的默认属性是.Value,当我们没有明确指定时,编译时就需要进行“自动类型适应”的过程,如果过程进行不下去,
      就会有错误发生,如:  i = Range("A1")    或   Range("A1") = 256,因为有一种“默认”及“适应”性,所以不会把A1的 Address属性 ($A$1) 赋给 i ,
      也不会把256 赋给A1的Height属性,而是赋给了.Value。
      
      下面说说无法适应的问题,比如说,我们A1单元格存储了另外一个工作表的名称,假设为“工作表2”,也就是说Range("A1") = "工作表2",
      我们现在想删除A1单元格所指定的工作表,用 Sheets(Range("A1")).Delete 会怎么样呢?
      答案是:会报错——“运行错误'13',类型不匹配”。但稍作修改,比如说将A1单元格的内容修改为2,那么仍然是用Sheets(Range("A1")).Delete这代码,
      运行后会怎么样呢?答案是:不会出错。
      那么,A1仍然是“工作表2”,而是将代码改为Sheets(CStr(Range("A1"))).Delete,结果又怎么样呢?答案是:正常运行!
      这说明什么问题呢?
      首先,Sheets()指的是某个对象,括号里可以用数字、也可以用文本作为参数来表示某个工作表,从上面不难看出来,其默认处理方式是数值格式,也就是
      表示工作表的序号,当我们使用“工作表2”这个文本想进入其默认处理方式时,就会存在无法匹配的问题,因此报错,而当我们用Cstr()函数,将A1的值,
      强制转换为文本类型然后再提供给Sheets(),这时候就是让其接受文本值,也理所当然会按工作表名来接收,所以顺利进行。

     终上所述:
     当我们不知道赋值号(=)左右两边对象默认的数据处理类型时,我们就必须明确指定,不然会出现类型无法匹配的错误。
     最较常见也最容易犯错的,就是我们区域向区域传值时,如Range("A1:A10") = Range("B1:B10").Value,后面的这个Value是必须使用的。
     大家可以测试一下左右加上与不加的各种结果……

TAG:

 

评分:0

我来说两句

Open Toolbar