Excel VBA 到 VB (DCOM)

发布于 2024-07-18 22:39:31 字数 505 浏览 3 评论 0原文

我继承了一个 Excel VBA 电子表格。 我的任务是把它转换成VB。

我认为应用程序使用 DCOM 对象从 PLC 获取数据。 以下代码在 MX1.0 更新时运行子 SBR1Select。

Sub Workbook_Open()
    ActiveWorkbook.SetLinkOnData "dassidirect|strandburner!MX1.0", "SBR1Select"
End Sub

当我打开控制面板 -> 管理工具 -> 组件服务,然后导航到控制台根目录 -> 组件服务-> 计算机 -> 我的电脑 -> DCOM Config 列出了项目“DASSIDirect”,我相信这是 Excel 引用的内容。

如何通过 DASSIDIRECT 组件将 VB 代码连接到 PLC?

注意:DASSIDIRECT 也是一项 Windows 服务(不确定这是否有助于回答问题)。

I inherited an Excel VBA spreadsheet. I have been tasked to convert it to VB.

I think that the application acquires data from a PLC using a DCOM object. The following code runs the sub SBR1Select when MX1.0 is updated.

Sub Workbook_Open()
    ActiveWorkbook.SetLinkOnData "dassidirect|strandburner!MX1.0", "SBR1Select"
End Sub

When I open Control Panel -> Administrative Tools -> Component Services, and then navigate to Console Root -> Component Services -> Computers -> My Computer -> DCOM Config the item "DASSIDirect" is listed, which I believe is what Excel references.

How do I connect VB code to the PLC through the DASSIDIRECT component?

NOTE: DASSIDIRECT is also a Windows service (not sure if this helps answer the question).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

救星 2024-07-25 22:39:31

我很久以前就做过一些关于 PLC 的工作,并询问了我的一位老同事。 他说您需要 WonderWare 的 InTouch,它有一组 .Net 2 兼容程序集,可以与 DASSIDIRECT 配合使用,满足您的需求。

这是最新版本,希望这是您正在寻找的版本。

I did some work with PLCs along time ago and asked one of my old colleagues. He says you need InTouch from WonderWare which has a set of .Net 2 compatible assemblys that will work with DASSIDIRECT to give you what you need.

Here's the latest version and I hope it is what you are looking for.

神仙妹妹 2024-07-25 22:39:31

