跳至主要內容
HK Learn AI
生成式 AI 教學

Google 表單複選資料整理:用 ChatGPT 寫 Excel VBA 拆分報名名單

Google 表單的核取方塊答案全擠在同一格?本文用匿名範例把分隔符號內的選項拆成逐列名單,完整示範需求規格、ChatGPT 提示詞、VBA、Module、測試、驗算與 Power Query 替代方案。

HK Learn AI 編輯部標誌

HK Learn AI 編輯部

編輯部

發佈於 2026年7月20日

最後審閱:2026年7月20日

分享這篇文章
Google 表單複選答案經 Excel VBA 拆成一位填表者一個選項一列的私隱安全重構流程圖,使用虛構資料,並非來源影片畫面

難度

初階

所需時間

45–60 分鐘(不計大型資料跑批)

你需要準備

Google Forms · Google Sheets · Microsoft Excel 桌面版(Windows 或 Mac) · ChatGPT · Visual Basic Editor · VBA · Power Query(可選替代方案)

開始之前

  • 擁有表單及回應試算表的合法存取權,並清楚哪些同事仍可存取連結的 Google Sheet
  • 已安裝 Microsoft Excel 桌面版;Excel 網頁版不能建立、執行或編輯 VBA
  • 準備一份只含虛構資料的測試副本,不在唯一一份正式回應檔首次執行
  • 知道複選欄的精確標題,以及匯出檔實際使用的分隔符號
  • 已確認公司允許使用 ChatGPT、VBA 及處理相關個人資料

Google 表單很適合收集課程、活動、義工或服務報名,但只要問題類型是「核取方塊」,同一位填表者選了三個項目,匯出到試算表後通常仍是一列、一個儲存格、三個答案。人眼看得懂,Excel 的篩選、樞紐分析、名額統計和下游匯入卻很難直接使用。

本教學會把資料正規化成清楚的規則:一位填表者 × 一個選項 = 一個輸出列。例如「陳同學/課程 A、課程 C」會變成「陳同學/課程 A」和「陳同學/課程 C」兩列;時間戳記、聯絡欄等資料隨每個選項重複,而原始回應表完全不改。

所有畫面均使用虛構資料並移除帳戶、人物、作者、頻道、社交平台及宣傳識別。你也應只用測試副本跟做,不要把正式姓名、電郵、電話或完整報名名單交給 AI。

結果先行:本文提供的巨集不讀瀏覽器、不登入 Google、不上載 Excel、不寄信,也不操作外部檔案。它只讀取目前含巨集活頁簿內明確命名的來源表,完成驗證後重建一張明確命名的輸出表。

先看清楚輸入與輸出

資料層每列代表甚麼「報名課程」例子用途
Google 表單原始回應一次提交課程 A, 課程 C保留提交紀錄
本文輸出一位填表者的一個選項第一列:課程 A
第二列:課程 C
篩選、統計、名單分組、匯入
匿名 Google 表單以核取方塊問題收集多個課程選項;私隱安全重構畫面,使用虛構資料,並非來源影片播放
Google 官方說明指出 Checkboxes 可讓填表者選取多個答案,也可加入 Other;正因如此,匯出後要先確認答案如何被序列化。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

Google 的問題類型說明確認核取方塊可多選。本文不是把三個選項拆成三欄,而是拆成三列,因為逐列結構更適合樞紐分析、每班人數、郵件合併和資料庫匯入。

完整流程:由表單到可驗收名單

  1. 確認表單問題、回應目的地和存取權。
  2. 在 Google Sheets 檢查欄名、複選內容和真正分隔符。
  3. 下載 Excel 副本,保留一份不含巨集的原始備份。
  4. 把來源頁籤命名為「表單回應」,另存測試用 .xlsm。
  5. 只把資料結構和虛構樣本寫成 ChatGPT 提示詞。
  6. 審查 VBA,再貼入標準 Module 並編譯。
  7. 執行巨集,讓結果寫入「輸出」。
  8. 核對總選項數、抽樣、空白、錯誤和重跑結果。
操作預覽:由表單回應進入連結試算表,檢查複選欄後下載 Excel 測試副本。片段只保留有意義的介面和游標操作,沒有原聲或身份資訊。 私隱安全重構說明:本片段使用虛構資料重新製作,並非來源影片播放。

步驟一:先確認表單和試算表的存取邊界

在 Google Forms 的 Responses/回應分頁,可進入連結的 Google Sheet。Google 的回應管理說明亦提醒:表單協作者可能同時擁有連結試算表的權限,而移除表單協作者不等於自動移除試算表權限。處理報名個人資料前,要分別檢查兩邊的分享名單。

Google 表單回應連結試算表並下載 Excel XLSX 副本;私隱安全重構畫面,使用虛構資料,並非來源影片播放
先核對表單是否仍收集回應、誰可檢視、Sheets 圖示連到哪一份試算表,再下載 Excel 測試副本;不要在錯誤檔案上工作。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

如果你只需要一次下載,Google 亦提供回應 CSV;本文沿用 Excel 工作流程,因為稍後要在桌面 Excel 執行 VBA。無論用 Sheet、CSV 或 XLSX,先把取得日期、表單版本和資料擁有人記錄在案。

步驟二:檢查欄名、資料列和分隔符

Google Sheets 內複選答案以分隔符放在同一儲存格;私隱安全重構畫面,使用虛構資料,並非來源影片播放
放大檢查實際儲存格內容,不要只看欄寬截斷後的畫面。選項可能由逗號、全形符號、分號或換行分隔。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

請逐項記錄以下規格,之後提示 AI 和驗收都會用到:

  • 來源工作表:本文統一命名為「表單回應」。
  • 標題列:第一列,且複選欄精確標題是「報名課程」。
  • 資料起點:第二列;不要假設固定有 100 或 1,000 列。
  • 分隔符:雙擊儲存格並複製到純文字編輯器,確認是半形逗號、全形逗號、分號還是換行。
  • 空白規則:沒有選項的提交不產生輸出列,但來源仍保留。
  • 重複規則:本文不靜默去重;若同一來源列真的重複「課程 A」,輸出也重複,讓負責人決定如何修正。
來源「報名課程」預期輸出列數備註
課程 A, 課程 B2半形逗號
課程 A,課程 C2全形逗號
課程 B;課程 D2全形分號
課程 A
課程 B
2儲存格內換行
課程 A,, 課程 C2空項略過
空白0來源列不刪除,只是不輸出

重要限制:若選項本身也可以含逗號,例如 Other/其他的自由文字是「Python, Excel」,純文字已無法分辨哪個逗號是答案、哪個是分隔符。不要用猜測修補;應限制選項字元、把自由文字放另一欄,或從保留結構的來源重新取得資料。

步驟三:下載 Excel 副本並固定測試環境

  1. 在 Google Sheets 選 File/檔案 → Download/下載 → Microsoft Excel (.xlsx)。
  2. 把原始下載檔改成容易辨認的備份,例如 course-registration_RAW_20260721.xlsx,不要在它執行巨集。
  3. 複製成 course-registration_TEST_20260721.xlsx,再用 Excel 桌面版開啟這份 TEST 副本。
  4. 在 Excel 選 File → Save As,檔案類型選 Excel Macro-Enabled Workbook (*.xlsm),另存為 course-registration_TEST_20260721.xlsm不要只在 Finder 或 File Explorer 改副檔名,否則內容格式與副檔名會不一致。
  5. 在 .xlsm 測試檔把來源頁籤精確命名為「表單回應」。
  6. 只保留 8–20 列虛構或已適當匿名化的測試資料,覆蓋正常、空白、混合分隔符和異常值。

要保留 VBA,檔案必須使用支援巨集的格式。Microsoft 的儲存巨集說明建議另存為 Excel Macro-Enabled Workbook(.xlsm);一般 .xlsx 不會保留 VBA。

步驟四:不要上載名單,只把規格交給 ChatGPT

ChatGPT 收到欄位結構、虛構樣本和安全限制的提示詞;私隱安全重構畫面,使用虛構資料,並非來源影片播放
高質素提示詞要交代工作表、欄名、分隔符、空白、重跑和禁止行為;不需要貼任何真實姓名或聯絡資料。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

直接說「幫我拆分 Excel」會留下太多猜測。以下提示詞把讀取範圍、輸出定義、錯誤條件和禁止行為寫清楚,可直接複製後按你的虛構結構修改:

你是資深 Microsoft Excel VBA 工程師。請只根據以下虛構結構撰寫可在 Excel 桌面版執行的 VBA,不要要求我上載真實活頁簿。

目標:把 Google 表單核取方塊匯出的複選答案,由「一位填表者一列、所有選項同一格」正規化為「一位填表者 × 一個選項一列」。

活頁簿與欄位:
- 只操作 ThisWorkbook。
- 來源工作表名稱:表單回應。
- 輸出工作表名稱:輸出。
- 第一列是標題。
- 複選欄標題:報名課程。
- 其他欄位可能包括時間戳記、姓名、電郵、電話;輸出時要逐列原樣重複,但來源工作表不可被修改。

分隔與清理規則:
- 支援半形逗號、全形逗號、半形分號、全形分號、CRLF、CR 或 LF。
- 去除每個選項前後空格,略過空白項目。
- 不可靜默去除重複選項;若來源重複,輸出也保留,方便人工追查。

安全與穩定要求:
1. 第一行使用 Option Explicit,所有變數完整宣告。
2. 使用 ThisWorkbook.Worksheets("表單回應"),不可使用 ActiveSheet、Selection 或 Select。
3. 用 Find("*") 找整張來源表真正最後一列及最後一欄,不可只依賴固定欄。
4. 先確認來源表、標題與資料存在;若「報名課程」標題重複,要停止並清楚報錯。
5. 先在記憶體完成計數和輸出陣列;所有驗證通過後才建立或清空「輸出」。
6. 「輸出」不存在便建立,存在便只清空該輸出表;不可刪除來源或其他工作表。
7. 每個輸出列保留全部來源欄位,只把「報名課程」改成單一選項。
8. 防止以 =、+、-、@ 開頭的文字在輸出時被當成公式;數字和日期仍保留為值。
9. 檢查輸出列數不超過 Excel 工作表上限,加入完整錯誤處理,還原 ScreenUpdating、EnableEvents 和 Calculation。
10. 不准使用 Shell、Kill、FileSystemObject、HTTP、電郵、自動開啟事件或任何外部連線。

交付格式:
- 先用 8 點解釋讀取、寫入、停止條件及重跑行為。
- 提供可直接貼入「標準 Module」的完整程式碼。
- 最後提供正常、混合分隔符、空白、錯誤值、重複標題、重跑及列數核對的測試清單。
- 不要聲稱程式碼毋須測試。

模型名稱和 ChatGPT 介面會改變,重點不是選一個舊版本,而是把可驗收規格寫完整。AI 回覆仍是未受信任的程式碼草稿;逐行審查、測試副本和人工驗收都不能省略。

步驟五:使用這個可重跑、保留來源的 VBA

以下版本把整份來源讀入記憶體,第一遍只驗證及計數,第二遍建立輸出陣列;所有驗證通過後,才建立或清空「輸出」。這比一邊讀、一邊逐列刪寫更容易控制失敗狀態,也較適合數千列資料。

Option Explicit

Private Const SOURCE_SHEET As String = "表單回應"
Private Const OUTPUT_SHEET As String = "輸出"
Private Const CHOICE_HEADER As String = "報名課程"

Public Sub SplitCheckboxResponses()
    Dim wb As Workbook
    Dim wsSource As Worksheet
    Dim wsOutput As Worksheet
    Dim sourceData As Variant
    Dim outputData() As Variant
    Dim choices As Variant
    Dim choiceValue As String
    Dim lastRow As Long
    Dim lastCol As Long
    Dim choiceCol As Long
    Dim sourceRow As Long
    Dim outputRow As Long
    Dim outputRowCount As Long
    Dim choiceIndex As Long
    Dim colIndex As Long
    Dim previousCalculation As XlCalculation
    Dim previousScreenUpdating As Boolean
    Dim previousEnableEvents As Boolean
    Dim settingsCaptured As Boolean
    Dim successMessage As String
    Dim errorMessage As String

    On Error GoTo HandleError

    Set wb = ThisWorkbook
    previousCalculation = Application.Calculation
    previousScreenUpdating = Application.ScreenUpdating
    previousEnableEvents = Application.EnableEvents
    settingsCaptured = True

    If StrComp(SOURCE_SHEET, OUTPUT_SHEET, vbTextCompare) = 0 Then
        Err.Raise vbObjectError + 1000, , _
            "來源工作表與輸出工作表不可同名。"
    End If

    Set wsSource = GetRequiredWorksheet(wb, SOURCE_SHEET)
    lastRow = LastUsedRow(wsSource)
    lastCol = LastUsedColumn(wsSource)

    If lastRow < 2 Or lastCol < 1 Then
        Err.Raise vbObjectError + 1001, , _
            "來源工作表沒有標題及至少一列資料。"
    End If

    choiceCol = FindUniqueHeaderColumn(wsSource, CHOICE_HEADER, lastCol)
    sourceData = wsSource.Range( _
        wsSource.Cells(1, 1), _
        wsSource.Cells(lastRow, lastCol) _
    ).Value2

    ' 第一遍只驗證及計算輸出列數,不修改任何工作表。
    outputRowCount = 1

    For sourceRow = 2 To UBound(sourceData, 1)
        If IsError(sourceData(sourceRow, choiceCol)) Then
            Err.Raise vbObjectError + 1002, , _
                "來源第 " & sourceRow & " 列的「" & CHOICE_HEADER & _
                "」是 Excel 錯誤值,請先修正。"
        End If

        choices = SplitChoices(CStr(sourceData(sourceRow, choiceCol)))

        For choiceIndex = LBound(choices) To UBound(choices)
            choiceValue = CleanChoice(CStr(choices(choiceIndex)))
            If Len(choiceValue) > 0 Then
                If outputRowCount = wsSource.Rows.Count Then
                    Err.Raise vbObjectError + 1004, , _
                        "拆分結果超過此 Excel 工作表的列數上限。"
                End If
                outputRowCount = outputRowCount + 1
            End If
        Next choiceIndex
    Next sourceRow

    If outputRowCount = 1 Then
        Err.Raise vbObjectError + 1003, , _
            "找不到任何非空白的複選答案,輸出工作表未被修改。"
    End If

    If outputRowCount > wsSource.Rows.Count Then
        Err.Raise vbObjectError + 1004, , _
            "拆分後需要 " & outputRowCount & _
            " 列,超過此 Excel 工作表的列數上限。"
    End If

    ReDim outputData(1 To outputRowCount, 1 To lastCol)

    For colIndex = 1 To lastCol
        outputData(1, colIndex) = SafeOutputValue(sourceData(1, colIndex))
    Next colIndex

    ' 第二遍建立輸出陣列:每個非空白選項各佔一列。
    outputRow = 1

    For sourceRow = 2 To UBound(sourceData, 1)
        choices = SplitChoices(CStr(sourceData(sourceRow, choiceCol)))

        For choiceIndex = LBound(choices) To UBound(choices)
            choiceValue = CleanChoice(CStr(choices(choiceIndex)))

            If Len(choiceValue) > 0 Then
                outputRow = outputRow + 1

                For colIndex = 1 To lastCol
                    outputData(outputRow, colIndex) = _
                        SafeOutputValue(sourceData(sourceRow, colIndex))
                Next colIndex

                outputData(outputRow, choiceCol) = SafeOutputValue(choiceValue)
            End If
        Next choiceIndex
    Next sourceRow

    ' 到這裏所有輸入已通過驗證,才建立或清空輸出工作表。
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Set wsOutput = GetOrCreateOutputWorksheet(wb, wsSource, OUTPUT_SHEET)
    If wsOutput.AutoFilterMode Then wsOutput.AutoFilterMode = False
    wsOutput.Cells.Clear

    With wsOutput.Range( _
        wsOutput.Cells(1, 1), _
        wsOutput.Cells(outputRowCount, lastCol) _
    )
        .Value2 = outputData
        .AutoFilter
    End With

    wsOutput.Rows(1).Font.Bold = True

    For colIndex = 1 To lastCol
        wsOutput.Columns(colIndex).NumberFormat = _
            wsSource.Cells(2, colIndex).NumberFormat
        wsOutput.Columns(colIndex).AutoFit
        If wsOutput.Columns(colIndex).ColumnWidth > 50 Then
            wsOutput.Columns(colIndex).ColumnWidth = 50
        End If
    Next colIndex

    successMessage = _
        "完成:讀取 " & (lastRow - 1) & " 個來源列,輸出 " & _
        (outputRowCount - 1) & " 個『填表者 × 選項』資料列。" & vbCrLf & _
        "來源工作表沒有被修改。請立即按驗收清單抽查。"

