J'ai terminé un script pour produire un fichier CSV qui affiche les données %MW du fichier DAT de PL7 Pro sous différents formats.
C'est réalisé en VBScript qui n'est clairement pas le langage le plus efficace pour la conversion des données... mais le calcul des valeurs à virgule flottante semble fiable.
Code : Tout sélectionner
'/// Pl7DatToCsv.vbs \\\
'\\\ forum-automatisme.net ///
'Version 1.0 - 2024-06-05
'Code source sous licence CeCILL v2.1 (https://cecill.info/licences/Licence_CeCILL_V2.1-fr.txt)
' attribué à la communauté de forum-automatisme.net
'Ce script permet de convertir un fichier .DAT généré par PL7 Pro
' en un fichier texte de type CSV contenant les valeurs des mots
' aux formats entier (%MW), entier double (%MD) et réel (%MF)
' ainsi que les représentations hexadécimale, binaire et ASCII.
'La conversion peut être lancée en ligne de commande ou par glisser-déposer
' du fichier à convertir sur le fichier Pl7DatToCsv.vbs.
Option Explicit
Const ForReading = 1, ForWriting = 2
Dim oFSO, oArgs
Dim oFichierDat, oFichierCsv
Dim sFicDat, sFicCsv, s
Dim sDat
Dim oRegExp, oMatch, oMatches
Dim sMW_Adr, sMW_Val, sMW_Val_Hexa, sMWprec_Adr, sMWprec_Val_Hexa
Dim lMW_Val_UINT, lMWprec_Val_UINT, lMW_Val_INT, lMWprec_Val_INT, lMW_Val_DINT
Dim sMW_Val_REAL
Dim Signe, Exposant, Mantisse
Dim tAscii
tAscii = array( _
"$00","$01","$02","$03","$04","$05","$06","$07","$08","$09","$0a","$0b","$0c","$0d","$0e","$0f", _
"$10","$11","$12","$13","$14","$15","$16","$17","$18","$19","$1a","$1b","$1c","$1d","$1e","$1f", _
" ","!","""","#","$$","%","&","'","(",")","*","+",",","-",".","/", _
"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?", _
"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O", _
"P","Q","R","S","T","U","V","W","X","Y","Z","[","\","]","^","_", _
"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o", _
"p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","$7F", _
"","","","","","
","","","","","","","","","","", _
"","","","","","","","","","","","","","","","", _
" ","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","","®","¯", _
"°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿", _
"À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï", _
"Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß", _
"à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï", _
"ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ")
Set oFSO = CreateObject("Scripting.FileSystemObject")
'--- Récupération du nom des fichiers en argument
Set oArgs = WScript.Arguments
If oArgs.Count < 1 Then
s= "Script de conversion d'un fichier .DAT PL7 Pro vers CSV" & vbCrLf
s=s & " avec des valeurs de types entier, entier double et réel." & vbCrLf
s=s & "-------------------------------------------------------------------" & vbCrLf
s=s & "Syntaxe :" & vbCrLf
s=s & " Pl7DatToCsv <dat> [<csv>]" & vbCrLf
s=s & " <dat> : fichier de données généré par PL7 Pro" & vbCrLf
s=s & " (doit exister)" & vbCrLf
s=s & " <csv> : fichier destination au format CSV" & vbCrLf
s=s & " (est créé ou écrasé)" & vbCrLf
s=s & " par défaut, il est nommé 'Conversion de <dat>.csv'" & vbCrLf
WScript.Echo s
WScript.Quit
Else
sFicDat = oArgs(0)
If Not oFSO.FileExists(sFicDat) Then
MsgBox "Le fichier " & sFicDat & " n'existe pas.", vbCritical, "Erreur"
WScript.Quit
End If
If oArgs.Count > 1 Then
sFicCsv = oArgs(1)
Else
'--- Composition du nom du fichier à créer à partir du fichier d'origine, dans le même répertoire
Set oFichierDat = oFSO.GetFile(sFicDat)
sFicCsv = Replace(oFichierDat.ParentFolder & "\Conversion de " & oFichierDat.Name, ".dat", ".csv", 1, -1, vbTextCompare)
End If
End If
Set oArgs = Nothing
'--- Ouverture et contrôle (basique) du fichier .DAT
Set oFichierDat = oFSO.OpenTextFile(sFicDat, ForReading)
If oFichierDat.Readline <> "[HEADER]" Then
MsgBox "Le fichier à convertir n'est pas un fichier de données PL7 Pro.", vbCritical, "Fichier non reconnu"
WScript.Quit
End If
Set oFSO = CreateObject("Scripting.FileSystemObject")
'--- Lecture du contenu du fichier
sDat = oFichierDat.ReadAll
'- Fermeture du fichier de données
oFichierDat.Close
'--- Expression rationnelle pour rechercher toutes les données
' et récupérer 2 informations : l'adresse du mot et sa valeur
Set oRegExp = New RegExp
oRegExp.Pattern = "AT (%MW[0-9]+) : WORD := \(([0-9]+)\);"
oRegExp.Global = True 'recherche de toutes les occurences
Set oMatches = oRegExp.Execute(sDat)
sDat = ""
If oMatches.Count = 0 Then
MsgBox "Bizarre, aucune donnée %MW n'a été détectée dans ce fichier...", vbExclamation, "Aucun résultat"
Else
'--- Création du fichier CSV
Set oFichierCsv = oFSO.OpenTextFile(sFicCsv, ForWriting,True)
' avec un en-tête des colonnes
oFichierCsv.WriteLine "Adresse;INT;DINT;REAL;WORD (hexa.);WORD (bin.);WORD (ASCII)"
'--- Traitement de tous les mots %MW
sMWprec_Adr = "" ' adresse mémorisée pour le double mot et utilisée à la lecture du 2e mot
For Each oMatch In oMatches
' on compte sur le fait que les résultats de l'expression rationnelle
' sont restitués dans l'ordre des adresses
sMW_Adr = oMatch.SubMatches(0) 'adresse du mot %MW
sMW_Val = oMatch.SubMatches(1) 'valeur du mot (16 bits)
'- Format INT
'conversion de la valeur non signée en valeur signée
lMW_Val_UINT = CLng(sMW_Val)
If lMW_Val_UINT > 32767 Then
lMW_Val_INT = lMW_Val_UINT - 65536
Else
lMW_Val_INT = lMW_Val_UINT
End If
' valeur hexadécimale sur 4 digits (16 bits) utilisée pour l'assemblage des mots doubles (32 bits)
' (on complète avec les zéros non significatifs que ne donne pas la fonction Hex)
sMW_Val_Hexa = Right("0000" & Hex(sMW_Val), 4)
' on commence à écrire au 2e passage pour avoir 2 mots (nécessaires à DINT et REAL)
If sMWprec_Adr <> "" Then
'- Format DINT
lMW_Val_DINT = CLng("&H" & sMW_Val_Hexa & sMWprec_Val_Hexa)
'- Format REAL
' décomposition des 3 parties binaires d'un nombre à virgule flottante sur 32 bits (selon standard IEEE 754)
Signe = Sgn(lMW_Val_DINT)
Exposant = (lMW_Val_DINT And &H7F800000) / &H800000
Mantisse = lMW_Val_DINT And &H007FFFFF
' reconstitution de la valeur réelle
If Exposant = 0 Then
If Mantisse = 0 Then
' valeur nulle
sMW_Val_REAL = "0"
Else
' valeur dénormalisée
sMW_Val_REAL = CStr(CSng(Signe * (2^(-126)) * (Mantisse / &H800000)))
End If
ElseIf Exposant = 255 Then
If Mantisse = 0 Then
' valeur infinie
If Signe = -1 Then sMW_Val_REAL = "-1.#INF" Else sMW_Val_REAL = "1.#INF" End If
Else
' Not a Number (pas un nombre)
If Signe = -1 Then sMW_Val_REAL = "-1.#NAN" Else sMW_Val_REAL = "1.#NAN" End If
End If
Else
sMW_Val_REAL = CStr(CSng((Signe * (2^(Exposant-127)) * (1 + Mantisse / &H800000))))
End If
' écriture des valeurs dans le fichier CSV
oFichierCsv.WriteLine sMWprec_Adr _
& ";" & lMWprec_Val_INT _
& ";" & lMW_Val_DINT _
& ";" & sMW_Val_REAL _
& ";16#" & sMWprec_Val_Hexa _
& ";2#" & HexToBinary(sMWprec_Val_Hexa) _
& ";'" & tAscii((lMWprec_Val_UINT And &HFF00) \ &H100) & tAscii(lMWprec_Val_UINT And &HFF) & "'"
End If
' valeurs mémorisées pour le tour suivant
sMWprec_Adr = sMW_Adr
lMWprec_Val_UINT = lMW_Val_UINT
lMWprec_Val_INT = lMW_Val_INT
sMWprec_Val_Hexa = sMW_Val_Hexa
Next
' écriture du dernier mot (qui ne peut pas constituer le poids faible d'un mot double)
oFichierCsv.WriteLine sMWprec_Adr _
& ";" & lMW_Val_INT _
& ";" _
& ";" _
& ";16#" & sMW_Val_Hexa _
& ";2#" & HexToBinary(sMW_Val_Hexa) _
& ";'" & tAscii((lMW_Val_UINT And &HFF00)\ &H100) & tAscii(lMW_Val_UINT And &HFF) & "'"
'- Fermeture du fichier CSV
oFichierCsv.Close
End If
Set oMatch = Nothing
Set oMatches = Nothing
Set oRegExp = Nothing
'-------------------------------
Function HexToBinary(ByVal sHex)
' Renvoie une chaine de caractères de bits équivalents aux digits hexadécimaux
' avec un espace séparant chaque quartet (groupe de 4 bits) pour la lisibilité
Dim tHexDigit
tHexDigit = "0123456789ABCDEF"
Dim tBin
tBin = Array("0000","0001","0010","0011","0100","0101","0110","0111", _
"1000","1001","1010","1011","1100","1101","1110","1111")
Dim i
Dim Result
Result = ""
For i = 1 To Len(sHex)
Result = Result & tBin(InStr(tHexDigit, Mid(sHex, i, 1)) - 1) & " "
Next
HexToBinary = Trim(Result)
End Function
Mais le copier/coller pose problème avec certains caractères de la table ASCII.
.