我需要动态加载程序集。目前我正在使用“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?
}
答案 0 :(得分: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];
答案 1 :(得分: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");
}
答案 2 :(得分: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;
答案 3 :(得分:0)
如果您使用的是.NET 3.5,则无法使用dynamic
关键字。您唯一的选择是使用一系列代理类(手动编写或自动生成),如@Francesco所述。但是,如果您需要访问许多Excel类/函数/属性,那么手动方法非常麻烦。您必须为您需要的每个成员编写一个函数/属性代理。
管理它的关键是,不是编写大量代理函数,而是将处理Excel的所有代码放在一个单独的软件层(如数据访问层,DAL)中,放在不同的库项目中。该层只为应用程序提供了一些高级接口(只有少数成员函数),因此应用程序甚至不知道MS Excel自动化的使用情况。
请注意,即使您不想动态加载程序集,这种Excel访问代码的封装也是一种很好的做法。例如,如果您发现令人沮丧的话,您可能更容易使用其他技术替换Office自动化,例如ADO.NET和reading from / writing to Excel files Microsoft.ACE.OLEDB.12.0
提供程序,您也会在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...
...
}
然后在一个名为Utils.OfficeAutomation.Impl
的单独项目中实现它,该项目引用Utils.OfficeAutomation
和真实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功能的网关。