當我們辛苦的在 ChatGPT 中對話得到的結果,如果其中含有數學公式相關的格式,在將結果複製到 Word 文件中時,其實是無法直接使用的,因為公式無法正確被顯示(如下圖)。

如何解決這樣的問題?

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

以下是目前我有找出最方便而簡單的方式。參考以下的作法:

1. 安裝 Pandoc 。

先連線:https://pandoc.org/,下載合於你使用的版本,並且先行安裝好。

2. 將 ChatGPT 提供你的解答,複製後貼至記事本中,再另存新檔為「*.md」。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

3. 我請 ChatGPT 提供一個 VBA 程式碼以將這個 Markdown 語法的內容轉換為 Word 文件。(VBA 程式碼放在網頁下方)

4. 新增一個 Word 文件,選取「開發人員/Visual Basic」。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

5. 選取「插入/模組」。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

6. 貼上先前複製的 VBA 程式碼,並且點選:執行。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

確認執行這個巨集:

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

7. 選取先前儲存由 ChatGPT 提供內容的 Markdown 語法檔案。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

8. 設定一個存檔的名稱,點選:儲存。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

整個工作完成,可以得到轉換後的 Word 文件。

將ChatGPT提供含有數學公式的內容順利轉換至Word文件

 

------- 以下為 VBA 程式碼 ----------------------------------------------------------------

Option Explicit

' ============================
' Windows + Pandoc 專用版本
' ============================

' 入口點
Sub MD_LaTeX_To_Word()
    Dim srcPath As String, dstPath As String, refDoc As String
    Dim ok As Boolean

    srcPath = PickSourceFile()
    If srcPath = "" Then Exit Sub

    dstPath = PickDestDocx(srcPath)
    If dstPath = "" Then Exit Sub

    If Not HasPandocWin() Then
        MsgBox "找不到 pandoc。請確認已安裝並已加入 PATH(在命令列輸入 pandoc -v 應可看到版本)。", vbCritical
        Exit Sub
    End If

    If MsgBox("要套用自訂 Word 樣板(reference .docx)嗎?", vbQuestion + vbYesNo, "Pandoc reference-doc") = vbYes Then
        refDoc = PickReferenceDocx(GetFolder(dstPath))
        If refDoc = "" Then
            If MsgBox("未選擇樣板,改用 Word 預設樣式繼續?", vbQuestion + vbYesNo) = vbNo Then Exit Sub
        End If
    End If

    ok = ConvertWithPandocWin(srcPath, dstPath, refDoc)
    If ok Then
        Documents.Open FileName:=dstPath
        MsgBox "轉換完成。", vbInformation
    Else
        MsgBox "轉換失敗(請檢查來源內容或 Pandoc 設定)。", vbCritical
    End If
End Sub

'── 檔案挑選(安全過濾,避免 Filters.Clear 在某些環境報錯) ────────────────
Private Sub SafeSetFilters(fd As FileDialog, ByVal desc As String, ByVal pattern As String)
    On Error Resume Next
    fd.Filters.Clear
    fd.Filters.Add desc, pattern
    On Error GoTo 0
End Sub

Private Function PickSourceFile() As String
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogFilePicker)
    With fd
        .Title = "選擇含 Markdown/LaTeX 的來源檔案"
        .AllowMultiSelect = False
        SafeSetFilters fd, "Markdown/LaTeX/Text", "*.md;*.markdown;*.tex;*.txt"
        If .Show = -1 Then
            PickSourceFile = .SelectedItems(1)
        Else
            PickSourceFile = ""
        End If
    End With
End Function

Private Function PickDestDocx(ByVal src As String) As String
    Dim fd As FileDialog
    Dim defName As String
    defName = Replace(GetFileName(src), GetFileExt(src), "") & "_converted.docx"

    Set fd = Application.FileDialog(msoFileDialogSaveAs)
    With fd
        .Title = "另存新檔(.docx)"
        ' 為避免相容性問題,不設定 Filters;副檔名由程式補上
        .InitialFileName = GetFolder(src) & "\" & defName
        If .Show = -1 Then
            Dim p As String: p = .SelectedItems(1)
            If LCase$(Right$(p, 5)) <> ".docx" Then p = p & ".docx"
            PickDestDocx = p
        Else
            PickDestDocx = ""
        End If
    End With
End Function

