# Excel oder Access: OPC-UA-Client unter VBA



## Aksels (11 September 2019)

Guten Tag liebe Mitleser,

ich möchte von Access aus auf einen OPC-UA-Server zugreifen. Leider bekomme ich ein Connection failed. Vermutlich liegt das an SignAndEncrypt, was das Excel-Beispiel von Siemens nicht beherrscht.
Hier im Forum habe ich nichts dazu gefunden.
Vielleicht hat jemand das bereits gelöst und kann helfen?

Hier meine Vorgehensweise:
Beispiel von Siemens 109748892_OPC_UA_ClientLibrary_CODE_V10 geladen.
Darin enthaltene OPC_UA_ClientLibrary nach Anleitung über regasm dem System bekannt gemacht.
Excel Beispiel geöffnet und Verbindungsdaten eingegeben: opc.tcp://192.168.126.3 auch Benutzername und Kennwort.
Das Excel-Beispiel ist wohl etwas älter. Denn es hat nur 7 Fächer für die Ergebnisse von GetEndpoints vorgesehen. Mein Server bringt 11 Ergebnisse. Also habe ich die User und PSW-Felder verschoben.
Folgende 11 Einträge bringt der Sinumerik-OPC-UA:

```
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256[/URL]    
[URL]http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256[/URL]
```

Wie man sieht gibt es identische Einträge. Mir war Anfangs nicht klar warum, also habe ich alle durchprobiert aber schon in Excel keine Connection bekommen.
In Access habe ich folgendes versucht:
Ein Klassenmodul K_OPCUA erstellt.

```
Option Compare Database

Option Explicit

Private k_OpcUaClient As OpcUaClient
Private k_endpoint As OpcUaEndpoint
Private k_Connect_String As String

Private Sub Class_Initialize()
    Dim i, iUbound, iLbound As Integer
    Dim LResult As Integer
    Dim Tempstring As String
    Dim endpoints() As OpcUaEndpoint
    Dim strSelectedEndpoint As String

    k_Connect_String = "opc.tcp://192.168.126.3:4840"
    Set k_OpcUaClient = New OpcUaClient
    On Error Resume Next
    endpoints = k_OpcUaClient.GetEndpoints(k_Connect_String)
   
    'error handling for GetEndpoints
    If Err.Number <> 0 Then
        MsgBox Err.Description
        Exit Sub
    End If
    iUbound = UBound(endpoints)
    iLbound = LBound(endpoints)
    strSelectedEndpoint = "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"
    For i = iLbound To iUbound
        Debug.Print endpoints(i).SecurityPolicyUri
        Tempstring = CStr(endpoints(i).SecurityPolicyUri)
        LResult = StrComp(strSelectedEndpoint, Tempstring, vbTextCompare)
        If LResult = 0 Then
            'selected endpoint found
            k_endpoint = endpoints(i)
            Exit Sub
        End If
    Next i
End Sub

Public Sub Do_Connect()

     'connect with user authentification
    On Error Resume Next
    k_OpcUaClient.Connect k_endpoint, True, "USER1", "KENNWORT1"
    
    'error handling for Connect
    If Err.Number <> 0 Then
        MsgBox Err.Description
        Err.Number = 0
        'MsgBox "try again. not connected "
        Exit Sub
    End If
    
    MsgBox "connected"
End Sub

Private Sub Class_Terminate()
    k_OpcUaClient.Disconnect
    Set k_OpcUaClient = Nothing
End Sub
```


Aufruf im Programm:


```
Dim m_Messmaschine As K_OPCUA
Set m_Messmaschine = New K_OPCUA
m_Messmaschine.Do_Connect
```

So hätte ich es erstmal hübsch gefunden. Tut aber nicht.
Erstes Problem: die Zeile k_Endpoint = endpoints(i) übergibt keinen Wert. k_Endpoint ist danach nothing. Deswegen habe ich in der DoConnect direkt den Endpoint angegeben:

```
On Error Resume Next
    endpoints = k_OpcUaClient.GetEndpoints(k_Connect_String)
    
    'error handling for GetEndpoints
    If Err.Number <> 0 Then
        MsgBox Err.Description
        Exit Sub
    End If
    'connect with user authentification
    On Error Resume Next
    k_OpcUaClient.Connect endpoints(11), True, "USER1", "PASSWORT1"
    
    'error handling for Connect
    If Err.Number <> 0 Then
        MsgBox Err.Description
        Err.Number = 0
        'MsgBox "try again. not connected "
        Exit Sub
    End If
    
    MsgBox "connected to "
    Exit Sub
```

Damit habe ich alle 11 durchprobiert. Ohne Erfolg.
Der Benutzer und das Kennwort stimmen, diese Kombination benutze ich auch in UAExpert, wo es funktioniert. Im UAExpert muss ich allerdings auch noch Sign&Encrypt auswählen.
Nach einigem Suchen fand ich:

```
Debug.Print endpoints(i).SecurityPolicyUri
        Debug.Print endpoints(i).EndpointDescription
        Debug.Print endpoints(i).SecurityLevel
        Debug.Print endpoints(i).SecurityMode
```
Damit sieht man, dass sie identischen Einträge sich in der Security unterscheiden:

```
http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15
55
Sign
http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15
105
SignAndEncrypt
http://opcfoundation.org/UA/SecurityPolicy#Basic256
60
Sign
http://opcfoundation.org/UA/SecurityPolicy#Basic256
110
SignAndEncrypt
http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
65
Sign
http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
115
SignAndEncrypt
http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15
55
Sign
http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15
105
SignAndEncrypt
und so weiter
```

Der Eintrag mit dem Index 1 (zählung ab 0) ist für mich der richtige. Aber es meldet immer Connection Error (oder failed, kann es gerade nicht testen).
Eigentlich hätte ich an der Connect Stelle wie bei allen anderen Clients auch den Hinweis erwartet, dass es sich um ein Self-Signed Certificate handelt. 
Kann das Excel-Beispiel das mit den Zertifikaten vielleicht gar nicht?
Gibt es Befehle/Erweiterungen, mit denen ich das bewerkstelligen kann?


----------



## Aksels (21 Oktober 2019)

Liebe Mitleser,
ich bin ein Stück weiter gekommen.
Es gibt auf der Siemens Homepage zwei Versionen (V10 V2_0) Mit der Version 10 bin ich nicht weiter gekommen. Dann habe ich V2_0 gefunden und mit dem beiliegenden Excel sofort eine Connection bekommen. Wenn mir jetzt noch jemand erklärt, wie die Node-IDs aussehen müssen, kann ich hier den funktionieren Access-Code posten.
Im Excel ist beispielhaft folgender String ;: ns=3;s="DataStatic"."myInt"
Ich habe den so abgewandelt: ns=2;s="/Plc/db2000.dbx0.0:BOOL"
Funktioniert leider nicht (BadNodeIDUnknown).
Auch mit dem an die UAExpert angelehnte Syntax klappt es nicht : NS2|String|/Plc/db2000.dbx0.0:BOOL
Wie muss das bei einer [FONT=&quot]SINUMERIK 840D sl OPC UA [/FONT]aussehen?


----------



## Aksels (31 Oktober 2019)

Guten Morgen.
Ich habe wieder ein weiteres Problem geknackt.
Die Syntax muss so aussehen:
ns=2;s=/Plc/db2000.dbx0.0:BOOL
Ich war zwar sicher es schoneinmal ohne Anführungszeichen versucht zu haben, aber vielleicht war da noch was mit Strichpunkten oder Slashes falsch.
Dieser Teil im Excel 2.0 Beispiel funktioniert also schon.
Nun muss ich noch den Fehler beim Compilieren in den Griff bekommen, den ich im Office-Forum gepostet habe.
Dann kann ich in VBA vollständig auf einen OPC-UA-Server zugreifen. Werde dann das Ergebnis hier posten.
Gruß,
Aksels


----------



## MFreiberger (9 Januar 2020)

Moin Aksels,

das Thema interessiert mich auch.

Leider schaffe ich es nicht einmal einen Verweis auf den Opc_Ua_ExcelClient in VBA zu erstellen.

Also die .dll zu registrieren klappt noch, aber nach der Anleitung unter Extras >> Verweise OPC_Ua_ExcelClient anzuwählen klappt nicht. Ist anscheinend nicht vorhanden. Wo sitzt da wohl wieder mein Denkfehler?

VG

MFreiberger


----------



## Aksels (10 Januar 2020)

Guten Morgen,
ich habe es inzwischen aufgegeben. Bei mir war der Verweis vorhanden. 


Da ich mit einer SQL-Datenbank arbeite mache ich ein C++ Programm, das sich mit der SQL-Datenbank verbindet und dort ein paar Bits pollt, die als Befehle zum Schreiben oder lesen auf OPC-UA dienen. Die Daten können so direkt im SQL-Server benutzt werden.

Gruß,
Aksels


----------

