首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 使用 Microsoft Word Interop 實現文件批次文字替換

     編輯:ASP.NET 基礎

前置需求

  • 伺服器安裝 Microsoft Office Word(或至少安裝 Word 互通組件)
  • 專案參考 `Microsoft.Office.Interop.Word`(COM 索引標籤中選取)
  • 目標應用程式集區身分識別需具備桌面互動權限(IIS 設定「載入使用者設定檔 = True」)

完整封裝類別

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Word;

namespace TextReplace
{
    public class WordOperator : IDisposable
    {
        private Application _app;
        private Document _doc;
        private readonly object _missing = Missing.Value;

        /// 
        /// 開啟 Word 文件
        /// 
        public void Open(string filePath)
        {
            _app = new ApplicationClass();
            object file = filePath;
            _doc = _app.Documents.Open(
                ref file, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing);
        }

        /// 
        /// 全文件文字替換
        /// 
        /// 搜尋文字
        /// 替換文字
        public void ReplaceAll(string findText, string replaceText)
        {
            _app.Selection.Find.ClearFormatting();
            _app.Selection.Find.Replacement.ClearFormatting();
            _app.Selection.Find.Text = findText;
            _app.Selection.Find.Replacement.Text = replaceText;
            
            object replaceAll = WdReplace.wdReplaceAll;
            _app.Selection.Find.Execute(
                ref _missing, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref replaceAll, ref _missing,
                ref _missing, ref _missing, ref _missing);
        }

        /// 
        /// 儲存文件
        /// 
        public void Save()
        {
            _doc.Save();
        }

        /// 
        /// 另存新檔
        /// 
        public void SaveAs(string filePath)
        {
            object file = filePath;
            _doc.SaveAs2(ref file, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing,
                ref _missing, ref _missing, ref _missing, ref _missing);
        }

        /// 
        /// 關閉文件並結束 Word 應用程式
        /// 
        public void Dispose()
        {
            try
            {
                if (_doc != null)
                {
                    _doc.Close(ref _missing, ref _missing, ref _missing);
                    Marshal.ReleaseComObject(_doc);
                    _doc = null;
                }
            }
            finally
            {
                if (_app != null)
                {
                    _app.Quit(ref _missing, ref _missing, ref _missing);
                    Marshal.ReleaseComObject(_app);
                    _app = null;
                }
                // 強制回收 COM 物件
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }

        /// 
        /// 緊急終止殘留 Word 進程
        /// 
        public static void KillWinwordProcesses()
        {
            foreach (var p in Process.GetProcessesByName("WINWORD"))
            {
                try { p.Kill(); } catch { }
            }
        }
    }
}

使用範例:批次處理多份文件

var replacements = new Dictionary<string, string>
{
    { "[ClientName]", "台積電" },
    { "[Date]", DateTime.Today.ToString("yyyy年MM月dd日") },
    { "[Amount]", "NT$ 1,250,000" }
};

foreach (var file in Directory.GetFiles(@"D:\Templates\", "*.docx"))
{
    using (var word = new WordOperator())
    {
        try
        {
            word.Open(file);
            foreach (var kvp in replacements)
                word.ReplaceAll(kvp.Key, kvp.Value);
            
            string output = Path.Combine(@"D:\Output\", Path.GetFileName(file));
            word.SaveAs(output);
        }
        catch (Exception ex)
        {
            Log.Error($"處理 {file} 失敗: {ex.Message}");
        }
    }
}

// 防禦性清理
WordOperator.KillWinwordProcesses();

關鍵技術細節與避坑指南

議題說明解決方案
COM 物件未釋放導致 Word 殘留進程Interop 物件需顯式 `Marshal.ReleaseComObject``Dispose()` 中釋放 Document/Application,呼叫 `GC.Collect()`
伺服器端自動化不支援Microsoft 官方不建議伺服器端自動化 Office改用 Open XML SDK、NPOI、Aspose.Words 等無 Office 相依的純 .NET 程式庫
對話框阻塞(如宏啟用、轉換確認)無人值守環境會卡住`_app.DisplayAlerts = WdAlertLevel.wdAlertsNone`;設定信任中心關閉宏警告
權限問題IIS 僅有者身分執行,無桌面權限應用程式集區「進階設定」→ 載入使用者設定檔 = True;身分識別使用具權限帳號
大量檔案處理效能逐個啟動/關閉 Word 極慢單一 Word 實例處理多檔案;或改用無 Office 相依方案

現代化替代方案推薦

  1. Open XML SDK:Microsoft 官方純 .NET 程式庫,操作 `.docx`(OOXML 格式),無 Office 安裝需求,效能極佳
  2. NPOI:Apache POI .NET 移植版,支援 `.doc`/`.docx`/`.xls`/`.xlsx`,社群活躍
  3. Aspose.Words:商業元件,功能最完整(郵件合併、轉 PDF、列印),付費授權
  4. DocX:輕量級 `.docx` 操作庫,API 簡潔易用

結語

Interop 方案適合低頻率、需精確排版、已有 Office 授權的內部工具。生產環境高併發、無人值守、跨平台部署場景,強烈建議改用 Open XML SDK 或 NPOI,避免 COM 互通層帶來的穩定性與授權風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved