VBA錯誤處理:交叉運用ChatGPT與Claude,找出工作表誤判原因

VBA錯誤處理不只是讓程式繼續執行。贊贊小屋請ChatGPT撰寫匯率備份程式,卻遇到工作表已存在的誤判,再交叉運用Claude找出變數保留舊參照的原因,加入Set ws = Nothing後,回到Excel實測修正成功。文章依序記錄排查過程,並整理如何向AI提供證據、驗證結果。

VBA錯誤處理特色圖:人物遇到程式警告、與AI助手一起檢查、回到Excel實測確認的三段流程,標題為「VBA錯誤處理」與「交叉運用AI,找原因、做驗證」

一、向ChatGPT提出下載匯率的需求

贊贊小屋先在ChatGPT貼上臺灣銀行的匯率網址,再用一句話交代需求:

傳給ChatGPT的需求https://rate.bot.com.tw/xrt?Lang=zh-TW
希望設計一個 VBA 程式,可以自動去下載臺灣銀行的匯率。寫到工作表中,並且把工作表的名稱設定為「最新匯率」

ChatGPT回覆這個版本適用於Excel 2016,並說明程式會處理三件事:自動連線到臺灣銀行匯率網站、把資料寫進「最新匯率」工作表,而不是目前選取的工作表;如果「最新匯率」已經存在,就清除舊資料後重新下載,不存在就自動建立。

程式碼之後,ChatGPT另外列了「執行前請注意」。贊贊小屋特別留意其中三項:活頁簿要另存成「Excel 啟用巨集的活頁簿(.xlsm)」才能保存VBA程式;這個版本會刪除B至E欄沒有數值的資料列,但網頁匯入後的欄位位置可能隨網站格式改變,實際結果若出現多餘資料或欄位錯位,就要再依匯入結果調整;每次執行都會重新下載網頁資料,並清除「最新匯率」工作表原有內容,所以不要在這張工作表存放需要保留的其他資料。

請AI寫自動化程式時,需求最好把「資料從哪裡來、放到哪裡、再次執行時怎麼處理」三件事交代清楚。這次的第一句話已經包含來源網址與目標工作表名稱,ChatGPT才能順勢補上「工作表不存在就新增、存在就更新」的處理。另外,程式中的ws.Cells.Clear會清除儲存格內容與格式,這也是ChatGPT提醒不要在「最新匯率」放其他資料的原因:它應該當成專門接收下載資料的工作表。從提出需求到取得匯率資料的另一次完整操作,可以參考Excel 自動抓取網頁資料:利用 VBA 與 AI 自動更新 Excel 表格。

在ChatGPT貼上臺灣銀行匯率網址,要求用VBA下載匯率並寫入名為「最新匯率」的工作表,ChatGPT列出三項處理方式 ChatGPT的「執行前請注意」:存成.xlsm、資料整理限制、每次執行會清除「最新匯率」原有內容 需求整理卡:資料來源、資料目的地與再次執行方式,三件事都要說清楚

二、將VBA程式放入模組並執行

接下來是把ChatGPT給的程式放進Excel;完整的貼上、存檔與執行步驟,也可以參考ChatGPT寫ExcelVBA:1鍵完成自動化的教學。在準備存放匯率資料的活頁簿按Alt+F11,開啟「Microsoft Visual Basic for Applications」編輯器,從上方選單選「插入」→「模組」。左側「專案-VBAProject」下會出現「模組」資料夾與「Module1」,贊贊小屋把程式貼進右側的程式碼視窗,第一行就是Sub 取得臺灣銀行匯率()。程式完整內容如下:

