TIA Array aus SPS in Textdatei schreiben/ Notepad aus Visu heraus öffnen VB Skript

Zombie

Level-1
Beiträge
732
Reaktionspunkte
120
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi zusammen,

ich habe eine Visualisierung in WinCC Advanced gebaut, die auf ein Signal von der SPS einen von zwei Datensätzen der in zwei Arrays of String steht in einer Textdatei abspeichert. Dazu wird die Datei gesucht, auf ihre Größe überprüft und dann entweder neu generiert oder an die existierende drangehängt.

Da kommt mein erstes Problem her. Manchmal funktioniert das nicht. Ich weiß nicht wieso, aber manchmal fehlen einfach die Daten von Stunden in der Datei. Der Trigger der das Skript triggert waren die beiden Füllstände der Arrays (iFuellstandXMD), bei jeder Wertänderung wurde das Skript getriggert, aber nur bei einem bestimmten Zahlenwert wurde in dem Skript auch was gemacht, jetzt ist es eine Boolsche Variable die entweder True oder False ist. Mit der zweiten Variante läuft es erst ein paar Stunden, da kann ich nicht sagen ob es funktioniert oder nicht.
Hier das Skript das die Datei erstellt.

Code:
Sub Telegramm_Log_MD()

'Telegramm In eine Datenbank sichern.
'Auf der Steuerung sind zwei Umlaufarchive mit den letzten 40 Telegrammen dieser Verbindung. Erreicht eines der Umlaufarchive den Füllstand 100%
'wird das Umlaufarchivs In die Datenbank geschrieben nachdem das andere zum Schreiben aktiviert wurde.


'If (HmiRuntime.SmartTags("iFüllstand1MD") >= 20 And HmiRuntime.SmartTags("iSpeicherAktMD") = 2) Or (HmiRuntime.SmartTags("iFüllstand2MD") >= 20 And HmiRuntime.SmartTags("iSpeicherAktMD") = 1) Then


     'Variablendeklaration
    Dim Verzeichnispfad, Verzeichnis, Datei, Objekt, Name, Endung, Inhalt, Groesse, Benutzer_alt, Benutzer_neu, Datum, Uhrzeit
    
     'Datum schreiben
    Datum = CStr(Date)
    Uhrzeit = CStr(Time)
    
     'Dateiname und Verzeichnispfad festlegen
    Verzeichnis = "C:\Users\inst\Documents\Telegramme\DataLog\"
    
    Name = "Telegramm_Log_MD"
    Endung = ".txt"
    
    Verzeichnispfad = Verzeichnis & Name & "_" & HmiRuntime.SmartTags("iLogNrMD") & Endung
    
     'ein Dateihandlingobjekt erstellen, dadurch kann ich mit Skript Auf eine Datei zugreifen
    Set Objekt = CreateObject("Scripting.FileSystemObject")
    
     'Durch "On Error Resume Next" bricht er das Skript bei einem Fehler nicht ab, 
     'er macht einfach mit dem nächsten Schritt weiter der Abbruch muss Durch "EXIT SUB" erfolgen
    On Error Resume Next
    
     'Prüfen ob die Datei existiert
    If Not Objekt.FileExists(Verzeichnispfad) Then
        Objekt.CreateTextFile Verzeichnispfad
        ShowSystemAlarm "Datei exisitert nicht, wird angelegt"
        
         'Dateipointer wird zugewiesen
        Set Datei = Objekt.GetFile(Verzeichnispfad)
        
         'Inhalt der Datei löschen und neu erstellen
        Set Inhalt = Datei.OpenAsTextStream(2, -2)
        
         'erste Zeile mit Datum und Uhrzeit, wann erstellt
        Inhalt.WriteLine("Log begonnen am " & Datum & " um " & Uhrzeit & " Telegrammuhrzeit = GMT, wir sind GMT + 1")
    End If
    
     'Wieder Prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
    If Err.Number <> 0 Then
        ShowSystemAlarm "Fehler 1" & CStr(Err.Number) & " " & Err.Description
        Err.Clear
        Exit Sub
    End If
    
     'Dateipointer wird zugewiesen
    Set Datei = Objekt.GetFile(Verzeichnispfad)
    
     'Erfassen der Dateigröße
    Groesse = Datei.Size
    
     'ist Datei zu groß wird Datei kopiert und neu angefangen
     '500000 sind 500 kByte Also 0,5 MByte
    If Groesse > 600000 Then 
        
         'Hilfsverzeichnispfad erzeugen
        Dim Verz_Neu 
        
         'Dateiname hochzählen
        If HmiRuntime.SmartTags("iLogNrMD") < 250 Then
            HmiRuntime.SmartTags("iLogNrMD") = HmiRuntime.SmartTags("iLogNrMD") + 1
        Else
            HmiRuntime.SmartTags("iLogNrMD") = 1
        End If
        
         'Neuer Dateiname ist originalname mit Anhang 
        Verz_Neu = Verzeichnis & Name & "_" & HmiRuntime.SmartTags("iLogNrMD") & Endung
        
         'Falls bereits eine Kopie existiert wird die Kopie weggeworfen
        If Objekt.FileExists(Verz_Neu) Then
            Objekt.DeleteFile Verz_Neu
        End If
        
         'Wieder Prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
        If Err.Number <> 0 Then
            ShowSystemAlarm "Fehler A" & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            Exit Sub
        End If    
        
         'die Ursprüngliche Datenbank wird kopiert
        Objekt.CopyFile Verzeichnispfad, Verz_Neu
        
         'Wieder Prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
        If Err.Number <> 0 Then
            ShowSystemAlarm "Fehler A" & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            Exit Sub
        End If    
        
         'Dateipointer wird zugewiesen
        Set Datei = Objekt.GetFile(Verz_Neu)
        
         'der Originalfile der jetzt 2mal vorhandenen Datenbank wird geöffnet, aber diesmal überschrieben
         'das geht ohne neuzuweisung weil sich am Originalpointer nichts geändert hat
        Set Inhalt = Datei.OpenAsTextStream(2, -2)
        
         'erste Zeile mit Datum und Uhrzeit, wann erstellt
        Inhalt.WriteLine("Log begonnen am " & Datum & " um " & Uhrzeit & " Telegrammuhrzeit = GMT, wir sind GMT + 1")
    Else
            
         'Datei wird geöffnet und zum Anhängen vorbereitet (Datenbank)    
        Set Inhalt = Datei.OpenAsTextStream(8, -2)
        
    End If
    
     'Wieder Prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
    If Err.Number <> 0 Then
        ShowSystemAlarm "Fehler 2" & CStr(Err.Number) & " " & Err.Description
        Err.Clear
         Exit Sub
    End If
    
     'Wieder Prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
'    If Err.Number <> 0 Then
'        ShowSystemAlarm "Fehler 5" & CStr(Err.Number) & " " & Err.Description
'        Err.Clear
'         Exit Sub
'    End If
    
     'schreiben des eigentlichen Datenbankeintrages
    If HmiRuntime.SmartTags("iFüllstand1MD") >= 20 And HmiRuntime.SmartTags("iSpeicherAktMD") = 2 Then
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[0]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[1]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[2]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[3]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[4]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[5]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[6]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[7]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[8]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[9]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[10]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[11]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[12]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[13]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[14]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[15]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[16]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[17]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[18]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp1MD[19]"))
        HmiRuntime.SmartTags("iFüllstand1MD") = 0
    ElseIf HmiRuntime.SmartTags("iFüllstand2MD") >= 20 And HmiRuntime.SmartTags("iSpeicherAktMD") = 1 Then
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[0]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[1]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[2]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[3]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[4]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[5]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[6]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[7]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[8]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[9]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[10]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[11]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[12]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[13]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[14]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[15]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[16]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[17]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[18]"))
        Inhalt.WriteLine(HmiRuntime.SmartTags("aTelSp2MD[19]"))
        HmiRuntime.SmartTags("iFüllstand2MD") = 0
    End If    
    
     'Wieder Prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
    If Err.Number <> 0 Then
        ShowSystemAlarm "Fehler 6" & CStr(Err.Number) & " " & Err.Description
        Err.Clear
         Exit Sub
    End If
    
     'Datei schließen
    Inhalt.Close
    
     'Pointer zurücksetzen
    Set Inhalt = Nothing
    Set Datei = Nothing
    Set Objekt = Nothing
    
     'Finale bestätigung ausgeben
    ShowSystemAlarm "MD- Datei wurde geschrieben"
