Archivierung per skript

Zuviel Werbung?
-> Hier kostenlos registrieren
Abschließend stelle ich jetzt mein Ergebnis rein. Vielleicht hilft es nochmal jemandem...

1. Archivdatei auf dem Stick anlegen.

Code:
Dim fs, f, FName, Header, strDir

' FileSystemObject erstellen
' Create FileSystemObject
Set fs = CreateObject("FileCtl.FileSystem")
 
' Prüfen ob USB-Stick vorhanden ist
' Checking if USB-device available
strDir = fs.dir ("\Storage Card USB\")    

If strDir = "" Then 'Ablagepfad nicht vorhanden / directory not exists, card not available
    Call ShowSystemAlarm ("Kein USB-Stick vorhanden / No USB-device available")
Else
    
' Archivierungspfad (Eingangsparameter) und Dateiname zusammensetzen 
' Combine archivepath (input parameter) and filename
FName = StoragePath & "\PAL_ID_" & CStr(DatePart("m",Date)) & "_" & CStr(DatePart("yyyy",Date)) & ".csv"

' Tabellenkopf zusammenstellen 
' Create table header 

 Header = "Zeitstempel;Barcode;Hoehe" &  Chr(10)

' FileObject erstellen
' Create FileObject
 Set f = CreateObject("FileCtl.File")

'Prüfen ob Ablagepfad vorhanden, wenn nicht -> erzeugen.
'Checks storage path availably, if not -> create
Ordnerpfad_anlegen StoragePath ' Übergabe des Ablagepfades aus dem Script "Script_Storage_Path" / Handing over of the storage path from the script "Script_Storage_Path"

' Datei öffnen bzw. erstellen, wenn sie noch nicht existiert
' Open File or create file if it does not exist 
 f.open FName, 8                                 

' Werte der Variablen in die Archivdatei schreiben (VAR_1)
' Write values of variables in archive file (VAR1)
 f.lineprint(CStr(Now) & ";" & CStr(SmartTags("PAL_ID")) & ";" & CStr(SmartTags("Hoehe"))) 

' Datei wieder schließen
' Close file
 f.Close
End If
' Verwendeten Speicher wieder freigeben
' Used storage will be freed
Set f  = Nothing
Set fs = Nothing

2. Daten vom Stick auf den Server kopieren

Dazu wird die Quelldatei Zeile für Zeile ausgelesen und im Append-Modus auf die Zieldatei geschrieben.
Schreibfreigabe und Vorhandensein der Dateien werden geprüft.

Code:
Dim PathSearch, Path, Index, Result, fso, SourceFile, DestFile, f, fs, Header, StartTime, StopTime, DelayTime, i, Laenge, fileContent

Set PathSearch = CreateObject("FileCtl.FileSystem")

'USB-Stick suchen
'--------------------

Path = "Storage Card USB" 
    
SetValue SmartTags("Status_kopieren"), 10                 'Text: Suche USB-Stick
    
StartTime = Now
DelayTime = 500        'Timer 100 endspricht 1sec.
StopTime = StartTime + DelayTime / 24 / 360000
Do
    If  PathSearch.Dir("\" & Path) = ""_
        And Now >= StopTime Then
        SetValue SmartTags("Status_kopieren"), 20            'Text: USB-Stick nicht gefunden!
        
        ElseIf PathSearch.Dir("\" & Path) = Path Then     
        SetValue SmartTags("Status_kopieren"), 30            'Text: Suche Zielordner
    End If
Loop Until Now >= StopTime

'30: Ziellaufwerk suchen
'-----------------------

If SmartTags("Status_kopieren") = 30 Then
    Path = "\\LAPTOP_WO\Logs\"
    
    StartTime = Now
    DelayTime = 500        'Timer 100 endspricht 1sec.
    StopTime = StartTime + DelayTime / 24 / 360000
    Do                        
        Result = Ziel_pruefen (Path)
        If  Result = "Logs" Then
            SetValue SmartTags("Status_kopieren"), 50            'Text: Schreibfreigabe prüfen
        ElseIf Now >= StopTime Then    
            SetValue SmartTags("Status_kopieren"), 40            'Text: Zielordner nicht gefunden
        End If
    Loop Until Now >= StopTime
End If 


'50: Schreibfreigabe prüfen
'--------------------------
' Die Datei "Write_Access.ok" muss im Zielordner vorhanden sein.
If SmartTags("Status_kopieren") = 50 Then
    Path = "\\LAPTOP_WO\Logs\Write_Access.ok"
    
    StartTime = Now
    DelayTime = 500        'Timer 100 endspricht 1sec.
    StopTime = StartTime + DelayTime / 24 / 360000
    Do                        
        Result = Ziel_pruefen (Path)
        If  Result = "Write_Access.ok" Then
            SetValue SmartTags("Status_kopieren"), 70            'Text: Zieldatei suchen
        ElseIf Now >= StopTime Then    
            SetValue SmartTags("Status_kopieren"), 60            'Text: keine Schreibfreigabe
        End If
    Loop Until Now >= StopTime
End If 

'70: Zieldatei prüfen
'---------------------

If SmartTags("Status_kopieren") = 70 Then
    
    Set f = CreateObject("FileCtl.File")
    Set fs = CreateObject("FileCtl.FileSystem")
    
    Path = "\\LAPTOP_WO\Logs\Archiv.csv"
    
    'Prüfen ob Ablagepfad vorhanden, wenn nicht -> erzeugen.
    Ordnerpfad_anlegen Path ' Übergabe des Ablagepfades aus dem Script "Script_Storage_Path" / Handing over of the storage path from the script "Script_Storage_Path"
    
    ' Datei öffnen bzw. erstellen, wenn sie noch nicht existiert
    f.open Path, 8                                 

    ' Tabellenkopf zusammenstellen 
    Header = "Zeitstempel;Barcode;Hoehe" &  Chr(10)
 
    ' Wenn Datei 0 Byte groß, dann ist sie neu
    If fs.FileLen(Path) = 0 Then                      
           f.lineprint(Header)
    '=0 => Tabellenkopf muss eingefügt werden
     End If 
     ' Datei wieder schließen
     f.Close
     
    StartTime = Now
    DelayTime = 1000        'Timer 100 endspricht 1sec.
    StopTime = StartTime + DelayTime / 24 / 360000
    Do                        
        Result = Ziel_pruefen (Path)
        If  Result = "Archiv.csv" Then
            SetValue SmartTags("Status_kopieren"), 90            'Text: Einträge kopieren
        ElseIf Now >= StopTime Then    
            SetValue SmartTags("Status_kopieren"), 80            'Text: Datei nicht gefunden
        End If
    Loop Until Now >= StopTime
End If 

'90: Datei suchen und auslesen
'-----------------------------

If SmartTags("Status_kopieren") = 90 Then
    
    Set fso = CreateObject("FileCtl.FileSystem")
    
    SmartTags("Name") = fso.Dir("\Storage Card USB\*.csv")        'Suchen nach ersten Dateiname auf Stick
    f.open("\Storage Card USB\" & SmartTags("Name")),1,1
    
    For i = 1 To 1000000
        If f.EOF = True Then Exit For
            fileContent = fileContent & f.LineInputString & vbCrLf
            'Leerzeile am Ende löschen
            Laenge = Len (fileContent - 2)
             fileContent = Left(fileContent,Laenge)
    Next
    ' Datei wieder schließen
     f.Close
     SetValue SmartTags("Status_kopieren"), 100
End If 


'100: Einträge im Appendmodus anhängen
'-------------------------------------

If SmartTags("Status_kopieren") = 100 Then
    
    ' FileObject erstellen
    Set f = CreateObject("FileCtl.File")
 
    ' Datei öffnen im Append-Modus
    f.open "\\LAPTOP_WO\Logs\Archiv.csv", 8 
    ' Einträge anhängen
    f.lineprint fileContent
    ' Datei wieder schließen
    f.Close 

    SetValue SmartTags("Status_kopieren"), 110
End If
    
'110: Quelldatei löschen
'-----------------------

If SmartTags("Status_kopieren") = 110 Then
     fs.Kill ("\Storage Card USB\" & SmartTags("Name"))
     SetValue SmartTags("Status_kopieren"), 200
End If

' Verwendeten Speicher wieder freigeben

Set f  = Nothing
Set fs = Nothing
Set fso = Nothing
Set PathSearch = Nothing

Es werden noch die Sub-Routine "Ordernpfad_anlegen" und die Funktion "Ziel_prüfen" verwendet.

Ordnerpfad anlegen:

Code:
'Hinweis/Note:
'Wenn der vorgegebene Ablagepfad im "Hauptscript" mehrere Unterordner enthält, 
'müssen diese Unterordner auf der Speicherkate komplett vorhanden sein. 
'Dieses Script dient dazu, dieses automatisch umzusetzen.

'If the predefined storage path includes several sub-folders in the "Main script", 
'the path of the sub-folders must already be completely available on the memory card . 
'This script serves to convert this automatically. 

Dim fs, strDir, strTemp, arr

' FileSystemObject erstellen
' Create FileSystemObject
Set fs = CreateObject("FileCtl.FileSystem") 

strTemp = "" ' Hilfsvariable / Help tag

arr = Split (strPath, "\") ' Ablagepfad in einzelen "\" zerlegen / split the Storage path in several "\" 

For Each strDir In arr ' Schleifenzähler / loop counter
    If Len(strDir) > 0 Then
        strTemp = strTemp + "\" + strDir
        
        strDir = fs.dir (strTemp)
        
        If strDir = "" Then ' Wenn kein "\" mehr vorhanden ist -> keine weiteren Unterpfade / If no "\" existing, then no further sub-folders
            fs.mkDir strTemp
        End If    
    End If
Next 

Set fs = Nothing

Ziel_pruefen:

Code:
Dim fso
  Set fso = CreateObject("FileCtl.FileSystem")
  Ziel_pruefen = fso.Dir(Ziel)
 
Zuletzt bearbeitet:
Vielleicht noch eine letzte Frage.
Ich lasse meine Schleife jetzt bis 1000000 laufen. Das wird sicher reichen. Ist aber auch nicht ganz sauber ausprogrammiert.
Gibt es eine Möglichkeit, das sauber zu programmieren?
Ach ja. Warum muss ich eigentlich "2" abziehen, um die Leerzeile zu löschen?

Guten Morgen,

zu deiner ersten Frage: ich würde eine Do...Loop-Schleife o.ä. verwenden, da du den Index 'i' ja nicht weiter benötigst/verwendest. Eine Abbruchbedingung hast du ja bereits jetzt integriert (If f.EOF...).
Zu deiner zweiten Frage: Ein Zeilenumbruch stellt sich unter Windows als die beiden Zeichen Chr(13) für CarriageReturn und Chr(10) für LineFeed dar.


Gruß, Fred
 
Abschließend stelle ich jetzt mein Ergebnis rein. Vielleicht hilft es nochmal jemandem...
Zunächst: Ein schönes Stück Arbeit - viele Programmierer kommen gar nicht so weit...
icon14.png


Natürlich gibt es da noch Sachen, die man verbessern kann:

1. Skriptnamen

Schreibe doch bitte in den Skripten als erste Zeile den (exakt geschriebenen!) Name der Sub/Function als Kommentar, wie z.B. hier
Code:
' Sub SettingsIniSpeichern()
Code:
' Function FolderExist(Path) prüft, ob ein angegebener Ordner existiert


2. In Deinem 2. Skript: Deine eigentlich gut gemeinten Timeout-Schleifen sind "unglücklich" gebaut und unnötig.

Auch wenn die gewünschte Operation erfolgreich war, so wird sie trotzdem 5 Sekunden lang wiederholt, ehe die Timeout-Schleife verlassen wird. Da fehlt "Exit Do". (Oder baue die Schleife anders: die gewünschte Operation in die Loop-Abbruchbedingung und den Timeout in den "Notausgang" Exit Do)
Code:
    Do                        
        Result = Ziel_pruefen (Path)
        If  Result = "Logs" Then
            SetValue SmartTags("Status_kopieren"), 50            'Text: Schreibfreigabe prüfen
            [COLOR="#FF0000"]Exit Do[/COLOR]
        ElseIf Now >= StopTime Then    
            SetValue SmartTags("Status_kopieren"), 40            'Text: Zielordner nicht gefunden
        End If
    Loop Until Now >= StopTime

Alle Deiner Zwangs-Warteschleifen (bzw. gewollte Timeout-Schleifen) sind aus meiner Sicht unnötig.
Z.B. die erste 5s-Warteschleife zum Suchen des USB-Sticks: Ein USB-Stick ist angeschlossen oder nicht, er taucht nicht innerhalb von 5s doch noch auf ...

Bei den meisten Funktionen ist es unerheblich, ob man sie einmal oder 5s lang immer wieder aufruft - wenn der erste Aufruf einen Fehler meldet, dann wird höchstwahrscheinlich auch der 1000. Aufruf den Fehler melden.
Es gibt echt sehr wenig Funktionen wo es sinnvoll ist, diese wiederholt aufzurufen. Da fällt mir gerade nur ein Beispiel ein: das Suchen einer entfernten Netzwerkressource, wo eventuell erst ein VPN-Kanal aufgebaut wird oder ein Computer aufgeweckt werden muß.

Funktionen wo ein Timeout sinnvoll ist haben meist einen eigenen Timeout und kommen sowieso nicht eher zum Skript zurück.


3. Variablen lesen von SPS in RT

Wenn Dein Skript dann nicht mehr die unnötigen langen Warteschleifen hat, dann wirst Du wahrscheinlich auf ein neues noch unentdecktes Problem stossen: Wie ist sichergestellt, daß die RT die aktuellen Werte Deiner zu archivierenden Variablen vor dem Schreiben in die Datei auch aus der SPS gelesen hat?
Zu diesem Thema schaue mal hier (Link zu einem Codebeispiel) und benutze die Forumssuche nach GetDataRecordTagsFromPLC



4. PS:
Jetzt habe ich quasi bei 0 angefangen und bin an 2 Wochenenden zum Ziel gekommen.
Ich kann mir sehr gut vorstellen, daß viele heute übliche Software genau in dem Stadium vergleichbar mit Deinem Entwicklungsstand ist. Die Programmierer sind bestimmt "stolz wie Hubatz" über ihre Software (weil die ohne sichtbare Fehlermeldungen irgendwann zu einem Ende kommt) und ahnen gar nicht, was für unsicheren Dreck sie da programmiert haben. Da wird nur aufwendig an bunten Animationen gefeilt statt die eigentliche Funktion kritisch zu überprüfen.

Also Tigerente1974: Du bist in professioneller Gesellschaft ;)

Für Deinen Willen, das Ergebnis Deiner Arbeit auch anderen zur Verfügung zu stellen, gebe ich Dir aber trotzdem ein DANKE. :D

Harald
 
Übrigens:
Um SmartTags einen Wert zuzuweisen oder den Wert zu lesen ist es nicht nötig, die Funktionen SetValue und GetValue zu benutzen. Man kann direkt das SmartTag-Objekt verwenden - das liest sich oft besser:
Code:
Dim scriptVar

scriptVar = SmartTags("Tag_1")
SmartTags("Tag_2") = scriptVar
SmartTags("Tag_3") = 50
SmartTags("Tag_4") = "Alles OK"
SmartTags("Tag_5") = SmartTags("Tag_3")

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald. Vielen Dank für Dein feedback.
Es drückt grade etwas die Zeit für mein Projekt. Trotzdem werde ich versuchen die Vorschläge noch umzusetzen.
Wenn ich getesteten Code habe, stelle ich noch eine Aktualisierung ein.
 
Hallo Harald.
Ich hatte heute morgen etwas Zeit mich intensiver einzulesen.
Das "Problem" mit der Datenkonsistenz wäre mir -wenn überhaupt- erst viel zu spät aufgefallen.
Ich habe jetzt eine fertige Lösung, die Deine Anregungen aufgreift.
Nächste Woche kann ich den Code testen und werde berichten.
 
Wie angekündigt poste ich die neue Version.
Diese berücksichtigt die bisherigen Anregungen. Vor allem auch das Einlesen der Variablen über eine Rezeptur, um Datenkonsistenz zu gewährleisten.
Bisher sind mir noch keine Fehler aufgefallen. Für weitere Anregungen bin ich weiterhin dankbar.

1. Variablen per Rezeptur einlesen
Code:
' Sub Variable_einlesen
' Um Datenkonsistenz für die zu archivierenden Variablen sicherzustellen, wurden diese in der
' Rezeptur "ReadVar" deklariert. Mit "GetDataRecordTagsFromPLC" werden die Variablen aus der SPS
' gelesen. Anschließend wird das Skript "String_archivieren_USB" angestossen, um die Daten zunächst 
' auf dem USB-Stick am HMI zu archivieren.

Dim wrStat, rdStat

' Variable in SPS schreiben mit Fertigmeldung
 SetDataRecordTagsToPLC "WriteVar", SmartTags("Archivierung\Schreibstatus")
' in Schleife auf Ende Var-Schreiben warten
Do
    wrStat = SmartTags("Archivierung\Schreibstatus")
Loop While (wrStat And 4) = 0 ' 4=fertig OK / 12=abgebrochen mit Fehler

' wenn Schreiben ohne Fehler, dann Antwort (Protokoll-Datensatz) aus SPS lesen
If wrStat = 4 Then
    ' Variablen aus SPS lesen mit Fertigmeldung
    GetDataRecordTagsFromPLC "ReadVar", SmartTags("Archivierung\Lesestatus")
    ' in Schleife auf Ende Var-Lesen warten
    Do
        rdStat = SmartTags("Archivierung\Lesestatus")
    Loop While (rdStat And 4) = 0 ' 4=fertig OK / 12=abgebrochen mit Fehler

    If rdStat = 4 Then
        String_archivieren_USB("\Storage Card USB\")
    End If
End If

If wrStat <> 4 Or rdStat <> 4 Then
    ShowSystemAlarm "Fehler beim Lesen der Protokollwerte!"
End If

2. Archivieren auf den USB-Stick
Code:
' Sub String_archivieren_USB(StoragePath)

Dim fs, f, FName, Header, strDir

' FileSystemObject erstellen
' Create FileSystemObject
Set fs = CreateObject("FileCtl.FileSystem")
 
' Prüfen ob USB-Stick vorhanden ist
strDir = fs.dir ("\Storage Card USB\")	

If strDir = "" Then 'Ablagepfad nicht vorhanden
	Call ShowSystemAlarm ("Kein USB-Stick vorhanden")
Else
	
' Archivierungspfad (Eingangsparameter) und Dateiname zusammensetzen 
FName = StoragePath & "\PAL_ID" & ".csv"

' FileObject erstellen
 Set f = CreateObject("FileCtl.File")

'Prüfen ob Ablagepfad vorhanden, wenn nicht -> erzeugen.
Ordnerpfad_anlegen StoragePath ' Übergabe des Ablagepfades aus dem Script "Ordnerpfad anlegen"

' Datei öffnen bzw. erstellen, wenn sie noch nicht existiert
 f.open FName, 8 								

' Werte der Variablen mit Zeitstempel in die Archivdatei schreiben
 f.lineprint(CStr(Now) & ";" & CStr(SmartTags("Archivierung\ARCHIV_COMMDB.PAL_ID")) & ";" & CStr(SmartTags("Archivierung\ARCHIV_COMMDB.Pal_Hoehe"))) 

' Datei wieder schließen
 f.Close
End If

' Verwendeten Speicher wieder freigeben
Set f  = Nothing
Set fs = Nothing

' Prüfen, ob Daten auf den Server geschrieben werden können
Datei_kopieren	'Skript zum Kopieren der Daten vom Stick auf den Server anstoßen

3. Prüfen, ob Daten auf den Server kopiert werden können.
Wenn ja: Quelldatei Zeile für Zeile auslesen und in die Zieldatei schreiben.
Anschließend die Quelldatei löschen.
Code:
'Sub Datei_kopieren

Dim PathSearch, Path, Index, Result, fso, SourceFile, DestFile, f, fs, Header, StartTime, StopTime, DelayTime, i, Laenge, fileContent

Set PathSearch = CreateObject("FileCtl.FileSystem")

'USB-Stick suchen
'--------------------

Path = "Storage Card USB" 
    
SmartTags("Archivierung\Status_kopieren") = 10                'Text: Suche USB-Stick
    
If  PathSearch.Dir("\" & Path) = "" Then
	SmartTags("Archivierung\Status_kopieren") = 20            'Text: USB-Stick nicht gefunden!
    ElseIf PathSearch.Dir("\" & Path) = Path Then     
    SmartTags("Archivierung\Status_kopieren") = 30            'Text: Suche Zielordner
End If

'30: Ziellaufwerk suchen
'-----------------------

If SmartTags("Archivierung\Status_kopieren") = 30 Then
	Path = "\\LAPTOP_WO\Logs"
	
	StartTime = Now
	DelayTime = 500		'Timer 100 endspricht 1sec.
	StopTime = StartTime + DelayTime / 24 / 360000
	Do                        
    	Result = Ziel_pruefen (Path)
    	If Result = "Logs" Then
    		SmartTags("Archivierung\Status_kopieren") = 50      'Text: Schreibfreigabe prüfen
    		Exit Do
    	ElseIf Now >= StopTime Then    
        	SmartTags("Archivierung\Status_kopieren") = 40      'Text: Zielordner nicht gefunden
		End If
	Loop Until Now >= StopTime
End If 


'50: Schreibfreigabe prüfen
'--------------------------
' Die Datei "Write_Access.ok" muss im Zielordner vorhanden sein.
If SmartTags("Archivierung\Status_kopieren") = 50 Then
	Path = "\\LAPTOP_WO\Logs\Write_Access.ok"                  
    Result = Ziel_pruefen (Path)
    If  Result = "Write_Access.ok" Then
    	SmartTags("Archivierung\Status_kopieren") = 70          'Text: Zieldatei suchen
    Else  
        SmartTags("Archivierung\Status_kopieren") = 60          'Text: keine Schreibfreigabe
	End If
End If 

'70: Zieldatei prüfen
'---------------------

If SmartTags("Archivierung\Status_kopieren") = 70 Then
	
	Set f = CreateObject("FileCtl.File")
	Set fs = CreateObject("FileCtl.FileSystem")
	
	Path = "\\LAPTOP_WO\Logs\Archiv.csv"
	'Prüfen ob Ablagepfad vorhanden, wenn nicht -> erzeugen.
	Ordnerpfad_anlegen Path ' Übergabe des Ablagepfades aus dem Script "Script_Storage_Path" / Handing over of the storage path from the script "Script_Storage_Path"
	
	' Datei öffnen bzw. erstellen, wenn sie noch nicht existiert
	f.open Path, 8 								

	' Tabellenkopf zusammenstellen 
	Header = "Zeitstempel;Barcode;Hoehe" &  Chr(10)
 
	' Wenn Datei 0 Byte groß, dann ist sie neu
	If fs.FileLen(Path) = 0 Then 					 
   		f.lineprint(Header)
	'=0 => Tabellenkopf muss eingefügt werden
 	End If 
 	' Datei wieder schließen
 	f.Close
 	
	Result = Ziel_pruefen (Path)
    If  Result = "Archiv.csv" Then
    	SmartTags("Archivierung\Status_kopieren") = 90            'Text: Quelldatei einlesen
    Else    
        SmartTags("Archivierung\Status_kopieren") = 80            'Text: Zieldatei nicht gefunden
	End If
End If 

'90: Datei suchen und auslesen
'-----------------------------

If SmartTags("Archivierung\Status_kopieren") = 90 Then
	
	Set fso = CreateObject("FileCtl.FileSystem")
	
	SmartTags("Archivierung\Name") = fso.Dir("\Storage Card USB\*.csv")        'Suchen nach erster csv-Datei auf Stick
	f.open("\Storage Card USB\" & SmartTags("Archivierung\Name")),1,1
	
	' Inhalt der gefundenen Datei Zeile für Zeile einlesen
	Do
		If f.EOF = True Then Exit Do
		fileContent = fileContent & f.LineInputString & vbCrLf
	Loop
	'Leerzeile am Ende abtrennen (sonst wird später mit jedem Kopiervorgang eine Leerzeile eingefügt)
	Laenge = Len (fileContent)
	fileContent = Left(fileContent,(Laenge-2))
	' Datei wieder schließen
 	f.Close
 	SmartTags("Archivierung\Status_kopieren") = 100				'Text: Quelldaten übertragen
End If 


'100: Einträge im Appendmodus anhängen
'-------------------------------------

If SmartTags("Archivierung\Status_kopieren") = 100 Then
	
	' FileObject erstellen
	Set f = CreateObject("FileCtl.File")
 
	' Datei öffnen im Append-Modus
	f.open "\\LAPTOP_WO\Logs\Archiv.csv", 8
	' Einträge anhängen
	f.lineprint fileContent
	' Datei wieder schließen
	f.Close 

	SmartTags("Archivierung\Status_kopieren") = 110			'Text: Quelldatei löschen
End If
	
'110: Quelldatei löschen
'-----------------------

'Damit die übertragenen Daten nicht erneut kopiert werden, soll die Quelldatei gelöscht werden. 
If SmartTags("Archivierung\Status_kopieren") = 110 Then
	 fs.Kill ("\Storage Card USB\" & SmartTags("Archivierung\Name"))
	 SmartTags("Archivierung\Status_kopieren") = 200
End If

' Verwendeten Speicher wieder freigeben
Set f  = Nothing
Set fs = Nothing
Set fso = Nothing
Set PathSearch = Nothing

Weiter werden noch diese Skripte verwendet:

Sub-Routine Ordnerpfad anlegen:
Code:
'Sub Ordnerpfad_anlegen

'Hinweis/Note:
'Wenn der vorgegebene Ablagepfad im "Hauptscript" mehrere Unterordner enthält, 
'müssen diese Unterordner auf der Speicherkate komplett vorhanden sein. 
'Dieses Script dient dazu, dieses automatisch umzusetzen.

Dim fs, strDir, strTemp, arr

' FileSystemObject erstellen
Set fs = CreateObject("FileCtl.FileSystem") 

strTemp = "" ' Hilfsvariable

arr = Split (strPath, "\") ' Ablagepfad in einzelen "\" zerlegen

For Each strDir In arr ' Schleifenzähler 
	If Len(strDir) > 0 Then
		strTemp = strTemp + "\" + strDir
		
		strDir = fs.dir (strTemp)
		
		If strDir = "" Then ' Wenn kein "\" mehr vorhanden ist -> keine weiteren Unterpfade
			fs.mkDir strTemp
		End If	
	End If
Next 

' Verwendeten Speicher wieder freigeben
Set fs = Nothing

Funktion Ziel prüfen:
Code:
'Function Ziel_pruefen(Ziel)

' Die Funktion gibt den Namen des letzten Ordners bzw. der Datei zurück,
' wenn dieser/diese im übergebenen Zielpfad vorhanden ist.
Dim fso
  Set fso = CreateObject("FileCtl.FileSystem")
  Ziel_pruefen = fso.Dir(Ziel)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Jetzt muss ich den thread doch nochmal ausgraben...

Bei der Inbetriebnahme ist noch ein neues Problem ausgetaucht.
Der Barcode zu der Palette ist ein String mit 20 Zeichen. Auf der SPS-Seite wurde der String wie gewünscht eingetragen.
Bei der Archivierung des Strings scheint der String als Zahl interpretiert zu werden. Jedenfalls werden die beiden Führungsnullen des Barcodes weggestrichen. "Sehen" kann ich das beim Öfnnen der csv-Datei auf dem USB-Stick. Schlimmer ist aber, dass der Barcode quasi gerundet wird.
Wie kann ich dafür sorgen, dass mein String 1:1 in die csv-Datei eingetragen wird?
 
Mit was öffnest du die .csv? Texteditor oder Excell? Bei letzterem hatte ich dies auch schon, obwohl es in der csv korrekt war.

Wähle einen Beruf, den du liebst,und du brauchst keinen Tag in deinem Leben mehr zu arbeiten. Konfuzius
 
Wie kann ich dafür sorgen, dass mein String 1:1 in die csv-Datei eingetragen wird?
Strings in doppelte Hochkomma " CHR(34) setzen:
Code:
' Write values of variables in archive file (VAR1)
 f.lineprint(CStr(Now) & ";" [COLOR="#FF0000"]& Chr(34)[/COLOR] & SmartTags("PAL_ID") [COLOR="#FF0000"]& Chr(34)[/COLOR] & ";" & CStr(SmartTags("Hoehe")))

Statt CStr(Now) würde ich den Zeitstempel unabhängig von den regionalen Einstellungen des Panels/Computers selber formatieren --> "31.12.2008 01:59:59"
Code:
' Write values of variables in archive file (VAR1)
 ts = Now

 sts = Chr(34)& Right("0" & DatePart("d", ts), 2) & "." & Right("0" & DatePart("m", ts), 2) & "." & DatePart("yyyy", ts) & " " _
              & Right("0" & DatePart("h", ts), 2) & ":" & Right("0" & DatePart("n", ts), 2) & ":" & Right("0" & DatePart("s", ts), 2) &Chr(34)

 f.lineprint(sts & ";" & Chr(34) & SmartTags("PAL_ID") & Chr(34) & ";" & CStr(SmartTags("Hoehe")))

Schau Dir auch mal diesen Thread an: Prozessdaten einer CPU 317 auf Speicherkarte eines TP277 6'' speichern

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Datei habe ich mit Excel geöffnet. Werde das mit dem Texteditor auch mal probieren.

Danke für den Tip mit den Anführungszeichen.
Über Probleme mit dem Zeitstempel hatte ich schon mal was gelesen. Da ging es glaube ich um Probleme, wenn der Zeitstempel in den Namen der Datei eingetragen werden soll. Welchen Nachteil gibt es noch?
Werde aber auch den Tip mit dem Zeitstempel noch umsetzen.
 
Hauptproblem bei der Datum/Uhrzeit-Formatierung ist, daß diese bei VBS abhängig von den regionalen Einstellungen im Control Panel (Systemsteuerung) des Erstellsystems ist. Hat das Zielsystem andere Einstellungen, dann gibt es Probleme beim Interpretieren des Zeitstempels.

Datum/Uhrzeit für Dateinamen: die "automatische" Formatierung enthält je nach Einstellung ":" und "/" und diese Zeichen sind in Dateinamen nicht erlaubt.

Es ist also immer besser, die Datumsformatierung (passend zum Zielsystem) selber vorzunehmen.

Ein weiterer Stolperstein ist die Einstellung des Dezimalpunkts bei Gleitkommazahlen - dazu gibt es einen FAQ von JesperMP.

Harald
 
Hallo Harald.

Danke für Deine Hilfe.
Ich habe beides umgesetzt.
Es funktioniert auch wie es soll. Allerdings ignoriert excel auch die "..." und macht eine gerundete Zahl daraus.
Mit dem Editor geöffnet sieht man, dass in beiden Fällen korrekt archiviert wurde. Einmal mit den Gänsefüßchen, einmal ohne.
Ich lasse die Gänsefüßchen jetzt nochmal weg und bespreche mit dem IT-ler, ob er die Daten korrekt auslesen kann.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn du in Excel die Datei nicht öffnest sondern importierst kannst du glaube ich auch das Format angeben den der Wert darstellt. So solltest du das ev. Hingekommen. ...

Gesendet von meinem GT-N7100 mit Tapatalk 2
 
Hallo Forum.

Ich grabe diesen thread nun noch einmal aus, weil es jetzt ein neues Problem gibt, für das ich noch keine Lösung gefunden habe.
Ich versuche das erstmal so gut wie möglich zu beschreiben. Vor gut einem Monat habe ich die Anlage erweitert. Es gibt nun eine 2. Stelle an der Daten archiviert werden sollen.
Die Skripte sind dazu nicht verändert worden. Es ist alles noch so wie vorher.
Um zu verhindern, dass ein Skript angestoßen wird, während die Skriptbearbeitung läuft habe ich mir ein Sperrbit gesetzt.
Grundsätzlich liegt zwischen den Archivierungen aber ein Zeitraum von mindestens 30s, bedingt durch den Ablauf an der Anlage.
Trotzdem hier die Frage: Angenommen der Code funktioniert nicht wie von mir gedacht, kann so etwas zu dem beschriebenen Verhalten führen?

Das hat bisher fehlerfrei geklappt.
Nun zu meinem Problem:
Ich kann nicht sicher sagen, ob der Auslöser dafür auf der Seite des Kundenservers oder bei mir liegt.
Angefangen hat es damit, dass der Kunde sich gemeldet hat, weil das HMI aus der Bedienoberfläche in die WinCE Oberfläche gesprungen ist.
Dort wurde das Fenster "Transfer" eingeblendet. In dem Fenster stand "Connecting to host". Nach einem Neustart (24V getrennt) fuhr das HMI wieder hoch, sprang aber nach kurzer Zeit von selbst wieder zu der gleichen Anzeige.
Ich habe das HMI per Fernwartung neu übertragen. Das Ergebnis blieb gleich.
Weiter erhielt ich die Info, dass die Archivierung auf dem Kundenserver seit über einem Tag nicht mehr funktioniert hat.

Da der Kunde ein Ersatzgerät zur Verfügung hatte, haben wir das ausgetauscht.
Zunächst hat die Anmeldung am Server nicht geklappt, weil das Passwort für die Anmeldung mal geändert wurde und das nicht gut dokumentiert wurde.
Das HMI hat dann jedes mal den Anmeldedialog zur Passworteingabe gebracht, wenn archiviert werden sollte.
So hat das dann etwa 2 Stunden ohne Archivierung gelaufen, bis das HMI genau wie das erste von allein in die WinCE-Oberfläche gesprungen ist und auf Transfer gewartet hat.
Wir haben dann den Netzwerkstecker zum Kundenserver gezogen. So läuft das wieder fehlerfrei, aber ohne Archivierung auf dem Kundenserver.

Der IT-Mitarbeiter des Kunden hat nun weiter nach der Ursache geforscht. Mittlerweile klappt die Anmeldung mit dem richtigen Passwort wieder.
Der Ablauf im sub-Skript "Datei kopieren" läuft bis Schritt 100. Dort wird die csv-Datei auf dem Kundenserver geöffnet.
Dann steigt das HMI aus. Was der Kunde mit dieser Beschreibung meint, muss ich noch einmal nachfragen.

Info des Mitarbeiters:
- Ich kann vom Panel aus in diesem Ordner Dateien anlegen, umbenennen und löschen (Schreibzugriff vorhanden).
- Ich kann vom Panel aus nicht testen, ob ich auch in den Dateien selbst Änderungen machen kann, da ich sie nicht öffnen kann (Fehlermeldung: Keine geeignete Applikation zum öffnen der Datei gefunden)
- Ich habe mich an meinem Rechner angemeldet und konnte die Dateien auf dem Serverordner öffnen, ändern, speichern (mit Editor geöffnet)

Hat jemand eine Idee?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier nochmal der Code:

Code:
Sub Datei_kopieren()
'Sub Datei_kopieren
Dim PathSearch, Path, Index, Result, fso, SourceFile, DestFile, f, fs, Header, StartTime, StopTime, DelayTime, i, Laenge, fileContent
Set PathSearch = CreateObject("FileCtl.FileSystem")
'USB-Stick suchen
'--------------------
Path = "Storage Card USB" 
    
SmartTags("Archivierung\Status_kopieren") = 10                'Text: Suche USB-Stick
    
If  PathSearch.Dir("\" & Path) = "" Then
 SmartTags("Archivierung\Status_kopieren") = 20            'Text: USB-Stick nicht gefunden!
    ElseIf PathSearch.Dir("\" & Path) = Path Then     
    SmartTags("Archivierung\Status_kopieren") = 30            'Text: Suche Zielordner
End If
'30: Ziellaufwerk suchen
'-----------------------
If SmartTags("Archivierung\Status_kopieren") = 30 Then
 Path = "\\DETET1AS0007\transfer$"
 'Path = "\\TGVM239\transfer$"
 'Path = "\\LAPTOP_CHRIS_WO\Logs"
 
 StartTime = Now
 DelayTime = 500  'Timer 100 endspricht 1sec.
 StopTime = StartTime + DelayTime / 24 / 360000
 Do                        
     Result = Ziel_pruefen (Path)
     If  Result = "transfer$" Then
     'If Result = "Logs" Then
      SmartTags("Archivierung\Status_kopieren") = 50      'Text: Schreibfreigabe prüfen
      Exit Do
     ElseIf Now >= StopTime Then    
         SmartTags("Archivierung\Status_kopieren") = 40      'Text: Zielordner nicht gefunden
  End If
 Loop Until Now >= StopTime
End If 

'50: Schreibfreigabe prüfen
'--------------------------
' Die Datei "NVE.ok" muss im Zielordner vorhanden sein.
If SmartTags("Archivierung\Status_kopieren") = 50 Then
 Path = "\\DETET1AS0007\transfer$\NVE.ok"
 'Path = "\\TGVM239\transfer$\NVE.ok"  
 'Path = "\\LAPTOP_CHRIS_WO\Logs\NVE.ok"                  
    Result = Ziel_pruefen (Path)
    If  Result = "NVE.ok" Then
     SmartTags("Archivierung\Status_kopieren") = 70          'Text: Zieldatei suchen
    Else  
        SmartTags("Archivierung\Status_kopieren") = 60          'Text: keine Schreibfreigabe
 End If
End If 
'70: Zieldatei prüfen
'---------------------
If SmartTags("Archivierung\Status_kopieren") = 70 Then
 
 Set f = CreateObject("FileCtl.File")
 Set fs = CreateObject("FileCtl.FileSystem")
 
 Path = "\\DETET1AS0007\transfer$\NVE.csv"
 'Path = "\\TGVM239\transfer$\NVE.csv"
 'Path = "\\LAPTOP_CHRIS_WO\Logs\NVE.csv"
 'Prüfen ob Ablagepfad vorhanden, wenn nicht -> erzeugen.
 Ordnerpfad_anlegen Path ' Übergabe des Ablagepfades aus dem Script "Script_Storage_Path" / Handing over of the storage path from the script "Script_Storage_Path"
 
 ' Datei öffnen bzw. erstellen, wenn sie noch nicht existiert
 f.open Path, 8         
 ' Tabellenkopf zusammenstellen (Anmerkung: Kunde wünscht keinen Header -> ausgeklammert)
 'Header = "Zeitstempel;Barcode;Hoehe" &  Chr(10)
 
 ' Wenn Datei 0 Byte groß, dann ist sie neu
 'If fs.FileLen(Path) = 0 Then       
    ' f.lineprint(Header)
 '=0 => Tabellenkopf muss eingefügt werden
  'End If 
  ' Datei wieder schließen
  f.Close
  
 Result = Ziel_pruefen (Path)
    If  Result = "NVE.csv" Then
     SmartTags("Archivierung\Status_kopieren") = 90            'Text: Quelldatei einlesen
    Else    
        SmartTags("Archivierung\Status_kopieren") = 80            'Text: Zieldatei nicht gefunden
 End If
End If 
'90: Datei suchen und auslesen
'-----------------------------
If SmartTags("Archivierung\Status_kopieren") = 90 Then
 
 Set fso = CreateObject("FileCtl.FileSystem")
 
 SmartTags("Archivierung\Name") = "PAL_ID.csv" ' fso.Dir("\Storage Card USB\*.csv")        'Suchen nach ersten Dateiname auf Stick
 f.open("\Storage Card USB\" & SmartTags("Archivierung\Name")),1,1
 Do
  If f.EOF = True Then Exit Do
  fileContent = fileContent & f.LineInputString & vbCrLf
 Loop
 'Leerzeile am Ende löschen
 Laenge = Len (fileContent)
 fileContent = Left(fileContent,(Laenge-2))
 ' Datei wieder schließen
  f.Close
  SmartTags("Archivierung\Status_kopieren") = 100    'Text: Quelldaten übertragen
End If 

'100: Einträge im Appendmodus anhängen
'-------------------------------------
If SmartTags("Archivierung\Status_kopieren") = 100 Then
 
 ' FileObject erstellen
 Set f = CreateObject("FileCtl.File")
 
 ' Datei öffnen im Append-Modus
 f.open "\\DETET1AS0007\transfer$\NVE.csv", 8 
 'f.open "\\TGVM239\transfer$\NVE.csv", 8 
 'f.open "\\LAPTOP_CHRIS_WO\Logs\NVE.csv", 8
 ' Einträge anhängen
 f.lineprint fileContent
 ' Datei wieder schließen
 f.Close 
 SmartTags("Archivierung\Status_kopieren") = 110   'Text: Quelldatei löschen
End If
 
'110: Quelldatei löschen
'-----------------------
If SmartTags("Archivierung\Status_kopieren") = 110 Then
  fs.Kill ("\Storage Card USB\" & SmartTags("Archivierung\Name"))
  SmartTags("Archivierung\Status_kopieren") = 200
End If
' Verwendeten Speicher wieder freigeben
Set f  = Nothing
Set fs = Nothing
Set fso = Nothing
Set PathSearch = Nothing
End Sub
 
Der Transfer-Dialog erscheint? - Die WinCC Runtime ist abgestürzt und meint offenbar, es sei keine gültige Runtime-Projektierung vorhanden. (Es scheint, als ob die Datei PDATA.FWX beschädigt ist oder ein anderes Problem mit dem Filesystem besteht.)

Schritt 100:
Du prüfst nicht, ob das Öffnen der Server-Datei für Append erfolgreich war.
Du prüfst nicht, ob das Anhängen/Schreiben an die Server-Datei erfolgreich war.
Du prüfst nicht, ob da Runtime-Errors aufgetreten sind.
Ich vermute, daß das Skript da durch einen Runtime-Error unsanft abgebrochen wird. Hast Du eine Meldeanzeige für Meldeereignisse in der Runtime drin, welche auch Meldungen der Meldeklasse "System" anzeigt? Darin sollte man Meldungen bezüglich Deines Skript-Problems finden.

Du solltest in dem Skript mit "On Error Resume Next" das Abbrechen des Skriptes verhindern und direkt nach den File-Operationen den Runtime-Error-Status auswerten:
Code:
Dim fs, f, ...
Const ForAppending = 8
On Error Resume Next
...

' FileSystemObject erstellen
Set fs = CreateObject("FileCtl.FileSystem")
If Err.Number <> 0 Then
  ShowSystemAlarm "Error #" & Err.Number & " " & Err.Description
  Err.Clear
  Exit Sub
End If
' FileObject erstellen
Set f = CreateObject("FileCtl.File")
If Err.Number <> 0 Then
  ShowSystemAlarm "Error #" & Err.Number & " " & Err.Description
  Err.Clear
  Exit Sub
End If
...

'100: Einträge im Appendmodus anhängen
'-------------------------------------
If SmartTags("Archivierung\Status_kopieren") = 100 Then

  ' Datei öffnen im Append-Modus
  f.open "\\DETET1AS0007\transfer$\NVE.csv", ForAppending
  If Err.Number <> 0 Then
    ShowSystemAlarm "Error #" & Err.Number & " " & Err.Description
    Err.Clear
    Exit Sub
  End If

  ' Einträge anhängen
  f.lineprint fileContent
  If Err.Number <> 0 Then
    ShowSystemAlarm "Error #" & Err.Number & " " & Err.Description
    Err.Clear
    f.Close
    Exit Sub
  End If

  ' Datei wieder schließen
  f.Close
  SmartTags("Archivierung\Status_kopieren") = 110   'Text: Quelldatei löschen
End If

Für mein Gefühl erstellst Du unnötigerweise zu viele File-/Filesystem-Objekte. Im Schritt 100 benutzt Du eine bereits benutzte Objektverweis-Variable (f) für die Erstellung eines neuen File-Objektes ohne das vorhandene File-Objekt freizugeben - dadurch geht der Verweis zum vorherigen Objekt verloren. Möglicherweise geht durch die zu vielen Objekte und die Runtime-Errors der Arbeitsspeicher zur Neige und die WinCC Runtime stürzt deshalb ab?
Ich würde vorschlagen, Du erstellst am Anfang des Skriptes je ein File-Objekt und FileSystem-Objekt und benutzt dann nur noch diese beiden Objekte.


Der Schritt 90 ist nicht gut gelöst - wozu eine komplette Datei in den Arbeitsspeicher einlesen?
Wie groß ist die Datei "\Storage Card USB\PAL_ID.csv"? - eventuell zu groß oder leer?
Kann es vorkommen, daß die Datei leer ist? Ich weiß nicht, was VBS macht, wenn man "fileContent = Left(fileContent,(Laenge-2))" mit einer resultierenden negativen Länge aufruft.
Wozu ungeprüft generell die letzten 2 Zeichen aus der Datei entfernen? Wo kommt die leere Zeile her?

Ich würde anstatt Schritt 90 im Schritt 100 die Datei vom Panel zeilenweise in die Datei auf dem Server kopieren (beide Dateien öffnen, in einer Schleife bis EOF von Quelldatei eine Zeile einlesen, wenn Länge > 0 dann die Zeile in die Zieldatei schreiben).


Ob das Panel alle erforderlichen Rechte auf dem Server hat kannst Du mit dem "Command Prompt" (Pocket CMD) des Panels ausprobieren, da bekommst Du eventuelle Fehlermeldungen auch gleich angezeigt. Etwa so:
Code:
 Pocket CMD
\> [COLOR="#0000FF"]echo blablabla > \temp\test.txt[/COLOR]
\> [COLOR="#0000FF"]copy \temp\test.txt \\DETET1AS0007\transfer$\test.csv[/COLOR]
\> [COLOR="#0000FF"]echo append123 >> \\DETET1AS0007\transfer$\test.csv[/COLOR]
\> [COLOR="#0000FF"]type \\DETET1AS0007\transfer$\test.csv[/COLOR]
blablabla
append123
\>
Danach sollte auf dem Server die Datei test.csv den Inhalt
blablabla
append123
haben.

Harald
 
Du solltest in dem Skript mit "On Error Resume Next" das Abbrechen des Skriptes verhindern und direkt nach den File-Operationen den Runtime-Error-Status auswerten:
Code:
...
If Err.Number <> 0 Then
  ShowSystemAlarm "Error #" & Err.Number & " " & Err.Description
  Err.Clear
  Exit Sub
End If
...
Der Aufwand macht natürlich nur Sinn, wenn Du in dem Skript auf den Fehler reagieren kannst/willst (z.B. einen Vorgang erneut versuchen oder etwas anderes versuchen). Wenn da nur eine Fehlermeldung ausgegeben und das Skript beendet werden soll, dann kannst Du das "On Error Resume Next" weglassen - das macht VBS sowieso automatisch so.

Harald
 
Zurück
Oben