VBA程式|取得臺灣銀行匯率()Sub 取得臺灣銀行匯率()
    Dim ws As Worksheet
    Dim 網址 As String
    Dim 最後列 As Long
    Dim i As Long
    '設定臺灣銀行匯率網址
    網址 = "https://rate.bot.com.tw/xrt?Lang=zh-TW"
    '尋找「最新匯率」工作表
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("最新匯率")
    On Error GoTo 錯誤處理
    '如果工作表不存在,就自動新增
    If ws Is Nothing Then
        Set ws = ThisWorkbook.Worksheets.Add
        ws.Name = "最新匯率"
    End If
    '清除舊資料
    ws.Cells.Clear
    '從臺灣銀行網站匯入網頁表格
    With ws.QueryTables.Add( _
        Connection:="URL;" & 網址, _
        Destination:=ws.Range("A1"))
        .WebSelectionType = xlAllTables
        .WebFormatting = xlWebFormattingNone
        .Refresh BackgroundQuery:=False
        .Delete
    End With
    '刪除沒有匯率數字的多餘資料列
    最後列 = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    For i = 最後列 To 1 Step -1
        If Application.WorksheetFunction.Count( _
            ws.Range("B" & i & ":E" & i)) = 0 Then
            ws.Rows(i).Delete
        End If
    Next i
    '調整內容
    ws.Columns.AutoFit
    '回到最新匯率工作表
    ws.Activate
    MsgBox "臺灣銀行匯率下載完成!", vbInformation
    Exit Sub
錯誤處理:
    MsgBox "下載匯率時發生錯誤。" & vbCrLf & _
           "請檢查網路連線、工作表名稱或網站是否正常。", _
           vbExclamation
End Sub

回到Excel按Alt+F8選擇巨集執行,或在編輯器把游標放進Sub內按F5。程式跑完後,Excel新增了「最新匯率」工作表,美金、港幣、英鎊、澳幣等幣別的匯率依序排列,同時跳出訊息「臺灣銀行匯率下載完成!」。

不過仔細看資料,F、G欄是「查詢」兩個字,H到K欄又重複了前面B到E欄的數字,而且第一列直接就是「美金」。所以這時只能說「取得了網頁上的匯率資料」,還不能說已經整理成乾淨的匯率表。「取得資料」和「整理資料」是兩件事,訊息方塊顯示完成,只代表程式跑完,資料是否符合預期,仍要自己核對幣別、欄位與數值。程式裡的ThisWorkbook指的是存放這段巨集的活頁簿,所以模組要插在準備存放資料的那一本檔案裡;存檔時也記得選.xlsm,否則VBA程式不會保留。另外,臺灣銀行匯率頁面說明牌告匯率資訊是靜態顯示,不會隨後續異動自動更新,所以程式取得的是下載當下的網頁資料,不是持續更新的即時報價。

VBA編輯器中專案總管出現Module1模組,右側程式碼視窗貼上Sub 取得臺灣銀行匯率() 「最新匯率」工作表顯示各幣別匯率並跳出「臺灣銀行匯率下載完成!」訊息,欄位中仍有「查詢」與重複資料 操作流程卡:開啟編輯器、插入模組、貼上完整程式、執行並檢查,下載完成不等於資料已整理完成

三、複製工作表卻出現已存在的警告

有了每天可更新的「最新匯率」,贊贊小屋接著想把當天的匯率保存下來,作為每日備份。於是再請ChatGPT撰寫第二支程式,需求是:

傳給ChatGPT的第二個需求我希望設計一個 VBA 程式,去複製一個名稱是「最新匯率」的工作表。複製之後,將它重新命名為最新的日期,用 6 個數字(分別是年月日)去命名。

ChatGPT確認採用yymmdd格式,並用表格說明:原始工作表是「最新匯率」,如果執行日期是2026年10月17日,複製後的工作表名稱就是「261017」,原始工作表保留不修改。要注意這裡的261017只是ChatGPT舉的範例日期,贊贊小屋實際執行時,程式產生的名稱是「261027」。

程式貼進模組執行後,Excel沒有複製工作表,而是跳出一個警告視窗:「工作表「261027」已經存在,請勿重複複製!」可是畫面下方的工作表標籤只有「最新匯率」和「工作表1」,根本沒有「261027」。

這個警告不是Excel自己發出的錯誤訊息,而是程式裡用MsgBox寫的提示文字。程式沒有語法錯誤,能夠順利執行,只是用來判斷「今天的工作表是否存在」的邏輯得到了錯誤的結果。這類「能執行、但結果與事實不符」的情況稱為邏輯錯誤,Excel不會主動報錯,必須從程式如何判斷去追查。日期命名採用Format(Date, "yymmdd"),在一般西曆設定下會得到兩位數年、月、日的六位數字串。要注意名稱取自電腦當天的日期,不等於銀行的掛牌日期,如果早上下載、晚上才複製,名稱仍是當天日期。如果想把每天的匯率另外整理成持續累積的紀錄表,可以參考Excel 自動產生報表:用 VBA 建立每日匯率紀錄。

向ChatGPT提出複製「最新匯率」並以六位數日期命名的需求,回覆以261017作為範例日期 Excel警告「工作表「261027」已經存在,請勿重複複製!」,但下方標籤只有「最新匯率」與「工作表1」 預期與實際比較卡:預期複製出261027備份,實際卻被程式自訂警告阻止

四、依照AI建議檢查隱藏工作表

遇到這個狀況,贊贊小屋先回頭問ChatGPT。附上警告畫面,問:

再問ChatGPT明明沒有這個工作表,為什麼程式執行會顯示有這個工作表?

ChatGPT根據畫面判斷,最有可能是工作表被隱藏了,或是存在於其他開啟的活頁簿,並表示單憑圖片還無法確定。它提供的「方法一」是檢查隱藏工作表:在Excel下方的工作表標籤上按滑鼠右鍵,看選單中有沒有「取消隱藏」,能點選就進去查看清單。這裡可以看到,ChatGPT回覆裡寫的是「261017」,與實際警告中的「261027」不同,不過這不影響它提出的檢查方向。

贊贊小屋照著操作,在標籤上按右鍵,選單中「隱藏」可以使用,「取消隱藏」則是灰色,無法點選。這代表目前活頁簿裡找不到可以用一般選單取消隱藏的工作表,這條排查方向沒有找到原因。

這個畫面還需要小心解讀。Excel的工作表有三種顯示狀態:正常顯示、隱藏(可從選單取消隱藏),以及「深度隱藏」(xlSheetVeryHidden),後者無法從一般的取消隱藏選單恢復,要透過VBA修改Visible屬性。所以「取消隱藏」反灰,只能說明這次未能透過一般取消隱藏選單找到日期工作表,不能單憑它排除所有可能。更重要的是排查的態度:AI提出的原因只是假設,要實際操作才知道成不成立;一條路走不通時,就該回頭檢查程式如何判斷工作表存在,因為那句「已經存在」本來就是程式自己說的,並不是Excel確認過的事實。

向ChatGPT詢問明明沒有這個工作表卻顯示已存在,ChatGPT建議先檢查是否有隱藏的工作表 工作表標籤右鍵選單中「隱藏」可選取,「取消隱藏」呈灰色 排查判斷卡:AI提出隱藏假設、檢查取消隱藏選單、記錄觀察、接著檢查程式判斷,反灰不等於已排除所有隱藏狀態

五、交叉使用Claude找出變數誤判原因

ChatGPT的建議沒有找到原因,贊贊小屋決定換另一個AI看看,把問題帶到Claude。這次提供的資料比較完整:剛才右鍵選單的畫面,加上完整的問題描述與整段VBA程式:

傳給Claude的問題我設計了一個 VBA 程式,去複製一個名稱是「最新匯率」的工作表。複製之後,將它重新命名為最新的日期,用 6 個數字(分別是年月日)去命名。但是執行結果它會顯示已經有這一張工作表,但我明明在活頁簿裡面沒有這張工作表。幫我檢查這個程式,看到底問題出在哪裡?

後面接著貼上的,就是當時ChatGPT寫的完整程式:

原版程式|複製最新匯率並依日期命名()Sub 複製最新匯率並依日期命名()
    Dim ws As Worksheet
    Dim 新工作表名稱 As String
    '設定原始工作表名稱
    新工作表名稱 = Format(Date, "yymmdd")
    '確認「最新匯率」工作表是否存在
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("最新匯率")
    On Error GoTo 0
    If ws Is Nothing Then
        MsgBox "找不到「最新匯率」工作表!", vbExclamation
        Exit Sub
    End If
    '確認今天的工作表是否已經存在
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets(新工作表名稱)
    On Error GoTo 0
    If Not ws Is Nothing Then
        MsgBox "工作表「" & 新工作表名稱 & _
               "」已經存在,請勿重複複製!", vbExclamation
        Exit Sub
    End If
    '複製「最新匯率」工作表
    ThisWorkbook.Worksheets("最新匯率").Copy _
        After:=ThisWorkbook.Worksheets( _
        ThisWorkbook.Worksheets.Count)
    '將複製後的工作表重新命名
    ActiveSheet.Name = 新工作表名稱
    MsgBox "匯率工作表複製完成!" & vbCrLf & _
           "新工作表名稱:" & 新工作表名稱, vbInformation
End Sub

Claude的第一句就點出問題:變數ws被重複使用,而且沒有在第二次檢查前清空。它的說明是:第一次檢查「最新匯率」時,ws已經被設定為「最新匯率」工作表,不是Nothing;第二次檢查今天日期的工作表時,找不到該工作表,Set這一行會出錯,卻被On Error Resume Next略過,所以ws仍然保留著第一次設定的「最新匯率」;後面的If Not ws Is Nothing因此成立,就誤報「工作表已經存在」。

把兩次查找的過程攤開來看,會更容易理解:

步驟ws的狀態
第一次找到「最新匯率」ws參照「最新匯率」工作表
第二次尋找「261027」找不到,Set發生錯誤,被On Error Resume Next略過,ws沒有改變
執行If Not ws Is Nothingws仍參照「最新匯率」,條件成立
顯示警告誤報工作表已存在

用一句白話說:程式沒有找到日期工作表,卻拿著上一次找到的工作表,當成這一次查找成功的證據。On Error Resume Next的作用是讓程式在發生執行階段錯誤後繼續執行下一行,它並不代表出錯的那一行已經成功,也不會自動替程式完成正確的存在判斷。要注意,這是同一次執行中,變數保留了舊的參照,並不是記憶體洩漏,也不是上一次執行留下來的資料。On Error GoTo 0則是停用目前程序的錯誤處理,同樣不會把ws清空,兩個指令解決的是不同的事。這個差別,正是VBA錯誤處理中很容易被忽略的地方。

向另一個AI求助時,這次贊贊小屋把完整程式、原本的需求、實際看到的現象與右鍵選單的畫面一次集中提供,Claude便從變數參照的角度找出了原因。

向Claude提出同一問題,附上右鍵選單畫面、問題描述與完整VBA程式 Claude指出變數ws被重複使用,第二次查找失敗後仍保留「最新匯率」的參照,所以誤報工作表已存在 變數狀態因果卡:ws參照最新匯率、查找261027失敗、錯誤後繼續執行、ws仍保留舊參照、誤判已存在

六、加入Set ws = Nothing並驗證修正

Claude給的修正很簡單:在第二次檢查前,先加上Set ws = Nothing,把變數清空。修正後的完整程式如下,只有「確認今天的工作表是否已經存在」那一段多了一行:

修正版程式|第二次檢查前加入 Set ws = NothingSub 複製最新匯率並依日期命名()
    Dim ws As Worksheet
    Dim 新工作表名稱 As String
    新工作表名稱 = Format(Date, "yymmdd")
    '確認「最新匯率」工作表是否存在
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("最新匯率")
    On Error GoTo 0
    If ws Is Nothing Then
        MsgBox "找不到「最新匯率」工作表!", vbExclamation
        Exit Sub
    End If
    '確認今天的工作表是否已經存在(先清空 ws)
    Set ws = Nothing
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets(新工作表名稱)
    On Error GoTo 0
    If Not ws Is Nothing Then
        MsgBox "工作表「" & 新工作表名稱 & _
               "」已經存在,請勿重複複製!", vbExclamation
        Exit Sub
    End If
    '複製「最新匯率」工作表
    ThisWorkbook.Worksheets("最新匯率").Copy _
        After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
    '將複製後的工作表重新命名
    ActiveSheet.Name = 新工作表名稱
    MsgBox "匯率工作表複製完成!" & vbCrLf & _
           "新工作表名稱:" & 新工作表名稱, vbInformation
End Sub

贊贊小屋把修正後的程式貼回模組,重新執行。這一次Excel沒有再誤報,而是跳出「匯率工作表複製完成!新工作表名稱:261027」,下方的工作表標籤也多了「261027」,與「工作表1」、「最新匯率」並列。「261027」成功建立,才證明修正有效。