'Else
            
'End If
End Sub

Das ist der Code des ersten Skriptes, FüllstandXMD sind die beiden Füllstände der Arrays. Das Skript macht im Test im Büro was es soll, hat eines der beiden Füllstände den Wert 20 und das andere Array ist zum Schreiben aktiviert, wird der Inhalt des ersten Skripts in die Datei geschrieben. Das funktioniert auch im Live Betrieb, jedoch nicht konsistent. Manchmal fehlen wie gesagt Stunden oder auch nur Minuten. Ich habe den Verdacht, dass das mit dem zweiten Skript zusammenhängt.
Dieses Skript soll aus Advanced heraus Notepad öffnen, die mit dem oberen Skript erstellte Datei kopieren und die Kopie in Notepad öffnet.
Bleibt das Notepad jedoch offen, scheint es entweder so zu sein, dass noch auf die Originaldatei zugegriffen wird, weshalb das andere Skript die Datei nicht zum schreiben öffnen kann, oder das Skript wird nach dem Öffnen von Notepad nicht beendet, sodass es verhindert dass ein weiteres Skript in Advanced aktiviert werden kann. Leider weiß ich nicht was es von beiden ist.

Code:
Sub Open_Log_MD()

' Der auf der Festplatte des Visu Rechners angelegte Visulog soll angezeigt werden. Dafür soll beim klicken auf 
' eine Schaltfläche der zuletzt angelegte Log geöffnet werden


' Variablendeklaration
    Dim Verzeichnispfad, Verzeichnisquelle, Verzeichnissenke, Datei, Objekt, Name, Endung, Inhalt, Verz_Neu
    Dim isPath, myShell
    
    Dim Wmi,system,Process,Computer,Programm
    
    Dim objShell
    
    ' Dateiname und Verzeichnispfad festlegen
    Verzeichnissenke = "C:\Users\inst\Documents\Telegramme\"
    Verzeichnisquelle = "C:\Users\inst\Documents\Telegramme\DataLog\"
    
    'Name = "Telegramm_Log_MD"
    Name = "Telegramm_Log_MD"
    Endung = ".txt"
    
    
    
    Programm = "notepad.exe"
    
    ' Fileobject erstellen
    Set Objekt = CreateObject("Scripting.FileSystemObject")
    
    ' Verzeichnispfad öffnen
    Verzeichnispfad = Verzeichnisquelle & Name & "_" & HmiRuntime.SmartTags("iLogNrMD") & Endung
        
    ' Prüfen ob Datei exisitert
    If Objekt.FileExists(Verzeichnispfad) Then
        
        ' Kopie anlegen        
        Verz_Neu = Verzeichnissenke & Name & "_" & HmiRuntime.SmartTags("iLogNrMD") & "_Kopie" & Endung
                
        ' Falls bereits eine Kopie existiert wird die Kopie weggeworfen
        If Objekt.FileExists(Verz_Neu) Then
            Objekt.DeleteFile Verz_Neu
        End If
        
        ' Wieder prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
        If Err.Number <> 0 Then
            ShowSystemAlarm "Löschen der Datei fehlgeschlagen" & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            Exit Sub
        End If    
        
        ' Die Ursprüngliche Datenbank wird kopiert
        Objekt.CopyFile Verzeichnispfad, Verz_Neu
        
        ' Wieder prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
        If Err.Number <> 0 Then
            ShowSystemAlarm "Kopieren der Datei fehlgeschlagen" & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            Exit Sub
        End If
        
        ' SHellobject erstellen
        'Set myShell = CreateObject("WScript.Shell")
        
        ' Wieder prüfen ob Fehler exisitierte, dadurch werden mehrere Fehler angezeigt
