首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# DataGridView 匯出 Excel 遇到 HRESULT:0x800A03EC 異常的解決方案

     編輯:程式設計綜合問答

錯誤現象

呼叫 excel.Save("D:\\234.xls") 拋出:

System.Runtime.InteropServices.COMException (0x800A03EC):異常來自 HRESULT:0x800A03EC

堆疊追蹤指向 ApplicationClass.SaveWorkspace。

根本原因

  • Application.Save() 是儲存工作區(.xlw),非儲存活頁簿(.xls/.xlsx)。
  • 儲存檔案應使用 Workbook.SaveAs() 或 Workbook.Save()。
  • 路徑 D:\\234.xls 若資料夾不存在、唯讀、或 Excel 程序無寫入權限,亦會觸發 0x800A03EC。
  • 未正確釋放 COM 物件導致 Excel 残留程序鎖定檔案。

修正後的完整匯出方法

using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

public bool ExportDataGridView(DataGridView gridView, string filePath)
{
    if (gridView.Rows.Count == 0)
    {
        MessageBox.Show("無資料可匯出", "提示");
        return false;
    }

    Excel.Application excel = null;
    Excel.Workbook wb = null;
    Excel.Worksheet ws = null;

    try
    {
        excel = new Excel.Application();
        excel.Visible = false;
        excel.DisplayAlerts = false; // 關閉覆蓋確認對話框

        wb = excel.Workbooks.Add(Type.Missing);
        ws = (Excel.Worksheet)wb.ActiveSheet;

        // 寫入標題列
        for (int c = 0; c < gridView.Columns.Count; c++)
            ws.Cells[1, c + 1] = gridView.Columns[c].HeaderText;

        // 寫入資料列(建議用陣列一次寫入,效能佳)
        object[,] data = new object[gridView.Rows.Count, gridView.Columns.Count];
        for (int r = 0; r < gridView.Rows.Count; r++)
            for (int c = 0; c < gridView.Columns.Count; c++)
                data[r, c] = gridView.Rows[r].Cells[c].Value?.ToString() ?? "";

        Excel.Range rng = ws.Range[ws.Cells[2, 1], ws.Cells[gridView.Rows.Count + 1, gridView.Columns.Count]];
        rng.Value2 = data;

        // 自動調整欄寬
        rng.EntireColumn.AutoFit();

        // 確保目錄存在
        var dir = Path.GetDirectoryName(filePath);
        if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);

        // 正確儲存:Workbook.SaveAs
        wb.SaveAs(filePath, Excel.XlFileFormat.xlWorkbookNormal,
                  Type.Missing, Type.Missing, false, false,
                  Excel.XlSaveAsAccessMode.xlNoChange,
                  Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

        return true;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"匯出失敗:{ex.Message}", "錯誤");
        return false;
    }
    finally
    {
        // 依序釋放 COM 物件(反向順序)
        if (ws != null) Marshal.ReleaseComObject(ws);
        if (wb != null) { wb.Close(false); Marshal.ReleaseComObject(wb); }
        if (excel != null) { excel.Quit(); Marshal.ReleaseComObject(excel); }
        GC.Collect(); GC.WaitForPendingFinalizers(); // 強制回收 RCW
    }
}

關鍵修正點

  1. 使用 Workbook.SaveAs 指定格式 xlWorkbookNormal(.xls)或 xlOpenXMLWorkbook(.xlsx)。
  2. 陣列批次寫入:Range.Value2 = object[,] 比逐格寫入快 100 倍以上。
  3. 正確釋放 COM 物件:Marshal.ReleaseComObject + GC.Collect(),避免 Excel.exe 残留。
  4. 關閉 DisplayAlerts:防止覆蓋檔案時彈窗卡住無人值守程序。

替代方案:免安裝 Excel 的純 .NET 庫

  • EPPlus(.xlsx,LGPL/商業授權):ws.Cells["A1"].LoadFromDataTable(dt, true);
  • NPOI(.xls/.xlsx,Apache 2.0):支援 HSSFWorkbook/XSSFWorkbook。
  • ClosedXML(.xlsx,MIT):語法簡潔 ws.Cell(1,1).Value = "標題";
  • DocumentFormat.OpenXml(Microsoft 官方,.xlsx,低階 SDK)。

若為伺服器端/容器化部署,強烈建議改用 EPPlus/NPOI/ClosedXML,避免 Office Interop 需安裝 Excel、權限、DCOM 設定等坑。

常見 0x800A03EC 其他成因

  • 檔案被其他程式開啟(含 Excel 預覽窗格)。
  • 路徑過長(>259 字元)或包含非法字元。
  • Excel 版本與 Interop 組件版本不匹配(如 Office 365 64-bit 搭配 32-bit Interop)。
  • 伺服器端 DCOM 設定:dcomcnfg → 元件服務 → Microsoft Excel Application → 身分識別 → 互動式使用者。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved