Ajout de données dans fichier XML

Fermé
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023 - 13 nov. 2022 à 07:54
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023 - 17 nov. 2022 à 14:44

Bonjour à toute la communauté,

Je me permets de venir vers vous car j'ai une petite question sur la création d'un fichier XML en C#. Mes connaissances étant très limitées, je bloque vite...

Je veux générer ce code en sachant que le noeud "datablock" contiendra plusieurs "enfants" variables avec des attributs différents. J'ai pensé à utiliser la fonction XmlDocSource.Descendants mais je ne sais pas l'implémenter et je me dis qu'il y a peut être mieux que ça comme fonction. Ci après, le fichier exemple de sortie

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<STExchangeFile>
	<fileHeader company="Schneider Automation" product="Control Expert V14.1 - 191122A" dateTime="date_and_time#2022-11-12-9:21:30" content="Fichier source ST" DTDVersion="41"></fileHeader>
	<contentHeader name="Station" version="0.0.141" dateTime="date_and_time#2022-11-5-18:21:51"></contentHeader>
	<program>
		<identProgram name="copie_ES" type="section" task="MAST"></identProgram>
		<STSource>(*Copies des entrees ANA depuis le Wago *)
EA_LT_Forage1 := Ilo_Wago_IN_AI_C1_V1	;
</STSource>
	</program>
	<dataBlock>
		<variables name="EA_LT_Forage1" typeName="INT"></variables>
        <variables name="EA_LT_Forage2" typeName="INT"></variables>
	</dataBlock>
</STExchangeFile>

Voici le code utilisé:

// Création du fichier de sortie
                //Déclaration des différentes variables
                List<EnteteEANA> EnteteEAna = new List<EnteteEANA>();
                List<EANA_API> Liste_EANA_API = new List<EANA_API>();

                
                List<EnteteETOR> Entete_ETOR = new List<EnteteETOR>();
                List<ETOR_API> Liste_ETOR_API = new List<ETOR_API>();

                List<EnteteSTOR> Entete_STOR = new List<EnteteSTOR>();
                List<STOR_API> Liste_STOR_API = new List<STOR_API>();

                List<EnteteSANA> Entete_SANA = new List<EnteteSANA>();
                List<SANA_API> Liste_SANA_API = new List<SANA_API>();

                //Création des différentes entête de chaque partie 
                EnteteEAna.Add(new EnteteEANA("(*Copies des entrees Analogiques *)"));

                Entete_SANA.Add(new EnteteSANA(" "));
                Entete_SANA.Add(new EnteteSANA("(*Copies des sorties Analogiques *)"));

                Entete_ETOR.Add(new EnteteETOR(" "));
                Entete_ETOR.Add(new EnteteETOR("(*Copies des entrees TOR *)"));

                Entete_STOR.Add(new EnteteSTOR(" "));
                Entete_STOR.Add(new EnteteSTOR("(*Copies des sorties TOR *)"));
                int Index;

                //Ajout des différentes entrées ANA
                for (Index = 0; Index <= NB_EANA - 1; Index++)
                {
                    Liste_EANA_API.Add(new EANA_API(Tab_EANA[Index, 1],Tab_EANA[Index, 0], Index));
                }

                //Ajout des différentes entrées TOR
                for (Index = 0; Index <= NB_ETOR - 1; Index++)
                {
                    Liste_ETOR_API.Add(new ETOR_API(Tab_ETOR[Index, 1], Tab_ETOR[Index, 0], Index));
                }

                //Ajout des différentes sorties TOR
                for (Index = 0; Index <= NB_STOR - 1; Index++)
                {
                    Liste_STOR_API.Add(new STOR_API(Tab_STOR[Index, 1], Tab_STOR[Index, 0], Index));
                }

                //Ajout des différentes sorties ANA
                for (Index = 0; Index <= NB_SANA - 1; Index++)
                {
                    Liste_SANA_API.Add(new SANA_API(Tab_SANA[Index, 1], Tab_SANA[Index, 0], Index));
                }

                //Création du fichier XML source
                XDocument XmlDoc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), new XElement("STExchangeFile", new XElement("fileHeader", new XAttribute("company", "Schneider Automation"), new XAttribute("product", "Control Expert V14.1 - 191122A"), new XAttribute("dateTime", "date_and_time#2018-3-12-16:50:53"), new XAttribute("content", "Fichier source ST"), new XAttribute("DTDVersion", "41")),
                                                                                                                         new XElement("contentHeader", new XAttribute("name", "Projet"), new XAttribute("version", "0.0.710"), new XAttribute("dateTime", "date_and_time#2018-2-14-14:39:27")),
                                                                                                                         new XElement("program", new XElement("identProgram", new XAttribute("name", "Copie_E_S"), new XAttribute("type", "section"), new XAttribute("task", "MAST")),
                                                                                                                         new XElement("STSource", from p in EnteteEAna select new XText(p.texte),
                                                                                                                                                  from p in Liste_EANA_API select new XText(p.EANA),
                                                                                                                                             
                                                                                                                                                  from p in Entete_ETOR select new XText(p.texte),
                                                                                                                                                  from p in Liste_ETOR_API select new XText(p.ETOR),

                                                                                                                                                  from p in Entete_STOR select new XText(p.texte),
                                                                                                                                                  from p in Liste_STOR_API select new XText(p.STOR),

                                                                                                                                                  from p in Entete_SANA select new XText(p.texte),
                                                                                                                                                  from p in Liste_SANA_API select new XText(p.SANA))),
                                                                                                                         new XElement("dataBlock", new XElement("variables"))));



//Création des différentes classes
public class EnteteEANA
    {
        public EnteteEANA() { }

        public EnteteEANA(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }

    public class EANA_API
    {
        public EANA_API() { }

        public EANA_API(string Mnémonique, string Adresse, int Index)
        {
            this.EANA = "IF AOM_AO[" + Index + "] = 0 THEN " + Mnémonique + " := " + Adresse + "; ELSE " + Mnémonique + " := A_MODIFIER[" + Index + "]; END_IF;" + "\n";
        }
        public string EANA { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }

    public class EnteteETOR
    {
        public EnteteETOR() { }

        public EnteteETOR(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }

    public class ETOR_API
    {
        public ETOR_API() { }

        public ETOR_API(string Mnémonique, string Adresse, int Index)
        {
            this.ETOR = Mnémonique + " := (" + Adresse + " AND AOM_I[" + Index + "] = 0) OR AOM_I[" + Index + "] = 1;" + "\n";
        }
        public string ETOR { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }



    public class EnteteSTOR
    {
        public EnteteSTOR() { }

        public EnteteSTOR(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }

    public class STOR_API
    {
        public STOR_API() { }

        public STOR_API(string Mnémonique, string Adresse, int Index)
        {
            this.STOR = Adresse + " := (" + Mnémonique + " AND AOM_O[" + Index + "] = 0) OR AOM_O[" + Index + "] = 1;" + "\n";
        }
        public string STOR { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }


    public class EnteteSANA
    {
        public EnteteSANA() { }

        public EnteteSANA(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }
    public class SANA_API
    {
        public SANA_API() { }

        public SANA_API(string Mnémonique, string Adresse, int Index)
        {
            this.SANA = "IF AOM_AO[" + Index + "] = 0 THEN " + Adresse + " := " + Mnémonique + "; ELSE " + Adresse + " := A_MODIFIER[" + Index + "]; END_IF;" + "\n";
        }
        public string SANA { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }

En vous remerciant par avance de votre retour
Windows / Chrome 107.0.0.0

A voir également:

21 réponses

Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
13 nov. 2022 à 10:11

Bonjour

Tout d'abord, quelques points généraux

  • pour pouvoir t'aider efficacement, il faudrait un jeu de données d'entrée représentatif sans être "confidentiel" et le fichier de sortie que tu voudrais avoir à partir de ça.
  • il est fortement déconseillé d'utiliser des signes diacritiques dans les noms de variables, classes, méthodes, espaces de noms etc....
  • la construction de strings par des + est archaïque et génératrice de bug, il existe depuis le début de C# (plus de 20 ans donc) 2 autres solutions, le string.Format et la classe stringbuilder, et depuis VS2017 (je crois), une implémentation simplifiée de string.Format avec le caractère clé $ en début de string (comme le @ pour les \)

Ensuite, ton code spécifiquement, je pense que tu te compliques la vie inutilement.

  • Tes classes d'entêtes :
    • elles sont identiques :
      • Au pire une seule suffirait avec si besoin une propriété pour distinguer de quel entête il s'agit
      • Si pour une autre raison que ce code, tu as vraiment besoin de classes différentes, alors une classe abstraite dans laquelle le commun est implémenté et des classes dérivées vides ou quasi vides serait une bien meilleure implémentation.
    • elles ne font rien d'autre que d'ajouter un saut de ligne à une string
      • je pense que ces classes ne sont pas utiles
  • Tes classes d'entrées et sorties :
    • ne remplissent pas les propriétés communes dans le constructeur
    • sont quasiment identiques :
      • même signature du constructeur
      • 3 propriétés communes
      • une propriété spécifique qui est construite selon la classe
        • c'est exactement le type de cas où une classe abstraite et des classes dérivées doit être utilisé
        • tu nommes la propriété spécifique avec un nom générique (Texte par exemple) et tu n'implémentes que ce code dans les classes dérivées, ou encore, puisque qu'il s'agit de strings, tu overrides ToString()

Avantages

  1. moins de code à écrire et à maintenir
  2. utilisation du polymorphisme, par exemple, une liste de la classe abstraite peut contenir des instances des classes dérivées.
  3. ça devrait être moins le fouillis dans le code de génération du xml

Exemple avec la proprétié Texte à implémenter dans les classes dérivées (pas de diacritique et string.Format via $ )

    public abstract class EntreesSortie
    {
        public EntreesSortie(string Mnemonique, string Adresse, int Index)
        {
            this.Mnemonique = Mnemonique;
            this.Adresse= Adresse;
            this.Index= Index;
        }

        public abstract string Texte { get; }
        public string Mnemonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }

    public class EANA_API : EntreesSortie
    {

        public EANA_API(string Mnemonique, string Adresse, int Index) : base(Mnemonique, Adresse, Index)
        {
        }

        public override string Texte
        {
            get { return $"IF AOM_AO[{Index}] = 0 THEN {Mnemonique} := {Adresse}; ELSE {Mnemonique} := A_MODIFIER[{Index}]; END_IF;\n"; }
        }
    }

Exemple avec utilisation de ToString dans les classes dérivées

    public abstract class EntreesSortie2
    {
        public EntreesSortie2(string Mnemonique, string Adresse, int Index)
        {
            this.Mnemonique = Mnemonique;
            this.Adresse = Adresse;
            this.Index = Index;
        }

        public string Mnemonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }

    public class EANA_API2 : EntreesSortie2
    {
        public EANA_API2(string Mnemonique, string Adresse, int Index) : base(Mnemonique, Adresse, Index)
        {
        }

        public override string ToString()
        {
            return $"IF AOM_AO[{Index}] = 0 THEN {Mnemonique} := {Adresse}; ELSE {Mnemonique} := A_MODIFIER[{Index}]; END_IF;\n";
        }
    }

0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
14 nov. 2022 à 09:50

Salut Whismeril, 

Merci pour ton retour. Je me suis servi de bout de code que tu m'avais donné il y a 5ans et j'ai tout mixé pour arriver à ce que je voulais. N'étant pas informaticien, j'avoue que mon code est plutôt brouillon...

Pour la source, c'est un fichier Excel dont j'extrais les données qui m'intéresse avec OLEDB.

OleDbConnection MyConnection = default(OleDbConnection);
            DataSet dataSetES = default(DataSet);
            OleDbDataAdapter MyCommand = default(OleDbDataAdapter);

            MyConnection = new OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = " + NomFichierSource.Text + "; Extended Properties = 'Excel 12.0 XML;HDR=YES;'; ");
            MyCommand = new OleDbDataAdapter("select * from [Liste_ES$]", MyConnection);

            MyConnection.Open();

            dataSetES = new DataSet();
            MyCommand.Fill(dataSetES);

            //Calcul du nombre de lignes et de colonnes pour dimensionner le tableau qui accueillera les données
            int nb_col = dataSetES.Tables[0].Columns.Count;
            nb_lignesES = dataSetES.Tables[0].Rows.Count;

            //Création du tableau qui accueillera les données du fichier excel
            string[,] Tableau_SourceES = new string[nb_lignesES + 1, nb_col + 1];
            int x = 0;
            int y = 0;
            for (x = 0; x <= nb_lignesES - 1; x++)
            {
                for (y = 0; y <= nb_col - 1; y++)
                {
                    Tableau_SourceES[x, y] = dataSetES.Tables[0].Rows[x].ItemArray[y].ToString();
                }
            }
            MyConnection.Close();

            int NB_EANA = 0;
            int NB_ETOR = 0;
            int NB_STOR = 0;
            int NB_SANA = 0;

            //Calcul du nombre d'entrées ANA, entrées TOR, sorties TOR, sorties ANA dans le tableau
            for (x = 0; x <= nb_lignesES - 1; x++)
            {
                if (Tableau_SourceES[x, 1].Contains("AI_"))
                    {
                        NB_EANA = NB_EANA + 1;
                    }

                if (Tableau_SourceES[x, 1].Contains("DI.C"))
                    {
                        NB_ETOR = NB_ETOR + 1;
                    }

                if (Tableau_SourceES[x, 1].Contains("DO.C"))
                    {
                        NB_STOR = NB_STOR + 1;
                    }

                if (Tableau_SourceES[x, 1].Contains("AO_"))
                    {
                        NB_SANA = NB_SANA + 1;
                    }
            }

            //Déclaration des tableaux d'entrées/sorties
            string[,] Tab_EANA = new string[NB_EANA, 3];
            string[,] Tab_ETOR = new string[NB_ETOR, 3];
            string[,] Tab_STOR = new string[NB_STOR, 3];
            string[,] Tab_SANA = new string[NB_SANA, 3];

            //Remplissage des tableaux d'entrées/sorties
            int Index_EANA =0;
            int Index_ETOR =0;
            int Index_STOR = 0;
            int Index_SANA = 0;

            for (x = 0; x <= nb_lignesES - 1; x++)
            {
                if (Tableau_SourceES[x, 1].Contains("AI_"))
                    {
                        Tab_EANA[Index_EANA, 0] = Tableau_SourceES[x, 1]; // Récupération de l'adresse de l'entrée
                        Tab_EANA[Index_EANA, 1] = Tableau_SourceES[x, 9]; // Récupération du Mnémonique
                        Tab_EANA[Index_EANA, 2] = Tableau_SourceES[x, 5] + " " + Tableau_SourceES[x, 7]; // Récupération du commentaire
                        Index_EANA = Index_EANA + 1;
                    }

                if (Tableau_SourceES[x, 1].Contains("DI.C"))
                    {
                        Tab_ETOR[Index_ETOR, 0] = Tableau_SourceES[x, 1]; // Récupération de l'adresse de l'entrée
                        Tab_ETOR[Index_ETOR, 1] = Tableau_SourceES[x, 9]; // Récupération du Mnémonique
                        Tab_ETOR[Index_ETOR, 2] = Tableau_SourceES[x, 5] + " " + Tableau_SourceES[x, 7]; // Récupération du commentaire
                        Index_ETOR = Index_ETOR + 1;
                    }

                if (Tableau_SourceES[x, 1].Contains("DO.C"))
                    {
                        Tab_STOR[Index_STOR, 0] = Tableau_SourceES[x, 1]; // Récupération de l'adresse de l'entrée
                        Tab_STOR[Index_STOR, 1] = Tableau_SourceES[x, 9]; // Récupération du Mnémonique
                        Tab_STOR[Index_STOR, 2] = Tableau_SourceES[x, 5] + " " + Tableau_SourceES[x, 7]; // Récupération du commentaire
                        Index_STOR = Index_STOR + 1;
                    }

                if (Tableau_SourceES[x, 1].Contains("AO_"))
                    {
                        Tab_SANA[Index_SANA, 0] = Tableau_SourceES[x, 1]; // Récupération de l'adresse de l'entrée
                        Tab_SANA[Index_SANA, 1] = Tableau_SourceES[x, 9]; // Récupération du Mnémonique
                        Tab_SANA[Index_SANA, 2] = Tableau_SourceES[x, 5] + " " + Tableau_SourceES[x, 7]; // Récupération du commentaire
                        Index_SANA = Index_SANA + 1;
                    }
            }


            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ////////////////////////////////////                                                                            ////////////////////////////////////
            ////////////////////////////////////                     Génération section de recopie E/S                      ////////////////////////////////////
            ////////////////////////////////////                                                                            ////////////////////////////////////            
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            if (RecopieE_S.Checked == true)
            {
                
                // Création du fichier de sortie
                //Déclaration des différentes variables
                List<EnteteEANA> EnteteEAna = new List<EnteteEANA>();
                List<EANA_API> Liste_EANA_API = new List<EANA_API>();

                
                List<EnteteETOR> Entete_ETOR = new List<EnteteETOR>();
                List<ETOR_API> Liste_ETOR_API = new List<ETOR_API>();

                List<EnteteSTOR> Entete_STOR = new List<EnteteSTOR>();
                List<STOR_API> Liste_STOR_API = new List<STOR_API>();

                List<EnteteSANA> Entete_SANA = new List<EnteteSANA>();
                List<SANA_API> Liste_SANA_API = new List<SANA_API>();

                //Création des différentes entête de chaque partie 
                EnteteEAna.Add(new EnteteEANA("(*Copies des entrees Analogiques *)"));

                Entete_SANA.Add(new EnteteSANA(" "));
                Entete_SANA.Add(new EnteteSANA("(*Copies des sorties Analogiques *)"));

                Entete_ETOR.Add(new EnteteETOR(" "));
                Entete_ETOR.Add(new EnteteETOR("(*Copies des entrees TOR *)"));

                Entete_STOR.Add(new EnteteSTOR(" "));
                Entete_STOR.Add(new EnteteSTOR("(*Copies des sorties TOR *)"));
                int Index;

                //Ajout des différentes entrées ANA
                for (Index = 0; Index <= NB_EANA - 1; Index++)
                {
                    Liste_EANA_API.Add(new EANA_API(Tab_EANA[Index, 1],Tab_EANA[Index, 0], Index));
                }

                //Ajout des différentes entrées TOR
                for (Index = 0; Index <= NB_ETOR - 1; Index++)
                {
                    Liste_ETOR_API.Add(new ETOR_API(Tab_ETOR[Index, 1], Tab_ETOR[Index, 0], Index));
                }

                //Ajout des différentes sorties TOR
                for (Index = 0; Index <= NB_STOR - 1; Index++)
                {
                    Liste_STOR_API.Add(new STOR_API(Tab_STOR[Index, 1], Tab_STOR[Index, 0], Index));
                }

                //Ajout des différentes sorties ANA
                for (Index = 0; Index <= NB_SANA - 1; Index++)
                {
                    Liste_SANA_API.Add(new SANA_API(Tab_SANA[Index, 1], Tab_SANA[Index, 0], Index));
                }

                //Création du fichier XML source
                XDocument XmlDoc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), new XElement("STExchangeFile", new XElement("fileHeader", new XAttribute("company", "Schneider Automation"), new XAttribute("product", "Control Expert V14.1 - 191122A"), new XAttribute("dateTime", "date_and_time#2018-3-12-16:50:53"), new XAttribute("content", "Fichier source ST"), new XAttribute("DTDVersion", "41")),
                                                                                                                         new XElement("contentHeader", new XAttribute("name", "Projet"), new XAttribute("version", "0.0.710"), new XAttribute("dateTime", "date_and_time#2018-2-14-14:39:27")),
                                                                                                                         new XElement("program", new XElement("identProgram", new XAttribute("name", "Copie_E_S"), new XAttribute("type", "section"), new XAttribute("task", "MAST")),
                                                                                                                         new XElement("STSource", from p in EnteteEAna select new XText(p.texte),
                                                                                                                                                  from p in Liste_EANA_API select new XText(p.EANA),
                                                                                                                                             
                                                                                                                                                  from p in Entete_ETOR select new XText(p.texte),
                                                                                                                                                  from p in Liste_ETOR_API select new XText(p.ETOR),

                                                                                                                                                  from p in Entete_STOR select new XText(p.texte),
                                                                                                                                                  from p in Liste_STOR_API select new XText(p.STOR),

                                                                                                                                                  from p in Entete_SANA select new XText(p.texte),
                                                                                                                                                  from p in Liste_SANA_API select new XText(p.SANA))),
                                                                                                                         new XElement("dataBlock",new XElement("variables", new XAttribute("version", "0.0.710")))));

                //Test si le fichier existe déjà
                if (File.Exists(NomDossierDest.Text + @"\Sections_ST.xst"))
                {
                    MessageBox.Show("Un fichier section existe déjà dans le dossier de destination. Annulation de l'opération");
                }
                else
                {
                    //Récupération du nom de la zone pour définir le nom du fichier
                    XmlDoc.Save(NomDossierDest.Text + @"\Sections_ST.xst");
                }
            }

public class EnteteEANA
    {
        public EnteteEANA() { }

        public EnteteEANA(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }

    public class EANA_API
    {
        public EANA_API() { }

        public EANA_API(string Mnémonique, string Adresse, int Index)
        {
            this.EANA = "IF AOM_AO[" + Index + "] = 0 THEN " + Mnémonique + " := " + Adresse + "; ELSE " + Mnémonique + " := A_MODIFIER[" + Index + "]; END_IF;" + "\n";
        }
        public string EANA { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }

    public class EnteteETOR
    {
        public EnteteETOR() { }

        public EnteteETOR(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }

    public class ETOR_API
    {
        public ETOR_API() { }

        public ETOR_API(string Mnémonique, string Adresse, int Index)
        {
            this.ETOR = Mnémonique + " := (" + Adresse + " AND AOM_I[" + Index + "] = 0) OR AOM_I[" + Index + "] = 1;" + "\n";
        }
        public string ETOR { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }



    public class EnteteSTOR
    {
        public EnteteSTOR() { }

        public EnteteSTOR(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }

    public class STOR_API
    {
        public STOR_API() { }

        public STOR_API(string Mnémonique, string Adresse, int Index)
        {
            this.STOR = Adresse + " := (" + Mnémonique + " AND AOM_O[" + Index + "] = 0) OR AOM_O[" + Index + "] = 1;" + "\n";
        }
        public string STOR { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }


    public class EnteteSANA
    {
        public EnteteSANA() { }

        public EnteteSANA(String texte)
        {
            this.texte = texte + "\n";
        }
        public string texte { get; set; }
    }
    public class SANA_API
    {
        public SANA_API() { }

        public SANA_API(string Mnémonique, string Adresse, int Index)
        {
            this.SANA = "IF AOM_AO[" + Index + "] = 0 THEN " + Adresse + " := " + Mnémonique + "; ELSE " + Adresse + " := A_MODIFIER[" + Index + "]; END_IF;" + "\n";
        }
        public string SANA { get; set; }
        public string Mnémonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
    }

Mon fichier de sortie ressemble à ça:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<STExchangeFile>
	<fileHeader company="Schneider Automation" product="Control Expert V14.1 - 191122A" dateTime="date_and_time#2022-11-12-8:51:59" content="Fichier source ST" DTDVersion="41"></fileHeader>
	<contentHeader name="Projet" version="0.0.533" dateTime="date_and_time#2022-7-1-15:22:18"></contentHeader>
	<program>
		<identProgram name="Copie_E_S" type="section" task="MAST"></identProgram>
		<STSource>(*Copies des entrees ANA depuis le Wago *)
EA_LT_Forage1		:=	Ilo_Wago_IN_AI_C1_V1	;
EA_LT_Forage2		:=	Ilo_Wago_IN_AI_C1_V2	;
EA_LT_Forage3		:=	Ilo_Wago_IN_AI_C1_V3	;
EA_FT_Lavage		:=	Ilo_Wago_IN_AI_C1_V4	;
EA_LT_Stockage		:=	Ilo_Wago_IN_AI_C1_V5	;
EA_AI_Chlore		:=	Ilo_Wago_IN_AI_C1_V6	;
EA_AI_pH		:=	Ilo_Wago_IN_AI_C1_V7	;
EA_PT_PmpRprise1	:=	Ilo_Wago_IN_AI_C1_V8	;
EA_PT_PmpRprise2	:=	Ilo_Wago_IN_AI_C2_V1	;
EA_FT_EauTraitee	:=	Ilo_Wago_IN_AI_C2_V2	;
EA_AI2_V3		:=	Ilo_Wago_IN_AI_C2_V3	;
EA_AI2_V4		:=	Ilo_Wago_IN_AI_C2_V4	;
EA_AI2_V5		:=	Ilo_Wago_IN_AI_C2_V5	;
EA_AI2_V6		:=	Ilo_Wago_IN_AI_C2_V6	;
EA_AI2_V7		:=	Ilo_Wago_IN_AI_C2_V7	;
EA_AI2_V8		:=	Ilo_Wago_IN_AI_C2_V8	;

(*Copies des entrees TOR depuis le Wago*)
CPE_BP_Klaxon		:=(Ilo_Wago_IN_DI_C1.0	AND 	AOM_I[0]=	0)	OR	AOM_I[0]=1;
CPE_CM3_AirOK		:=(Ilo_Wago_IN_DI_C1.1	AND	AOM_I[1]=	0)	OR	AOM_I[1]=1;
CPE_RM_Forg1		:=(Ilo_Wago_IN_DI_C1.2	AND	AOM_I[2]=	0)	OR	AOM_I[2]=1;
CPE_DEF_Forg1		:=(Ilo_Wago_IN_DI_C1.3	AND	AOM_I[3]=	0)	OR	AOM_I[3]=1;
CPE_RM_Forg2		:=(Ilo_Wago_IN_DI_C1.4	AND	AOM_I[4]=	0)	OR	AOM_I[4]=1;
CPE_DEF_Forg2		:=(Ilo_Wago_IN_DI_C1.5	AND	AOM_I[5]=	0)	OR	AOM_I[5]=1;
CPE_RM_Forg3		:=(Ilo_Wago_IN_DI_C1.6	AND	AOM_I[6]=	0)	OR	AOM_I[6]=1;
CPE_DEF_Forg3		:=(Ilo_Wago_IN_DI_C1.7	AND	AOM_I[7]=	0)	OR	AOM_I[7]=1;
CPE_RM_PmpPurg		:=(Ilo_Wago_IN_DI_C1.8	AND	AOM_I[8]=	0)	OR	AOM_I[8]=1;
CPE_DEF_PmpPurg		:=(Ilo_Wago_IN_DI_C1.9	AND	AOM_I[9]=	0)	OR	AOM_I[9]=1;
CPE_LSH_EauPurg		:=(Ilo_Wago_IN_DI_C1.10	AND	AOM_I[10]=	0)	OR	AOM_I[10]=1;
CPE_CPT_EauBrute	:=(Ilo_Wago_IN_DI_C1.11	AND	AOM_I[11]=	0)	OR	AOM_I[11]=1;
CPE_CM1_EauBrute	:=(Ilo_Wago_IN_DI_C1.12	AND	AOM_I[12]=	0)	OR	AOM_I[12]=1;
CPE_RM_SouflAir		:=(Ilo_Wago_IN_DI_C1.13	AND	AOM_I[13]=	0)	OR	AOM_I[13]=1;
CPE_DEF_SouflAir	:=(Ilo_Wago_IN_DI_C1.14	AND	AOM_I[14]=	0)	OR	AOM_I[14]=1;
CPE_RM_PmpLavg		:=(Ilo_Wago_IN_DI_C1.15	AND	AOM_I[15]=	0)	OR	AOM_I[15]=1;
CPE_DEF_PmpLavg		:=(Ilo_Wago_IN_DI_C2.0	AND	AOM_I[16]=	0)	OR	AOM_I[16]=1;
CPE_CM2_EauLavg		:=(Ilo_Wago_IN_DI_C2.1	AND	AOM_I[17]=	0)	OR	AOM_I[17]=1;
CPE_D2_EauLavg		:=(Ilo_Wago_IN_DI_C2.2	AND	AOM_I[18]=	0)	OR	AOM_I[18]=1;
CPE_PosOuvP00		:=(Ilo_Wago_IN_DI_C2.3	AND	AOM_I[19]=	0)	OR	AOM_I[19]=1;
CPE_PosFermP00		:=(Ilo_Wago_IN_DI_C2.4	AND	AOM_I[20]=	0)	OR	AOM_I[20]=1;
CPE_PosOuvP01		:=(Ilo_Wago_IN_DI_C2.5	AND	AOM_I[21]=	0)	OR	AOM_I[21]=1;
CPE_PosFermP01		:=(Ilo_Wago_IN_DI_C2.6	AND	AOM_I[22]=	0)	OR	AOM_I[22]=1;
CPE_PosOuvP02		:=(Ilo_Wago_IN_DI_C2.7	AND	AOM_I[23]=	0)	OR	AOM_I[23]=1;
CPE_PosFermP02		:=(Ilo_Wago_IN_DI_C2.8	AND	AOM_I[24]=	0)	OR	AOM_I[24]=1;
CPE_PosOuvEV0		:=(Ilo_Wago_IN_DI_C2.9	AND	AOM_I[25]=	0)	OR	AOM_I[25]=1;
CPE_PosFermEV0		:=(Ilo_Wago_IN_DI_C2.10	AND	AOM_I[26]=	0)	OR	AOM_I[26]=1;
CPE_PosOuvP10		:=(Ilo_Wago_IN_DI_C2.11	AND	AOM_I[27]=	0)	OR	AOM_I[27]=1;
CPE_PosFermP10		:=(Ilo_Wago_IN_DI_C2.12	AND	AOM_I[28]=	0)	OR	AOM_I[28]=1;
CPE_PosOuvP11		:=(Ilo_Wago_IN_DI_C2.13	AND	AOM_I[29]=	0)	OR	AOM_I[29]=1;
CPE_PosFermP11		:=(Ilo_Wago_IN_DI_C2.14	AND	AOM_I[30]=	0)	OR	AOM_I[30]=1;
CPE_PosOuvP12		:=(Ilo_Wago_IN_DI_C2.15	AND	AOM_I[31]=	0)	OR	AOM_I[31]=1;
CPE_PosFermP12		:=(Ilo_Wago_IN_DI_C3.0	AND	AOM_I[32]=	0)	OR	AOM_I[32]=1;
CPE_PosOuvP13		:=(Ilo_Wago_IN_DI_C3.1	AND	AOM_I[33]=	0)	OR	AOM_I[33]=1;
CPE_PosFermP13		:=(Ilo_Wago_IN_DI_C3.2	AND	AOM_I[34]=	0)	OR	AOM_I[34]=1;
CPE_PosOuvEV1		:=(Ilo_Wago_IN_DI_C3.3	AND	AOM_I[35]=	0)	OR	AOM_I[35]=1;
CPE_PosFermEV1		:=(Ilo_Wago_IN_DI_C3.4	AND	AOM_I[36]=	0)	OR	AOM_I[36]=1;
CPE_PosOuvP20		:=(Ilo_Wago_IN_DI_C3.5	AND	AOM_I[37]=	0)	OR	AOM_I[37]=1;
CPE_PosFermP20		:=(Ilo_Wago_IN_DI_C3.6	AND	AOM_I[38]=	0)	OR	AOM_I[38]=1;
CPE_PosOuvP21		:=(Ilo_Wago_IN_DI_C3.7	AND	AOM_I[39]=	0)	OR	AOM_I[39]=1;
CPE_PosFermP21		:=(Ilo_Wago_IN_DI_C3.8	AND	AOM_I[40]=	0)	OR	AOM_I[40]=1;
CPE_PosOuvP22		:=(Ilo_Wago_IN_DI_C3.9	AND	AOM_I[41]=	0)	OR	AOM_I[41]=1;
CPE_PosFermP22		:=(Ilo_Wago_IN_DI_C3.10	AND	AOM_I[42]=	0)	OR	AOM_I[42]=1;
CPE_PosOuvP23		:=(Ilo_Wago_IN_DI_C3.11	AND	AOM_I[43]=	0)	OR	AOM_I[43]=1;
CPE_PosFermP23		:=(Ilo_Wago_IN_DI_C3.12	AND	AOM_I[44]=	0)	OR	AOM_I[44]=1;
CPE_PosOuvEV2		:=(Ilo_Wago_IN_DI_C3.13	AND	AOM_I[45]=	0)	OR	AOM_I[45]=1;
CPE_PosFermEV2		:=(Ilo_Wago_IN_DI_C3.14	AND	AOM_I[46]=	0)	OR	AOM_I[46]=1;
CPE_PosOuvP30		:=(Ilo_Wago_IN_DI_C3.15	AND	AOM_I[47]=	0)	OR	AOM_I[47]=1;
CPE_PosFermP30		:=(Ilo_Wago_IN_DI_C4.0	AND	AOM_I[48]=	0)	OR	AOM_I[48]=1;
CPE_PosOuvP31		:=(Ilo_Wago_IN_DI_C4.1	AND	AOM_I[49]=	0)	OR	AOM_I[49]=1;
CPE_PosFermP31		:=(Ilo_Wago_IN_DI_C4.2	AND	AOM_I[50]=	0)	OR	AOM_I[50]=1;
CPE_PosOuvP32		:=(Ilo_Wago_IN_DI_C4.3	AND	AOM_I[51]=	0)	OR	AOM_I[51]=1;
CPE_PosFermP32		:=(Ilo_Wago_IN_DI_C4.4	AND	AOM_I[52]=	0)	OR	AOM_I[52]=1;
CPE_PosOuvP33		:=(Ilo_Wago_IN_DI_C4.5	AND	AOM_I[53]=	0)	OR	AOM_I[53]=1;
CPE_PosFermP33		:=(Ilo_Wago_IN_DI_C4.6	AND	AOM_I[54]=	0)	OR	AOM_I[54]=1;
CPE_PosOuvEV3		:=(Ilo_Wago_IN_DI_C4.7	AND	AOM_I[55]=	0)	OR	AOM_I[55]=1;
CPE_PosFermEV3		:=(Ilo_Wago_IN_DI_C4.8	AND	AOM_I[56]=	0)	OR	AOM_I[56]=1;
CPE_PosOuvP40		:=(Ilo_Wago_IN_DI_C4.9	AND	AOM_I[57]=	0)	OR	AOM_I[57]=1;
CPE_PosFermP40		:=(Ilo_Wago_IN_DI_C4.10	AND	AOM_I[58]=	0)	OR	AOM_I[58]=1;
CPE_PosOuvP41		:=(Ilo_Wago_IN_DI_C4.11	AND	AOM_I[59]=	0)	OR	AOM_I[59]=1;
CPE_PosFermP41		:=(Ilo_Wago_IN_DI_C4.12	AND	AOM_I[60]=	0)	OR	AOM_I[60]=1;
CPE_PosOuvP42		:=(Ilo_Wago_IN_DI_C4.13	AND	AOM_I[61]=	0)	OR	AOM_I[61]=1;
CPE_PosFermP42		:=(Ilo_Wago_IN_DI_C4.14	AND	AOM_I[62]=	0)	OR	AOM_I[62]=1;
CPE_PosOuvP43		:=(Ilo_Wago_IN_DI_C4.15	AND	AOM_I[63]=	0)	OR	AOM_I[63]=1;
CPE_PosFermP43		:=(Ilo_Wago_IN_DI_C5.0	AND	AOM_I[64]=	0)	OR	AOM_I[64]=1;
CPE_PosOuvEV4		:=(Ilo_Wago_IN_DI_C5.1	AND	AOM_I[65]=	0)	OR	AOM_I[65]=1;
CPE_PosFermEV4		:=(Ilo_Wago_IN_DI_C5.2	AND	AOM_I[66]=	0)	OR	AOM_I[66]=1;
CPE_PosOuvP50		:=(Ilo_Wago_IN_DI_C5.3	AND	AOM_I[67]=	0)	OR	AOM_I[67]=1;
CPE_PosFermP50		:=(Ilo_Wago_IN_DI_C5.4	AND	AOM_I[68]=	0)	OR	AOM_I[68]=1;
CPE_PosOuvP51		:=(Ilo_Wago_IN_DI_C5.5	AND	AOM_I[69]=	0)	OR	AOM_I[69]=1;
CPE_PosFermP51		:=(Ilo_Wago_IN_DI_C5.6	AND	AOM_I[70]=	0)	OR	AOM_I[70]=1;
CPE_PosOuvP52		:=(Ilo_Wago_IN_DI_C5.7	AND	AOM_I[71]=	0)	OR	AOM_I[71]=1;
CPE_PosFermP52		:=(Ilo_Wago_IN_DI_C5.8	AND	AOM_I[72]=	0)	OR	AOM_I[72]=1;
CPE_PosOuvP53		:=(Ilo_Wago_IN_DI_C5.9	AND	AOM_I[73]=	0)	OR	AOM_I[73]=1;
CPE_PosFermP53		:=(Ilo_Wago_IN_DI_C5.10	AND	AOM_I[74]=	0)	OR	AOM_I[74]=1;
CPE_PosOuvEV5		:=(Ilo_Wago_IN_DI_C5.11	AND	AOM_I[75]=	0)	OR	AOM_I[75]=1;
CPE_PosFermEV5		:=(Ilo_Wago_IN_DI_C5.12	AND	AOM_I[76]=	0)	OR	AOM_I[76]=1;
CPE_PosOuvP1		:=(Ilo_Wago_IN_DI_C5.13	AND	AOM_I[77]=	0)	OR	AOM_I[77]=1;
CPE_PosFermP1		:=(Ilo_Wago_IN_DI_C5.14	AND	AOM_I[78]=	0)	OR	AOM_I[78]=1;
CPE_PosOuvP2		:=(Ilo_Wago_IN_DI_C5.15	AND	AOM_I[79]=	0)	OR	AOM_I[79]=1;
CPE_PosFermP2		:=(Ilo_Wago_IN_DI_C6.0	AND	AOM_I[80]=	0)	OR	AOM_I[80]=1;
CPE_PulsAnalyseur	:=(Ilo_Wago_IN_DI_C6.1	AND	AOM_I[81]=	0)	OR	AOM_I[81]=1;
CPE_DefAnalyseur	:=(Ilo_Wago_IN_DI_C6.2	AND	AOM_I[82]=	0)	OR	AOM_I[82]=1;
CPE_RM_PmpReprs1	:=(Ilo_Wago_IN_DI_C6.3	AND	AOM_I[83]=	0)	OR	AOM_I[83]=1;
CPE_DEF_PmpReprs1	:=(Ilo_Wago_IN_DI_C6.4	AND	AOM_I[84]=	0)	OR	AOM_I[84]=1;
CPE_RM_PmpReprs2	:=(Ilo_Wago_IN_DI_C6.5	AND	AOM_I[85]=	0)	OR	AOM_I[85]=1;
CPE_DEF_PmpReprs2	:=(Ilo_Wago_IN_DI_C6.6	AND	AOM_I[86]=	0)	OR	AOM_I[86]=1;
CPE_D1_EauTrait		:=(Ilo_Wago_IN_DI_C6.7	AND	AOM_I[87]=	0)	OR	AOM_I[87]=1;
CPE_RM_PmpChlor		:=(Ilo_Wago_IN_DI_C6.8	AND	AOM_I[88]=	0)	OR	AOM_I[88]=1;
CPE_DEF_PmpChlor	:=(Ilo_Wago_IN_DI_C6.9	AND	AOM_I[89]=	0)	OR	AOM_I[89]=1;
DI_C6.10	:=(Ilo_Wago_IN_DI_C6.10	AND	AOM_I[90]=	0)	OR	AOM_I[90]=1;
DI_C6.11	:=(Ilo_Wago_IN_DI_C6.11	AND	AOM_I[91]=	0)	OR	AOM_I[91]=1;
DI_C6.12	:=(Ilo_Wago_IN_DI_C6.12	AND	AOM_I[92]=	0)	OR	AOM_I[92]=1;
DI_C6.13	:=(Ilo_Wago_IN_DI_C6.13	AND	AOM_I[93]=	0)	OR	AOM_I[93]=1;
DI_C6.14	:=(Ilo_Wago_IN_DI_C6.14	AND	AOM_I[94]=	0)	OR	AOM_I[94]=1;
DI_C6.15	:=(Ilo_Wago_IN_DI_C6.15	AND	AOM_I[95]=	0)	OR	AOM_I[95]=1;
DI_C7.0		:=(Ilo_Wago_IN_DI_C7.0	AND	AOM_I[96]=	0)	OR	AOM_I[96]=1;
DI_C7.1		:=(Ilo_Wago_IN_DI_C7.1	AND	AOM_I[97]=	0)	OR	AOM_I[97]=1;
DI_C7.2		:=(Ilo_Wago_IN_DI_C7.2	AND	AOM_I[98]=	0)	OR	AOM_I[98]=1;
DI_C7.3		:=(Ilo_Wago_IN_DI_C7.3	AND	AOM_I[99]=	0)	OR	AOM_I[99]=1;
DI_C7.4		:=(Ilo_Wago_IN_DI_C7.4	AND	AOM_I[100]=	0)	OR	AOM_I[100]=1;
DI_C7.5		:=(Ilo_Wago_IN_DI_C7.5	AND	AOM_I[101]=	0)	OR	AOM_I[101]=1;
DI_C7.6		:=(Ilo_Wago_IN_DI_C7.6	AND	AOM_I[102]=	0)	OR	AOM_I[102]=1;
DI_C7.7		:=(Ilo_Wago_IN_DI_C7.7	AND	AOM_I[103]=	0)	OR	AOM_I[103]=1;
DI_C7.8		:=(Ilo_Wago_IN_DI_C7.8	AND	AOM_I[104]=	0)	OR	AOM_I[104]=1;
DI_C7.9		:=(Ilo_Wago_IN_DI_C7.9	AND	AOM_I[105]=	0)	OR	AOM_I[105]=1;
DI_C7.10	:=(Ilo_Wago_IN_DI_C7.10	AND	AOM_I[106]=	0)	OR	AOM_I[106]=1;
DI_C7.11	:=(Ilo_Wago_IN_DI_C7.11	AND	AOM_I[107]=	0)	OR	AOM_I[107]=1;
DI_C7.12	:=(Ilo_Wago_IN_DI_C7.12	AND	AOM_I[108]=	0)	OR	AOM_I[108]=1;
DI_C7.13	:=(Ilo_Wago_IN_DI_C7.13	AND	AOM_I[109]=	0)	OR	AOM_I[109]=1;
DI_C7.14	:=(Ilo_Wago_IN_DI_C7.14	AND	AOM_I[110]=	0)	OR	AOM_I[110]=1;
DI_C7.15	:=(Ilo_Wago_IN_DI_C7.15	AND	AOM_I[111]=	0)	OR	AOM_I[111]=1;

(*Copies des sorties TOR dans le Wago*)
Ilo_Wago_OUT_DO_C1.0	:=(CPS_Alarme		AND 	AOM_O[0]=	0)	OR	AOM_O[0]=1;
Ilo_Wago_OUT_DO_C1.1	:=(CPS_Klaxon		AND	AOM_O[1]=	0)	OR	AOM_O[1]=1;
Ilo_Wago_OUT_DO_C1.2	:=(CPS_Gyrophare	AND	AOM_O[2]=	0)	OR	AOM_O[2]=1;
Ilo_Wago_OUT_DO_C1.3	:=(CPS_Cmd_Forg1	AND	AOM_O[3]=	0)	OR	AOM_O[3]=1;
Ilo_Wago_OUT_DO_C1.4	:=(CPS_Autors_Forg1	AND	AOM_O[4]=	0)	OR	AOM_O[4]=1;
Ilo_Wago_OUT_DO_C1.5	:=(CPS_Cmd_Forg2	AND	AOM_O[5]=	0)	OR	AOM_O[5]=1;
Ilo_Wago_OUT_DO_C1.6	:=(CPS_Autors_Forg2	AND	AOM_O[6]=	0)	OR	AOM_O[6]=1;
Ilo_Wago_OUT_DO_C1.7	:=(CPS_Cmd_Forg3	AND	AOM_O[7]=	0)	OR	AOM_O[7]=1;
Ilo_Wago_OUT_DO_C1.8	:=(CPS_Autors_Forg3	AND	AOM_O[8]=	0)	OR	AOM_O[8]=1;
Ilo_Wago_OUT_DO_C1.9	:=(CPS_Cmd_PmpPurg	AND	AOM_O[9]=	0)	OR	AOM_O[9]=1;
Ilo_Wago_OUT_DO_C1.10	:=(CPS_Cmd_EV10		AND	AOM_O[10]=	0)	OR	AOM_O[10]=1;
Ilo_Wago_OUT_DO_C1.11	:=(CPS_Cmd_SouflAir	AND	AOM_O[11]=	0)	OR	AOM_O[11]=1;
Ilo_Wago_OUT_DO_C1.12	:=(CPS_Cmd_PmpLavg	AND	AOM_O[12]=	0)	OR	AOM_O[12]=1;
Ilo_Wago_OUT_DO_C1.13	:=(CPS_Cmd_P00		AND	AOM_O[13]=	0)	OR	AOM_O[13]=1;
Ilo_Wago_OUT_DO_C1.14	:=(CPS_Cmd_P01		AND	AOM_O[14]=	0)	OR	AOM_O[14]=1;
Ilo_Wago_OUT_DO_C1.15	:=(CPS_Cmd_P02		AND	AOM_O[15]=	0)	OR	AOM_O[15]=1;
Ilo_Wago_OUT_DO_C2.0	:=(CPS_Cmd_EV0		AND	AOM_O[16]=	0)	OR	AOM_O[16]=1;
Ilo_Wago_OUT_DO_C2.1	:=(CPS_Cmd_P10		AND	AOM_O[17]=	0)	OR	AOM_O[17]=1;
Ilo_Wago_OUT_DO_C2.2	:=(CPS_Cmd_P11		AND	AOM_O[18]=	0)	OR	AOM_O[18]=1;
Ilo_Wago_OUT_DO_C2.3	:=(CPS_Cmd_P12		AND	AOM_O[19]=	0)	OR	AOM_O[19]=1;
Ilo_Wago_OUT_DO_C2.4	:=(CPS_Cmd_P13		AND	AOM_O[20]=	0)	OR	AOM_O[20]=1;
Ilo_Wago_OUT_DO_C2.5	:=(CPS_Cmd_EV1		AND	AOM_O[21]=	0)	OR	AOM_O[21]=1;
Ilo_Wago_OUT_DO_C2.6	:=(CPS_Cmd_P20		AND	AOM_O[22]=	0)	OR	AOM_O[22]=1;
Ilo_Wago_OUT_DO_C2.7	:=(CPS_Cmd_P21		AND	AOM_O[23]=	0)	OR	AOM_O[23]=1;
Ilo_Wago_OUT_DO_C2.8	:=(CPS_Cmd_P22		AND	AOM_O[24]=	0)	OR	AOM_O[24]=1;
Ilo_Wago_OUT_DO_C2.9	:=(CPS_Cmd_P23		AND	AOM_O[25]=	0)	OR	AOM_O[25]=1;
Ilo_Wago_OUT_DO_C2.10	:=(CPS_Cmd_EV2		AND	AOM_O[26]=	0)	OR	AOM_O[26]=1;
Ilo_Wago_OUT_DO_C2.11	:=(CPS_Cmd_EV11		AND	AOM_O[27]=	0)	OR	AOM_O[27]=1;
Ilo_Wago_OUT_DO_C2.12	:=(CPS_Cmd_P30		AND	AOM_O[28]=	0)	OR	AOM_O[28]=1;
Ilo_Wago_OUT_DO_C2.13	:=(CPS_Cmd_P31		AND	AOM_O[29]=	0)	OR	AOM_O[29]=1;
Ilo_Wago_OUT_DO_C2.14	:=(CPS_Cmd_P32		AND	AOM_O[30]=	0)	OR	AOM_O[30]=1;
Ilo_Wago_OUT_DO_C2.15	:=(CPS_Cmd_P33		AND	AOM_O[31]=	0)	OR	AOM_O[31]=1;
Ilo_Wago_OUT_DO_C3.0	:=(CPS_Cmd_EV3		AND	AOM_O[32]=	0)	OR	AOM_O[32]=1;
Ilo_Wago_OUT_DO_C3.1	:=(CPS_Cmd_P40		AND	AOM_O[33]=	0)	OR	AOM_O[33]=1;
Ilo_Wago_OUT_DO_C3.2	:=(CPS_Cmd_P41		AND	AOM_O[34]=	0)	OR	AOM_O[34]=1;
Ilo_Wago_OUT_DO_C3.3	:=(CPS_Cmd_P42		AND	AOM_O[35]=	0)	OR	AOM_O[35]=1;
Ilo_Wago_OUT_DO_C3.4	:=(CPS_Cmd_P43		AND	AOM_O[36]=	0)	OR	AOM_O[36]=1;
Ilo_Wago_OUT_DO_C3.5	:=(CPS_Cmd_EV4		AND	AOM_O[37]=	0)	OR	AOM_O[37]=1;
Ilo_Wago_OUT_DO_C3.6	:=(CPS_Cmd_P50		AND	AOM_O[38]=	0)	OR	AOM_O[38]=1;
Ilo_Wago_OUT_DO_C3.7	:=(CPS_Cmd_P51		AND	AOM_O[39]=	0)	OR	AOM_O[39]=1;
Ilo_Wago_OUT_DO_C3.8	:=(CPS_Cmd_P52		AND	AOM_O[40]=	0)	OR	AOM_O[40]=1;
Ilo_Wago_OUT_DO_C3.9	:=(CPS_Cmd_P53		AND	AOM_O[41]=	0)	OR	AOM_O[41]=1;
Ilo_Wago_OUT_DO_C3.10	:=(CPS_Cmd_EV5		AND	AOM_O[42]=	0)	OR	AOM_O[42]=1;
Ilo_Wago_OUT_DO_C3.11	:=(CPS_LSB_Stockg	AND	AOM_O[43]=	0)	OR	AOM_O[43]=1;
Ilo_Wago_OUT_DO_C3.12	:=(CPS_LSH_Stockg	AND	AOM_O[44]=	0)	OR	AOM_O[44]=1;
Ilo_Wago_OUT_DO_C3.13	:=(CPS_Cmd_P1		AND	AOM_O[45]=	0)	OR	AOM_O[45]=1;
Ilo_Wago_OUT_DO_C3.14	:=(CPS_Cmd_P2		AND	AOM_O[46]=	0)	OR	AOM_O[46]=1;
Ilo_Wago_OUT_DO_C3.15	:=(CPS_Cmd_Analyseur	AND	AOM_O[47]=	0)	OR	AOM_O[47]=1;
Ilo_Wago_OUT_DO_C4.0	:=(CPS_Cmd_V_CH1	AND	AOM_O[48]=	0)	OR	AOM_O[48]=1;
Ilo_Wago_OUT_DO_C4.1	:=(CPS_Cmd_V_CH2	AND	AOM_O[49]=	0)	OR	AOM_O[49]=1;
Ilo_Wago_OUT_DO_C4.2	:=(CPS_Cmd_PmpChlor	AND	AOM_O[50]=	0)	OR	AOM_O[50]=1;
Ilo_Wago_OUT_DO_C4.3	:=(DO_C4.3	AND	AOM_O[51]=	0)	OR	AOM_O[51]=1;
Ilo_Wago_OUT_DO_C4.4	:=(DO_C4.4	AND	AOM_O[52]=	0)	OR	AOM_O[52]=1;
Ilo_Wago_OUT_DO_C4.5	:=(DO_C4.5	AND	AOM_O[53]=	0)	OR	AOM_O[53]=1;
Ilo_Wago_OUT_DO_C4.6	:=(DO_C4.6	AND	AOM_O[54]=	0)	OR	AOM_O[54]=1;
Ilo_Wago_OUT_DO_C4.7	:=(DO_C4.7	AND	AOM_O[55]=	0)	OR	AOM_O[55]=1;
Ilo_Wago_OUT_DO_C4.8	:=(DO_C4.8	AND	AOM_O[56]=	0)	OR	AOM_O[56]=1;
Ilo_Wago_OUT_DO_C4.9	:=(DO_C4.9	AND	AOM_O[57]=	0)	OR	AOM_O[57]=1;
Ilo_Wago_OUT_DO_C4.10	:=(DO_C4.10	AND	AOM_O[58]=	0)	OR	AOM_O[58]=1;
Ilo_Wago_OUT_DO_C4.11	:=(DO_C4.11	AND	AOM_O[59]=	0)	OR	AOM_O[59]=1;
Ilo_Wago_OUT_DO_C4.12	:=(DO_C4.12	AND	AOM_O[60]=	0)	OR	AOM_O[60]=1;
Ilo_Wago_OUT_DO_C4.13	:=(DO_C4.13	AND	AOM_O[61]=	0)	OR	AOM_O[61]=1;
Ilo_Wago_OUT_DO_C4.14	:=(DO_C4.14	AND	AOM_O[62]=	0)	OR	AOM_O[62]=1;
Ilo_Wago_OUT_DO_C4.15	:=(DO_C4.15	AND	AOM_O[63]=	0)	OR	AOM_O[63]=1;



</STSource>
	</program>
	<dataBlock>
		<variables name="Ilo_Wago_IN_AI_C1_V8" typeName="INT" topologicalAddress="%MW3023"></variables>
		<variables name="CPS_Cmd_PmpPurg" typeName="BOOL" topologicalAddress="%MW303.0">
			<comment>ORDRE MARCHE - POMPE REPRISE EAU DE PURGE</comment>
		</variables>
		<variables name="CPE_PosFermP43" typeName="BOOL" topologicalAddress="%MW331.2">
			<comment>POSITION FERMEE - VANNE P43</comment>
		</variables>
		<variables name="CPE_PosOuvEV1" typeName="BOOL" topologicalAddress="%MW317.1">
			<comment>POSITION OUVERTE - VANNE EV1</comment>
		</variables>
		<variables name="CPE_PosOuvP23" typeName="BOOL" topologicalAddress="%MW321.1">
			<comment>POSITION OUVERTE - VANNE P23</comment>
		</variables>
		<variables name="Ilo_Wago_IN_DI_C2" typeName="WORD" topologicalAddress="%MW3033"></variables>
		<variables name="CPS_Cmd_EV3" typeName="BOOL" topologicalAddress="%MW327.0">
			<comment>OUVERTURE - VANNE EV3</comment>
		</variables>
		<variables name="EA_LT_Forage2" typeName="INT"></variables>
		<variables name="CPE_PosFermP22" typeName="BOOL" topologicalAddress="%MW320.2">
			<comment>POSITION FERMEE - VANNE P22</comment>
		</variables>
		<variables name="CPE_PosOuvP52" typeName="BOOL" topologicalAddress="%MW335.1">
			<comment>POSITION OUVERTE - VANNE P52</comment>
		</variables>
		<variables name="CPE_PosFermEV2" typeName="BOOL" topologicalAddress="%MW322.2">
			<comment>POSITION FERMEE - VANNE EV2</comment>
		</variables>
		<variables name="CPE_PosOuvP33" typeName="BOOL" topologicalAddress="%MW326.1">
			<comment>POSITION OUVERTE - VANNE P33</comment>
		</variables>
		<variables name="CPE_PosFermP53" typeName="BOOL" topologicalAddress="%MW336.2">
			<comment>POSITION FERMEE - VANNE P53</comment>
		</variables>
		<variables name="EA_PT_PmpRprise1" typeName="INT"></variables>
		<variables name="Ilo_Wago_IN_AI_C2_V4" typeName="INT" topologicalAddress="%MW3027"></variables>
		<variables name="CPE_PosFermP2" typeName="BOOL" topologicalAddress="%MW340.2">
			<comment>POSITION FERMEE - VANNE P2</comment>
		</variables>
		<variables name="CPE_D1_EauTrait" typeName="BOOL">
			<comment>IMPULSIONS DEBITMETRE D1 - EAU TRAITEE</comment>
		</variables>
		<variables name="CPE_RM_Forg2" typeName="BOOL" topologicalAddress="%MW301.3">
			<comment>RETOUR MARCHE - POMPE FORAGE 2</comment>
		</variables>
		<variables name="CPE_PulsAnalyseur" typeName="BOOL">
			<comment>RETOUR TOP DOSAGE - ANALYSEUR CHLORE + PH</comment>
		</variables>
		<variables name="CPE_PosFermP12" typeName="BOOL" topologicalAddress="%MW315.2">
			<comment>POSITION FERMEE - VANNE P12</comment>
		</variables>
		<variables name="CPS_Cmd_EV11" typeName="BOOL" topologicalAddress="%MW338.0">
			<comment>ELECTROVANNE EV11 - AIR OXYDATION</comment>
		</variables>
		<variables name="EA_AI2_V7" typeName="INT"></variables>
		<variables name="CPS_Cmd_P32" typeName="BOOL" topologicalAddress="%MW325.0">
			<comment>OUVERTURE - VANNE P32</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C1_V3" typeName="INT" topologicalAddress="%MW3018"></variables>
		<variables name="CPE_PosOuvP1" typeName="BOOL" topologicalAddress="%MW339.1">
			<comment>POSITION OUVERTE - VANNE P1</comment>
		</variables>
		<variables name="CPS_Cmd_PmpChlor" typeName="BOOL" topologicalAddress="%MW343.0"></variables>
		<variables name="Ilo_Wago_IN_DI_C3" typeName="WORD" topologicalAddress="%MW3034"></variables>
		<variables name="CPE_PosOuvEV0" typeName="BOOL" topologicalAddress="%MW312.1">
			<comment>POSITION OUVERTE - VANNE PEV0</comment>
		</variables>
		<variables name="CPE_PosOuvP20" typeName="BOOL" topologicalAddress="%MW318.1">
			<comment>POSITION OUVERTE - VANNE P20</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C2_V5" typeName="INT" topologicalAddress="%MW3028"></variables>
		<variables name="CPE_PosFermEV1" typeName="BOOL" topologicalAddress="%MW317.2">
			<comment>POSITION FERMEE - VANNE EV1</comment>
		</variables>
		<variables name="CPE_CM2_EauLavg" typeName="BOOL">
			<comment>CONTACTEUR MANOMETRIQUE CM2 - SECURITE SURPESSION</comment>
		</variables>
		<variables name="CPS_Cmd_P2" typeName="BOOL" topologicalAddress="%MW340.0">
			<comment>OUVERTURE - VANNE P2</comment>
		</variables>
		<variables name="CPE_PosFermP23" typeName="BOOL" topologicalAddress="%MW321.2">
			<comment>POSITION FERMEE - VANNE P23</comment>
		</variables>
		<variables name="CPE_PosFermP52" typeName="BOOL" topologicalAddress="%MW335.2">
			<comment>POSITION FERMEE - VANNE P52</comment>
		</variables>
		<variables name="CPS_Cmd_P33" typeName="BOOL" topologicalAddress="%MW326.0">
			<comment>OUVERTURE - VANNE P33</comment>
		</variables>
		<variables name="CPS_Cmd_EV4" typeName="BOOL" topologicalAddress="%MW332.0">
			<comment>OUVERTURE - VANNE EV4</comment>
		</variables>
		<variables name="CPS_Gyrophare" typeName="BOOL">
			<comment>GYROPHARE</comment>
		</variables>
		<variables name="CPE_PosOuvP32" typeName="BOOL" topologicalAddress="%MW325.1">
			<comment>POSITION OUVERTE - VANNE P32</comment>
		</variables>
		<variables name="CPE_RM_Forg3" typeName="BOOL" topologicalAddress="%MW302.3">
			<comment>RETOUR MARCHE - POMPE FORAGE 3</comment>
		</variables>
		<variables name="CPS_Cmd_P21" typeName="BOOL" topologicalAddress="%MW319.0">
			<comment>OUVERTURE - VANNE P21</comment>
		</variables>
		<variables name="EA_AI2_V6" typeName="INT"></variables>
		<variables name="CPS_Cmd_EV10" typeName="BOOL" topologicalAddress="%MW308.0">
			<comment>ELECTROVANNE EV10 - AIR OXYDATION</comment>
		</variables>
		<variables name="CPE_PosFermP33" typeName="BOOL" topologicalAddress="%MW326.2">
			<comment>POSITION FERMEE - VANNE P33</comment>
		</variables>
		<variables name="CPE_PosFermP32" typeName="BOOL" topologicalAddress="%MW325.2">
			<comment>POSITION FERMEE - VANNE P32</comment>
		</variables>
		<variables name="EA_FT_Lavage" typeName="INT"></variables>
		<variables name="CPE_DEF_Forg1" typeName="BOOL">
			<comment>DEFAUT - POMPE FORAGE 1</comment>
		</variables>
		<variables name="CPS_Cmd_P12" typeName="BOOL" topologicalAddress="%MW315.0">
			<comment>OUVERTURE - VANNE P12</comment>
		</variables>
		<variables name="CPE_PosOuvP2" typeName="BOOL" topologicalAddress="%MW340.1">
			<comment>POSITION OUVERTE - VANNE P2</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C1_V2" typeName="INT" topologicalAddress="%MW3017"></variables>
		<variables name="CPS_Cmd_V_CH1" typeName="BOOL" topologicalAddress="%MW341.0">
			<comment>OUVERTURE - VANNE CH1</comment>
		</variables>
		<variables name="AOM_O" typeName="ARRAY[0..100] OF INT" topologicalAddress="%MW2200">
			<comment>Tableau d'AOM forçage sorties</comment>
			<instanceElementDesc name="[0]">
				<comment>Prealarme générale (30KA1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[1]">
				<comment>Alarme générale (30KA2)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[2]">
				<comment>Niveau Eau forage OK (1 = niveau recouvert / Atteint) (36KA1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[3]">
				<comment>S2- Démarrage à distance Tête régul. Adoucisseur n°1 (S2_16REG01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[4]">
				<comment>S2-  démarrage à distance Tête régul. Adoucisseur n°2 (S2_16REG02)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[5]">
				<comment>Consigne pompe doseuse 1 / Javel (puls) (7DP01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[6]">
				<comment>Consigne pompe doseuse 2 / Soude (puls) (7DP02)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[7]">
				<comment>Niveau cuve de stockage ok (1 = niveau recouvert) (61KA1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[8]">
				<comment>DO1_V9</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[9]">
				<comment>DO1_V10</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[10]">
				<comment>DO1_V11</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[11]">
				<comment>DO1_V12</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[12]">
				<comment>DO1_V13</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[13]">
				<comment>DO1_V14</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[14]">
				<comment>DO1_V15</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[15]">
				<comment>DO1_V16</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[16]">
				<comment>Ordre de marche variateur Pompe de forage 1 (35KA1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[17]">
				<comment>S1-signal inhibition Tete régul. adoucisseur n°1 (S1_16REG01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[18]">
				<comment>Ouverture EV P00 eaux brutes  vers dénitratation n°1 (41P00)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[19]">
				<comment>Ouverture EV P02 retour eaux  vers dénitratation n°1 (41P02)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[20]">
				<comment>S1-signal inhibition Tete régul. adoucisseur n°2 (S1_16REG02)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[21]">
				<comment>Ouverture EV P10 eaux brutes vers dénitratation n°2 (43P10)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[22]">
				<comment>Ouverture EV P12 retour eaux traitées vers dénitratation n°2 (43P12)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[23]">
				<comment>Ouverture EV P1 sortie filtre charbon actif vers égoût (45P1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[24]">
				<comment>Ouverture EV P2 sortie filtre charbon actif vers cuve (46P2)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[25]">
				<comment>Ordre de marche pompe doseuse 1 / Javel (7DP01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[26]">
				<comment>Ordre de marche pompe doseuse 2 / Soude (7DP02)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[27]">
				<comment>Ordre de marche thermoplongeur soude (0= arrêt ) (52TH01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[28]">
				<comment>Ordre de marche  pompe de lavage PPL01 (55KM4)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[29]">
				<comment>Ouverture EV P3 appoint eau de ville dans cuve (60P3)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[30]">
				<comment>Ouverture EV P4 retour eau traitée vers cuve (61P4)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[31]">
				<comment>DO2_V16</comment>
			</instanceElementDesc>
		</variables>
		<variables name="CPE_CM1_EauBrute" typeName="BOOL">
			<comment>CONTACTEUR MANOMETRIQUE CM1 - SECURITE SURPESSION</comment>
		</variables>
		<variables name="CPE_PosOuvP21" typeName="BOOL" topologicalAddress="%MW319.1">
			<comment>POSITION OUVERTE - VANNE P21</comment>
		</variables>
		<variables name="CPE_PosFermEV0" typeName="BOOL" topologicalAddress="%MW312.2">
			<comment>POSITION FERMEE - VANNE PEV0</comment>
		</variables>
		<variables name="EA_AI_pH" typeName="INT"></variables>
		<variables name="CPS_Cmd_P1" typeName="BOOL" topologicalAddress="%MW339.0">
			<comment>OUVERTURE - VANNE P1</comment>
		</variables>
		<variables name="CPS_Cmd_P20" typeName="BOOL" topologicalAddress="%MW318.0">
			<comment>OUVERTURE - VANNE P20</comment>
		</variables>
		<variables name="EA_AI_Chlore" typeName="INT"></variables>
		<variables name="Ilo_Wago_IN_AI_C2_V2" typeName="INT" topologicalAddress="%MW3025"></variables>
		<variables name="Ilo_Wago_IN_DI_C4" typeName="WORD" topologicalAddress="%MW3035"></variables>
		<variables name="CPS_Cmd_EV5" typeName="BOOL" topologicalAddress="%MW337.0">
			<comment>OUVERTURE - VANNE EV5</comment>
		</variables>
		<variables name="CPS_Autors_Forg3" typeName="BOOL">
			<comment>SECURITE NIVEAU BAS - FORAGE 3</comment>
		</variables>
		<variables name="CPE_PosOuvP31" typeName="BOOL" topologicalAddress="%MW324.1">
			<comment>POSITION OUVERTE - VANNE P31</comment>
		</variables>
		<variables name="CPE_PosFermP20" typeName="BOOL" topologicalAddress="%MW318.2">
			<comment>POSITION FERMEE - VANNE P20</comment>
		</variables>
		<variables name="CPS_Autors_Forg2" typeName="BOOL">
			<comment>SECURITE NIVEAU BAS - FORAGE 2</comment>
		</variables>
		<variables name="CPE_PosOuvP30" typeName="BOOL" topologicalAddress="%MW323.1">
			<comment>POSITION OUVERTE - VANNE P30</comment>
		</variables>
		<variables name="CPE_PosFermP31" typeName="BOOL" topologicalAddress="%MW324.2">
			<comment>POSITION FERMEE - VANNE P31</comment>
		</variables>
		<variables name="CPS_Cmd_P13" typeName="BOOL" topologicalAddress="%MW316.0">
			<comment>OUVERTURE - VANNE P13</comment>
		</variables>
		<variables name="CPE_PosOuvEV5" typeName="BOOL" topologicalAddress="%MW337.1">
			<comment>POSITION OUVERTE - VANNE EV5</comment>
		</variables>
		<variables name="CPS_LSH_Stockg" typeName="BOOL">
			<comment>NIVEAU HAUT CUVE STOCKAGE</comment>
		</variables>
		<variables name="CPE_DEF_Forg2" typeName="BOOL">
			<comment>DEFAUT - POMPE FORAGE 2</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C1_V5" typeName="INT" topologicalAddress="%MW3020"></variables>
		<variables name="Ilo_Wago_IN_AI_C2_V8" typeName="INT" topologicalAddress="%MW3031"></variables>
		<variables name="Ilo_Wago_IN_DI_C5" typeName="WORD" topologicalAddress="%MW3036"></variables>
		<variables name="CPE_PosFermP21" typeName="BOOL" topologicalAddress="%MW319.2">
			<comment>POSITION FERMEE - VANNE P21</comment>
		</variables>
		<variables name="CPE_DEF_PmpReprs2" typeName="BOOL">
			<comment>DEFAUT - POMPE REPRISE PR2</comment>
		</variables>
		<variables name="CPS_Cmd_P23" typeName="BOOL" topologicalAddress="%MW321.0">
			<comment>OUVERTURE - VANNE P23</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C2_V3" typeName="INT" topologicalAddress="%MW3026"></variables>
		<variables name="CPS_Cmd_P52" typeName="BOOL" topologicalAddress="%MW335.0">
			<comment>OUVERTURE - VANNE P52</comment>
		</variables>
		<variables name="CPS_Alarme" typeName="BOOL">
			<comment>ALARME</comment>
		</variables>
		<variables name="CPS_Cmd_P53" typeName="BOOL" topologicalAddress="%MW336.0">
			<comment>OUVERTURE - VANNE P53</comment>
		</variables>
		<variables name="CPS_Autors_Forg1" typeName="BOOL">
			<comment>SECURITE NIVEAU BAS - FORAGE 1</comment>
		</variables>
		<variables name="CPE_PosFermP30" typeName="BOOL" topologicalAddress="%MW323.2">
			<comment>POSITION FERMEE - VANNE P30</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C1_V4" typeName="INT" topologicalAddress="%MW3019"></variables>
		<variables name="CPS_Cmd_P10" typeName="BOOL" topologicalAddress="%MW313.0">
			<comment>OUVERTURE - VANNE P10</comment>
		</variables>
		<variables name="CPE_PosOuvP00" typeName="BOOL" topologicalAddress="%MW309.1">
			<comment>POSITION OUVERTE - VANNE P00</comment>
		</variables>
		<variables name="CPE_PosOuvP11" typeName="BOOL" topologicalAddress="%MW314.1">
			<comment>POSITION OUVERTE - VANNE P11</comment>
		</variables>
		<variables name="CPE_PosOuvP01" typeName="BOOL" topologicalAddress="%MW310.1">
			<comment>POSITION OUVERTE - VANNE P01</comment>
		</variables>
		<variables name="AOM_I" typeName="ARRAY[0..150] OF INT" topologicalAddress="%MW2000">
			<comment>Tableau d'AOM forçcage entrées</comment>
			<instanceElementDesc name="[0]">
				<comment>Arrêt d'urgence général (0 = AU) (31AU1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[1]">
				<comment>Général auxiliaire 10Q1 disjoncté (0 = Disjonction) (10Q1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[2]">
				<comment>Capteur Manque AIR , (0 = manque air) (32CMF0)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[3]">
				<comment>compteur de cycle BY-PASS (32C1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[4]">
				<comment>compteur de cycle eau de ville (32C2)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[5]">
				<comment>compteur de cycle regénération (32C3)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[6]">
				<comment>retour de marche pompe de forage PPF1 (R1_4VF_PR1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[7]">
				<comment>retour de défaut variateur pompe forage PPF1 (R2_4VF_PR1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[8]">
				<comment>Fonct. en auto. pompe forage ( 1 = AUTO) (Commutateur 35S1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[9]">
				<comment>impulsion débimètre sortie pompe forage (15FIT01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[10]">
				<comment>capteur de surpression pompe forage (0 = surpression) (36CMPPF01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[11]">
				<comment>S3 - signal en service / regénération Tête régul. adoucisseur n°1 (S3_16REG01)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[12]">
				<comment>FDC vanne P00 ouverte (41P00_O1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[13]">
				<comment>FDC vanne P00 fermée (41P00_F1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[14]">
				<comment>FDC vanne P02 ouverte  (41P02_O1)</comment>
			</instanceElementDesc>
			<instanceElementDesc name="[15]">
				<comment>FDC vanne P02 fermée (41P02_F1)</comment>
			</instanceElementDesc>
		</variables>
		<variables name="CPE_DEF_Forg3" typeName="BOOL">
			<comment>DEFAUT - POMPE FORAGE 3</comment>
		</variables>
		<variables name="Ilo_Wago_IN_DI_C6" typeName="WORD" topologicalAddress="%MW3037"></variables>
		<variables name="DI_C6" typeName="WORD"></variables>
		<variables name="CPS_Cmd_Forg3" typeName="BOOL" topologicalAddress="%MW302.0">
			<comment>SECURITE NIVEAU BAS - FORAGE 3</comment>
		</variables>
		<variables name="Ilo_Wago_OUT_DO_C4" typeName="WORD" topologicalAddress="%MW3219"></variables>
		<variables name="CPE_PosOuvEV4" typeName="BOOL" topologicalAddress="%MW332.1">
			<comment>POSITION OUVERTE - VANNE EV4</comment>
		</variables>
		<variables name="CPS_Cmd_P02" typeName="BOOL" topologicalAddress="%MW311.0">
			<comment>OUVERTURE - VANNE P02</comment>
		</variables>
		<variables name="CPS_LSB_Stockg" typeName="BOOL">
			<comment>NIVEAU BAS CUVE STOCKAGE</comment>
		</variables>
		<variables name="CPE_DEF_PmpChlor" typeName="BOOL">
			<comment>DEFAUT - POMPE CHLORATION</comment>
		</variables>
		<variables name="EA_AI2_V8" typeName="INT"></variables>
		<variables name="CPS_Cmd_P22" typeName="BOOL" topologicalAddress="%MW320.0">
			<comment>OUVERTURE - VANNE P22</comment>
		</variables>
		<variables name="CPE_PosFermEV5" typeName="BOOL" topologicalAddress="%MW337.2">
			<comment>POSITION FERMEE - VANNE EV5</comment>
		</variables>
		<variables name="EA_AI2_V3" typeName="INT"></variables>
		<variables name="CPS_Cmd_P43" typeName="BOOL" topologicalAddress="%MW331.0">
			<comment>OUVERTURE - VANNE P43</comment>
		</variables>
		<variables name="CPE_D2_EauLavg" typeName="BOOL">
			<comment>IMPULSIONS DEBITMETRE D2 - LAVAGE</comment>
		</variables>
		<variables name="CPE_DEF_PmpReprs1" typeName="BOOL">
			<comment>DEFAUT - POMPE REPRISE PR1</comment>
		</variables>
		<variables name="EA_LT_Stockage" typeName="INT"></variables>
		<variables name="Ilo_Wago_IN_AI_C2_V1" typeName="INT" topologicalAddress="%MW3024"></variables>
		<variables name="CPS_Cmd_P42" typeName="BOOL" topologicalAddress="%MW330.0">
			<comment>OUVERTURE - VANNE P42</comment>
		</variables>
		<variables name="EA_LT_Forage1" typeName="INT"></variables>
		<variables name="CPE_PosFermP11" typeName="BOOL" topologicalAddress="%MW314.2">
			<comment>POSITION FERMEE - VANNE P11</comment>
		</variables>
		<variables name="CPE_RM_PmpLavg" typeName="BOOL" topologicalAddress="%MW305.3">
			<comment>RETOUR MARCHE - POMPE LAVAGE FILTRES</comment>
		</variables>
		<variables name="CPE_PosOuvP51" typeName="BOOL" topologicalAddress="%MW334.1">
			<comment>POSITION OUVERTE - VANNE P51</comment>
		</variables>
		<variables name="CPE_DEF_PmpLavg" typeName="BOOL">
			<comment>DEFAUT - POMPE LAVAGE FILTRES</comment>
		</variables>
		<variables name="Ilo_Wago_OUT_DO_C3" typeName="WORD" topologicalAddress="%MW3218"></variables>
		<variables name="Ilo_Wago_IN_AI_C1_V7" typeName="INT" topologicalAddress="%MW3022"></variables>
		<variables name="CPE_PosOuvP40" typeName="BOOL" topologicalAddress="%MW328.1">
			<comment>POSITION OUVERTE - VANNE P40</comment>
		</variables>
		<variables name="Ilo_Wago_IN_DI_C7" typeName="WORD" topologicalAddress="%MW3038"></variables>
		<variables name="CPS_Cmd_EV0" typeName="BOOL" topologicalAddress="%MW312.0">
			<comment>OUVERTURE - VANNE EV0</comment>
		</variables>
		<variables name="DI_C7" typeName="WORD"></variables>
		<variables name="CPE_PosOuvP02" typeName="BOOL" topologicalAddress="%MW311.1">
			<comment>POSITION OUVERTE - VANNE P02</comment>
		</variables>
		<variables name="CPS_Cmd_V_CH2" typeName="BOOL" topologicalAddress="%MW342.0">
			<comment>OUVERTURE - VANNE CH2</comment>
		</variables>
		<variables name="CPS_Cmd_P50" typeName="BOOL" topologicalAddress="%MW333.0">
			<comment>OUVERTURE - VANNE P50</comment>
		</variables>
		<variables name="DO_C4" typeName="WORD"></variables>
		<variables name="CPE_PosFermP00" typeName="BOOL" topologicalAddress="%MW309.2">
			<comment>POSITION FERMEE - VANNE P00</comment>
		</variables>
		<variables name="CPE_DEF_PmpPurg" typeName="BOOL">
			<comment>DEFAUT - POMPE REPRISE EAU DE PURGE</comment>
		</variables>
		<variables name="CPS_Cmd_Analyseur" typeName="BOOL">
			<comment>ORDRE ANALYSE - ANALYSEUR CHLORE + PH AMI TRIDES</comment>
		</variables>
		<variables name="CPE_PosFermP01" typeName="BOOL" topologicalAddress="%MW310.2">
			<comment>POSITION FERMEE - VANNE P01</comment>
		</variables>
		<variables name="CPE_RM_PmpChlor" typeName="BOOL" topologicalAddress="%MW343.3">
			<comment>RETOUR MARCHE - POMPE CHLORATION</comment>
		</variables>
		<variables name="CPS_Cmd_Forg2" typeName="BOOL" topologicalAddress="%MW301.0">
			<comment>ORDRE MARCHE - POMPE FORAGE 2</comment>
		</variables>
		<variables name="CPS_Cmd_P11" typeName="BOOL" topologicalAddress="%MW314.0">
			<comment>OUVERTURE - VANNE P11</comment>
		</variables>
		<variables name="CPS_Cmd_P01" typeName="BOOL" topologicalAddress="%MW310.0">
			<comment>OUVERTURE - VANNE P01</comment>
		</variables>
		<variables name="CPE_PosOuvP10" typeName="BOOL" topologicalAddress="%MW313.1">
			<comment>POSITION OUVERTE - VANNE P10</comment>
		</variables>
		<variables name="CPE_PosFermEV4" typeName="BOOL" topologicalAddress="%MW332.2">
			<comment>POSITION FERMEE - VANNE EV4</comment>
		</variables>
		<variables name="CPE_PosOuvP50" typeName="BOOL" topologicalAddress="%MW333.1">
			<comment>POSITION OUVERTE - VANNE P50</comment>
		</variables>
		<variables name="CPS_Cmd_EV1" typeName="BOOL" topologicalAddress="%MW317.0">
			<comment>OUVERTURE - VANNE EV1</comment>
		</variables>
		<variables name="CPE_CPT_EauBrute" typeName="BOOL">
			<comment>COMPTEUR ARRIVEE EAU BRUTE</comment>
		</variables>
		<variables name="CPE_PosOuvP13" typeName="BOOL" topologicalAddress="%MW316.1">
			<comment>POSITION OUVERTE - VANNE P13</comment>
		</variables>
		<variables name="CPE_DefAnalyseur" typeName="BOOL">
			<comment>RETOUR DEFAUT - ANALYSEUR CHLORE + PH</comment>
		</variables>
		<variables name="CPE_PosOuvEV3" typeName="BOOL" topologicalAddress="%MW327.1">
			<comment>POSITION OUVERTE - VANNE EV3</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C2_V6" typeName="INT" topologicalAddress="%MW3029"></variables>
		<variables name="CPE_RM_PmpPurg" typeName="BOOL" topologicalAddress="%MW303.3">
			<comment>RETOUR MARCHE - POMPE REPRISE EAU DE PURGE</comment>
		</variables>
		<variables name="CPE_LSH_EauPurg" typeName="BOOL">
			<comment>POIRE NIVEAU HAUT EAUX DE PURGE</comment>
		</variables>
		<variables name="Ilo_Wago_OUT_DO_C2" typeName="WORD" topologicalAddress="%MW3217"></variables>
		<variables name="EA_FT_EauTraitee" typeName="INT"></variables>
		<variables name="CPE_PosFermP51" typeName="BOOL" topologicalAddress="%MW334.2">
			<comment>POSITION FERMEE - VANNE P51</comment>
		</variables>
		<variables name="CPE_PosOuvP41" typeName="BOOL" topologicalAddress="%MW329.1">
			<comment>POSITION OUVERTE - VANNE P41</comment>
		</variables>
		<variables name="CPE_BP_Klaxon" typeName="BOOL">
			<comment>BP Arret Klaxon</comment>
		</variables>
		<variables name="CPE_PosFermP10" typeName="BOOL" topologicalAddress="%MW313.2">
			<comment>POSITION FERMEE - VANNE P10</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C1_V6" typeName="INT" topologicalAddress="%MW3021"></variables>
		<variables name="CPS_Cmd_P30" typeName="BOOL" topologicalAddress="%MW323.0">
			<comment>OUVERTURE - VANNE P30</comment>
		</variables>
		<variables name="CPS_Cmd_P41" typeName="BOOL" topologicalAddress="%MW329.0">
			<comment>OUVERTURE - VANNE P41</comment>
		</variables>
		<variables name="EA_AI2_V5" typeName="INT"></variables>
		<variables name="CPS_Cmd_P51" typeName="BOOL" topologicalAddress="%MW334.0">
			<comment>OUVERTURE - VANNE P51</comment>
		</variables>
		<variables name="CPE_RM_PmpReprs2" typeName="BOOL" topologicalAddress="%MW307.3">
			<comment>RETOUR MARCHE - POMPE REPRISE PR2</comment>
		</variables>
		<variables name="CPE_PosFermP40" typeName="BOOL" topologicalAddress="%MW328.2">
			<comment>POSITION FERMEE - VANNE P40</comment>
		</variables>
		<variables name="CPE_PosFermP02" typeName="BOOL" topologicalAddress="%MW311.2">
			<comment>POSITION FERMEE - VANNE P02</comment>
		</variables>
		<variables name="CPE_PosOuvP42" typeName="BOOL" topologicalAddress="%MW330.1">
			<comment>POSITION OUVERTE - VANNE P42</comment>
		</variables>
		<variables name="CPS_Cmd_Forg1" typeName="BOOL" topologicalAddress="%MW300.0">
			<comment>ORDRE MARCHE - POMPE FORAGE 1</comment>
		</variables>
		<variables name="CPS_Cmd_P00" typeName="BOOL" topologicalAddress="%MW309.0">
			<comment>OUVERTURE - VANNE P00</comment>
		</variables>
		<variables name="Ilo_Wago_IN_DI_C1" typeName="WORD" topologicalAddress="%MW3032"></variables>
		<variables name="CPE_PosOuvEV2" typeName="BOOL" topologicalAddress="%MW322.1">
			<comment>POSITION OUVERTE - VANNE EV2</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C2_V7" typeName="INT" topologicalAddress="%MW3030"></variables>
		<variables name="CPE_PosFermEV3" typeName="BOOL" topologicalAddress="%MW327.2">
			<comment>POSITION FERMEE - VANNE EV3</comment>
		</variables>
		<variables name="CPS_Cmd_P40" typeName="BOOL" topologicalAddress="%MW328.0">
			<comment>OUVERTURE - VANNE P40</comment>
		</variables>
		<variables name="EA_PT_PmpRprise2" typeName="INT"></variables>
		<variables name="CPE_RM_Forg1" typeName="BOOL" topologicalAddress="%MW300.3">
			<comment>RETOUR MARCHE - POMPE FORAGE 1</comment>
		</variables>
		<variables name="CPS_Cmd_PmpLavg" typeName="BOOL" topologicalAddress="%MW305.0">
			<comment>ORDRE MARCHE - POMPE LAVAGE FILTRE</comment>
		</variables>
		<variables name="CPE_DEF_SouflAir" typeName="BOOL">
			<comment>DEFAUT - GROUPE D'AIR</comment>
		</variables>
		<variables name="CPE_CM3_AirOK" typeName="BOOL">
			<comment>CONTACTEUR MANOMETRIQUE CM3 - PRESENCE AIR COMPRIME</comment>
		</variables>
		<variables name="CPE_PosFermP41" typeName="BOOL" topologicalAddress="%MW329.2">
			<comment>POSITION FERMEE - VANNE P41</comment>
		</variables>
		<variables name="CPE_PosFermP42" typeName="BOOL" topologicalAddress="%MW330.2">
			<comment>POSITION FERMEE - VANNE P42</comment>
		</variables>
		<variables name="Ilo_Wago_IN_AI_C1_V1" typeName="INT" topologicalAddress="%MW3016"></variables>
		<variables name="CPE_PosOuvP12" typeName="BOOL" topologicalAddress="%MW315.1">
			<comment>POSITION OUVERTE - VANNE P12</comment>
		</variables>
		<variables name="CPE_PosOuvP22" typeName="BOOL" topologicalAddress="%MW320.1">
			<comment>POSITION OUVERTE - VANNE P22</comment>
		</variables>
		<variables name="EA_LT_Forage3" typeName="INT"></variables>
		<variables name="CPE_PosFermP13" typeName="BOOL" topologicalAddress="%MW316.2">
			<comment>POSITION FERMEE - VANNE P13</comment>
		</variables>
		<variables name="CPE_PosOuvP53" typeName="BOOL" topologicalAddress="%MW336.1">
			<comment>POSITION OUVERTE - VANNE P53</comment>
		</variables>
		<variables name="CPS_Cmd_P31" typeName="BOOL" topologicalAddress="%MW324.0">
			<comment>OUVERTURE - VANNE P31</comment>
		</variables>
		<variables name="CPS_Klaxon" typeName="BOOL">
			<comment>KLAXON</comment>
		</variables>
		<variables name="CPE_PosFermP50" typeName="BOOL" topologicalAddress="%MW333.2">
			<comment>POSITION FERMEE - VANNE P50</comment>
		</variables>
		<variables name="CPS_Cmd_EV2" typeName="BOOL" topologicalAddress="%MW322.0">
			<comment>OUVERTURE - VANNE EV2</comment>
		</variables>
		<variables name="CPE_PosFermP1" typeName="BOOL" topologicalAddress="%MW339.2">
			<comment>POSITION FERMEE - VANNE P1</comment>
		</variables>
		<variables name="EA_AI2_V4" typeName="INT"></variables>
		<variables name="Ilo_Wago_OUT_DO_C1" typeName="WORD" topologicalAddress="%MW3216"></variables>
		<variables name="CPS_Cmd_SouflAir" typeName="BOOL" topologicalAddress="%MW304.0">
			<comment>ORDRE MARCHE - GROUPE D'AIR</comment>
		</variables>
		<variables name="CPE_RM_PmpReprs1" typeName="BOOL" topologicalAddress="%MW306.3">
			<comment>RETOUR MARCHE - POMPE REPRISE PR1</comment>
		</variables>
		<variables name="CPE_PosOuvP43" typeName="BOOL" topologicalAddress="%MW331.1">
			<comment>POSITION OUVERTE - VANNE P43</comment>
		</variables>
		<variables name="CPE_RM_SouflAir" typeName="BOOL" topologicalAddress="%MW304.3">
			<comment>RETOUR MARCHE - GROUPE D'AIR</comment>
		</variables>
	</dataBlock>
</STExchangeFile>

Mon fichier source étant un fichier Excel, je ne sais pas comment te le transférer sur le forum mais après, c'est pas forcément le plus important je dirai car l'extraction des données est fonctionnelle

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
14 nov. 2022 à 20:53

, c'est pas forcément le plus important je dirai car l'extraction des données est fonctionnelle

Pour t'aider, il faut qu'on essaye de notre côté, et franchement, je n'ai pas envie de passer des heures à me bricoler un jeu de données, qui pourrait ne pas être correct.

Je ne te demande pas un fichier complet et confidentiel, mais 3 ou 4 "lignes" de chaque "type".

Tu peux le poster sur un site de partage comme cjoint ou autre


0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
14 nov. 2022 à 21:06

SAlut Whismeril, 

Oui je comprends. Je te donne ça:

https://wetransfer.com/downloads/bf6088c9030754479d18a397543a1c9d20221114200609/03498c

Je t'ai fait un weTransfer en espérant que ça fonctionne

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
15 nov. 2022 à 06:46

Je regarde ça ce soir


0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
15 nov. 2022 à 18:44

Alors, ton de lecture du fichier Excel par OLEBD ne fonctionne pas chez moi, je ne dois pas avoir le bon driver ou la même version d'Excel que toi.

Du coup, je voulais lire le fichier autrement, mais je ne retrouve pas les données de ce fichier Excel dans les 2 exemples de xml que tu as mis plus haut.

Donc, je ne peux toujours pas tester de mon côté.

Dans mon premier message, je t'avais pourtant demandé un jeu de données d'entrée et le xml qui en découle.



Deuxième point, dans ton code de lecture, tu initialises des tableaux, puis tu crées des listes de tes classes à partir de ces tableaux.

Est-ce que ces tableaux te servent ailleurs, dans la négative, ils n'ont pas d'intérêt et ça charge la RAM inutilement, tes données sont à la fois dans

  1. le dataset
  2. les tableaux
  3. les listes.

0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
15 nov. 2022 à 20:34

Salut Whismeril,

Je viens de te faire un Excel source et un xml:

https://wetransfer.com/downloads/87815fbefb9e8849ae3a570f376b2b8520221115193116/d02f0a

J'ai vachement simplifié par rapport au premier Excel car ça suffira pour avoir une base je pense.

Pour répondre à ta question sur mes tableaux, non ils ne me servent pas donc effectivement, il pourrait sauter. ça allègerait mon code en plus. 

Je me penche sur le sujet.

Merci

0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
15 nov. 2022 à 21:22
OleDbConnection MyConnection = default(OleDbConnection);
            DataSet dataSetES = default(DataSet);
            OleDbDataAdapter MyCommand = default(OleDbDataAdapter);

            MyConnection = new OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = " + NomFichierSource.Text + "; Extended Properties = 'Excel 12.0 XML;HDR=YES;'; ");
            MyCommand = new OleDbDataAdapter("select * from [Liste_ES$]", MyConnection);

            MyConnection.Open();

            dataSetES = new DataSet();
            MyCommand.Fill(dataSetES);

            //Calcul du nombre de lignes et de colonnes pour dimensionner le tableau qui accueillera les données
            int nb_col = dataSetES.Tables[0].Columns.Count;
            nb_lignesES = dataSetES.Tables[0].Rows.Count;

            //Création du tableau qui accueillera les données du fichier excel
            string[,] Tableau_SourceES = new string[nb_lignesES + 1, nb_col + 1];
            int x = 0;
            int y = 0;
            for (x = 0; x <= nb_lignesES - 1; x++)
            {
                for (y = 0; y <= nb_col - 1; y++)
                {
                    Tableau_SourceES[x, y] = dataSetES.Tables[0].Rows[x].ItemArray[y].ToString();
                }
            }
            MyConnection.Close();

            //Remplissage des tableaux d'entrées/sorties
            int Index_EANA = 0;
            int Index_ETOR = 0;
            int Index_STOR = 0;
            int Index_SANA = 0;


            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ////////////////////////////////////                                                                            ////////////////////////////////////
            ////////////////////////////////////                     Génération section de recopie E/S                      ////////////////////////////////////
            ////////////////////////////////////                                                                            ////////////////////////////////////            
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            if (RecopieE_S.Checked == true)
            {
                
                // Création du fichier de sortie
                //Déclaration des différentes variables
                List<EANA_API> Liste_EANA_API = new List<EANA_API>();
                List<ETOR_API> Liste_ETOR_API = new List<ETOR_API>();
                List<STOR_API> Liste_STOR_API = new List<STOR_API>();
                List<SANA_API> Liste_SANA_API = new List<SANA_API>();


                for (int Index = 0; Index <= nb_lignesES - 1; Index++)
                {
                    //Ajout des différentes entrées ANA
                    if (Tableau_SourceES[Index, 1].Contains("AI_"))
                    {
                        Liste_EANA_API.Add(new EANA_API(Tableau_SourceES[Index, 9], Tableau_SourceES[Index, 1], Index_EANA));
                        Index_EANA = Index_EANA + 1;
                    }

                    //Ajout des différentes entrées TOR
                    if (Tableau_SourceES[Index, 1].Contains("DI.C"))
                    {
                        Liste_ETOR_API.Add(new ETOR_API(Tableau_SourceES[Index, 9], Tableau_SourceES[Index, 1], Index_ETOR));
                        Index_ETOR = Index_ETOR + 1;
                    }

                    //Ajout des différentes sorties TOR
                    if (Tableau_SourceES[Index, 1].Contains("DI.C"))
                    {
                        Liste_STOR_API.Add(new STOR_API(Tableau_SourceES[Index, 9], Tableau_SourceES[Index, 1], Index_STOR));
                        Index_STOR = Index_STOR + 1;
                    }

                    //Ajout des différentes sorties ANA
                    if (Tableau_SourceES[Index, 1].Contains("AO_"))
                    {
                        Liste_SANA_API.Add(new SANA_API(Tableau_SourceES[Index, 9], Tableau_SourceES[Index, 1], Index_SANA));
                        Index_SANA = Index_SANA + 1;
                    }

                }

                //Création du fichier XML source
                XDocument XmlDoc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), new XElement("STExchangeFile", new XElement("fileHeader", new XAttribute("company", "Schneider Automation"), new XAttribute("product", "Control Expert V14.1 - 191122A"), new XAttribute("dateTime", "date_and_time#2018-3-12-16:50:53"), new XAttribute("content", "Fichier source ST"), new XAttribute("DTDVersion", "41")),
                                                                                                                         new XElement("contentHeader", new XAttribute("name", "Projet"), new XAttribute("version", "0.0.710"), new XAttribute("dateTime", "date_and_time#2018-2-14-14:39:27")),
                                                                                                                         new XElement("program", new XElement("identProgram", new XAttribute("name", "Copie_E_S"), new XAttribute("type", "section"), new XAttribute("task", "MAST")),
                                                                                                                         new XElement("STSource", new XText("(*Copies des entrees Analogiques *)" + "\n"),
                                                                                                                                                  from p in Liste_EANA_API select new XText(p.EANA),

                                                                                                                                                  new XText("\n"),
                                                                                                                                                  new XText("(*Copies des entrées TOR *)" + "\n"),
                                                                                                                                                  from p in Liste_ETOR_API select new XText(p.ETOR),

                                                                                                                                                  new XText("\n"),
                                                                                                                                                  new XText("(*Copies des sorties TOR *)" + "\n"),
                                                                                                                                                  from p in Liste_STOR_API select new XText(p.STOR),

                                                                                                                                                  new XText("\n"),
                                                                                                                                                  new XText("(*Copies des sorties Analogiques *)" + "\n"),
                                                                                                                                                  from p in Liste_SANA_API select new XText(p.SANA))),
                                                                                                                         new XElement("dataBlock",new XElement("variables", new XAttribute("version", "0.0.710")))));

                //Test si le fichier existe déjà
                if (File.Exists(NomDossierDest.Text + @"\Sections_ST.xst"))
                {
                    MessageBox.Show("Un fichier section existe déjà dans le dossier de destination. Annulation de l'opération");
                }
                else
                {
                    //Récupération du nom de la zone pour définir le nom du fichier
                    XmlDoc.Save(NomDossierDest.Text + @"\Sections_ST.xst");
                }
            }

Code mis à jour suite à tes remarques Whismeril. J'ai sauté mes classes "En_tête" qui n'apportait rien

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
15 nov. 2022 à 23:00

Alors, j'ai exporté ton excel en csv.

Ça je n'ai pas de problème de compatibilité ou autre avec mon vieux Excel.

J'ai réécrit tes classes comme ça (mais y'a encore du code redondant, il faudra faire mieux)

 public abstract class EntreesSortie
    {
        /// <summary>
        /// Le constructeur prend en paramètres un tableau de string qui correspond à une ligne du csv, et l'index
        /// </summary>
        /// <param name="LigneCSV"></param>
        /// <param name="Index"></param>
        public EntreesSortie(string[] LigneCSV, int Index)
        {
            this.Mnemonique = LigneCSV[9];
            this.Adresse = LigneCSV[1];
            this.Comment = $"{LigneCSV[5]} {LigneCSV[7]}";
            this.Index = Index;
        }

        public abstract string Texte { get; }
        public string Mnemonique { get; set; }
        public string Adresse { get; set; }
        public int Index { get; set; }
        public string Comment { get; set; }
    }

    public class EANA_API : EntreesSortie
    {
        //le constructeur appelle directement celui de la classe abstraite, et rien d'autre
        public EANA_API(string[] LigneCSV, int Index) : base(LigneCSV, Index)
        {
        }

        public override string Texte
        {
            get { return $"{Mnemonique} := {Adresse}"; }
        }

        //Overrider ToString est utile pour le débug, quand on regarde le contenu d'une liste, c'est ça qui est affiché
        public override string ToString()
        {
            return $"Index: {Index}, Adresse: {Adresse}, Mnémonique: {Mnemonique}";
        }
    }

    public class SANA_API : EntreesSortie
    {
        public SANA_API(string[] LigneCSV, int Index) : base(LigneCSV, Index)
        {
        }

        public override string Texte
        {
            get { return $"{Mnemonique} := {Adresse}"; }
        }

        public override string ToString()
        {
            return $"Index: {Index}, Adresse: {Adresse}, Mnémonique: {Mnemonique}";
        }
    }

    public class ETOR_API : EntreesSortie
    {
        public ETOR_API(string[] LigneCSV, int Index) : base(LigneCSV, Index)
        {
        }

        public override string Texte
        {
            get { return $"{Mnemonique} := ({Adresse} AND AOM_I[{Index}] = 0) OR AOM_I[{Index}] = 1;"; }
        }

        public override string ToString()
        {
            return $"Index: {Index}, Adresse: {Adresse}, Mnémonique: {Mnemonique}";
        }
    }

    public class STOR_API : EntreesSortie
    {
        public STOR_API(string[] LigneCSV, int Index) : base(LigneCSV, Index)
        {
        }

        public override string Texte
        {
            get { return $"{Adresse} := ({Mnemonique} AND AOM_O[{Index}] = 0) OR AOM_O[{Index}] = 1;"; }
        }

        public override string ToString()
        {
            return $"Index: {Index}, Adresse: {Adresse}, Mnémonique: {Mnemonique}";
        }
    }

Je lis le fichier csv de façon à enfaire une liste de tableaux, chaque tableau correspond à une ligne et chaque item d'un tableau à une cellule de cette ligne, tu pourras transposer avec ton dataset.

            //Je lis toutes les lignes du CSV, je les splite et j'en fais une liste de tableaux, 1 tableau par ligne du CSV
            List<string[]> lignes = File.ReadAllLines("Exemple fichier ES Whismeril.csv").Select(l => l.Split(';')).ToList();

Je lis toutes les entrées et sorties pour en faire une liste unique

            //Constitution de la liste d'EntreeSortie
            List<EntreesSortie> entreesSorties = new List<EntreesSortie>();
            entreesSorties.AddRange(lignes.Where(l => l.Length > 1 && l[1].Contains("AI_")).Select((l, i) => new EANA_API(l, i)));
            entreesSorties.AddRange(lignes.Where(l => l.Length > 1 && l[1].Contains("AO_")).Select((l, i) => new SANA_API(l, i)));
            entreesSorties.AddRange(lignes.Where(l => l.Length > 1 && l[1].Contains("DI.C")).Select((l, i) => new ETOR_API(l, i)));
            entreesSorties.AddRange(lignes.Where(l => l.Length > 1 && l[1].Contains("DO.C")).Select((l, i) => new STOR_API(l, i)));

Ensuite, j'en extrais le contenu de la balise STSource sous forme de liste, une ligne par item

            //Je constitue le contenu de la balise STSource à part, afin de vérifier que c'est correct en débug
            List<string> stSource = new List<string> { "(*Copies des entrees Analogiques *)" };
            stSource.AddRange(entreesSorties.OfType<EANA_API>().Select(e => e.Texte));
            stSource.Add("");
            stSource.Add("(*Copies des entrees TOR *)");
            stSource.AddRange(entreesSorties.OfType<ETOR_API>().Select(e => e.Texte));
            stSource.Add("");
            stSource.Add("(*Copies des sorties TOR *)");
            stSource.AddRange(entreesSorties.OfType<STOR_API>().Select(e => e.Texte));
            stSource.Add("");
            stSource.Add("(*Copies des sorties Analogiques *)");
            stSource.AddRange(entreesSorties.OfType<SANA_API>().Select(e => e.Texte));

Enfin, j'édite le fichier xml

            XDocument XmlDoc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), new XElement("STExchangeFile", new XElement("fileHeader", new XAttribute("company", "Schneider Automation"), new XAttribute("product", "Control Expert V14.1 - 191122A"), new XAttribute("dateTime", "date_and_time#2018-3-12-16:50:53"), new XAttribute("content", "Fichier source ST"), new XAttribute("DTDVersion", "41")),
                                                                                                                         new XElement("contentHeader", new XAttribute("name", "Projet"), new XAttribute("version", "0.0.710"), new XAttribute("dateTime", "date_and_time#2018-2-14-14:39:27")),
                                                                                                                         new XElement("program", new XElement("identProgram", new XAttribute("name", "Copie_E_S"), new XAttribute("type", "section"), new XAttribute("task", "MAST")),
                                                                                                                         new XElement("STSource", string.Join("\n",stSource)),
                                                                                                                         new XElement("dataBlock", from es in entreesSorties
                                                                                                                                                   select new XElement("variables", new XAttribute("name", es.Mnemonique), new XAttribute("typeName", "INT"),
                                                                                                                                                   string.IsNullOrWhiteSpace(es.Comment) ? null : new XElement("comment", es.Comment)))
                                                                                                                         )));
            XmlDoc.Save("Test.xml");

Je n'arrive pas exactement au même fichier que toi, tu peux tester mon code avec le csv là https://cjoint.com/c/LKpv5bFEyXx

 Ce que je n'ai pas compris, c'est comment tu détermines que telle est un int et telle autre un bool?

J'avais commencé à coder les commentaires, mais sans être sûr d'avoir compris, je les ai laissés, tu me diras


0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
16 nov. 2022 à 08:03

Salut Whismeril,

Merci pour ton aide. Je vais regarder plus en détail ton code.

Pour la détermination du type "INT" ou "BOOL", c'est en fonction de l'adresse de ma variable. Sur mon automate, j'ai deux types d'entrées/sorties. Il y a ce qu'on appelle du TOR (tout ou rien = 0 ou 1) et des analogiques (Nombre de points entre 0 et 32768 selon le modèle d'automate). En interne, on a une codification à savoir: DI = Digital input = entrée TOR, DO= Digital output = sortie TOR, AI = analog input = entrée analogique et AO = Analog output = sortie analogique.

Donc lorsque je lit mon fichier, si j'ai DI ou DO dans l'adresse, je sais que c'est un BOOL et si j'ai AI ou AO, ce sera du INT.

En espérant avoir répondu à ton interrogation

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
16 nov. 2022 à 08:25

Ok, c'est ce que j'avais supposé, mais j'avais quand même un doute sur la terminologie, pour moi (je suis dans la mesures) analogique c'est pas pas un nombre déjà encodé, c'est avant le CAN.

Et puis dans le xml du message #2, il y a aussi des variables de type word, comment on sait pour celles là ?


Dans ce même xml, il y a un attribut topologicalAddress, ça sort d'où ?


Quand au code que j'ai posté hier, teste le, regarde le, mais ne le prends pas pour argent comptant.

Les classes dérivées sont tellement proches les une des autres (entrée et sortie analogique sont identiques et les TOR n'ont qu'un paramètre d'écart dans Texte) que je pense pourvoir ne faire qu'une classe et sans dériver.

Cela dit ce code reste un petit exemple de polymorphisme.


0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
16 nov. 2022 à 08:39

Pour les variables de type "WORD", je ne les déclare pas car c'est du spécifique. Pour faire simple, je récupère les données via une communication avec un module déportées. Il me donne un "WORD" que je viens ensuite décomposer pour en extraire les bits un à un. En gros, j'ai un word par tranche de 16 entrées TOR.

Pour la topogical adresse, c'est une adresse interne dans l'automate mais c'est pareil, c'est trop spécifique au projet donc je ne gère pas. Ce sera fait quand je fais ma config automate.

J'ai repris ton code et il y a juste la transposition de mon dataset en list que je n'arrive pas à faire. J'ai regardé pas mal d'exemple mais j'avoue ne pas bien les comprendre donc pour les mettre en oeuvre....

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
16 nov. 2022 à 11:13

Y'a pas besoin de liste puisque tu as un dataset.

J'ai utilisé une collection de lignes, chaque ligne étant un tableau.

Un dataset est aussi une collection de lignes, chaque ligne étant une datarow ou un truc dans le genre.

Tu peux modifier les constructeurs pour qu'ils prenent un datarow en paramètre à la place du tableau.


0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
16 nov. 2022 à 11:14

Tu peux aussi, remettre des constructeurs comme tu avais fais avec chacun des paramètres que tu veux utliser.

D'ailleurs, à quoi te sert l'index?

0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
16 nov. 2022 à 11:35

C'est bon, j'ai enfin compris le principe. J'ai modifié pour avoir mon Dataset en entrée et ça fonctionne. J'ai modifié quelques bricoles pour correspondre à ce que je voulais et ça me va. Un grand merci de ton aide Whismeril

Pour répondre à ta question, l'index sert à balayer mon tableau dans le code automate

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
16 nov. 2022 à 11:40

Oui, donc si je te propose une solution sans l'index ça ne change rien pour toi?


0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
16 nov. 2022 à 11:50

Tant que la partie "texte" est la même que celle que j'ai donné, il n'y a aucun soucis pour moi. Après, j'ai envie de te dire que la solution que tu m'as donné fonctionne donc je ne voudrais pas abuser de ta gentillesse.

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
16 nov. 2022 à 11:56

Oui, mais comme je te l'ai dit y'a du code redondant. C'est pas bien.


0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
16 nov. 2022 à 18:33

Alors avec une seule classe EntreeSortie codée comme ça

    public class EntreesSortie
    {

        //pour les index de chaque nature
        private static int indexAI = 0;
        private static int indexAO = 0;
        private static int indexDI = 0;
        private static int indexDO = 0;

        /// <summary>
        /// Le constructeur prend en paramètres un tableau de string qui correspond à une ligne du csv, et l'index
        /// </summary>
        /// <param name="LigneCSV"></param>
        /// <param name="Index"></param>
        public EntreesSortie(string[] LigneCSV)
        {
            this.Mnemonique = LigneCSV[9];
            this.Adresse = LigneCSV[1];
            this.Comment = $"{LigneCSV[5]} {LigneCSV[7]}";

            //on détermine si c'est une entrée ou une sortie
            if (Adresse.Contains("AI_"))
            {
                Nature = Nature.Entree | Nature.Analogique;
                Index = indexAI++;//on affecte l'index et ensuite la variable static est incrémentée
            }
            else if (Adresse.Contains("AO_"))
            {
                Nature = Nature.Sortie | Nature.Analogique;
                Index = indexAO++;
            }
            else if (Adresse.Contains("DI.C"))
            {
                Nature = Nature.Entree | Nature.TOR;
                Index = indexDI++;
            }
            else if (Adresse.Contains("DO.C"))
            {
                Nature = Nature.Sortie | Nature.TOR;
                Index = indexDO++;
            }

            if (Nature == Nature.Indefinie)//il y a un problème on génére une erreur
                throw new Exception("Y'a un problème");
        }

        /// <summary>
        /// Retourne un texte qui dépend de la nature de l'instance
        /// </summary>
        public string Texte
        {
            get
            {
                //dans ton dernier fichier exemple, je me suis aperçu ce soir, que les datas sont inversées entre l'entrée et la sorties
                string champ1 = Nature.HasFlag(Nature.Entree) ? Mnemonique : Adresse;
                string champ2 = Nature.HasFlag(Nature.Entree) ? Adresse : Mnemonique;

                if (Nature.HasFlag(Nature.Analogique))
                    return $"{champ1} := {champ2}";

                //de même pour les TOR, y'a un I qui se change en O
                string io = Nature.HasFlag(Nature.Entree) ? "I" : "0";

                return $"{champ1} := ({champ2} AND AOM_{io}[{Index}] = 0) OR AOM_{io}[{Index}] = 1;";
            }
        }

        public string TypeVariable { get { return Nature.HasFlag(Nature.Analogique) ? "INT" : "BOOL"; } }

        public string Mnemonique { get; private set; }

        public string Adresse { get; private set; }

        public string Comment { get; private set; }

        public int Index { get; private set; }

        public Nature Nature { get; private set; }
    }

    /// <summary>
    /// Enumérable permetant de savoir à quoi correspond cette instance
    /// </summary>
    /// <remarks>Cet enum est flagable => il peut prendre plusieurs valeurs</remarks>
    [Flags()]
    public enum Nature
    {
        Indefinie = 0,
        Entree = 1,
        Sortie = 2,
        Analogique = 4,
        TOR = 8
    }

Et la lecture du fichier CSV, puis l'export en xml codé comme ça

            //Je lis toutes les lignes du CSV, je les splite et j'en fais une liste de tableaux, 1 tableau par ligne du CSV
            List<string[]> lignes = File.ReadAllLines("Exemple fichier ES Whismeril.csv").Select(l => l.Split(';')).ToList();

            //Constitution de la liste d'EntreeSortie
            List<EntreesSortie> entreesSorties = lignes.Where(l => l.Length > 1 && (l[1].Contains("AI_") || l[1].Contains("AO_") || l[1].Contains("DI.C") || l[1].Contains("DO.C")))
                                                        .Select(l => new EntreesSortie(l))
                                                        .ToList();

            //Je constitue le contenu de la balise STSource à part, afin de vérifier que c'est correct en débug
            List<string> stSource = new List<string> { "(*Copies des entrees Analogiques *)" };
            stSource.AddRange(entreesSorties.Where(es => es.Nature == (Nature.Entree | Nature.Analogique)).Select(e => e.Texte));
            stSource.Add("");
            stSource.Add("(*Copies des entrees TOR *)");
            stSource.AddRange(entreesSorties.Where(es => es.Nature == (Nature.Entree | Nature.TOR)).Select(e => e.Texte));
            stSource.Add("");
            stSource.Add("(*Copies des sorties TOR *)");
            stSource.AddRange(entreesSorties.Where(es => es.Nature == (Nature.Sortie | Nature.TOR)).Select(e => e.Texte));
            stSource.Add("");
            stSource.Add("(*Copies des sorties Analogiques *)");
            stSource.AddRange(entreesSorties.Where(es => es.Nature == (Nature.Sortie | Nature.Analogique)).Select(e => e.Texte));

            XDocument XmlDoc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), new XElement("STExchangeFile", new XElement("fileHeader", new XAttribute("company", "Schneider Automation"), new XAttribute("product", "Control Expert V14.1 - 191122A"), new XAttribute("dateTime", "date_and_time#2018-3-12-16:50:53"), new XAttribute("content", "Fichier source ST"), new XAttribute("DTDVersion", "41")),
                                                                                                                         new XElement("contentHeader", new XAttribute("name", "Projet"), new XAttribute("version", "0.0.710"), new XAttribute("dateTime", "date_and_time#2018-2-14-14:39:27")),
                                                                                                                         new XElement("program", new XElement("identProgram", new XAttribute("name", "Copie_E_S"), new XAttribute("type", "section"), new XAttribute("task", "MAST")),
                                                                                                                         new XElement("STSource", string.Join("\n",stSource)),
                                                                                                                         new XElement("dataBlock", from es in entreesSorties
                                                                                                                                                   select new XElement("variables", new XAttribute("name", es.Mnemonique), new XAttribute("typeName", es.TypeVariable),
                                                                                                                                                   string.IsNullOrWhiteSpace(es.Comment) ? null : new XElement("comment", es.Comment)))
                                                                                                                         )));
            XmlDoc.Save("Test.xml");

J'arrive à un fichier plus proche qu'hier, mais pas exactement le même :

  • Il y a de tabulations que je n'ai pas mises, je ne sais pas si c'est important, dans l'affirmative, il faut les ajouter dans la propriété Texte.
  • Les noms des variables sont différents, le jeu de données d'entrées l'est peut-être encore un peu.

Je me suis servi d'un enumérable flaggable (c'est-à-dire qu'il peut prendre plusieurs valeurs, détails ici)  afin de savoir la nature de l'instance (entrée ou sortie, analogique ou TOR).

Tantôt, je teste la valeur exacte, tantôt, une partie (est-ce une entrée ou une sortie).


Le code d'hier, si tu ne le conserves pas dans ton projet, garde le dans un coin comme exemple de polymorphisme.

Celui d'aujourd'hui est un exemple d'enum flaggable.


0
Tintin2256 Messages postés 25 Date d'inscription mardi 3 octobre 2017 Statut Membre Dernière intervention 18 septembre 2023
17 nov. 2022 à 13:39

Salut Whismeril,

Merci beaucoup. Le premier code me semble plus simple d'un point de vue compréhension pour le non-informaticien que je suis. Il consomme sûrement plus de ressource mais c'est pas grave car le code est utilisé une fois, au début du projet et c'est tout donc même si la génération prend 2min de plus, c'est pas ça qui va me tuer vu le temps que je gagne à côté.

Il me reste maintenant à bosser sur le reste de la génération de code mais j'aurai sûrement besoin de tes conseils si tu es ok

0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
17 nov. 2022 à 14:37

Plus de ressources pas sûr, mais, pas de code redondant donc maintenance simplifiée.

Après comme je te l'ai dit l'un ou l'autre son des exemples de 2 implémentations du même besoin


0