Professional Documents
Culture Documents
開啟新檔
Sub open_new_file ()
Workbooks.Add
End Sub
開起舊檔
Sub open_old_file ()
Workbooks.Open(“D:\... .xlsx”)
End Sub
使用物件變數方式開啟舊檔
Sub open2 ()
Dim Wkb As Workbook
Set Wkb=Workbooks.Open(FileName:=”… .xlsx”)
End Sub
截取檔案名稱
Sub catch()
Dim wkb As Workbook
Set wkb = Workbooks.Open(“D:\test.xlsx”)
MsgBox wkb.Name
MsgBox wkb.FullName
MsgBox wkb.Path
End Sub
->執行結果
MsgBox wkb.Name
test.xlsx
MsgBox wkb.FullName
D:\test.xlsx
MsgBox wkb.Path
D:
將已開啟的活頁簿變為作用中的活頁簿
Sub 啟動活頁簿()
Workbooks(“test.xlsx”).Activate
End Sub
另存新檔
Sub save_as()
Dim wkb As Workbook
Set wkb=Workbooks.Open(“D:\test.xlsx”)
Wkb.SaveAs Filename:=”test1.xlsx”
End Sub
直接存檔
Sub save()
ActiveWorkbook.Save
End Sub
關閉檔案
關閉檔案時會跳出詢問視窗,詢問是否儲存檔案
ActiveWorkbook.Close
直接儲存並關閉
ActiveWorkbook.close SaveChanges:=True
直接關閉但不儲存
ActiveWorkbook.Close SaveChanges:=False
視窗
啟動視窗
Sub window()
Workbooks(“test.xlsx”).Activate ‘啟動活頁簿
Windows(“test.xlsm”).Activate ‘啟動視窗
End Sub
最大化或最小化視窗
Sub 視窗調整()
Windows(1).WindowState=xlMaximized ‘最大化
Windows(2).WindowState=xlMinimzed ‘最小化
End Sub
視窗關閉
Sub close()
Windows(1).close
Windows(“test.xlsx”).close
Workbooks(“temp.xlsm”).close
End Sub
工作表
儲存格、工作表與活頁簿的操作
儲存格
Range
Range 用來選取要操作的儲存格。
Range(“A1”).Value=”Hi!” ‘將 Hi 字串放入儲存格
Range(“A1:B4”).Value= 123 ‘將每個儲存格填入 123
Range(“A1:A3,D1:E2”).Value=100 ‘可以給動任意範圍
Cells
除了 Range 之外,Cells 也是一個可以用來操作儲存格的物件,其功能跟
Range 都差不多,只不過它是使用行與列的編號來指定儲存格,這種指定方式
在撰寫自動化程式時會比較好用。
Cells(1,1).Value=123 ‘等同於 Range(“A1”).Value=123
Range 與 Cells 搭配
Range(Cells(1,1),Cells(3,3)).Value=333
選擇某一個範圍內之儲存格
Range(Cells(1,1),Cells(3,3)).Select
Rows 與 Colums
若要選取整個欄或列可以使用 Colums 或 Rows
複製與貼上
Range(“資料範圍”).Select
Selection.Copy
Range(“貼上之位置”).Select
ActiveSheet.Paste
刪除儲存格內容
1.
Range(“資料範圍”).ClearContents
2.
Range(“資料範圍”)value=””
工作表
更改工作表中儲存格
以工作表名稱指定工作
Worksheets("工作表 1").Range("A1").Value = "工作表 1 的 A1"
Worksheets("工作表 2").Range("A1").Value = "工作表 2 的 A1"
以工作表順序指定工作表
Worksheets(1).Range("A1").Value = "工作表 1 的 A1"
Worksheets(2).Range("A1").Value = "工作表 2 的 A1"
新增工作表
Worksheets.Add
改變工作表名稱
Worksheets(“工作表名稱”or 編號).Name= “新的名稱”
其他功能
計算工作表數目
Worksheets.Count
活頁簿
更改活頁簿中某工作表中儲存格
Workbooks("活頁簿名稱"or 編號).Worksheets(“工作表名稱”or 編號).
Range("儲存格").Value = 內容
改變活頁簿名稱
Workbooks(“活頁簿名稱”or 編號).Name=“新的名稱”
打開活頁簿
Workbooks.Open "路徑"
指定活頁簿
Workbooks("名稱").Activate
活頁簿存檔
Workbooks("名稱").Save
關閉活頁簿
Workbooks("名稱").Close
*關閉 excel 程式: Application.Quit
變數
變數的宣告與初始值
變數類型
整數-Integer(5, 12,…)
浮點數-Double (1.23…)
布林值-Boolean(True..)
字串-String(“Hellow!”)
時間-Data
未經宣告的變數
萬用型變數
萬用類型變數,也就是一種可以儲存任何資料的類型,其稱為 Variant,其使
用方式與一般的類型類似。
Dim x As Variant
x = "G.T.Wang"
MsgBox "My name is " & x
x = 123
MsgBox "The value is " & x
如果在宣告變數時不指定變數類型,則 VBA 預設會將變數視為 Variant 類型,
所以這兩種寫法的效果是相同的。
Dim x As Variant
Dim x ' 預設為 Variant
**Variant 類型的變數通常可用於從 Excel 儲存格中讀取使用者輸入的資料,由
於使用者輸入的資料變異性很大,可能會是任何類型,所以直接使用 Variant
來儲存會比較方便。
雖然 Variant 非常方便,但它的缺點就是程式執行效能較差,所以除非必要,
在一般的情況下還是使用固定的變數類型較佳。
變數範圍
區域變數
在一般的 Sub 副程式中宣告的變數,其範圍僅限於該副程式,也就是所謂的區
域變數。
全域變數
若希望一個變數可以在整個模組內的副程式中使用,則可將變數宣告於副程式
之外,建立模組層級的變數。
跨模組變數
如果在程式比較複雜時,一個應用程式中可能會有好多個模組,一般模組層級
的變數只能在該變數隸屬的模組之內被存取,若要在其他模組之內也可以存取,
就必須將變數宣告為公開(public)的變數,宣告方式是將 Dim 改為 Public。
常數
如果希望變數的內容在程式的執行過程中都是固定的,不會不小心被更改,將
Dim 改成 Const,即宣告為常數。
運算子
算數運算子
運算子 說明 優先順序
^ 冪運算(次方) 1
* 乘法 2
/ 除法 2
\ 整數除法 3
Mod 餘數 4
+ 加法 5
- 減法 5
字串運算
運算子 說明
& 串接兩個字串
Text1=”Hi!~”&”Mason”
比較運算子
運算子 說明
= 等於
<> 不等於
< 小於
> 大於
<= 小於或等於
>= 大於或等於
邏輯與位元運算子
運算子 說明
And AND 運算
Or OR 運算
Not NOT 運算
Xor XOR 運算
Dim a, b, c, x, y, z As Integer
a = 10
b=8
c=6
x = (a And b) ' 結果為 8
y = (a And c) ' 結果為 2
z = (b And c) ' 結果為 0
MsgBox "x = " & x & ", y = " & y & ", z = " & z
條件判斷
如果希望電腦依據設定的條件判斷後做出不同的結果,就會需要使用條件判斷
的語法。
IF THEN ,ELSE
IF 條件判斷式 THEN
條件成立時執行
ELSE
條件不成立時執行
END IF
Dim grade As Integer
grade= 92 ' 分數
If grade > 60 Then
MsgBox "及格!"
Else
MsgBox "當掉!!"
End If
IF THEN, ELSE IF
IF 條件判斷式 1 THEN
條件 1 成立時執行
ELSEIF 條件判斷式 2 THEN
條件 2 成立時執行
ELSE
都不成立時執行
END IF
Dim grade As Integer
grade= 92 ' 分數
If grade > 60 Then
MsgBox "及格!"
Elseif grade >50 Then
MsgBox "可補考!!"
Else
MsgBox "當掉!!"
End If
SELECT CASE
Dim Number
Number = 8 ' Initialize variable.
Select Case Number ' Evaluate Number.
Case 1 To 5 ' Number between 1 and 5, inclusive.
Debug.Print "Between 1 and 5"
' The following is the only Case clause that evaluates to True.
Case 6, 7, 8 ' Number between 6 and 8.
Debug.Print "Between 6 and 8"
Case 9 To 10 ' Number is 9 or 10.
Debug.Print "Greater than 8"
Case Else ' Other values.
Debug.Print "Not between 1 and 10"
End Select
迴圈控制是各種程式語言都會有的基本功能,他的作用是可以讓電腦重複執行
某一段類似的動作,在運用得當的情況下,可以幫助使用者快速處理大料的資
料,既省時又省力。
FOR
Dim i, s As Integer
s=0
For i = 1 To 10
s=s+i
If i >= 4 Then
Exit For ' 中斷迴圈
End If
Next i
MsgBox "s = " & s
**Exit For: 如果想要中途跳出迴圈,可以加上 Exit For 來中斷迴圈。
FOR EACH
DO WHILE
Do While 條件判斷式
運算內容
Loop
Do 迴圈可以重複執行某一段程式碼,直到指定的條件判斷式成立或是不成立的
時候,才停止迴圈的執行。
Do 條件判斷式
運算內容
Loop While
While 的條件判斷式也可以放在迴圈結尾處,這樣的話迴圈在執行時就會先執
行第一次的迭代,執行完第一次之後才判斷是否要繼續執行下一次的迭代,如
果條件成立則繼續執行,若不成立就立刻中止迴圈,這樣的寫法只是檢查條件
判斷式的時機不同,觀念上大同小異。
** Exit Do:欲在 Do Loop 迴圈執行到一半時終止迴圈的執行,可以在迴圈中加
入 Exit Do 用來跳出迴圈。
Dim i, s As Integer
s=0
i=1
Do While i <= 10
s=s+i
i=i+1
Loop
MsgBox "s = " & s
DO UNTIL
Do Until 條件判斷式
運算內容
Loop
Do Until Loop 迴圈與 Do While Loop 迴圈在條件的判斷上剛好相反,Do
Until Loop 迴圈會在指定條件不成立(判斷為 False)時繼續執行,當判斷條
件成立時(判斷為 True)則終止迴圈。
Do 條件判斷式
運算內容
Loop Until
Do Until Loop 迴圈也可以將條件判斷式放在迴圈的最後面,這跟上面 Do
While Loop 迴圈也很類似。
Dim i, s As Integer
s=0
i=1
Do Until i > 10
s=s+i
i=i+1
If i > 4 Then
Exit Do ' 中斷迴圈
End If
Loop
MsgBox "s = " & s
Dim i, s As Integer
s=0
i=1
Do
s=s+i
i=i+1
Loop Until i > 10
MsgBox "s = " & s
其他結構
WITH
With 對象
.[属性 1] = 屬性值
.[属性 2] = 屬性值
…
End with
VBA 中,With 結構用於組合同一個對象的多個屬性和方法,避免重複寫同一
個對象名稱,提高程式撰寫效率與簡潔性。
在圖表中新增其他曲線
ActiveSheet.ChartObjects("圖表 1").Activate
With ActiveChart.SeriesCollection.NewSeries
.XValues = Range("A15:a20")
.Values = Range("b15:b20")
.Name = Range("a14").Value
End With
以上等同於
ActiveChart.SeriesCollection.NewSeries .XValues = Range("A15:a20")
ActiveChart.SeriesCollection.NewSeries .Values = Range("b15:b20")
ActiveChart.SeriesCollection.NewSeries .Name = Range("a14").Value
字串處理
字串的宣告與定義
連接字串
其他字串相關的函數
字串建立函數
STRING 函數
用來建立重複字元的字串。
Dim text1, text2 As String
text1 = String(6, "A") '產生 AAAAAA
text2 = String(3, 100) '產生 ddd (100 就是指 d 的 ASCII 編碼)
字串截取函數
Len 函數
可以用來取得一個字串的長度。
INSTR 函數
INSTR(母字串, 子字串)
用來尋找一個子字串位於某個字串的位置。
Dim pos As Integer
pos = InStr("Hello, world.", "world")
MsgBox "pos = " & pos
**InStr 預設在搜尋時,英文的大小寫是視為不同的,若希望不分大小寫,可將
比對方式參數設定為 vbTextCompare。
Dim pos As Integer
pos = InStr(1, "Hello, World.", "world", vbTextCompare)
MsgBox "pos = " & pos
**這裡的第一個參數是用來指定搜尋的起始位置,在上面的範例中我們將這個
參數省略掉了,在這裡使用比對方式參數時就要加進來,這樣執行之後 InStr
在比對字串時就會將英文字母的大小寫視為相同的。
LEFT 函數
LEFT(字串, 截取長度)
從左邊開始擷取出子字串,第一個參數是完整的字串,而第二個參數則是要擷
取的子字串長度。
**RIGHT 則功能相反,其由右邊開始截取字串。
MID 函數
MID(字串, 左起第幾個位置開始, 截取長度)
MsgBox Mid("This is a message.", 6, 2) ‘is
**如果使用 Mid 時不指定擷取的字串長度,則 Mid 就會從指定的位置開始擷
取直到整個字串的結尾。
字串分割函數
SPLIT 函數
Split 函數其傳回的結果就是一個一維的陣列,將分割的字串分別放入陣列內。
Dim arr As Variant
Dim ub As Integer
' 取得陣列長度
ub = UBound(arr)
' 輸出陣列內容
For i = 0 To ub
MsgBox (i & " = " & arr(i))
Next i
刪除字串空白字元函數
LTRIM 函數
LTRIM(字串)
用來移除左邊開頭所有的空白。
Dim mystr As String
mystr = " Hello, world."
MsgBox "After LTrim : " & LTrim(mystr)
RTRIM 函數
功能則是移除字串右邊所有的空白。
TRIM 函數
功能是移除開頭與結尾的所有空白。
SPACE(數字)
插入想要多少空白
字串取代函數
Replace 函數
Replace(字串, 被替換文字, 用來替換之文字[, 起始位置[, 替換次數[, 比對方
式]]])
Dim mystr As String
mystr = "This is a message."
newstr = Replace(mystr, "message", "dog")
MsgBox "After Replace : " & newstr
字串比較函數
STRCOMP 函數
STRCOMP(字串一, 字串二, [比對方式])
前兩個參數就是兩個要比較的字串,而第三個比對方式參數可用來指定是否區
分 大 小 寫 , 預 設 值 是 vbBinaryCompare ( 大 小 寫 視 為 不 同 ) , 若 設 定 為
vbTextCompare 則會將大小寫視為相同。
狀況 傳回數值
字串一 < 字串二 -1
字串一 = 字串二 0
字串一 > 字串二 1
字串搜尋函數
INSTR 函數
INSTR(目標字串, 欲搜尋之子字串)
字串反轉
STRREVERSE 函數
STRREVERSE(字串)
功能為將字串順序顛倒。
VAL 函數
VAL(字串)
功能為將字串轉成數值
陣列
一維陣列
多維陣列
自訂索引範圍
某些時候索引值由 0 開始會使得陣列處理起來有些綁手綁腳,若要改變陣列索
引的起始值,可以自行指定索引範圍的開始與結束值。
Dim MyArray2(1 To 3) As Integer ‘MyArray(1), MyArray(2), MyArray(3)
陣列初值給定
Array 函數可以讓設計者輸入一連串的資料,直接建立一個陣列,這種寫法對
於初始化一些包含常數的靜態陣列非常有用。
Dim arr As Variant
arr = Array(1, 2, 3)
MsgBox (arr(1))
動態陣列
一般的陣列在宣告時就必須決定好陣列的大小,但是有的時候我們無法事先預
知程式所需要的陣列大小,要等到實際執行時才會知道需要多少空間,這時候
就可以使用動態陣列的方式來儲存資料。
動態陣列(dynamic arrays)的特點就是可以動態改變陣列的大小,在空間不
足時可以擴增,而空間太大時也可以縮減。
' 宣告動態陣列
Dim 陣列名稱() As Integer
' 調整陣列大小
ReDim 陣列名稱(陣列的結尾索引值)
**釋放記憶體: 當動態陣列使用完畢之後,我們可以使用 Erase 將系統配置給動
態陣列的記憶體收回。
Erase 陣列名稱
** LBound 與 UBound 是用來查詢陣列索引下限與上限的函數。
其他應用
分割字串
' 取得陣列長度
ub = UBound(arr)
' 輸出陣列內容
For i = 0 To ub
MsgBox (i & " = " & arr(i))
Next i
或是我們也可以使用 For Each 的方式來處理陣列,這樣就可以省去取得陣列長
度的步驟。
' 使用 For Each 輸出陣列內容
For Each s In arr
MsgBox (s)
Next s
若要將陣列的所有元素串接成一個字串,可以使用 Join 函數。
Dim str As String
MsgBox (str)
篩選陣列元素
Filter 函數可以篩選陣列的每個元素,將符合條件的元素拿出來,組成新的陣列
並傳回。
Dim arr, flt As Variant
' 建立測試用陣列
arr = Array("ABC", "BCD", "CDE")
' 輸出結果
For Each x In flt
MsgBox ("result: " & x)
Next x
取得陣列元素位置
' 建立測試用陣列
arr = Array("ABC", "BCD", "CDE")
子程式
子程式的參數
傳值與傳參考呼叫
在預設的情況下,如果我們在子程序改變的傳入參數的值,原來的值也會
跟著改變,也就是 VBA 為傳址呼叫(call by reference)。如果不想要讓
子程序去改變原本的變數值,可以改用傳值呼叫(call by value)的方式
來定義子程序的參數。(在子程式參數前加上 ByVal)
Sub mySub3(ByVal x As Integer) ‘call by value
x=x+1
End Sub
函數
Sub test()
Dim y as integer
y=sum(5,9)
End Sub
Function sum(x1 As Integer, x2 As Integer) As Integer
Sum=x1+x2
End Function
函數的參數
函數的預設參數值用法與子程序相同,同樣都是使用 Optional。
Function myFun2(Optional x As Integer = 3, Optional y As Integer = 4) As Integer
myFun = x + y
End Function
傳值與傳參考呼叫
將選定範圍內所有偶數加總
Function SumEvenNumbers(r As Range) As Integer
Dim c As Range
SumEvenNumbers = 0
' 將範圍內的每一個儲存格資料取出
For Each c In r
' 檢查是否為偶數
If c.Value Mod 2 = 0 Then
' 將偶數加總起來
SumEvenNumbers = SumEvenNumbers + c.Value
End If
Next c
End Function
時間
日期與時間是一種比較特別,但是也時常會被使用到的資料類型,在 VBA 中我
們可以使用 Date 這種特殊的變數類型來儲存日期與時間的資料,同時 VBA 中
也內建了許多用來處理日期與時間的工具函數。
設定日期
設定時間
取得現在時間
' 現在日期
d = Date
MsgBox ("現在是:" & d)
' 現在時間
d = Time()
MsgBox ("現在是:" & d)
' 現在日期與時間
d = Now()
MsgBox ("現在是:" & d)
**Timer 函數可以傳回從當天 12:00 AM 到目前的秒數,精確度可以到千分之一
秒。
日期與時間的運算
DateAdd 函數可以計算日期或時間的加減法運算,算出某段時間之後的時
間點。
Dim d As Date
d = "01-Jan-2013"
MsgBox ("一年後:" & DateAdd("yyyy", 1, d))
MsgBox ("一季後:" & DateAdd("q", 1, d))
MsgBox ("一月後:" & DateAdd("m", 1, d))
MsgBox ("一天後:" & DateAdd("d", 1, d))
MsgBox ("一週後:" & DateAdd("ww", 1, d))
d = "01-Jan-2013 12:00:00"
MsgBox ("一小時後:" & DateAdd("h", 1, d))
MsgBox ("一分鐘後:" & DateAdd("n", 1, d))
MsgBox ("一秒鐘後:" & DateAdd("s", 1, d))
DateDiff 函數可以計算兩個時間點之間的時間間隔。
Dim d1, d2 As Date
d1 = "2017/10/02"
d2 = "2018/11/14"
d1 = "01-Jan-09 00:00:00"
d2 = "01-Jan-10 23:59:00"
MsgBox ("相差小時: " & DateDiff("h", d1, d2))
MsgBox ("相差分鐘: " & DateDiff("n", d1, d2))
MsgBox ("相差秒鐘 : " & DateDiff("s", d1, d2))
取出部分日期或時間
取出目標 函數
年 Year(變數)
月 Month(變數)
日 Day(變數)
星期 Weekday(變數)
時 Hour(變數)
分 Minute(變數)
秒 Second(變數)
**Weekday 預設會傳回 1 到 7 的整數,分別代表星期日到星期六,如果要取
得星期名稱,可再使用 WeekdayName 函數轉換,而月份名稱也是用類似的
方式,使用 MonthName 函數轉換。
WeekdayName(Weekday(變數))
MonthName(Month(變數))
日期與時間輸出格式
FormatDateTime 函數可依據指定的格式輸出日期與時間,可用的輸出格
式如下:
FormatDateTime(變數, 格式代碼)
格式代碼 說明
0 或 vbGeneralDate 完整格式(預設值)
1 或 vbLongDate 完整日期
2 或 vbShortDate 簡短日期
3 或 vbLongTime 完整時間
4 或 vbShortTime 簡短時間
檔案的輸入與輸出
檔案讀入
這個語法跟之前讀檔的語法類似,只是把開檔的模式改為 Output,檔案
位置就填入要寫入的檔案路徑,而檔案代碼也是自己取一個不重複的數字
即可。開啟檔案之後,即可使用 Print 函數將指定的資料寫入檔案中。
' 開啟文字檔,使用編號 #num 代表檔案代碼
Open “檔案路徑” For Output As #檔案編號
附加方式寫入檔案
自動選擇檔案代碼
如果要使用程式自動開啟多個檔案,不想使用手動指定檔案代碼的話,可以使
用 FreeFile 這個函數自動取得可用的檔案代碼。
Dim FileCount As Integer
Dim FileNumber As Integer
Dim FileName As String
' 使用迴圈自動寫入 5 個檔案
For FileCount = 1 To 5
' 自動取得檔案代碼
FileNumber = FreeFile()
' 檔案名稱
FileName = "C:\ExcelDemo\demo_output_" & FileCount & ".txt"
' 開啟檔案
Open FileName For Output As #FileNumber
' 寫入檔案
Print #FileNumber, "Hello, World"
' 關閉檔案
Close #FileNumber
Next FileCount
事件
當 使 用 者 在 Excel 中 進 行 某 些 特 定 的 操 作 時 , 就 會 觸 發 所 謂 的 事 件
(events),例如當使用者選擇一張工作表時,就會觸發工作表選擇的事
件,而像點選儲存格或儲存檔案等動作也都會觸發對應的事件。
程式設計者可以靠著各種事件的的觸發來設計可以自動執行的 VBA 程式,
例如在選擇工作表時,自動執行某些 VBA 程式等。以下介紹如何在 Excel
VBA 中使用事件。
使用說明
STEP 1
在工具列中點選「Visual Basic」,開啟 Visual Basic 編輯器,或是直接使用快
速鍵 Alt + F11 開啟。
STEP 2
如果要處理活頁簿的事件,就要把事件處理子程序寫在活頁簿中,若是要處理
單張工作表的事件,就放在對應的工作表中。這裡我們以活頁簿事件來作為示
範,點擊兩下活頁簿,開啟程式碼編輯視窗。
STEP 3
選擇活頁簿(Workbook)。
如果只要處理特定工作表中的儲存格變更事件,也可以把事件處理子程序寫在
對應的工作表中。
STEP 4
這時候程式碼編輯視窗內會出現一個預設的 Workbook_Open 處理子程序,這
個就是對應到活頁簿開啟事件(open event)的處理子程序,寫在這裡的程式
碼就會在活頁簿開啟時自動執行。
在右上角的下拉式選單中可以選擇其他的事件,建立不同事件的處理子程序。
這個例子我們先以 Workbook_Open 處理子程序做為示範。
STEP 5
在 Workbook_Open 子程序中,填入當活頁簿開啟時所要執行的程式碼,這裡
我以一行簡單的 MsgBox 輸出訊息作為示範。
STEP 7
存檔之後,先將 Excel 檔案關閉,再重新打開,而開啟時 Workbook_Open 處
理子程序中的 VBA 程式就會自動被執行,所以就會看到我們剛剛寫的提示訊息。
參考資料
1. https://blog.gtwang.org/programming/vba/