CleanExit:
    On Error Resume Next
    If settingsCaptured Then
        Application.Calculation = previousCalculation
        Application.EnableEvents = previousEnableEvents
        Application.ScreenUpdating = previousScreenUpdating
    End If
    On Error GoTo 0

    If Len(errorMessage) > 0 Then
        MsgBox errorMessage, vbCritical, "拆分未完成"
    ElseIf Len(successMessage) > 0 Then
        MsgBox successMessage, vbInformation, "拆分完成"
    End If

    Exit Sub

HandleError:
    errorMessage = _
        "錯誤 " & Err.Number & ": " & Err.Description & vbCrLf & _
        "來源工作表不應被修改;請核對工作表名、欄名及測試資料。"
    Resume CleanExit
End Sub

Private Function GetRequiredWorksheet( _
    ByVal wb As Workbook, _
    ByVal sheetName As String _
) As Worksheet
    On Error Resume Next
    Set GetRequiredWorksheet = wb.Worksheets(sheetName)
    On Error GoTo 0

    If GetRequiredWorksheet Is Nothing Then
        Err.Raise vbObjectError + 1010, , _
            "找不到來源工作表「" & sheetName & "」。"
    End If
End Function

Private Function GetOrCreateOutputWorksheet( _
    ByVal wb As Workbook, _
    ByVal wsSource As Worksheet, _
    ByVal sheetName As String _
) As Worksheet
    On Error Resume Next
    Set GetOrCreateOutputWorksheet = wb.Worksheets(sheetName)
    On Error GoTo 0

    If GetOrCreateOutputWorksheet Is Nothing Then
        Set GetOrCreateOutputWorksheet = _
            wb.Worksheets.Add(After:=wsSource)
        GetOrCreateOutputWorksheet.Name = sheetName
    End If
End Function

