使用VSTO的Microsoft Access加载项

时间:2018-09-16 10:46:17

标签: c# visual-studio ms-access plugins office-addins

我正在尝试扩展MS Access的功能。我希望用户能够从Access应用程序中触发此功能,最好是单击我介绍的按钮。我希望能够使用C#来实现此功能。

如果我定位到MS Word,Excel,Outlook,PowerPoint,Visio,InfoPath, 或Project,那么Visual Studio Tools for Office(请参见here)将是理想的选择。但是,Access从来没有(正式地)成为该计划的一部分,或者早在dropped之前就获得了它的正式支持。有一家名为Add-In Express的公司似乎为example支持带Access的VSTO,但是许可证非常昂贵,如果可以直接完成,我不希望不涉及第三方软件。有一篇来自2008年的MS博客文章,带有hack,该文章利用了“ VSTO外接程序项目在很大程度上与主机无关的性质”,并将Word外接程序转换为Access外接程序。注意:

  

但是请注意,我不鼓励人们在生产中使用这种方法-我们尚未测试这种行为,并且显然不以任何方式支持该行为。我要做的是探索VSTO如何设计成与主机无关的最佳方式,从而使加载项模型尽可能灵活-而不用考虑到旧的“共享”加载项提供的松散类型的极端性模型。

此方法是针对this最近的SO问题提出的,显然已被问题提问者成功使用。尽管我对缺乏官方支持感到担忧,但这可能足以满足原型要求,并且我已尝试使用它。

按照步骤1至8进行操作,没有任何问题后,我点击了Debug,MS Access启动,然后引发以下错误对话框:

Microsoft Office Customization Installer
There was an error during installation.

Downloading file:///C:/Temp/MyAddIn/bin/Debug/MyAddIn.vsto did not succeed.

Details:

************** Exception Text **************
System.Deployment.Application.DeploymentDownloadException: Downloading 
file:///C:/Temp/MyAddIn/bin/Debug/MyAddIn.vsto did not succeed. ---> 
System.Net.WebException: Could not find a part of the path 
'C:\Temp\MyAddIn\bin\Debug\MyAddIn.vsto'. ---> System.Net.WebException: 
Could not find a part of the path 'C:\Temp\MyAddIn\bin\Debug\MyAddIn.vsto'. 
---> System.IO.DirectoryNotFoundException: Could not find a part of the path 
'C:\Temp\MyAddIn\bin\Debug\MyAddIn.vsto'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess 
access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, 
FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean 
bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess 
access, FileShare share, Int32 bufferSize, FileOptions options, String 
msgPath, Boolean bFromProxy)
   at System.Net.FileWebStream..ctor(FileWebRequest request, String path, 
FileMode mode, FileAccess access, FileShare sharing, Int32 length, Boolean 
async)
   at System.Net.FileWebResponse..ctor(FileWebRequest request, Uri uri, 
FileAccess access, Boolean asyncHint)
   --- End of inner exception stack trace ---
   at System.Net.FileWebResponse..ctor(FileWebRequest request, Uri uri, 
FileAccess access, Boolean asyncHint)
   at System.Net.FileWebRequest.GetResponseCallback(Object state)
   --- End of inner exception stack trace ---
   at System.Net.FileWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Net.FileWebRequest.GetResponse()
   at 
System.Deployment.Application.SystemNetDownloader.DownloadSingleFile
(DownloadQueueItem next)
--- End of inner exception stack trace --- 

Google搜索“ vsto下载文件未成功”给我带来了here,这似乎很重要:

  

问题是Office应用程序正在查找部署清单(.vsto)和应用程序清单(.dll.manifest),但找不到它们。

我在机器上搜索了一个vsto文件扩展名,发现的唯一一个是在VS solution文件夹中。因此,我认为博客方法中的第6步可能是错误的,最后一行应替换为此vsto文件的路径。但是,这似乎不是问题。

然后,我找到了此MSDN article,该书用于排查常见的VSTO问题,并且常见错误4是匹配的。列出的“解决方案”是:

  

当VSTO解决方案试图从域控制器获取证书信息(发布者名称和其他数据)并且超时时,通常会出现此问题。若要解决此问题,请安装此修补程序:KB 981574。

此链接here是标题为页面的页面

  

当您尝试在安装了.NET Framework 3.5 SP1的计算机上启动Excel时,启动屏幕保持打开状态的时间比平常长。

似乎完全无关。这是断开的链接吗?我不确定如何进行。

1 个答案:

答案 0 :(得分:2)

我认为VSTO工具确实不值得麻烦,而且,如果您创建“加载项”,那么将在Access启动时为所有Access应用程序加载此类add = in,而不是仅限于您的一个应用程序。并且必须在Office OFTEN中注册该加载项会导致Access中启动的问题。因此,您的加载项将必须加载,并为任何出于任何原因而启动Access的所有情况加载。

所有VSTO工具真正做的就是设置一个com到office的接口,只需要在.net中构建一个“简单”类,然后通过访问中的VBA按钮就可以使用它了。 >

因此,一种简单的方法是“仅”使用VBA /办公代码中的.net类。无论如何,对VSTO的困扰实际上并没有多大帮助,并且随着您使VSTO的所有工作正常进行,只需在.net中编写一个简单的类就可以使您早日完成。

一些提示: 确保选中.net“注册”中的COM互操作复选框。请记住,此选项仅在您的开发计算机上的开发过程中为您的方便而执行重排。

另一个选项(仍然是默认设置!!)在装配区域中,您只需要确保“使装配COM可见”即可。

要进行分发,您将必须包含一个小的批处理文件或使用安装程序。这个简单的批处理文件或安装程序必须在目标计算机(非开发计算机)上执行“重排”。

并确保将项目强制为x86(假设您使用的是Office x32,这是肯定的情况)。因此,请勿使用“任何” CPU,而应将项目强制为x86 CPU。

除了上面以外,就是这样。

这是一个简单的.net类。假设使用.net 4.5或更高版本,则可以从Access VBA创建zip文件。

(。net项目中需要同时使用system.IO.Compression和system.io.compression.Filesystem作为引用。结果是从Access中压缩文件而没有任何第三方工具。

.net中的类是这样的:

Imports System.Runtime.InteropServices
Imports System.IO.Compression
Imports System.IO

<ClassInterface(ClassInterfaceType.AutoDual)>
Public Class AlbertCom1

Private m_Times2 As Integer

Public Sub MsgHello()

    MsgBox("Hello world", MsgBoxStyle.Information, "VB.net example")

End Sub

Public Sub MyZipper(strFileName As String, strZipFile As String)

    Using archive As ZipArchive = ZipFile.Open(strZipFile, ZipArchiveMode.Update)
        archive.CreateEntryFromFile(strFileName, Path.GetFileName(strFileName), CompressionLevel.Fastest)
    End Using

End Sub

Public Function GetConValue(strSetting As String) As String

    ' read a simple value from config file
    Return My.Settings(strSetting).ToString

End Function

Public Property Times2 As Integer
    Get
        Return m_Times2
    End Get
    Set(value As Integer)
        m_Times2 = value * 2
    End Set
End Property

End Class

因此,以上内容非常简单且简短。

在Access VBA的按钮后面,我们可以使用以下代码:

从上方调用/使用Hello消息框方法:

Sub TestCOMHello()

  Dim mycom      As Object
  Set mycom = CreateObject("AlbertCom1.AlbertCom1")

  mycom.MsgHello

End Sub

请注意LATE绑定是如何进行的-在VBA中无需引用该对象的情况下就可以工作。 (因此createObject()是必需的。)

但是,以下示例使用早期绑定,但是所有示例都可以按照上述方式创建对象。

从VBA压缩文件:

Sub TestCOMZip()

  Dim strFromFile      As String
  Dim strToFile        As String

  Dim mycom      As New AlbertCom1.AlbertCom1

  strFromFile = "c:\test\data.txt"
  strToFile = "c:\test\data.zip"

  mycom.MyZipper strFromFile, strToFile


End Sub

更多提示:

您实际上不必在课堂上构建自定义界面,尽管许多人在使用AutoDual时并不满意,但我认为这种方法很好。互联网上花费所有时间创建自定义界面的“示例”确实只是世界贫困的借口。

最后一个重要提示: 不要在您的类中公开任何不兼容的数据类型。如果暴露(偶然或有意)与标准“ com”对象不兼容的任何.net对象类型,则您的.net类将编译得很好,但是Access将无法正确查看或使用该对象。因此,在实际的上述类中,将这些变量和例程保留(声明)为私有。 (其他代码和部分无关紧要-我所说的只是一个类)。

例如,请勿公开.net长数据类型。如果您坚持使用字符串,标准集合,数组等,那么您应该还不错。您实际上可以“将”不兼容的对象类型“公开”为.net中的“对象”。 (Access中的Intel-sense不会显示对象方法,但是您仍然可以使用它们。)

尽管对于您的对象方法而言,公共函数甚至公共变量最简单,但这里还是按照“标准”方法使用get / set方法来创建类方法。

所以在.net中,我们有:

Public Property Times2 As Integer
    Get
        Return m_Times2
    End Get
    Set(value As Integer)
        m_Times2 = value * 2
    End Set
End Property

在您的VBA代码中,我们有:

Sub TestTimes()

   Dim mycom     As New AlbertCom1.AlbertCom1

   mycom.Times2 = 40

   Debug.Print mycom.Times2

End Sub

output: 80

请注意早期绑定,然后Access VBA编辑器将“吐出”该类的属性和方法:

例如:

enter image description here

总的来说,使用VSTO总体来说是过大的。只需构建一个简单的.net类,以展示您需要从VBA使用/调用的内容,然后开始比赛。而其他的大缺点是,可以从Windows脚本,VB6,FoxPro,Excel,Word,powerpoint等使用此COM对象。换句话说,您不限于任何一个平台或仅访问即可使用+使用您的简单类您公开为COM对象。在大多数情况下,我很难为VSTO辩护。因此,现在可以轻松地在任何办公应用程序(VBA代码)中使用此对象。