VBA數(shù)組(一)
一、什么是數(shù)組 對于數(shù)組,在前面7樓的貼子里我們已經(jīng)簡單介紹了一些簡單的概念,如果你忘記了,請回過頭去花兩分種讀一讀。 讀完了也許你還是不清楚,沒關(guān)系,請接著往下看。 新學(xué)期開始了,我上七(1)班數(shù)學(xué),學(xué)生太多了,我老是記不住學(xué)生的名字,還好班主任為了便于管理,為班上的學(xué)生都編了學(xué)號(hào),所以上課時(shí)點(diǎn)名我習(xí)慣性只點(diǎn)學(xué)生學(xué)號(hào),我說,5號(hào)同學(xué)請上黑板演示一下你的解題過程,10號(hào)同學(xué)下課后請?zhí)胬蠋煱汛蠹业淖鳂I(yè)收起來……下課后,在辦公室,和大家聊天,我更不叫學(xué)生名字而直接統(tǒng)稱為“七(1)班”。 待我學(xué)習(xí)了VBA的數(shù)組后,我忽然明白了,這種簡化的稱呼方式原來就是“數(shù)組”。 這里,我們是把一群學(xué)生聚在了一起組成了“七(1)班”(數(shù)組名)這個(gè)集合,班級里的學(xué)生我們通過“學(xué)號(hào)”(索引號(hào))對其進(jìn)行區(qū)分。上課時(shí),我問:“5號(hào)同學(xué)是誰?”,一個(gè)同學(xué)站起來答:“我叫moon2778”,于是,我知道了,“七(1)班”這個(gè)數(shù)組里的第5個(gè)元素就是“moon2778”。用數(shù)組來表示就是“七(1)班(5)”,也就是數(shù)組名加索引號(hào)。好了,當(dāng)別人果問你:“‘七(1)班(5)’的同學(xué)是誰?”時(shí),你一定要知道,是“moon2778”。 那么,什么是數(shù)組,你知道了吧?它有什么特點(diǎn),我們可以試著簡單小結(jié)一下: 1、數(shù)組共享一個(gè)名字,即數(shù)組名; 2、數(shù)組是變量的集合,有多個(gè)元素; 3、數(shù)組中的元素按順序保存在數(shù)組中,元素通過索引數(shù)字加以區(qū)分; 4、數(shù)組是變量。 二、定義數(shù)組 聲名數(shù)組同聲明其他變量的方式一樣,唯一不同的是數(shù)組有大小,包含多個(gè)單個(gè)變量。 初一學(xué)生報(bào)名入學(xué)后開始分班級,領(lǐng)導(dǎo)說,七(1)班分50個(gè)學(xué)生(確定了班級學(xué)生的個(gè)數(shù)最多只能有50個(gè)學(xué)生,再多一個(gè)都不行,因?yàn)闆]有座位了。),知道有50個(gè)學(xué)生后,老師拿到學(xué)生花名冊就開始給學(xué)生編學(xué)號(hào),建學(xué)籍。1號(hào)是誰?2號(hào)是誰?……50號(hào)是誰? 這就是一個(gè)定義數(shù)組,并給數(shù)組賦值的過程,用語句來表示,可以這樣: Dim 七(1)班(1 To 50) 七(1)班(1) = "張三" 七(1)班(2) = "李四" 七(1)班(3) = "王王" ..... 七(1)班(50) = "趙六" 這里,我們定義了一個(gè)50個(gè)元素的一維數(shù)組,并分別給數(shù)組的元素賦值。當(dāng)然,這里用的只是一個(gè)模擬的語句。如果我們需要定義一個(gè)數(shù)組arr,存放1到100的整數(shù)集合,則代碼為: 復(fù)制內(nèi)容到剪貼板
其實(shí)“Dim arr(1 To 100) As Integer”我們也可以寫成“Dim arr(99) As Integer”,這樣,定義的數(shù)組同樣是100個(gè)元素的一維數(shù)組,因?yàn)槿绻恢付ㄆ鹗妓饕?hào)的話,VBA默認(rèn)從0開始。代碼: Sub ggsmart() 當(dāng)然,你也是可以通過OPTION BASE 來修改數(shù)組默認(rèn)的起始序號(hào),在模塊的第一句寫上“OPTION BASE 1”這樣,默認(rèn)的數(shù)組起始序號(hào)就是1了。 學(xué)習(xí)累了,恰好第二節(jié)課剛下,課間操時(shí)間,順便可以到操場練練??墒?,有些同學(xué)不認(rèn)真啊,這不,老師在廣播里叫上了:“七年級,(1)班的第五個(gè)同學(xué)請認(rèn)真一點(diǎn),七年級,(2)班的第三個(gè)同學(xué)注意隊(duì)形……” 天了,我驚奇地發(fā)現(xiàn),原來我們生活中有這么多“數(shù)組”,可是,你知道上面的這兩個(gè)同學(xué)共享了一個(gè)什么名字嗎? 是的,“七年級”就是它們共有的名字。 新生分班時(shí),校長就說了,550名新生,每班50人,分成11個(gè)班,到各個(gè)班級里,老師都給學(xué)生分了學(xué)號(hào)(1到50號(hào)),11個(gè)班級就有11個(gè)1號(hào),也有11個(gè)50號(hào)。暈,一個(gè)班的學(xué)生名字我都記不住,如果11個(gè)班的學(xué)生全站在一起,我該怎么稱呼? 我高興了,還好,我會(huì)數(shù)組。找到“moon2278”同學(xué),我會(huì)說“七年級,1班,5號(hào)同學(xué)”,哈,難不了我。如果“寶貝有酒窩”同學(xué)是初一(9)班的25號(hào),沒關(guān)系,我也會(huì)說“七年級,9班,25號(hào)同學(xué)”。 哇,好簡單,前面加個(gè)班級的序號(hào)區(qū)分就行了。 這里,“七年級”實(shí)際上是一個(gè)由11個(gè)一維數(shù)組(11個(gè)班)組成的二維數(shù)組,它的元素的個(gè)數(shù)是11*50(11個(gè)班,每個(gè)班級50名學(xué)生)個(gè)。習(xí)慣性,大家會(huì)說它是一個(gè)11*50的二維數(shù)組。 如果要寫成代碼,那就是: Dim 七年級(1 To 11, 1 To 50) 七年級(1, 1) = "張三" 七年級(1, 2) = "李四" '...... 七年級(2, 1) = "錢林" 七年級(2, 50) = "林平" '...... 七年級(11, 50) = "周六" 我們說上面的數(shù)組是一個(gè)11*50的二維數(shù)組,放到表格里就相當(dāng)于是一個(gè)11行50列的數(shù)組。 如果我們想定義一個(gè)二維數(shù)組,第一列存放1到100的奇數(shù),第二列存放1到100的偶數(shù),代碼為: 復(fù)制內(nèi)容到剪貼板
1到100的奇偶數(shù).rar (6.63 KB)
把代碼復(fù)制到模塊里,按F5可以看到程序運(yùn)行的效果。代碼: Sub ggsmart() 上面,我們講的是一維數(shù)組和二維數(shù)組,你也可以按同樣的思路來理解三維、四維數(shù)組,甚至五維、六維……或者更多。 無非就是將稱呼moon2278同學(xué)的方式改為“XX中學(xué)、七年級、1班、5號(hào)同學(xué)”或“XX市、XX中學(xué)、七年級、1班、5號(hào)同學(xué)”而已,如果你喜歡,你還可以將這個(gè)稱呼擴(kuò)展,隨你了,這里不再舉例。 三、動(dòng)態(tài)數(shù)組 聲明一個(gè)數(shù)組,必須指定數(shù)組的大小,即它是幾維數(shù)組,有多少個(gè)元素。 但有些時(shí)候,我們在定義數(shù)組的時(shí)候,并不能確定數(shù)組的大小,這時(shí),我們在首次定義數(shù)組的時(shí)候括號(hào)內(nèi)為空(當(dāng)然先指定一個(gè)大小也是可以的,但純屬是多余),在程序過程中用Redim語句去重新指定數(shù)組的大小,這就是動(dòng)態(tài)數(shù)組。 比如一個(gè)工作表的A列存儲(chǔ)了學(xué)生姓名,現(xiàn)在我們需要把把有姓“張”的學(xué)生存儲(chǔ)在數(shù)組arr中,預(yù)先我們并不知道A列姓張的學(xué)生有三十個(gè)還是五十個(gè),所以,我們在定義時(shí)代碼可以這樣: 復(fù)制內(nèi)容到剪貼板
姓“張”的學(xué)生.rar (7.16 KB)
代碼: Sub ggsmart() 四、其他創(chuàng)建數(shù)組的幾種方式 其實(shí)在上面,我們已經(jīng)接觸了如何創(chuàng)建數(shù)組了。無非就是像給學(xué)生排座位一樣,你坐第一排,我坐第二排,他坐第三排,然后你們大家統(tǒng)稱為第一組。 好簡單,這里,我再介紹幾種上面沒講到,但常見的方法: 1、使用Array創(chuàng)建數(shù)組 看以下代碼: 復(fù)制內(nèi)容到剪貼板
這里使用Array函數(shù)將1到10的自然數(shù)賦給數(shù)組arr這里,我就不上傳附件了,大家將代碼復(fù)制到模塊里查看效果。代碼: Sub ggsmart() 引用:提醒一點(diǎn):使用Array創(chuàng)建的數(shù)組索引號(hào)默認(rèn)從0開始,當(dāng)然,如果已經(jīng)用“OPTION BASE 1”語句指定了的另當(dāng)別論。 復(fù)制內(nèi)容到剪貼板
2、使用Split創(chuàng)建數(shù)組代碼: arr = Array("張祝", "徐國軍", "陳茜", "王歡", "許松", "張小海", "陳飛", "張明元", "徐國東", "張款") Split的作用是把一個(gè)文本,根據(jù)指定的分隔符,建立一個(gè)數(shù)組。感覺就有點(diǎn)像我們基礎(chǔ)操作中的“分列”。不同的是“分列”操作是將一個(gè)單元格的文本按指定的分隔符分開,存放在同行的多個(gè)單元格里,而Split的作用是將一個(gè)文本(也可以是存放在單元格里的)按指定的分隔符分開,存放在一個(gè)數(shù)組變量里。 如果你使用過“分列”,再來看這個(gè),就簡單多了。 還是上面的那串姓名“張祝,徐國軍,陳茜,王歡,許松,張小海,陳飛,張明元,徐國東,張款”,只是這時(shí),這些姓名是一個(gè)完整的字符串,此時(shí),如果我們想把這些姓號(hào)按逗號(hào)(,)分開,存放在數(shù)組arr里,則代碼為: 復(fù)制內(nèi)容到剪貼板
你可以用上面的方式將生成的數(shù)組輸入到單元格查看效果。當(dāng)然,也可以在立即窗口里查看,這樣就更方便了。代碼: arr = Split("張祝,徐國軍,陳茜,王歡,許松,張小海,陳飛,張明元,徐國東,張款", ",") 特別強(qiáng)調(diào)一點(diǎn):用Split把文本轉(zhuǎn)換成數(shù)組,索引號(hào)總是從0開始。不管你是否使用了Option Base語句,這點(diǎn)和Array不同。 3、通過Range創(chuàng)建數(shù)組 (1)循環(huán)給單元格賦值 比如想把A1:A100單元格的值給數(shù)組arr,則代碼為: 復(fù)制內(nèi)容到剪貼板
(2)直接等于單元格區(qū)域代碼: Sub a() 這個(gè)很簡單,直接數(shù)組名等于單元格區(qū)域就可以了。 比如想把A1:A100單元格的值給數(shù)組arr,代碼還可以簡單寫為: 復(fù)制內(nèi)容到剪貼板
好了,很簡單,我就不再多說,大家自己去練習(xí)吧。代碼: arr = [a1:a100] 兩種方法哪種的效率高顯而易見吧?呵呵……有興趣,可以自己去比較一下。 五、UBount和LBound函數(shù) 我們定義數(shù)組時(shí),我們可以指定數(shù)組的起始索引號(hào)不為0,而為1或其他的任意數(shù)。比如Dim arr(5 to 6)定義的這個(gè)數(shù)組起始索引號(hào)為5,共有兩個(gè)元素。 那么,對于一個(gè)已經(jīng)定義了的數(shù)組,我們想知道它的最大索引號(hào)(上界)和最小索引號(hào)(下界)是多少,怎么辦呢?別慌,用UBound和LBound兩個(gè)函數(shù)就可以了。 如,要想知道數(shù)組arr的上界是多少,則:UBound(arr) 要想知道數(shù)組arr的下界是多少,則:LBound(arr) 想知道數(shù)組有多少個(gè)元素,則:UBound(arr)- LBound(arr)+1 如: 復(fù)制內(nèi)容到剪貼板
如果是一個(gè)二維數(shù)組,想知道它的上界是多少,就得指定維數(shù),看一看下面的例子:代碼: Sub ggsmart() 復(fù)制內(nèi)容到剪貼板
六、Join函數(shù)代碼: Sub ggmsart() Join的作用和Split的作用相反。Split是將字符按指定字符轉(zhuǎn)為數(shù)組,Join是將數(shù)組以指定字符分開,連成一個(gè)字符串。如: 復(fù)制內(nèi)容到剪貼板
Join的第二參數(shù),即分隔符可以不指定,在不指定時(shí),默認(rèn)為以空格作分隔符。代碼: Sub ggsmart() 七、將數(shù)組輸入單元格區(qū)域 1、使用循環(huán)輸入 如將存儲(chǔ)了1到60000的數(shù)的數(shù)組寫入A列,則: 復(fù)制內(nèi)容到剪貼板
以上程序是使用循環(huán),將數(shù)組里的元素逐個(gè)寫入單元格,為了對比不同的輸入方式的效率,我加入了計(jì)算時(shí)間的代碼,有了前面的基礎(chǔ),相信讀上面的代碼對大家來說,不會(huì)太困難。代碼: Sub test1() 2、批量寫入 實(shí)際上用一條語句就可以將數(shù)的內(nèi)容寫入單元格區(qū)域中,即:單元格區(qū)域=數(shù)組名 還是上面的例子,我們可改為: 復(fù)制內(nèi)容到剪貼板
這里,我們用“[a1:a60000] = Application.WorksheetFunction.Transpose(arr)”代替了上面代碼For循環(huán),在我的電腦上,程序的效率就提高了25倍以上。 數(shù)組寫入單元格.rar (8.04 KB)
所以在大批量的數(shù)據(jù)需要寫入時(shí),我建議盡量不要用循環(huán)的方式寫入。代碼: Sub test2() 這種批量寫入的方式在上面的例子里其實(shí)我已經(jīng)用到了,相信大家不會(huì)陌生。 這里,我再補(bǔ)充兩點(diǎn)我個(gè)人在學(xué)習(xí)過程中的心得: (1)一維數(shù)組寫入單元格區(qū)域時(shí),這個(gè)單元格必須是水平方向的,也就是一個(gè)一行多列的單元格區(qū)域,如果想寫入垂直區(qū)域,必須使用工作表的Transpose函數(shù)轉(zhuǎn)換一下; (2)和工作表的多單元格數(shù)組公式一樣,數(shù)組寫入單元格時(shí),單元格的區(qū)域必須和數(shù)組的大小一致。 |
|