Private Function FindUniqueHeaderColumn( _
    ByVal ws As Worksheet, _
    ByVal expectedHeader As String, _
    ByVal lastCol As Long _
) As Long
    Dim colIndex As Long
    Dim foundColumn As Long
    Dim headerValue As String

    For colIndex = 1 To lastCol
        If Not IsError(ws.Cells(1, colIndex).Value2) Then
            headerValue = CleanChoice(CStr(ws.Cells(1, colIndex).Value2))

            If StrComp(headerValue, expectedHeader, vbTextCompare) = 0 Then
                If foundColumn > 0 Then
                    Err.Raise vbObjectError + 1011, , _
                        "標題「" & expectedHeader & _
                        "」出現多於一次,請先改成唯一欄名。"
                End If
                foundColumn = colIndex
            End If
        End If
    Next colIndex

    If foundColumn = 0 Then
        Err.Raise vbObjectError + 1012, , _
            "第一列找不到標題「" & expectedHeader & "」。"
    End If

    FindUniqueHeaderColumn = foundColumn
End Function

Private Function LastUsedRow(ByVal ws As Worksheet) As Long
    Dim lastCell As Range

    Set lastCell = ws.Cells.Find( _
        What:="*", _
        After:=ws.Cells(1, 1), _
        LookIn:=xlFormulas, _
        LookAt:=xlPart, _
        SearchOrder:=xlByRows, _
        SearchDirection:=xlPrevious, _
        MatchCase:=False, _
        SearchFormat:=False _
    )

    If lastCell Is Nothing Then
        LastUsedRow = 0
    Else
        LastUsedRow = lastCell.Row
    End If
End Function

Private Function LastUsedColumn(ByVal ws As Worksheet) As Long
    Dim lastCell As Range

    Set lastCell = ws.Cells.Find( _
        What:="*", _
        After:=ws.Cells(1, 1), _
        LookIn:=xlFormulas, _
        LookAt:=xlPart, _
        SearchOrder:=xlByColumns, _
        SearchDirection:=xlPrevious, _
        MatchCase:=False, _
        SearchFormat:=False _
    )

    If lastCell Is Nothing Then
        LastUsedColumn = 0
    Else
        LastUsedColumn = lastCell.Column
    End If
End Function

Private Function SplitChoices(ByVal value As String) As Variant
    value = Replace(value, vbCrLf, ",")
    value = Replace(value, vbCr, ",")
    value = Replace(value, vbLf, ",")
    value = Replace(value, ",", ",")
    value = Replace(value, ";", ",")
    value = Replace(value, ";", ",")

    SplitChoices = Split(value, ",")
End Function

Private Function CleanChoice(ByVal value As String) As String
    value = Replace(value, ChrW(160), " ")
    value = Replace(value, ChrW(12288), " ")
    value = Replace(value, vbTab, " ")
    CleanChoice = Trim$(value)
End Function

Private Function SafeOutputValue(ByVal value As Variant) As Variant
    Dim firstCharacter As String

    If VarType(value) = vbString Then
        If Len(value) > 0 Then
            firstCharacter = Left$(CStr(value), 1)

            Select Case firstCharacter
                Case "=", "+", "-", "@"
                    SafeOutputValue = "'" & CStr(value)
                Case Else
                    SafeOutputValue = value
            End Select
        Else
            SafeOutputValue = value
        End If
    Else
        SafeOutputValue = value
    End If
End Function

這段程式實際做了甚麼?

程式區段作用安全理由
Option Explicit 與三個常數強制宣告變數;集中管理來源、輸出和欄名減少拼錯變數或改漏多處名稱
ThisWorkbook鎖定存放巨集的活頁簿不受使用者當時點選哪個檔案或頁籤影響
Find("*")從整張表找最後使用列和欄不假設 A 欄永遠完整,也不使用固定資料量
FindUniqueHeaderColumn找出唯一「報名課程」欄缺欄或同名欄會停止,不會猜其中一欄
第一遍迴圈檢查錯誤值、計算實際輸出列數在修改輸出前先發現資料問題和列數上限
SplitChoices把換行、全形逗號和兩種分號統一為逗號再拆分避免只支援單一分隔符
SafeOutputValue把以 =、+、-、@ 開頭的文字保留為文字降低文字在新儲存格被當成公式的風險
GetOrCreateOutputWorksheet不存在便建立,存在便重用只清空指定輸出表,不刪來源或其他頁籤
CleanExit還原 Calculation、Events 和 ScreenUpdating錯誤時亦盡量把 Excel 應用程式狀態還原

巨集輸出的是,不是來源公式;這可避免把外部連結或運算邏輯複製到新表。程式亦沿用來源第二列的欄位格式,以便時間戳記和日期正常顯示。若同一欄混合多種格式,應在驗收後統一格式。

步驟六:貼入標準 Module,再編譯

