使用VSTO和COM Interop,我正在尝试访问和操作已在Microsoft Access中打开的数据库。我可以掌握Access应用程序对象,当前用户名和其他属性。但是,当我尝试获取表列表以打印表名称时,代码将失败。
我的最终目标是使用'application.Run(“ MyMacroName”)'运行Access VBA宏。谁能告诉我我在想什么或做错了什么?谢谢。
更新解决方案
谢谢Albert(见下文),他一直提供(Visual Basic)信息,直到我能够使用C#代码为止。我所缺少的最大的东西是1)使用引用的DAO(VStudio最初说我并不需要它),以及2)循环的explicit DAO TableDef类型(“ var”不起作用)。
有效的更新代码:
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Access;
using Microsoft.Office.Interop.Access.Dao; // *MUST* have DAO as well
using Access = Microsoft.Office.Interop.Access; // Access = a namespace qualifier
[TestMethod()]
public void MsAccessComInteropTest() {
// explicitly cast the object to an Access.Application
// I used 'Access.Application' to qualify from a System.xxxx.Application type
var app = (Access.Application) Marshal.GetActiveObject("Access.Application");
Dprint($"{app.Name}"); // prints Microsoft Access
Dprint($"{app.CurrentUser()}"); // prints Admin
var db = app.CurrentDb();
// *MUST* use TableDef type explicitly from DAO in loop - cannot use 'var'
foreach (TableDef tbl in db.TableDefs) {
// Attributes == 0 means a user-defined table
if (tbl.Attributes == 0) {
Debug.Print($"{tbl.Name} '{tbl.Attributes.ToString()}'");
}
}
app.Run("MyVbaMacroName");
}
您需要同时访问Access和DAO。
这两个:
Microsoft.Office.Interop.Access
C:\Program Files (x86)\Microsoft Visual Studio 12.0\
Visual Studio Tools for Office\PIA\Office14\
Microsoft.Office.Interop.Access.dll
您需要这个:
Microsoft.Office.Interop.Access.Dao
C:\Program Files (x86)\Microsoft Visual Studio 12.0\
Visual Studio Tools for Office\PIA\Office14\
Microsoft.Office.interop.access.dao.dll
因此您的代码将如下所示:
{
Access.Application app;
app = Interaction.GetObject(Class: "Access.Application");
Access.Dao.Database db;
db = app.CurrentDb;
Access.Dao.TableDef tblDef;
foreach (var tblDef in db.TableDefs)
Debug.Print(tblDef.Name);
}
实际上,您可以使用后期绑定,甚至不引用互操作程序集。
例如此:
{
var app = Interaction.GetObject(Class: "Access.Application");
var db = app.CurrentDB;
var tblDef;
foreach (var tblDef in db.TableDefs)
Debug.Print(tblDef.Name);
}
但是,如果您进行100%的后期绑定,那么您将不会获得任何智能感知。
而且,这看起来很奇怪:
using Access = Microsoft.Office.Interop.Access;
为什么上面的“ =”-我认为看起来不正确。
应该是:
using Access Microsoft.Office.Interop.Access;
因此,如果要使用互操作进行引用-您需要Access + DAO。 (而且它们是不同的汇编,但是使用相同的名称空间-不确定c#中是否存在问题,但在vb.net中存在]
如果要获取完整的表列表,通常使用CurrentDb.Tabledefs
var db = app.CurrentDb();
foreach (var td in db.TableDefs) {
Dprint(td.Name);
}