使用 Excel Interop 打开后文件被锁定

File Locked after Opening with Excel Interop

我正在打开一个 excel 文件,刷新它的数据源,然后使用 c# 应用程序将其保存为 PDF。我基于像 this 这样的代码示例。但是,即使在调用最终发布之后,该文件仍保持锁定状态。

Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();

// Open the Workbook:
Microsoft.Office.Interop.Excel.Workbook wb = excelApp.Workbooks.Open(
    @"c:\test\test.xlsx",
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing);

Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets[1];

wb.RefreshAll();
Thread.Sleep(4000); //surely a better way to do this

//ws.PrintOut(Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wb.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, @"c:\test\test.pdf");

// Cleanup:
GC.Collect();
GC.WaitForPendingFinalizers();

Marshal.FinalReleaseComObject(ws);

wb.Close(false, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(wb);

excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);

哪些额外的步骤可以确保它在该过程完成后不被锁定?

  1. 我认为您在这里做的一些工作没有按顺序进行 - 即,在关闭您的应用程序或工作簿之前进行收集。
  2. 我已经到了清理 Excel 对象的每个部分的地步 - 工作表、工作簿、应用程序和进程 ID。这可能是非常谨慎的,但最好确保您正在清理内存 IMO。
  3. 我不知道这是你的问题,但我倾向于使用更完整的语句来导出 PDF。我会考虑的。

    xlWorkbook.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, 文件路径, Excel.XlFixedFormatQuality.xlQualityStandard, true, false, 1, 1, true, missing);

我为自己的工作所做的是创建两个函数来处理杀死 ghost 进程的工作(这可能会导致您的锁定)。

我的代码打包在一个 class 中,我创建它来为我处理 Excel 个名为 singleExcel 的实例,所以根据需要调整它,但它应该能让你在路上。

public Excel._Worksheet xlWorksheet { get; set; }
public Excel.Application xlApp { get; set; }
public Excel.Workbook xlWorkbook { get; set; }
public Process excelProcess { get; set; }

public static void CloseSheet(singleExcel thisExcel)
{
    if (thisExcel.excelProcess != null)
    {
        try
        {
            thisExcel.excelProcess.Kill();
            thisExcel.excelProcess.Dispose();
        }
        catch (Exception ex)
        {
            // depending on your needs   
        }
    }
    else
    {
        thisExcel.xlWorkbook.Close(true);
        thisExcel.xlApp.Quit();
    }
    releaseObject(thisExcel.xlWorksheet);
    releaseObject(thisExcel.xlWorkbook);
    releaseObject(thisExcel.xlApp);
    releaseObject(thisExcel.excelProcess);
    releaseObject(thisExcel);
}

public static void releaseObject(object obj)
{
    try
    {
        Marshal.ReleaseComObject(obj);
        obj = null;
    }
    catch
    {
        obj = null;
    }
    finally
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}