1

我需要动态加载程序集。目前我正在使用“Microsoft.Office.Microsoft.Office.Interop.dll”。我需要打开一个 excel 文件并从中获取工作表和数据。谁能告诉我该怎么做?

Assembly SampleAssembly = Assembly
          .Load("Microsoft.Office.Interop.Excel, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

if (SampleAssembly != null)
{
    Type type = SampleAssembly.GetType("Microsoft.Office.Interop.Excel.ApplicationClass");
    Object AppClass = Activator.CreateInstance(type);

   //How will I get ApplicationClass object and Workbooks objects here?
}
4

4 回答 4

3

利用dynamic

 Type type = SampleAssembly.GetTypes().Single(t => t.Name == "ApplicationClass");
 dynamic appClass = Activator.CreateInstance(type);

 var workbook = appClass.Workbooks.Open("C:\\test.csv");
 var worksheet = workbook.Worksheets[1];
于 2012-09-27T05:02:08.403 回答
2

如果您不能/不想使用动态,我将定义一个带有接口(或一组接口)的项目,该接口公开您需要使用的 excel 方法/对象,并且您可以在代码中引用而无需任何参考实际的excel dll。然后在引用 excel 并将动态加载的不同项目中实现它。

像这样的东西:

public interface IExcelApp
{
    IExcelWorkbook OpenWbk(string aPath);
    // other stuff
}

public interface IExcelWorkbook
{
    //the stuff you need
}

实现(在我称为 ExcelBridge 的项目中):

public class ExcelApp : IExcelApp
{
    private ApplicationClass _app;

    public ExcelApp()
    {
    }

    public IExcelWorkbook OpenWbk(string aPath)
    {
        return new ExcelWorkbook(_app.Workbooks.Open(aPath));
    }
}

public class ExcelWorkbook : IExcelWorkbook
{
    private Workbook _wbk;

    public ExcelWorkbook(Workbook aWbk)
    {
        _wbk = aWbk;
    }
}

那么你的代码可能是这样的:

Assembly SampleAssembly = Assembly.Load("ExcelBridge", Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

if (SampleAssembly != null)
{
    Assembly YourExcelAssembly = Assembly.Load("ExcelBridge.dll");
    Type type = YourExcelAssembly .GetType("ExcelApp");
    IExcel AppClass = Activator.CreateInstance(type) as IExcelApp;

   //now you can write:
   IExcelWorkBook aWbk = AppClass.Open("your xls path");
}
于 2012-09-27T08:17:42.380 回答
0

如果您使用的是 .NET 3.5,则不能使用dynamic关键字。您唯一的选择是使用@Francesco 所述的一系列代理类(手动编写或自动生成)。但是如果您需要访问大量 Excel 类/函数/属性,手动方法确实很麻烦。您必须为您需要的每个成员编写一个函数/属性代理。

管理这一点的关键是,您无需编写大量代理函数,而是将所有处理 Excel 的代码放在一个单独的软件层(类似于数据访问层,DAL)中,放在不同的库项目中。该层只是为应用程序提供了一些高级接口(只有几个成员函数),因此应用程序甚至不知道 MS Excel 自动化的使用。

请注意,即使您不想动态加载程序集,Excel 访问代码的这种封装也是一种很好的做法。例如,如果您觉得 Office 自动化令人沮丧,您可以很容易地用另一种技术(如 ADO.NET)替换它,该技术带有Microsoft.ACE.OLEDB.12.0用于读取/写入 Excel 文件的提供程序,您也会发现在 x64 平台中也令人沮丧!


例如,如果您想从 Excel 文件中获取工作表和数据,您可以在名为的项目中提供以下接口,例如Utils.OfficeAutomation(不引用Microsoft.Office.Interop.Excel.dll):

interface IExcelLayer {
    ...
    bool ImportFrom(string fileName, string sheetName, out object[,] cells, bool skipHeaderRow = true);

    // a few other members...
    ...
}

然后在一个名为 say 的单独项目中实现它,该项目Utils.OfficeAutomation.Impl同时引用Utils.OfficeAutomation和 real Microsoft.Office.Interop.Excel.dll

class ExcelMagician : IExcelLayer {
    ...
    bool ImportFrom(string fileName, string sheetName, out object[,] cells, bool skipHeaderRow = true)
    {
         Excel.Application excelApp = new Excel.Application()
         ...
    }
    ...
}

主应用程序仅对Utils.OfficeAutomation. 作为回报,Utils.OfficeAutomation它以某种方式负责动态查找和加载Utils.OfficeAutomation.Impl,或者在出现问题时生成错误:

IExcelLayer m_instance = null;

...

try
{
    Assembly assembly = Assembly.Load("Utils.OfficeAutomation.Impl");
    Type excelType = assembly.GetType("Utils.OfficeAutomation.Impl.ExcelMagician");
    m_instance = (IExcelLayer) Activator.CreateInstance(excelType);

}
catch (Exception e)
{
    throw new Exception("Couldn't load Excel assembly.")
}

如果未安装适当版本的 Microsoft Excel,则加载程序集会Utils.OfficeAutomation.Impl失败,或者调用类似的成员会ImportFrom生成异常。

您最终需要在内部编写包装类Utils.OfficeAutomation作为 Excel 访问层或 Excel 功能的网关。

于 2013-10-30T12:15:03.427 回答
0

这是您在 C# 中的操作方法

using Microsoft.Office.Interop.Excel;
Type type = SampleAssembly.GetType("Microsoft.Office.Interop.Excel.ApplicationClass");
var application = Activator.CreateInstance(type);
var workbook = application.Workbooks.Open(fileName);
var worksheet = workbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
于 2012-09-27T04:25:56.650 回答