C# 和 Excel 互操作

10

我的一个用户在尝试通过我的 C# 应用程序打开 Excel 文件时遇到了问题。

当我从我的计算机运行它并且对其他用户也起作用时,一切正常。由于我不是 Excel 互操作性专家,希望你们能帮助我解决这个问题。

这是设置方式:

我向我的应用程序添加了对 Microsoft.Office.Interop.Excel.dll 的引用,版本为 10.0.4504.0(我相信是 Excel 2002)。在我的计算机上,我安装了 Excel 2007。在我的代码中,我尝试像这样打开一个工作表:

using Microsoft.Office.Interop
...
Microsoft.Office.Interop.Excel.ApplicationClass _excelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = _excelApp.Workbooks.Open(workbookPath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", false, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelWorkbook.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet excelWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)excelSheets.get_Item(1);

我将用户的版本记录为Excel 9.0(即2000年版)。用户收到的错误信息是:

Exception='System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at Microsoft.Office.Interop.Excel.Workbooks.Open(String Filename, Object UpdateLinks, Object ReadOnly, Object Format, Object Password, Object WriteResPassword, Object IgnoreReadOnlyRecommended, Object Origin, Object Delimiter, Object Editable, Object Notify, Object Converter, Object AddToMru, Object Local, Object CorruptLoad)

看起来无法打开工作簿。确认文件存在,但它只是在用户的C:驱动器上松散存在。我认为使用PIA后就不用担心Excel版本问题了。我知道其他用户正在使用Excel 2000,并且在我的开发机器上可以正常运行。

有什么想法吗?也许我打开Excel文件的调用应该被更改?不幸的是,我无法重现这个问题。


如果您能,请帮忙解决这个问题:https://dev59.com/SWkw5IYBdhLWcg3wV5ID - Alex Gordon
3个回答

14

"我原以为使用PIA后,就不用担心Excel版本问题了。我知道有其他用户在使用Excel 2000,并且它可以在我的开发机上运行。"

基本上是正确的,但还不太完全。

通过使用Excel 2002的PIA进行开发,您的程序将与所有Excel 2002(10.0)及以上版本兼容。然而,失败的计算机正在运行Excel 2000(9.0),这是一个低于您所开发的版本。

在Excel 2002以下没有官方支持的PIA,因此,如果您需要您的程序在Excel 2000(9.0)上运行,则必须创建自己的自定义互操作程序集。您可以使用TlbImp.exe创建Excel 9.0的互操作程序集,如文章Achieving Backward Compatibility with .NET Interop: Excel as Case Study中所述。

"
如果您的程序集是强名称的,那么您需要创建一个强命名互操作程序集。这可以通过使用 /keyfile 开关提供 .pfx 或 .snk 文件的名称来完成,如文章如何创建主要互操作程序集(PIA)所示。该文章还使用了 /primary 开关来创建“主要互操作程序集”。在您的情况下,使互操作程序集成为主要程序集并不是必需的,但也无妨。然而,文章遗漏了使用 /sysarray 开关,您应该使用它。
然而,创建强名称互操作程序集确实有一些需要考虑的复杂性。有关更多细节,请阅读使用TLBIMP.exe创建强名称互操作程序集。(除其他外,本文还解释了需要使用 /sysarray 开关的原因。)
简而言之,如果您的程序集没有强名称,则创建自定义互操作程序集非常简单。如果您的程序集具有强名称,则更加复杂,因此您需要创建一个强名称互操作程序集。但希望这些文章能帮助您入门。
-- Mike

没问题Jaspion...顺便说一下,如果你正在使用.NET 4.0,你根本不需要再创建Interop程序集了。 :-) 因此,这个解决方案的需求仅适用于.NET 3.5及以下版本。 - Mike Rosenblum

2

我正在使用Microsoft.Office.Interop.Excel.dll:

运行时版本:v1.1.4322

版本:12.0.0.0

你可以尝试这个:

  private object mMissingValue = System.Reflection.Missing.Value;

  private void CreateWorkbook(string fileName)
  {
     if (File.Exists(fileName))
     {
        // Create the new excel application reference
        mExcelApplication = new Application();
        // Open the file
        Workbook excel_workbook = mExcelApplication.Workbooks.Open(templatePath,
              mMissingValue, mMissingValue, mMissingValue, mMissingValue, mMissingValue,
              mMissingValue, mMissingValue, mMissingValue, mMissingValue, mMissingValue,
              mMissingValue, mMissingValue, mMissingValue, mMissingValue);
        Worksheet sheet = (Worksheet)mExcelWorkbook.Worksheets[1];
    }
 }

0

我现在更喜欢将Excel文件保存为XML电子表格,然后使用System.Xml对象打开它们。我经常使用XML来处理各种事情,而Interop对我来说则是一种黑魔法。如果这种方式能够满足您的需求,那么它可能比与Interop库纠缠要容易得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接