Set ws = Nothing做的事,是解除ws原本對「最新匯率」的參照,讓它不再指向那張工作表;「最新匯率」本身與裡面的資料都還在,並沒有被清除。所以加入之後,第二次查找的流程變成:先解除舊參照;再嘗試尋找日期工作表;找到了,ws取得新的參照;找不到,ws維持Nothing;最後才判斷能不能複製。位置也要放對,必須在第二次Set之前,而不是放在判斷之後。

目前的畫面證明的是「當天日期工作表不存在時,修正後能成功建立」。若要進一步確認重複執行時的判斷,可以在同一天再執行一次,檢查是否出現「已經存在」的提示,並確認原本備份的資料沒有被覆蓋。

Claude提供的修正版程式,在第二次檢查前加入Set ws = Nothing 訊息「匯率工作表複製完成!新工作表名稱:261027」,下方工作表標籤新增261027 修正流程卡:先解除舊參照,再查找日期工作表,依新狀態判斷是否複製

七、將解決方式帶回ChatGPT

問題解決後,贊贊小屋把Claude的診斷貼回原本的ChatGPT對話,開頭寫「人家解決了:」,後面接上Claude整段說明,包括「問題原因」與「修正方式」。這樣做的用意,是讓原本的對話也掌握最新程式與原因,供後續請ChatGPT繼續修改時參考。

ChatGPT讀完後回覆:你找出的原因完全正確,這次問題確實是VBA物件變數ws沒有重新清空,導致第二次檢查時仍保留第一次找到的「最新匯率」工作表;關鍵就是Set ws = Nothing這一行,它會把ws解除原本的工作表參照,讓第二次檢查能正確判斷是否找到日期工作表。

ChatGPT還補充了一個可以讓程式更穩定的方向:複製完成後,直接指定新工作表的名稱,不必依賴ActiveSheet。ActiveSheet是當下作用中的工作表,如果執行過程中畫面焦點改變,命名的對象就可能不是預期的那一張。Claude在診斷中也提醒過類似的做法,例如把最後的命名改成ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count).Name = 新工作表名稱,直接用工作表的位置指定對象。

不過ChatGPT認同原因,屬於回顧與確認,並不能取代實測。真正證明問題解決的,是前一節Excel裡成功新增「261027」的結果。至於改成明確指定工作表的寫法,採用後仍應回到Excel重新執行,確認命名對象與結果符合預期。

把Claude的診斷貼回原本的ChatGPT對話,開頭寫著「人家解決了:」 ChatGPT確認ws沒有重新清空是原因,並建議複製後直接指定新工作表名稱、不依賴ActiveSheet 證據分類卡:已實測的Excel新增261027、ChatGPT確認的原因回顧、減少依賴ActiveSheet的改進建議,三者性質不同

善用AI的第二意見,也要回到Excel驗證

回頭看整個過程,這次有三個做法派上用場。第一,AI給的原因只是假設,贊贊小屋照ChatGPT的建議實際檢查隱藏工作表,這條排查路徑沒有找到原因,問題因此回到程式本身。第二,卡關時,把完整程式、實際現象與畫面一起交給另一個AI重新檢查,這次Claude從變數狀態找到了原因。第三,最後仍然要回到Excel,執行修正後的程式,確認工作表真的建立,才算解決。

這次的經驗只能說明:同一個問題換一個AI,加上更完整的資料,可能找到不同的切入點;不能因此推論哪一個AI在所有VBA問題上都比較強。贊贊小屋長期同時使用ChatGPT、Gemini與Claude的分工心得,可以參考除了 ChatGPT 還有哪些 AI?Gemini、Claude 長期使用心得與付費理由。使用者能做的,是把證據交代清楚、理解原因是什麼,並且自己驗證結果。遇到「程式能執行,結果卻不對」時,不妨想想那一行用On Error Resume Next跳過的錯誤,是不是讓某個變數還拿著舊的內容。

總結卡:提供證據、尋求第二意見、理解原因、實際驗證,AI協助找方向,實測確認結果
發布日期:
分類:AI工具、ChatGPT VBA