如果你未用過 VBE,可先看 ChatGPT 寫 Excel VBA 入門了解 Module、.xlsm、Alt+F8 和安全警告。這裏只列本案例必需步驟:

  1. 用 Excel 桌面版開啟測試 .xlsm。
  2. Windows 可按 Alt+F11;或由 Developer/開發人員 → Visual Basic 開啟 VBE。
  3. 在左側選中測試檔的 VBAProject,不是 Personal.xlsb 或另一個活頁簿。
  4. 選 Insert → Module,建立標準 Module。
  5. 把上方程式由 Option Explicit 到最後一個 End Function 完整貼入。
  6. 選 Debug → Compile VBAProject;有錯誤便先記下訊息和反白行。
  7. 儲存、關閉並重開 .xlsm,確認程式仍在。
Visual Basic Editor 在正確活頁簿插入標準 Module;私隱安全重構畫面,使用虛構資料,並非來源影片播放
一般手動執行的 Public Sub 放在標準 Module。貼入完整程式後先選 Compile VBAProject;不要放入 Sheet 物件、ThisWorkbook 事件或不相關專案。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

Excel 網頁版不能執行 VBA。Microsoft 的官方說明指出,網頁版不能建立、執行或編輯 VBA;必須在桌面應用程式操作。

步驟七:先看來源不動,再執行巨集

  1. 確認目前檔案是 TEST .xlsm,不是原始備份。
  2. 確認來源頁籤叫「表單回應」,第一列只有一個「報名課程」。
  3. 記錄來源資料列數,並抽查三個複選儲存格。
  4. 由 Developer → Macros,或 Windows 按 Alt+F8。
  5. SplitCheckboxResponses,按 Run/執行。
  6. 等待完成訊息;資料量大時不要連續重按。
操作預覽:在標準 Module 貼入程式,執行巨集後切到「輸出」查看每個選項各佔一列。片段沒有模糊載入、過場、重複畫面或身份資訊。 私隱安全重構說明:本片段使用虛構資料重新製作,並非來源影片播放。

步驟八:逐項驗收「輸出」工作表

Excel 輸出工作表每位填表者每個選項各佔一列;私隱安全重構畫面,使用虛構資料,並非來源影片播放
同一來源的時間戳記和聯絡欄會重複;「報名課程」每格只剩一個修剪後的非空白選項。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

完成訊息中的來源列數和輸出列數只是第一層檢查。正式使用前要完成以下驗收:

  1. 來源不變:來源資料列數、三個抽樣儲存格和工作表修改時間符合預期。
  2. 總數相等:人工計算小樣本內所有非空白選項總數,應等於輸出資料列數。
  3. 一格一項:輸出「報名課程」不再含預期分隔符,也沒有前後空白。
  4. 欄位重複正確:同一來源列拆出的姓名、電郵、電話和時間戳記完全相同。
  5. 空白不輸出:沒有選項的來源列不應產生一列空白課程。
  6. 混合符號:逗號、全形逗號、兩種分號和換行的測試列都正確。
  7. 重跑一致:再執行一次,輸出列數和內容不應倍增。
  8. 負面測試:把標題暫時改錯或複製一個同名標題,程式應停止並保留舊輸出。
Excel 以來源選項總數、輸出列數和抽樣對照驗收拆分結果;私隱安全重構畫面,使用虛構資料,並非來源影片播放
最可靠的測試是先用 8–20 列小樣本列出預期答案,再逐列比較;大型資料可加樞紐分析按選項和來源 ID 核對。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

若資料會重複匯出,建議保留穩定的提交 ID;沒有 ID 時可暫用時間戳記加電郵作抽查鍵,但不要假設這個組合永遠唯一。本文故意不自動去重,因為同名、同電郵或同一人多次提交是否應合併,是業務規則,不應由程式自行猜測。

巨集安全:不要為了執行而「啟用所有巨集」

Microsoft 的巨集安全指引明確不建議 Enable all macros。從互聯網或即時通訊下載的 Office 檔案,在 Windows 亦可能按政策被封鎖;應由 IT 或檔案擁有人處理信任和簽署,而不是關掉全域保護。

審查 AI 生成程式時,至少搜尋 KillShellFileSystemObject、HTTP、Outlook、Workbook_OpenActiveSheetSelection。本文範例不需要刪檔、外連、寄信、自動啟動或依賴當前焦點。

私隱:寫 VBA 不需要把真實表格交給 ChatGPT

「只在 Excel 執行」只適用於本文 VBA 本身;如果你把完整回應表貼入或上載 ChatGPT,資料已離開本機工作簿。個人 ChatGPT 工作區的內容是否用於模型改進,取決於帳戶的 Data Controls;可查閱 OpenAI 最新的Data Controls FAQ。OpenAI 的ChatGPT Business 私隱說明指出工作區資料預設不作模型訓練,但公司批准、存取權、保留期和 PDPO 責任仍需獨立處理。

