使用 COM Interop 从 VSTO C# 列出现有 Access 实例的 MS Access 表
List MS Access tables of existing Access instance from VSTO C# using COM Interop
使用 VSTO 和 COM Interop,我正在尝试访问和操作已在 Microsoft Access 中打开的数据库。我可以获得 Access 应用程序对象、当前用户名和其他属性。但是,当我尝试获取 table 的列表以打印 table 名称时,代码失败了。
我的最终目标是 运行 使用 '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");
}
如果你想要完整的表格列表,通常使用CurrentDb.Tabledefs
var db = app.CurrentDb();
foreach (var td in db.TableDefs) {
Dprint(td.Name);
}
您需要对 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。 (它们是不同的程序集,但使用相同的名称 space - 不确定这是否是 c# 中的问题,但它在 vb.net
中
使用 VSTO 和 COM Interop,我正在尝试访问和操作已在 Microsoft Access 中打开的数据库。我可以获得 Access 应用程序对象、当前用户名和其他属性。但是,当我尝试获取 table 的列表以打印 table 名称时,代码失败了。
我的最终目标是 运行 使用 '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");
}
如果你想要完整的表格列表,通常使用CurrentDb.Tabledefs
var db = app.CurrentDb();
foreach (var td in db.TableDefs) {
Dprint(td.Name);
}
您需要对 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。 (它们是不同的程序集,但使用相同的名称 space - 不确定这是否是 c# 中的问题,但它在 vb.net
中