【问题标题】:Microsoft Access Add-In using VSTO使用 VSTO 的 Microsoft Access 加载项
【发布时间】:2018-09-16 10:46:17
【问题描述】:

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

如果我的目标是 MS Word、Excel、Outlook、PowerPoint、Visio、InfoPath、 或 Project,然后 Visual Studio Tools for Office(请参阅here)将是理想的选择。但是,Access 要么从来没有(正式)成为该计划的一部分,要么是 dropped 在很久以前得到它的官方支持。有一家名为 Add-In Express 的公司似乎支持带有 Access 的 VSTO,用于example,但许可证非常昂贵,如果可以直接完成,我宁愿不涉及第三方软件。 2008 年有一篇带有 hack 的 MS 博客文章,它利用了“VSTO 加载项项目在很大程度上与主机无关的性质”,并将 Word 加载项转换为 Access 加载项。这有一个警告:

但是请注意,我不鼓励人们在生产中使用这种方法——我们没有测试过这种行为,并且明确表示不以任何方式支持它。我所做的是探索如何将 VSTO 设计为最佳地与主机无关,以便插件模型尽可能灵活 - 不会达到旧的“共享”插件提供的松散类型的极端型号。

此方法是针对 this 最近的 SO 问题提出的,并且显然已被提问者成功使用。虽然我担心缺乏官方支持,但这对于原型来说可能就足够了,我已经尝试使用它。

按照步骤 1 到 8 没有任何问题后,我点击调试,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 --- 

谷歌搜索“vsto 下载文件未成功”给我带来了here,这似乎很相关:

问题是 Office 应用程序正在寻找部署清单 (.vsto) 和应用程序清单 (.dll.manifest) 并且无法找到它们。

我在我的机器上搜索了一个 vsto 文件扩展名,发现唯一的一个在我的 VS 解决方案文件夹中。所以我想也许博客方法中的第 6 步是错误的,最后一行应该替换为这个 vsto 文件的路径。然而,这似乎不是问题。

然后我发现这个 MSDN article 解决常见 VSTO 问题和常见错误 4 是匹配的。列出的“解决方案”是:

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

这链接here这是一个标题为页面

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

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

【问题讨论】:

  • “这个”已经烂掉了(?),你可以通过检查来发现。至于dosc:例如,使用Visual Studio 2010 Standard,您可以为Office 2000到2016构建一个插件。
  • 谢谢古斯塔夫。我不应该假设。在进行更多研究后,“这”似乎是一家销售这项技术的公司。我想知道是否有办法在不使用第三方的情况下做到这一点。我在这方面取得了进展,然后遇到了另一个障碍,现在已经对问题进行了重大编辑。它仍然符合标题,因此我将其保留为编辑而不是新问题。
  • 好的,到目前为止我还没有阅读。我已投票支持重新讨论​​该问题。我第一次这样做,所以我不知道结果如何......
  • 感谢古斯塔夫的投票。

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


【解决方案1】:

我不认为 VSTO 工具真的值得麻烦,而且如果你创建一个“插件”,那么这样的插件将在 Access 启动时为所有 Access 应用程序加载,而不是仅限于您的一个应用程序。并且必须在 Office OFTEN 注册加载项会导致在 Access 中启动问题。因此,您的加载项必须加载,并加载任何和所有出于任何原因简单地启动 Access 的情况。

所有 VSTO 工具真正做的就是设置一个到 office 的 com 接口,在 .net 中构建一个“简单”类,然后在访问中通过 VBA 按钮使用它确实少了很多麻烦。

因此,一种简单的方法是“仅”使用来自 VBA/office 代码的 .net 类。无论如何,搞乱 VSTO 确实没有多大帮助,当你让所有 VSTO 东西工作时,你只需在 .net 中编写一个简单的类就可以完成并完成。

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

另一个选项(无论如何都是默认设置的!!!)在程序集区域中,您只需确保“使程序集 COM 可见)。

对于分发,您必须包含一个小批处理文件或使用安装程序。那个简单的批处理文件或安装程序必须在目标机器(非开发计算机)上执行“regasm”。

并确保您将项目强制为 x86(假设您使用的是 x32 的 office,这肯定是这种情况)。所以不要使用“任何”CPU,而是强制项目使用 x86 CPU。

除此之外,仅此而已。

这是一个简单的 .net 类。假设 .net 4.5 或更高版本,这允许您从 Access VBA 创建 zip 文件。

(您需要 system.IO.Compression 和 system.io.compression.Filesystem 作为 .net 项目中的引用。结果是在没有任何第三方工具的情况下从 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 long 数据类型。如果你坚持使用字符串、标准集合、数组等,那么你应该没问题。而且您实际上“可以”将不兼容的对象类型公开为 .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编辑器会“吐出”类的属性和方法:

例如:

总的来说,使用 VSTO 是一种巨大的矫枉过正。只需构建一个简单的 .net 类来公开您需要从 VBA 使用/调用的内容,然后您就可以参加比赛了。另一个大好处是这个 COM 对象可以在 windows 脚本、VB6、FoxPro、Excel、Word、power-point 等中使用。换句话说,你不限于任何一个平台或只是访问来消费 + 使用你的简单类您公开为 COM 对象。在大多数情况下,我很难为 VSTO 提出理由。因此,现在可以在任何办公应用程序(VBA 代码)中轻松使用此对象。

【讨论】:

  • 这是一个非常有趣的建议。我什至没有考虑过VBA。我已经玩了一些,并且已经有了一些简单的工作。看起来我单独使用 VBA 可能会有很长的路要走,尤其是知道有一个 .net 备份计划。感谢您的彻底回应。
  • 不客气。使用 VSTO 插件,您曾建议用户在某种形式上点击按钮 - 在这种情况下 VSTO 甚至没有多大用处。在大多数情况下,必须从功能区调用您的加载项。使用按钮构建表单,然后这种方法比 VSTO 工作量少,而且我通常不希望加载项仅限于功能区,而只是想使用 VBA 后面的一些很酷的 .net 功能按钮。我一直在做上面的事情。我不得不使用 Sage Accounting SDK 接口。 VBA 没有,但 .net 很棒,因此使用了上面的 COM 想法 - 效果很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多