Private Function PickReferenceDocx(ByVal initialFolder As String) As String
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogFilePicker)
    With fd
        .Title = "選擇 reference .docx 樣板(可省略)"
        .AllowMultiSelect = False
        .InitialFileName = initialFolder & "\"
        SafeSetFilters fd, "Word 文件", "*.docx"
        If .Show = -1 Then
            PickReferenceDocx = .SelectedItems(1)
        Else
            PickReferenceDocx = ""
        End If
    End With
End Function

'── Pandoc 偵測與轉換(Windows) ───────────────────────────────────────────
Private Function HasPandocWin() As Boolean
    On Error GoTo EH
    Dim sh As Object, ex As Object, outStr As String, errStr As String
    Set sh = CreateObject("WScript.Shell")
    Set ex = sh.Exec("cmd /c where pandoc")

    Dim t As Date: t = Now
    Do While ex.Status = 0
        DoEvents
        If Now - t > TimeSerial(0, 0, 5) Then Exit Do ' 最多 5 秒
    Loop

    outStr = ex.StdOut.ReadAll
    errStr = ex.StdErr.ReadAll
    HasPandocWin = (InStr(1, outStr, "pandoc.exe", vbTextCompare) > 0) Or (InStr(1, outStr, "pandoc", vbTextCompare) > 0)
    Exit Function
EH:
    HasPandocWin = False
End Function

Private Function ConvertWithPandocWin(ByVal src As String, ByVal dst As String, ByVal refDoc As String) As Boolean
    On Error GoTo EH
    Dim sh As Object, ex As Object
    Dim cmd As String, outStr As String, errStr As String

    ' 說明:
    ' -f markdown+tex_math_dollars+latex_macros :啟用 $...$ / $$...$$ 與 LaTeX 宏
    ' -t docx --standalone :輸出為 Word(Pandoc 會把 LaTeX 數學轉為 OMML 原生方程式)
    ' --wrap=none            :避免硬換行
    ' --resource-path        :讓圖片等資源能以來源檔所在資料夾為基準
    cmd = "pandoc " & QuoteWin(src) & _
          " -f markdown+tex_math_dollars+latex_macros" & _
          " -t docx --standalone --wrap=none" & _
          " --resource-path=" & QuoteWin(GetFolder(src))

    If Len(refDoc) > 0 Then
        cmd = cmd & " --reference-doc=" & QuoteWin(refDoc)
    End If

    cmd = cmd & " -o " & QuoteWin(dst)

    Set sh = CreateObject("WScript.Shell")
    Set ex = sh.Exec("cmd /c " & cmd)

    ' 等待完成(最多 5 分鐘,可自行調整)
    Dim t As Date: t = Now
    Do While ex.Status = 0
        DoEvents
        If Now - t > TimeSerial(0, 5, 0) Then Exit Do
    Loop

    outStr = ex.StdOut.ReadAll
    errStr = ex.StdErr.ReadAll

    If Len(errStr) > 0 And Not FileExists(dst) Then
        MsgBox "Pandoc 錯誤輸出:" & vbCrLf & errStr, vbExclamation
        ConvertWithPandocWin = False
        Exit Function
    End If

    ConvertWithPandocWin = FileExists(dst)
    Exit Function
EH:
    MsgBox "執行 Pandoc 時發生錯誤:" & Err.Description, vbExclamation
    ConvertWithPandocWin = False
End Function

'── 路徑/字串/檔案工具 ──────────────────────────────────────────────────────
Private Function QuoteWin(ByVal s As String) As String
    QuoteWin = """" & s & """"
End Function

Private Function GetFolder(ByVal path As String) As String
    GetFolder = Left$(path, InStrRev(path, "\") - 1)
End Function

Private Function GetFileName(ByVal path As String) As String
    GetFileName = Mid$(path, InStrRev(path, "\") + 1)
End Function

Private Function GetFileExt(ByVal path As String) As String
    Dim p As Long: p = InStrRev(path, ".")
    If p > 0 Then GetFileExt = Mid$(path, p) Else GetFileExt = ""
End Function

Private Function FileExists(ByVal path As String) As Boolean
    On Error Resume Next
    FileExists = (Len(Dir$(path, vbNormal)) > 0)
End Function

學不完.教不停.用不盡文章列表

文章標籤
ChatGPT Word 數學公式
全站熱搜
創作者介紹
創作者 vincent 的頭像
vincent

學不完.教不停.用不盡

vincent 發表在 痞客邦 留言(0) 人氣()