Excel 與 VBA 財務應用 第六課 (336)

Eugene Chang (張佑成)

February 20th 2025

# Excel 與 VBA 財務應用初階班 ![](https://www.dropbox.com/s/wkfzhogsx7xwlx0/3.png?dl=1) --- # 範例 Excel 檔案 請下載:[Lecture 6 - For 巢狀迴圈範例](https://drive.google.com/uc?export=download&id=1T8_jvUTYSZTkrPrKHlIvuJl3WqgKiBR_) --- ## 範例:計算 FANG(牙尖股)的報酬率 ![](https://drive.google.com/uc?export=download&id=10LTu5DqML19xZjJc6qgBxjKvYuoETTxz) --- # 巢狀迴圈(Nested For Loop) 一個 VBA 迴圈一次只能夠遍歷一個方向 由上往下或由左至右迭代 若今天希望能夠同時往兩個方向迭代 就需要巢狀迴圈 --- # 巢狀迴圈(Nested For Loop) 簡單來説,就是在 For 迴圈内再寫一個 For 迴圈 ```vb Dim i as Integer Dim j as Integer '外面的迴圈會從 1 到 3 For i = 1 To 3 For j = 6 To 8 '當外面的 For 迭代一次,裏面的 For 會全部都迭代 Debug.print "i = " & i & " j = " & j Next j Next i ``` --- # 巢狀迴圈(Nested For Loop) ```sh i = 1 j = 6 i = 1 j = 7 i = 1 j = 8 i = 2 j = 6 i = 2 j = 7 i = 2 j = 8 i = 3 j = 6 i = 3 j = 7 i = 3 j = 8 ``` --- ## 巢狀迴圈(Nested For Loop) 接下來我們就可以用巢狀迴圈計算所有股票的報酬率 ![](https://drive.google.com/uc?export=download&id=1Mg00fbrochg8ZSDoPxPlD4yuqGs4Jgrv) --- # 第二步:比較每一天MSFT與IBM何者的報酬率高 ```vb Dim i as Integer For i = 2 To 25 If Cells(i, "C").value > Cells(i, "E").value Then Cells(i, "F").value = "MSFT" Else Cells(i, "F").value = "IBM" End IF Next i ``` --- ### 範例:比較每一天MSFT與IBM何者的報酬率高 ![](https://drive.google.com/uc?export=download&id=134ezQgOkD2G1F7GycFAbSQ3Bs_feSPqD) --- # 但是... 我們還漏考慮了一個狀況... 若同一天兩支股票的報酬率都是 0 呢? --- # 練習:修改判斷式 可能的結果有三種: 1. MSFT 比較高 2. IBM 比較高 3. 兩者都沒有波動 修改原本的程式碼,讓我們的程式能夠正確處理以上三種狀況 --- # 讓使用者選擇要比較的日期 問題是我們缺乏一個良好的界面 --- # 要如何通過使用者輸入的日期去找到欲查詢的日期? --- # InputBox() 函數 顯示可輸入文字的對話方塊 ![](https://drive.google.com/uc?export=download&id=1t0wp4oC-kBgzz0D_Ux0Q6qsjafuph-SK) --- # InputBox() 函數 InputBox() 函數會將使用者的輸入存入等號左邊的變數 ```vb Dim targetDate as Date targetDate = InputBox("請輸入欲查詢日期:") ``` --- # Cells.Find() 搜尋指定的值所在的儲存格 ```vb Cells.Find(what:=<要查詢的值>, After:=<在哪個儲存格之後>) ``` --- # 練習 利用 `Cells.find()` 查詢 **456** --- # Cells.Find() 搜尋指定的值所在的儲存格 ```vb '將 targetCell 宣告成一個 Range,能夠儲存一個儲存格物件 Dim targetCell as Range '賦值時記得需要加上 Set 關鍵字 Set targetCell = Cells.Find(what:=targetDate, After:=Cells(4, "D")) '檢查是否搜尋到正確的儲存格 Debug.print targetCell.row Debug.print targetCell.column ``` --- # Cells.find() 但是若找不到指定的值,就會回傳 Nothing ```vb Sub FindEx() Dim findCell As Range Set findCell = Cells.Find(What:=911, After:=Cells(4, "D")) End Sub ``` --- ## Nothing 空值 若使用者沒有輸入任何訊息,InputBox() 會回傳 `Nothing`,也就是 VBA 的空值 ---- # TypeName() 函數 檢查一個變數内的資料型別 ```vb Sub FindEx() Dim findCell As Range '尋找一個不存在的數字,若 Cells.Find() 找不到便會回傳 Nothing Set findCell = Cells.Find(What:=911, After:=Cells(4, "D")) Msgbox(TypeName(findCell)) End Sub ``` 就會顯示 `Nothing` --- ### 0 vs Nothing 0 與空值是兩回事,不要搞混了! 0 是表示有無 空值是用來代表**不存在**的意思 ![](https://drive.google.com/uc?export=download&id=1HSLZ5vGaG8XQ7G4BFNpCbiPFJfk_8z6c) --- # 錯誤處理 爲了防範 Nothing 往下執行破壞我們的程式,我們需要防錯機制 --- # Exit Sub 强制推出目前的 `Sub` 子程序 ```vb Sub ExitSubEx() Msgbox("我會被執行哦!") Exit Sub Msgbox("我不會被執行哦!") End Sub ``` --- # Exit Sub 修改原本的程式碼,加入 `Exit Sub` 避免程式碼出錯 ```vb Sub FindEx() Dim findCell As Range Dim targetDate As Date Set findCell = Cells.Find(What:=targetDate, After:=Cells(4, "D")) If findCell Is Nothing Then MsgBox ("找不到值哦,啾咪!") Exit Sub End If End Sub ``` --- # On Error Goto --- # On Error Goto ```vb On Error Goto <標籤名稱> 一段有可能出錯的程式碼 標籤: 若出錯了,就跳到這邊,不往下執行 ``` --- # On Error Goto ```vb Sub FindEx() Dim findCell As Range Dim targetRow as Integer Dim targetCol as Integer '要是 Cells.Find 出錯,就跳到 FindFail On Error Goto FindFail Set findCell = Cells.Find(What:=911, After:=Cells(4, "D")) targetRow = findCell.Row targetCol = findCell.Column Debug.print "cell.row =" & targetRow Exit Sub FindFail: Msgbox("找不到指定的值!") End Sub ``` --- # 更多關於 On Error Goto 官方文件:[連結](https://docs.microsoft.com/zh-tw/office/vba/language/reference/user-interface-help/on-error-statement) --- # 判斷走勢 現在我們再打造另一個功能:判斷 MSFT 與 IBM 兩支股票的走勢是否相同 ![](https://drive.google.com/uc?export=download&id=1hMMUnEYB425OMxlk4BhkYGBmSXvnwCKV) --- # 我們的邏輯 寫成判斷式非常可怕... ```vb If (msftReturn > 0 And ibmReturn > 0) Or (msftReturn < 0 And ibmReturn < 0) Or (msftReturn = 0 And ibmReturn = 0) Then ... ``` --- # Sgn() 函數 判斷一個數字是正數、負數、或是0 若正數,則回傳 1 若負數,則回傳 -1 若是零,則回傳 0 --- # 練習 利用 Sgn() 簡化判斷式 --- ## 回家作業 請下載:[Lecture 6 - 稅率計算機](https://drive.google.com/uc?export=download&id=15xuZOvuBsRUpFemwssqh_SuKjR7zZwWM) --- 根據範例Excel檔的資料,計算第一年的月薪數目 ```vb Sub GetMonthlySalary() End Sub ``` --- ## 回家作業 根據範例Excel檔的資料,計算每一年的月薪數目 ```vb Sub GetYearlySalary() End Sub ``` --- ## 回家作業 根據範例Excel檔的資料,計算每一年的年薪數目 ```vb Sub TotalIncome End Sub ``` --- ## 回家作業 根據範例Excel檔的資料,計算一輩子的收入數目 ```vb Sub GetLifeSalary() End Sub ``` --- # For Each 迴圈 將一個儲存格範圍内所有的**儲存格物件**迭代一次 順序是固定從**上往下,由左至右** ```vb '宣告變數的型別為一個 range Dim cell As Range '迭代從 A1 到 C3 的儲存格 For Each cell In Range("A1:C3") Debug.Print cell.Value Next cell ``` --- # While 迴圈 另一種常用的迴圈 ```vb While <條件式> '若條件式成立就繼續執行... Wend ``` --- # 範例 寫一支 VBA 程式,用 While 迴圈將 1 至 100 的加總算出來 ```vb Dim sum As Integer: sum = 1 Dim count As Integer: count = 1 '若 count 還沒大於等於 100 就繼續迭代 While count <= 100 '每迭代一次就將 sum 加上 count 值 sum = sum + count '每迭代一次就將 count 加上 1 count = count + 1 Wend Debug.print "sum: " & sum ``` --- # Do While 迴圈 ```vb Dim count As Integer: count = 1 Do While count <= 10 count = count + 1 Debug.print count Loop ``` --- # 當你在寫 While 迴圈時 ## 請想好你的結束迴圈的機制! ## 請想好你的結束迴圈的機制! ## 請想好你的結束迴圈的機制! *很重要所以說三次 --- # Exit Do 提前結束迴圈 ```vb Dim count As Integer: count = 1 '讓程式一直執行 Do While True count = count + 1 Msgbox(count) If count = 10 Then Exit Do End If Loop Msgbox("我在迴圈外面!") ``` --- # For vs While 當你很明確的知道迴圈需要執行幾次,使用 For Loop 當你不確定迴圈需要執行幾次,使用 While Loop

Thanks for Watching

Contact: yuyueugene84@gmail.com

Download PDF