香港私隱公署的僱員使用生成式 AI 指引清單建議機構制定使用範圍、可輸入資料、輸出核實、資料保留、事故回報和培訓安排。實務上應:

  • 只提供欄名、資料類型、分隔規則和虛構樣本。
  • 以「測試姓名 001」「test001@example.invalid」「9000 0001」取代真實資料。
  • 不要把身份證號碼、電話、健康、付款、登入或內部評語放入提示。
  • 先確認 Google 表單、連結試算表、下載檔和輸出檔各自的存取權。
  • 按用途設定保留期限;完成名單後,不要無限期保留多份本機副本。
  • 由資料負責人覆核輸出,而不是把 AI 回覆視為最終決定。

機構若要把這類流程擴展到正式營運,可再按私隱公署的AI 個人資料保障模範框架建立管治、風險評估、人為監督和持續監察安排。

需要更完整的香港情境做法,可參考 ChatGPT 私隱與資料安全指南

不用 VBA:Power Query、TEXTSPLIT 與 Office Scripts 比較

方法最適合優點限制
VBA桌面 Excel、固定流程、一鍵重建輸出可加入驗證、錯誤處理和格式要使用 .xlsm、巨集政策和程式維護
Power Query定期匯入、清理、刷新步驟可見,Split into Rows 很直接混合分隔符要先正規化;刷新和權限仍要管理
TEXTSPLIT一次性、小量、支援動態陣列的 Excel不用巨集,公式即時跨多列堆疊、重複其他欄位和舊版相容較麻煩
Office Scripts獲支援的 Microsoft 365 網頁/雲端自動化TypeScript、可與雲端流程整合租戶、授權、管理政策及 API 與 VBA 不同

Power Query 的等效步驟

  1. 把來源範圍轉成 Excel Table,保留原始表不改。
  2. Data → From Table/Range 開啟 Power Query。
  3. 如有全形逗號、分號或換行,先用 Replace Values 統一為單一分隔符。
  4. 選「報名課程」→ Split Column → By Delimiter。
  5. 在 Advanced options 選 Split into Rows,不是 Columns。
  6. Transform → Format → Trim,再篩走空白。
  7. Close & Load 到新工作表,刷新後核對列數和抽樣。
Power Query 按分隔符把報名課程欄拆成 Rows;私隱安全重構畫面,使用虛構資料,並非來源影片播放
Advanced options 必須選 Split into Rows。Microsoft 的官方步驟亦區分拆成欄和拆成列;選錯會得到完全不同結構。 私隱安全重構說明:本畫面使用虛構資料重新製作,並非來源影片播放。

可參考 Microsoft 的Power Query 拆欄說明。如果團隊不允許巨集、但需要每週刷新同一份表,Power Query 往往是更容易交接的選擇。

常見錯誤與精確修正

現象最可能原因修正方法
找不到來源工作表頁籤不是精確的「表單回應」複製頁籤實際名稱,修改 SOURCE_SHEET 常數;檢查前後空格
找不到「報名課程」第一列標題不同、合併儲存格或標題列不是第一列把表整理成單一標題列,或修改 CHOICE_HEADER
標題出現多於一次匯出後有兩欄同名先改成唯一欄名,不要讓程式自行猜其中一欄
一個選項被錯拆成兩個答案內容本身含逗號或分號改表單設計、獨立自由文字欄,或從結構化來源重取
所有資料仍在一格實際分隔符不在支援清單用純文字工具找出 Unicode 字元,再明確加入 SplitChoices
輸出列數太少空白被略過、資料含錯誤或看似逗號其實是其他符號用小樣本逐格列出預期選項數,再比較完成訊息
輸出列數第二次倍增執行的不是本文版本,或另一巨集用追加方式確認主程序名稱,搜尋輸出邏輯是否先 Clear
巨集清單沒有程序程式不在標準 Module、編譯錯誤或 Sub 有參數移到標準 Module,Compile,再找無參數 Public Sub
完成後日期變成數字來源第二列格式不是日期或同欄混合格式在輸出表統一套用日期格式;值本身未必錯
安全警告阻止執行下載來源標記、企業政策或未信任檔案不要全域啟用;核對來源並交 IT 按政策處理

向 ChatGPT 回報錯誤時,只提供錯誤編號、完整訊息、VBE 反白行、虛構欄位結構、預期結果和實際結果。不要因為除錯而上載整份正式名單。

交付正式名單前的最後檢查

  • 原始 Google 回應、RAW 下載檔和 TEST .xlsm 分開保存,沒有覆蓋唯一來源。
  • 來源與輸出工作表名稱固定,欄名有版本控制。
  • 測試包含半形/全形逗號、兩種分號、換行、空白、錯誤值和答案內分隔符。
  • 總選項數等於輸出資料列數,並完成至少 10 個來源列的逐項抽查。
  • 第二次執行結果一致,沒有在舊輸出底部追加。
  • 沒有未批准的刪檔、外連、寄信、Shell、自動開啟或 ActiveSheet 行為。
  • 輸出接收者、分享方式和保留期限已批准;不再需要的測試副本已按政策處理。
  • 若新回應仍持續進入 Google Sheet,已清楚標示本次匯出的截止時間。

下一步:由一次拆分升級成可維護流程

這個案例的真正價值不只是「ChatGPT 幫你寫 VBA」,而是把模糊需求變成可測試規格:固定來源、固定輸出、清楚分隔規則、錯誤時停止、重跑不累積、完成後可驗算。相同方法可延伸到活動時段、技能標籤、服務地區或多選問卷,但每次都要先確認分隔符和業務去重規則。

若你想理解 ChatGPT 在 Excel 的公式、分析、圖表和報告用途,可閱讀 ChatGPT Excel 香港工作指南;要把多個重複辦公步驟串成流程,可再看 香港中小企 AI 自動化指南香港工作提示詞實例

資料來源與引用

我們附上第一手及官方來源,方便你逐一核實。

  1. 1.Choose a type of question for your formGoogle Docs Editors Help
  2. 2.View & manage form responsesGoogle Docs Editors Help
  3. 3.Choose where to save form responsesGoogle Docs Editors Help
  4. 4.Show the Developer tabMicrosoft Support
  5. 5.Run a macro in ExcelMicrosoft Support
  6. 6.Save a macroMicrosoft Support
  7. 7.File formats that are supported in ExcelMicrosoft Support
  8. 8.Change macro security settings in ExcelMicrosoft Support
  9. 9.Macros from the internet are blocked by default in OfficeMicrosoft Learn
  10. 10.Work with VBA macros in Excel for the webMicrosoft Support
  11. 11.Split a column of text (Power Query)Microsoft Support
  12. 12.Split a cell in ExcelMicrosoft Support
  13. 13.Introduction to Office Scripts in ExcelMicrosoft Support
  14. 14.Data Controls FAQOpenAI Help Center
  15. 15.Managing data, sharing, and privacy in ChatGPT BusinessOpenAI Help Center
  16. 16.Checklist on Guidelines for the Use of Generative AI by EmployeesOffice of the Privacy Commissioner for Personal Data, Hong Kong
  17. 17.Artificial Intelligence: Model Personal Data Protection FrameworkOffice of the Privacy Commissioner for Personal Data, Hong Kong

常見問題

Google 表單的核取方塊答案為甚麼會擠在同一格?

核取方塊允許同一位填表者選多個答案,但試算表仍以一次提交為一列,所以多個選項會序列化在同一儲存格。這適合保留原始回應,卻不方便按選項篩選、樞紐分析或匯入其他系統。

這個 VBA 會修改 Google 表單或來源工作表嗎?

不會。程式只讀取 ThisWorkbook 內名為「表單回應」的工作表,並把結果寫到「輸出」。它不連接 Google、不回寫表單,也不改來源儲存格;不過仍應先在副本測試。

複選欄不是「報名課程」怎麼辦?

只修改程式開首的 CHOICE_HEADER 常數,令它與第一列標題完全相同。若工作表名也不同,修改 SOURCE_SHEET;不要把 ActiveSheet 當捷徑。

選項含逗號或「其他」自由文字,仍可安全拆分嗎?

不一定。若逗號既是分隔符又可能是答案內容,純文字已失去結構資訊,任何逗號拆分都可能誤切。應限制選項文字、另設自由文字欄、改用不會出現在答案內的分隔符,或從結構化來源重新取得資料。

為甚麼第二次執行不會一直新增重複列?

巨集每次都先在記憶體重建完整結果,驗證成功後才清空指定的「輸出」工作表再一次寫入。它不會在舊輸出底部追加;來源本身若有重複答案,則會忠實保留供追查。

Excel 網頁版可不可以執行這段 VBA?

不可以。Microsoft 說明 Excel for the web 不能建立、執行或編輯 VBA。請用桌面 Excel;若流程必須在網頁或雲端執行,可評估 Office Scripts 或 Power Automate。

一定要把真實 Excel 檔案上載給 ChatGPT 嗎?

不需要,也不建議。為這類程式提供工作表名、欄位名、分隔規則、兩三列虛構輸入與預期輸出已足夠。真實姓名、電郵、電話和報名內容應留在獲批准的系統內。

不用 VBA 還有甚麼方法?

需要可刷新清理流程時,Power Query 的 Split Column by Delimiter 並選 Split into Rows 通常更易審計;一次性小資料可用 TEXTSPLIT;雲端 Microsoft 365 流程可評估 Office Scripts。

本文遵循我們的 編輯準則.

HK Learn AI 編輯部標誌

關於作者

HK Learn AI 編輯部

HK Learn AI 編輯部負責研究、查證同編寫每一篇內容,並引用官方及第一手來源。