'        If Err.Number <> 0 Then
'            ShowSystemAlarm "Fehler H" & CStr(Err.Number) & " " & Err.Description
'            Err.Clear
'            Exit Sub
'        End If    
        
        ' Verzeichnis anzeigen
        HmiRuntime.SmartTags("sPfad") = Verz_Neu'Verzeichnis
    
        ' Programm öffnen
        'myShell.Run Verz_Neu,3,False 
        ' 3 öffnet Notepad Bildschirmfüllend, False bringt der Routine myshell.Run bei nicht auf das 
        ' schließen des Notepads zu warten sondern das Skript bis zum Ende zu bearbeiten
        
        ' Externes Programm schließen
        ' Abfrage ob der WMI Dienst gestartet ist
        On Error Resume Next
        Set Wmi = GetObject("winmgmts:")
        If Err.Number<>0 Then
            ' WMI nicht gestartet
            ShowSystemAlarm "WMI not startet" & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            Set Wmi = Nothing
            Exit Sub
        End If
        On Error GoTo 0
        Computer = "." 'Lokal
        ' Dienst suchen
        Set Wmi = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & Computer & "\root\cimv2")
        Set system = Wmi.instancesOf("win32_process")
        ' Nach Zugriff auf System wird jeder Prozess nach notepad.exe untersucht
        For Each Process In system
            If LCase(Process.name)=(Programm) Then
                Process.Terminate (0)' Prozess schließen
            End If
        Next
        
        ' Datei mit Notepad.exe anzeigen
        Set objShell = CreateObject("Shell.Application")
        objShell.ShellExecute "notepad.exe",Verz_Neu,"","open",3
        
        
        Set myShell = Nothing
        Set Objekt = Nothing
        Set Wmi = Nothing
        Set system = Nothing
        Set objShell = Nothing
        ShowSystemAlarm "bin feddich midde weld"


    End If


End Sub

Ich hab mir die Skripte natürlich nicht komplett selbst ausgedacht, das meiste hab ich aus Codefragmenten aus diesem und anderen Foren entnommen und dann in einen Topf geworfen. Besonders beim zweiten Skript komme ich nicht wirklich klar was der Teil macht der Notepad öffnet.
 
Zuletzt bearbeitet:
Was heißt "Daten fehlen"?
Wird das Skript manchmal nicht getriggert? Das Ereignis Wertänderung kommt nur, wenn die Variable verwendet wird oder deren Aktualisierung auf "zyklisch fortlaufend" steht.
Landen in der Datei falsche Datenwerte, z.B. 0-Werte oder alte Werte? Da werden vermutlich Variablenwerte in die Datei geschrieben bevor die Werte aus der SPS gelesen werden. Garantiert aktualisierte Werte bekommt man nur mit Leseanforderung mit Handshake in die HMI gelesen, z.B. per Rezeptur z.B. mit GetDataRecordTagsFromPLC()

Das Thema mit seinen speziellen Problemen gabs hier schon sooo oft, verwende mal die Forumssuche mit dem Suchbegriff "GetDataRecordTagsFromPLC"

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja, Daten fehlen halt. In jedem String ist ein Zeitstempel enthalten. Da ist ein Datensatz von 10:31:23 Uhr und 19 davor die in wenigen Minuten zusammengekommen sind und der nächste ist von 13:16:45 Uhr mit 19 weiteren die ebenfalls in wenigen Minuten entstanden sind. Nun kann das entweder heißen dass in der Zeit keine Daten angefallen sind, was ich aber ausschließen kann, denn ich saß neben der Anlage, oder das Skript arbeitet einfach nicht.
Ja, die Variable wird verwendet, jedoch nicht auf jeder Seite. Die Variable steht auf Zyklisch im Betrieb.

Alte Daten hab ich so nicht bemerkt, einmal war jedoch eine Lücke von drei Werten drin, die ich mir nicht erklären konnte.

Was du schreibst macht Sinn, die Varable wird nicht immer verwendet, deshalb fehlen die Werte wenn eine Seite aktiv ist auf der sie nicht zu sehen ist und die Lücke macht dann auch Sinn.
Ich dachte ich könnte das umgehen indem ich erst die Daten schreibe nachdem sie allesamt aktualisiert wurden.

Ich baue das morgen um und schaue mir auch die Rezepte an.

Danke
 
Zuletzt bearbeitet:
Das Öffnen des externen Programms Notepad und das Aktivieren/nach vorne bringen von dessen Fenster könnte die Aktualisierung beeinflussen. Da habe ich aber keine Erfahrung, weil das Umschalten zu einer anderen Anwendung/Fenster in WinCC Advanced eigentlich "illegal" (von Siemens nicht vorgesehen/nicht supported) ist.

Harald
 
Zurück
Oben