哇,DDE。 DDE,我相信您也知道,它已经相当古老了。 网络 DDE 已被折旧,并且将不再在 Vista 中运行。 我只能想象这种趋势可能会持续下去。 但是 user32 中的 DDE API 仍然有效(参考在这里: http://msdn.microsoft.com/en-us/library/ms674605(VS.85).aspx),您可以通过一些工作从 .net 应用程序中调用它。 我能找到的唯一示例是针对 VB6 的,即使在那时它们也已经很旧了。 我相信你可以想象这有点痛苦。 无论如何,我从 API 指南(来自 Mentalis)中挖出了这个示例。 它不是 .Net,但无论如何它应该能让你开始:

'This application shows you how to use DDE to create a better PrevInstance-function.
'Compile this sample and start it two times
'The first instance minimizes itself and when the second instance is started, it will
'send a message to the first instance to maximize itself.

'in a module
Public Const VBServerName = "TestServer"
Public Const VBTopicName = "SHOW_YOUR_MAIN_WINDOW"
Public Const XCLASS_BOOL = &H1000
Public Const XTYPF_NOBLOCK = &H2 ' CBR_BLOCK will not work
Public Const XTYP_CONNECT = &H60 Or XCLASS_BOOL Or XTYPF_NOBLOCK
Public Const CP_WINANSI = 1004 ' default codepage for windows & old DDE convs.
Public Const SW_RESTORE = 9
Public Const DDE_FACK = &H8000
Public Const XCLASS_FLAGS = &H4000
Public Const XTYP_EXECUTE = &H50 Or XCLASS_FLAGS
Public Const DNS_REGISTER = &H1
Public Const DNS_UNREGISTER = &H2
Public Declare Function DdeInitialize Lib "user32" Alias "DdeInitializeA" (pidInst As Long, ByVal pfnCallback As Long, ByVal afCmd As Long, ByVal ulRes As Long) As Integer
Public Declare Function DdeCreateStringHandle Lib "user32" Alias "DdeCreateStringHandleA" (ByVal idInst As Long, ByVal psz As String, ByVal iCodePage As Long) As Long
Public Declare Function DdeConnect Lib "user32" (ByVal idInst As Long, ByVal hszService As Long, ByVal hszTopic As Long, pCC As Any) As Long
Public Declare Function DdeNameService Lib "user32" (ByVal idInst As Long, ByVal hsz1 As Long, ByVal hsz2 As Long, ByVal afCmd As Long) As Long
Public Declare Function DdeFreeStringHandle Lib "user32" (ByVal idInst As Long, ByVal hsz As Long) As Long
Public Declare Function DdeQueryString Lib "user32" Alias "DdeQueryStringA" (ByVal idInst As Long, ByVal hsz As Long, ByVal psz As String, ByVal cchMax As Long, ByVal iCodePage As Long) As Long
Public Declare Function DdeUninitialize Lib "user32" (ByVal idInst As Long) As Long
Function DdeCllback(ByVal uType As Long, ByVal uFmt As Long, ByVal hConv As Long, ByVal hszTopic As Long, ByVal hszItem As Long, ByVal hData As Long, ByVal dwData1 As Long, ByVal dwData2 As Long) As Long
    DdeCllback = Form1.AppDdeCallback(uType, uFmt, hConv, hszTopic, hszItem, hData, dwData1, dwData2)
End Function
'in a form
Dim isRun As Boolean, idInst As Long, hszVBServer As Long, hszVBTopic As Long
Dim hconvVBServer As Long, dderesult As Long
Private Sub Form_Load()
   'KPD-Team 2000
   'URL: http://www.allapi.net/
   'E-Mail: [email protected]
   If DdeInitialize(idInst, AddressOf DdeCllback, 0, 0) Then Exit Sub
   hszVBServer = DdeCreateStringHandle(idInst, VBServerName, CP_WINANSI)
    hszVBTopic = DdeCreateStringHandle(idInst, VBTopicName, CP_WINANSI)
    'try to find the first instance
    hconvVBServer = DdeConnect(idInst, hszVBServer, hszVBTopic, ByVal 0&)
    If hconvVBServer Then
        Unload Me
        Exit Sub
    End If
    DdeNameService idInst, hszVBServer, 0, DNS_REGISTER
    Me.WindowState = vbMinimized
End Sub
Private Sub Form_Unload(Cancel As Integer)
        DdeFreeStringHandle idInst, hszVBServer
        DdeFreeStringHandle idInst, hszVBTopic
        'only unregister the DDE server for first instance
        If isRun Then
            If DdeNameService(idInst, hszVBServer, 0, DNS_UNREGISTER) Then
                MsgBox "in ServiceUnRegister", vbOKOnly, "Error"
            End If
        End If
        DdeUninitialize idInst
End Sub
Function AppDdeCallback(ByVal wType As Long, ByVal wFmt As Long, ByVal hConv As Long, ByVal hszTopic As Long, ByVal hszItem As Long, ByVal hData As Long, ByVal lData1 As Long, ByVal lData2 As Long) As Long
        Dim iCount As Long, Buffers As String, Ret As Long
        Select Case wType
            Case XTYP_CONNECT
                iCount = DdeQueryString(idInst, hszTopic, vbNullString, 0, CP_WINANSI)
                Buffers = Space(iCount)
                DdeQueryString idInst, hszTopic, Buffers, iCount + 1, CP_WINANSI
                If Buffers = VBTopicName Then
                    Me.WindowState = vbNormal
                    'add any code for the first instance have found the second one is launch
                    Ret = DDE_FACK
                End If
                AppDdeCallback = Ret
            Case XTYP_EXECUTE
                AppDdeCallback = Ret
        End Select
End Function

Wow, DDE. DDE, as I am sure you are aware is fairly old. Network DDE has already been depreciated and will no longer work in Vista. I can only imagine that trend is likely to continue. However the DDE API in user32 still works (the reference is here: http://msdn.microsoft.com/en-us/library/ms674605(VS.85).aspx) and you can call that from .net apps, with a little work. The only examples I could find were for VB6 and they were old even then. As I am sure you can imagine it's a little painful. At any rate I dug this example out of API-Guide (from Mentalis). It's not .Net but it ought to get you started anyway:

'This application shows you how to use DDE to create a better PrevInstance-function.
'Compile this sample and start it two times
'The first instance minimizes itself and when the second instance is started, it will
'send a message to the first instance to maximize itself.

'in a module
Public Const VBServerName = "TestServer"
Public Const VBTopicName = "SHOW_YOUR_MAIN_WINDOW"
Public Const XCLASS_BOOL = &H1000
Public Const XTYPF_NOBLOCK = &H2 ' CBR_BLOCK will not work
Public Const XTYP_CONNECT = &H60 Or XCLASS_BOOL Or XTYPF_NOBLOCK
Public Const CP_WINANSI = 1004 ' default codepage for windows & old DDE convs.
Public Const SW_RESTORE = 9
Public Const DDE_FACK = &H8000
Public Const XCLASS_FLAGS = &H4000
Public Const XTYP_EXECUTE = &H50 Or XCLASS_FLAGS
Public Const DNS_REGISTER = &H1
Public Const DNS_UNREGISTER = &H2
Public Declare Function DdeInitialize Lib "user32" Alias "DdeInitializeA" (pidInst As Long, ByVal pfnCallback As Long, ByVal afCmd As Long, ByVal ulRes As Long) As Integer
Public Declare Function DdeCreateStringHandle Lib "user32" Alias "DdeCreateStringHandleA" (ByVal idInst As Long, ByVal psz As String, ByVal iCodePage As Long) As Long
Public Declare Function DdeConnect Lib "user32" (ByVal idInst As Long, ByVal hszService As Long, ByVal hszTopic As Long, pCC As Any) As Long
Public Declare Function DdeNameService Lib "user32" (ByVal idInst As Long, ByVal hsz1 As Long, ByVal hsz2 As Long, ByVal afCmd As Long) As Long
Public Declare Function DdeFreeStringHandle Lib "user32" (ByVal idInst As Long, ByVal hsz As Long) As Long
Public Declare Function DdeQueryString Lib "user32" Alias "DdeQueryStringA" (ByVal idInst As Long, ByVal hsz As Long, ByVal psz As String, ByVal cchMax As Long, ByVal iCodePage As Long) As Long
Public Declare Function DdeUninitialize Lib "user32" (ByVal idInst As Long) As Long
Function DdeCllback(ByVal uType As Long, ByVal uFmt As Long, ByVal hConv As Long, ByVal hszTopic As Long, ByVal hszItem As Long, ByVal hData As Long, ByVal dwData1 As Long, ByVal dwData2 As Long) As Long
    DdeCllback = Form1.AppDdeCallback(uType, uFmt, hConv, hszTopic, hszItem, hData, dwData1, dwData2)
End Function
'in a form
Dim isRun As Boolean, idInst As Long, hszVBServer As Long, hszVBTopic As Long
Dim hconvVBServer As Long, dderesult As Long
Private Sub Form_Load()
   'KPD-Team 2000
   'URL: http://www.allapi.net/
   'E-Mail: [email protected]
   If DdeInitialize(idInst, AddressOf DdeCllback, 0, 0) Then Exit Sub
   hszVBServer = DdeCreateStringHandle(idInst, VBServerName, CP_WINANSI)
    hszVBTopic = DdeCreateStringHandle(idInst, VBTopicName, CP_WINANSI)
    'try to find the first instance
    hconvVBServer = DdeConnect(idInst, hszVBServer, hszVBTopic, ByVal 0&)
    If hconvVBServer Then
        Unload Me
        Exit Sub
    End If
    DdeNameService idInst, hszVBServer, 0, DNS_REGISTER
    Me.WindowState = vbMinimized
End Sub
Private Sub Form_Unload(Cancel As Integer)
        DdeFreeStringHandle idInst, hszVBServer
        DdeFreeStringHandle idInst, hszVBTopic
        'only unregister the DDE server for first instance
        If isRun Then
            If DdeNameService(idInst, hszVBServer, 0, DNS_UNREGISTER) Then
                MsgBox "in ServiceUnRegister", vbOKOnly, "Error"
            End If
        End If
        DdeUninitialize idInst
End Sub
Function AppDdeCallback(ByVal wType As Long, ByVal wFmt As Long, ByVal hConv As Long, ByVal hszTopic As Long, ByVal hszItem As Long, ByVal hData As Long, ByVal lData1 As Long, ByVal lData2 As Long) As Long
        Dim iCount As Long, Buffers As String, Ret As Long
        Select Case wType
            Case XTYP_CONNECT
                iCount = DdeQueryString(idInst, hszTopic, vbNullString, 0, CP_WINANSI)
                Buffers = Space(iCount)
                DdeQueryString idInst, hszTopic, Buffers, iCount + 1, CP_WINANSI
                If Buffers = VBTopicName Then
                    Me.WindowState = vbNormal
                    'add any code for the first instance have found the second one is launch
                    Ret = DDE_FACK
                End If
                AppDdeCallback = Ret
            Case XTYP_EXECUTE
                AppDdeCallback = Ret
        End Select
End Function
樱娆 2024-07-25 22:39:31

处理此问题的最简单方法是使用 VB 6 并创建一个“ActiveX EXE”,用于将 DDE 与 SIDirect 进行通信。 从 VB 6 执行 DDE 很简单。 然后使用 tlbimp 公开为 VB 6 模块创建主互操作程序集,或者直接从 C# 代码中将 EXE 引用为 COM 组件。

The easiest way to handle this is to use VB 6 and create an "ActiveX EXE" which communicates DDE to SIDirect. Doing DDE from VB 6 is trivial. Then expose create a primary interop assembly for the VB 6 module, using tlbimp, or simply reference the EXE as a COM component from your C# code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文