Conversion xls > xml
Bonjour à tous,
Je me permets de vous contacter dans le cadre de mon boulot. Je suis charpentier et dispose dans mon entreprise d'une tronçonneuse numérique qui lit des listes de pièces à découper au format xml. Le bureau d'études lui les exporte au format excel sous la forme suivante:
N° pièce
Hauteur
Epaisseur
Longueur
Quantité
N° mur
Voici ici un exemple d'excel avec une liste de production brute et une macro qui générerait un tri par section stricte (https://www.cjoint.com/c/HAmwBwePFny ).
Au sein du fichier xml, les pièces sont regroupées par section (hauteur ET épaisseur strictement identiques) sous un en-tête qui liste ensuite les longueurs (variables), le numéro de mur (s'il y en a un) et la quantité de chacune (variable aussi). Voici ci-dessous un exemple de code avec trois section différentes 30x65, 45x240 et 80x240 avec pour chacune, plusieurs longueurs et dans le cas du 45x240, deux longueurs de 555 n'appartenant pas au même mur (MD101 et MD102) et donc codées l'une à la suite de l'autre.
<?xml version="1.0"?>
<Programs fileversion="version 1.0">
<PrgProgram>02012018_Test_Stromab</PrgProgram>
<PrgHeadTrimmingLength>0</PrgHeadTrimmingLength>
<PrgTailTrimmingLength>0</PrgTailTrimmingLength>
<PrgPrinterField1></PrgPrinterField1>
<PrgPrinterField2></PrgPrinterField2>
<PrgPrinterField3></PrgPrinterField3>
<PrgPreOptimized>0</PrgPreOptimized>
<PrgProgrammedBarLength>0</PrgProgrammedBarLength>
<PrgSections>
<SecSectionID>1</SecSectionID>
<SecHeight>30</SecHeight>
<SecMinWidth/>
<SecMaxWidth/>
<SecWidth>65</SecWidth>
<PreOpt/>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>1</PcPieceID>
<PcLength>830</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>2</PcUnloader1>
<PcUnloader2>0</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2572</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>2</PcPieceID>
<PcLength>3980</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>1</PcUnloader1>
<PcUnloader2>3</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2562</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<SecSectionID>2</SecSectionID>
<SecHeight>45</SecHeight>
<SecMinWidth/>
<SecMaxWidth/>
<SecWidth>240</SecWidth>
<PreOpt/>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>3</PcPieceID>
<PcLength>413</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>2</PcUnloader1>
<PcUnloader2>0</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2546</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>4</PcPieceID>
<PcLength>452</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>2</PcUnloader1>
<PcUnloader2>0</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2544</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>5</PcPieceID>
<PcLength>555</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>2</PcUnloader1>
<PcUnloader2>0</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2534</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>6</PcPieceID>
<PcLength>555</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>2</PcUnloader1>
<PcUnloader2>0</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2534</PcPrinterField2>
<PcPrinterField3>MD102</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<SecSectionID>3</SecSectionID>
<SecHeight>80</SecHeight>
<SecMinWidth/>
<SecMaxWidth/>
<SecWidth>240</SecWidth>
<PreOpt/>
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>12</PcPieceID>
<PcLength>2945</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>1</PcUnloader1>
<PcUnloader2>3</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2481</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
</PrgSections>
</Programs>
Afin de faciliter la tâche des gars à l'atelier, je souhaiterais un peu d'aide pour développer un fichier excel qui automatiserait la conversion.
Avez-vous des idées sur la conception (la forme que pourrait prendre l'interface) et d'éventuelles idées de fonction, macros etc ?
D'avance merci, bien à vous.
Baptiste.
Bonjour,
Une piste peut être !
En créant un squelette du groupe principal qui nécessite le changement de valeurs avec ces dernières dans un tableau dont tu auras au préalable défini le nombre de dimensions nécessaires (les valeurs pouvant être récupérées dans une feuille de calcul). Une fois tous les paramètres définis, construction de la chaîne complète :
Sub Test()
Dim Tbl() As String
Dim XML As String
Dim ChaineXML As String
Dim I As Integer
'créer autant de dimensions que nécessaire !
ReDim Tbl(1 To 5, 1 To 2)
Tbl(1, 1) = "M101" 'PcPrinterField3
Tbl(2, 1) = "830" 'PcLength
Tbl(3, 1) = "2572" 'PcPrinterField2
Tbl(4, 1) = "1" 'PcQuality
Tbl(5, 1) = "1" 'PcPieceID
Tbl(1, 2) = "M102"
Tbl(2, 2) = "3980"
Tbl(3, 2) = "2562"
Tbl(4, 2) = "1"
Tbl(5, 2) = "2"
'Etc...
For I = 1 To UBound(Tbl, 2)
XML = "<PrgPieces>" & vbCrLf
XML = XML & "<PcPage/>" & vbCrLf
XML = XML & "<PcQuality>" & Tbl(4, I) & "</PcQuality>" & vbCrLf
XML = XML & "<PcPieceID>" & Tbl(5, I) & "</PcPieceID>" & vbCrLf
XML = XML & "<PcLength>" & Tbl(2, I) & "</PcLength>" & vbCrLf
XML = XML & "<PcNumberOfPieces>1</PcNumberOfPieces>" & vbCrLf
XML = XML & " <PcPriority>0</PcPriority>" & vbCrLf
XML = XML & "<PcUnloader1>2</PcUnloader1>" & vbCrLf
XML = XML & "<PcUnloader2>0</PcUnloader2>" & vbCrLf
XML = XML & "<PcPrinterCode></PcPrinterCode>" & vbCrLf
XML = XML & "<PcPrinterId></PcPrinterId>" & vbCrLf
XML = XML & "<PcPrinterField1></PcPrinterField1>" & vbCrLf
XML = XML & "<PcPrinterField2>" & Tbl(3, I) & "</PcPrinterField2>" & vbCrLf
XML = XML & "<PcPrinterField3>" & Tbl(1, I) & "</PcPrinterField3>" & vbCrLf
XML = XML & "<PcPrinterField4></PcPrinterField4>" & vbCrLf
XML = XML & "<PcPrinterField5></PcPrinterField5>" & vbCrLf
XML = XML & "<PcPrinterField6></PcPrinterField6>" & vbCrLf
XML = XML & "<PcPrinterField7></PcPrinterField7>" & vbCrLf
XML = XML & "<PcPrinterField8></PcPrinterField8>" & vbCrLf
XML = XML & "<PcPrinterField9></PcPrinterField9>" & vbCrLf
XML = XML & "<PcPrinterField10></PcPrinterField10>" & vbCrLf
XML = XML & "<PcNumberOfDonePieces>0</PcNumberOfDonePieces>" & vbCrLf
XML = XML & "<PcSelected>1</PcSelected>" & vbCrLf
XML = XML & "</PrgPieces>"
ChaineXML = ChaineXML & XML
MsgBox ChaineXML 'n'affichera pas tout au second passage mais c'est pour le test !
Next I
End Sub
Génial cette réponse Theze !
J'avoue que je me rends compte que la solution dépasse largement mon champs de compétences (je suis charpentier à la base hein !), mais ça me motive d'autant plus après avoir suivi un petit tuto sur le VBA de savoir qu'un cas concret me tend les bras.
Cependant, une légère zone d'ombre concernant ton texte introductif. Tu parles de "groupe principal qui nécessite le changement de valeur avec ces dernières dans un tableau dont j'aurais au préalable défini le nombre de dimensions nécessaires". Cela signifie-t-il de regrouper toutes les pièces par sections identiques, comme le fait la petite macro de tri dans mon exemple ?
Néanmoins, je ne vois pas apparaître les sections dans ta macro, dois-je réfléchir à une macro à part entière qui générerait ce code xml d'en-tête ?
Désolé pour ce manque de discernement, mais je ne m'attendais à une avancée si folle après mon premier post, un énorme merci pour le temps consacré !
Baptiste.
Re,
On peut voir que tu as les balises :
<PrgPieces>
'...
<PrgPieces>
Qui se répètent et qui ont des valeurs variables. Donc j'imagine qu'il est possible de définir les débuts et fin du code, pour le début :
<?xml version="1.0"?>
<Programs fileversion="version 1.0">
<PrgProgram>02012018_Test_Stromab</PrgProgram>
<PrgHeadTrimmingLength>0</PrgHeadTrimmingLength>
<PrgTailTrimmingLength>0</PrgTailTrimmingLength>
<PrgPrinterField1></PrgPrinterField1>
<PrgPrinterField2></PrgPrinterField2>
<PrgPrinterField3></PrgPrinterField3>
<PrgPreOptimized>0</PrgPreOptimized>
<PrgProgrammedBarLength>0</PrgProgrammedBarLength>
<PrgSections>
<SecSectionID>1</SecSectionID>
<SecHeight>30</SecHeight>
<SecMinWidth/>
<SecMaxWidth/>
<SecWidth>65</SecWidth>
<PreOpt/>
pour la fin :
</PrgSections>
</Programs>
et donc, les différents groupes ou "blocs" dont je parlais dans mon précédent post, comme celui-ci :
<PrgPieces>
<PcPage/>
<PcQuality>1</PcQuality>
<PcPieceID>1</PcPieceID>
<PcLength>830</PcLength>
<PcNumberOfPieces>1</PcNumberOfPieces>
<PcPriority>0</PcPriority>
<PcUnloader1>2</PcUnloader1>
<PcUnloader2>0</PcUnloader2>
<PcPrinterCode></PcPrinterCode>
<PcPrinterId></PcPrinterId>
<PcPrinterField1></PcPrinterField1>
<PcPrinterField2>2572</PcPrinterField2>
<PcPrinterField3>MD101</PcPrinterField3>
<PcPrinterField4></PcPrinterField4>
<PcPrinterField5></PcPrinterField5>
<PcPrinterField6></PcPrinterField6>
<PcPrinterField7></PcPrinterField7>
<PcPrinterField8></PcPrinterField8>
<PcPrinterField9></PcPrinterField9>
<PcPrinterField10></PcPrinterField10>
<PcNumberOfDonePieces>0</PcNumberOfDonePieces>
<PcSelected>1</PcSelected>
</PrgPieces>
<PrgPieces>
qui je pense, définissent les pièces à usiner et dont il est possible de définir les variables (valeurs qui sont changeantes) comme par exemple :
<PcLength>830</PcLength>
où 830 est une variable que j'ai fais évoluer avec un tableau :
Tbl(2, 1) = "830" 'PcLength
Re-bonsoir Theze,
Et merci pour tant de réactivité et de clarté.
Tu as effectivement raison sur l'architecture du code du fichier, à ce détail près: les pièces de bois sont avant tout réuni sous la balise
<SecSectionID>1</SecSectionID>
<SecHeight>30</SecHeight>
<SecMinWidth/>
<SecMaxWidth/>
<SecWidth>65</SecWidth>
<PreOpt/>
qui se répètent pour chaque section (hauteur x épaisseur, ou height et width).
Pour chaque section, il faut donc générer cet "en-tête" de code puis puis le code que tu as déjà rédigé pour les pièces qui possèdent cette section.
Cela change-t-il la structure de ta macro ?
Bonjour,
Je pense que la partie "Section" peut être répétée pour chaque pièce sans que le compilateur de la machine en prenne ombrage
Je suis parti avec un "type Utilisateur" afin de rendre le code plus facile à manipuler et en fin de proc, un fichier XML est créé dans le même dossier que celui du classeur où tu colleras le code ci-dessous. Pour les différentes valeurs, tu peux créer un tableau dans une feuille et ensuite, les récupérer dans le tableau de type Utilisateur dans une boucle avant de l'injecter dans le code xml :
Type Piece
IDPiece As Integer
IDSection As Integer
Mur As String
Largeur As Double
Hauteur As Double
Longueur As Double
Qualite As Integer
NBPiece As Integer
Nombre As Integer
Champ2 As Long
'etc...
End Type
Sub Test()
Dim Tbl() As Piece
Dim DebutXML As String
Dim FinXML As String
Dim XML As String
Dim ChaineXML As String
Dim I As Integer
'créer autant de dimensions que nécessaire !
'les valeurs pouvant être récupérées dans un tableau sur une feuille
ReDim Tbl(1 To 2) 'pour le test, deux dimensions
Tbl(1).IDPiece = 1
Tbl(1).IDSection = 1
Tbl(1).Mur = "M101"
Tbl(1).Hauteur = 30
Tbl(1).Largeur = 65
Tbl(1).Longueur = 830
Tbl(1).NBPiece = 1
Tbl(1).Qualite = 1
Tbl(1).Nombre = 1
Tbl(1).Champ2 = 2572
Tbl(2).IDPiece = 1
Tbl(2).IDSection = 1
Tbl(2).Mur = "M101"
Tbl(2).Hauteur = 30
Tbl(2).Largeur = 65
Tbl(2).Longueur = 830
Tbl(2).NBPiece = 1
Tbl(2).Qualite = 1
Tbl(2).Nombre = 1
Tbl(2).Champ2 = 2562
DebutXML = "<?xml version=""1.0""?>" & vbCrLf
DebutXML = DebutXML & "<Programs fileversion=""version 1.0"">" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgProgram>02012018_Test_Stromab</PrgProgram>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgHeadTrimmingLength>0</PrgHeadTrimmingLength>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgTailTrimmingLength>0</PrgTailTrimmingLength>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPrinterField1></PrgPrinterField1>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPrinterField2></PrgPrinterField2>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPrinterField3></PrgPrinterField3>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPreOptimized>0</PrgPreOptimized>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgProgrammedBarLength>0</PrgProgrammedBarLength>" & vbCrLf
DebutXML = DebutXML & vbCrLf
FinXML = Space(4) & "</PrgSections>" & vbCrLf
FinXML = FinXML & "</Programs>" & vbCrLf
For I = 1 To UBound(Tbl)
XML = XML & vbCrLf
XML = Space(4) & "<PrgSections>" & vbCrLf
XML = XML & Space(8) & "<SecSectionID>" & Tbl(I).IDSection & "</SecSectionID>" & vbCrLf
XML = XML & Space(8) & "<SecHeight>" & Tbl(I).Hauteur & "</SecHeight>" & vbCrLf
XML = XML & Space(8) & "<SecMinWidth/>" & vbCrLf
XML = XML & Space(8) & "<SecMaxWidth/>" & vbCrLf
XML = XML & Space(8) & "<SecWidth>" & Tbl(I).Largeur & "</SecWidth>" & vbCrLf
XML = XML & Space(8) & "<PreOpt/>" & vbCrLf
XML = XML & vbCrLf
XML = XML & Space(8) & "<PrgPieces>" & vbCrLf
XML = XML & Space(12) & "<PcPage/>" & vbCrLf
XML = XML & Space(12) & "<PcQuality>" & Tbl(I).Qualite & "</PcQuality>" & vbCrLf
XML = XML & Space(12) & "<PcPieceID>" & Tbl(I).IDPiece & "</PcPieceID>" & vbCrLf
XML = XML & Space(12) & "<PcLength>" & Tbl(1).Longueur & "</PcLength>" & vbCrLf
XML = XML & Space(12) & "<PcNumberOfPieces>" & Tbl(1).Nombre & "</PcNumberOfPieces>" & vbCrLf
XML = XML & Space(12) & "<PcPriority>0</PcPriority>" & vbCrLf
XML = XML & Space(12) & "<PcUnloader1>2</PcUnloader1>" & vbCrLf
XML = XML & Space(12) & "<PcUnloader2>0</PcUnloader2>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterCode></PcPrinterCode>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterId></PcPrinterId>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField1></PcPrinterField1>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField2>" & Tbl(I).Champ2 & "</PcPrinterField2>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField3>" & Tbl(I).Mur & "</PcPrinterField3>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField4></PcPrinterField4>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField5></PcPrinterField5>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField6></PcPrinterField6>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField7></PcPrinterField7>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField8></PcPrinterField8>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField9></PcPrinterField9>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField10></PcPrinterField10>" & vbCrLf
XML = XML & Space(12) & "<PcNumberOfDonePieces>0</PcNumberOfDonePieces>" & vbCrLf
XML = XML & Space(12) & "<PcSelected>1</PcSelected>" & vbCrLf
XML = XML & Space(12) & "</PrgPieces>" & vbCrLf
XML = XML & vbCrLf
ChaineXML = ChaineXML & XML
Next I
ChaineXML = DebutXML & ChaineXML & FinXML
CreerXML ChaineXML
End Sub
Sub CreerXML(Chaine As String)
Dim I As Integer
Open ThisWorkbook.Path & "\TestXML.xml" For Output As #1
Print #1, Chaine
Close #1
End Sub
Re,
Je viens de bosser un peu plus sur mon exemple (et corrigé 2, 3 fautes dues au copier/coller). Je n'avais pas fais attention que tu avais posté un classeur sur cjoint donc, à partir de ce classeur j'ai créé une seconde feuille avec les valeur de la feuille "Feuil1" etg j'ai mis des commentaires de même pour le code. A toi de voir si ça convient !
Re-bonjour,
Génial, ça me semble tout bonnement parfait ! Je dois rajouter deux champs liés au type d'éjection (PcUnloader1 et 2) dans le type utilisateur. Aussi, le fichier sera utilisé par des novices d'Excel, je vais chercher une macro pour trier directement le fichier par ID Section <
Et la macro du début permet de classer les pièces par section pour avoir un oeil sur celle qui est la plus représentée et la longueur en mètre linéaire pour chaque quantité (longueur * quantité), mais je ne l'ai pas abouti, ça n'est donc pas indispensable.
Merci encore,
Baptiste.
Si tu rencontre un problème, n'hésites surtout pas à revenir !
Une idée pour générer automatiquement un ID par section ? Merci d'avance
Edit: le mieux est que j'essaye en bidouillant pour éviter de te déranger et que tu fasses tout le boulot. Je suis au bureau cet aprèm, je t'envoie une esquisse dans la soirée.
Bonne après-midi !
Re,
Je pense qu'après un tri sur la hauteur puis l'épaisseur (ou vice versa) il est possible de créer un IDSection chaque fois que l'une des deux ou les deux valeurs différent des précédentes, je regarde ça demain !
Bonne soirée
Hervé
Bonjour Theze,
Dans ce fichier, j'ai créé la colonne ID Section avec la condition =SI(ET(C3=C2;D3=D2);B2;B2+1) et un filtre croissant pour éviter que la même section porte différents ID Section mais cela ne suffit pas... Je regarde du côté des TCD
Ensuite pour les balises Pc Unloader 1 et 2, j'ai intégré deux colonnes EJ1 et EJ2 avec un remplissage par condition selon la longueur de la pièce. J'ai ainsi créé dans le type Utilisateur, les variables:
[codeEj1 As Byte
Ej2 As Byte][/code]
puis renseigné leur emplacement dans le tableau (colonne 8 et 9):
Tbl(I).Ej1 = Plage(I, 9).Value
Tbl(I).Ej2 = Plage(I, 10).Value
et enfin dans le corps du code à l'endroit des Pcunloader:
XML = XML & Space(12) & "<PcUnloader1>" & Tbl(I).Ej1 & "</PcUnloader1>" & vbCrLf
XML = XML & Space(12) & "<PcUnloader2>" & Tbl(I).Ej2 & "</PcUnloader2>" & vbCrLf
Néanmoins, lorsque je lance la macro, il m'affiche un message d'erreur: erreur d’exécution "13" et le débogage m'amène à la ligne
Tbl(I).Ej1 = Plage(I, 8).Value
. J'ai comme l'impression que l'erreur vient de moi...!
Bonjour,
Je poste le code complet avec la Sub de tri et création des IDSection :
Type Piece
IDPiece As Integer
IDSection As Integer
Mur As String
Epaisseur As Double
Hauteur As Double
Longueur As Double
Qualite As Integer
Quantite As Integer
Champ2 As Long 'je ne sais pas ce que c'est ?
'etc...
End Type
Sub Test()
Dim Tbl() As Piece
Dim Plage As Range
Dim DebutXML As String
Dim FinXML As String
Dim XML As String
Dim ChaineXML As String
Dim I As Integer
Dim Section As Integer
'la plage est définie à partir de A2 sur toute la feuille "Feuil2"
Set Plage = DefPlage(Worksheets("Feuil2"), 2, 1)
'tri et création des IDSection
TriSection Plage
'les valeurs correspondantes sont entrées dans le tableau
For I = 1 To Plage.Rows.Count
ReDim Preserve Tbl(1 To I)
Tbl(I).IDPiece = Plage(I, 1).Value
Tbl(I).IDSection = Plage(I, 2).Value
Tbl(I).Hauteur = Plage(I, 3).Value
Tbl(I).Epaisseur = Plage(I, 4).Value
Tbl(I).Longueur = Plage(I, 5).Value
Tbl(I).Quantite = Plage(I, 6).Value
Tbl(I).Mur = Plage(I, 7).Value
Tbl(I).Champ2 = Plage(I, 8).Value
Tbl(I).Qualite = 1 '<--- valeur identique pour tous les champs
Next I
'début du code XML
DebutXML = "<?xml version=""1.0""?>" & vbCrLf
DebutXML = DebutXML & "<Programs fileversion=""version 1.0"">" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgProgram>02012018_Test_Stromab</PrgProgram>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgHeadTrimmingLength>0</PrgHeadTrimmingLength>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgTailTrimmingLength>0</PrgTailTrimmingLength>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPrinterField1></PrgPrinterField1>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPrinterField2></PrgPrinterField2>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPrinterField3></PrgPrinterField3>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgPreOptimized>0</PrgPreOptimized>" & vbCrLf
DebutXML = DebutXML & Space(4) & "<PrgProgrammedBarLength>0</PrgProgrammedBarLength>" & vbCrLf
DebutXML = DebutXML & vbCrLf
'fin du code XML
FinXML = Space(4) & "</PrgSections>" & vbCrLf
FinXML = FinXML & "</Programs>" & vbCrLf
'construit le corps do code
For I = 1 To UBound(Tbl)
'n'inscrit le bloc de la section que si l'ID change
'(la variable "Section" étant initialisée à 0, le début du corps comporte d'office le bloc de section)
If Tbl(I).IDSection <> Section Then
XML = XML & Space(4) & "<PrgSections>" & vbCrLf
XML = XML & Space(8) & "<SecSectionID>" & Tbl(I).IDSection & "</SecSectionID>" & vbCrLf
XML = XML & Space(8) & "<SecHeight>" & Tbl(I).Hauteur & "</SecHeight>" & vbCrLf
XML = XML & Space(8) & "<SecMinWidth/>" & vbCrLf
XML = XML & Space(8) & "<SecMaxWidth/>" & vbCrLf
XML = XML & Space(8) & "<SecWidth>" & Tbl(I).Epaisseur & "</SecWidth>" & vbCrLf
XML = XML & Space(8) & "<PreOpt/>" & vbCrLf
XML = XML & vbCrLf
'pour le contrôle afin de ne pas doublonner
Section = Tbl(I).IDSection
End If
'valeurs propre à chaque pièce
XML = XML & Space(8) & "<PrgPieces>" & vbCrLf
XML = XML & Space(12) & "<PcPage/>" & vbCrLf
XML = XML & Space(12) & "<PcQuality>" & Tbl(I).Qualite & "</PcQuality>" & vbCrLf
XML = XML & Space(12) & "<PcPieceID>" & Tbl(I).IDPiece & "</PcPieceID>" & vbCrLf
XML = XML & Space(12) & "<PcLength>" & Tbl(I).Longueur & "</PcLength>" & vbCrLf
XML = XML & Space(12) & "<PcNumberOfPieces>" & Tbl(I).Quantite & "</PcNumberOfPieces>" & vbCrLf
XML = XML & Space(12) & "<PcPriority>0</PcPriority>" & vbCrLf
XML = XML & Space(12) & "<PcUnloader1>2</PcUnloader1>" & vbCrLf
XML = XML & Space(12) & "<PcUnloader2>0</PcUnloader2>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterCode></PcPrinterCode>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterId></PcPrinterId>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField1></PcPrinterField1>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField2>" & Tbl(I).Champ2 & "</PcPrinterField2>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField3>" & Tbl(I).Mur & "</PcPrinterField3>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField4></PcPrinterField4>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField5></PcPrinterField5>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField6></PcPrinterField6>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField7></PcPrinterField7>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField8></PcPrinterField8>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField9></PcPrinterField9>" & vbCrLf
XML = XML & Space(12) & "<PcPrinterField10></PcPrinterField10>" & vbCrLf
XML = XML & Space(12) & "<PcNumberOfDonePieces>0</PcNumberOfDonePieces>" & vbCrLf
XML = XML & Space(12) & "<PcSelected>1</PcSelected>" & vbCrLf
XML = XML & Space(12) & "</PrgPieces>" & vbCrLf
XML = XML & vbCrLf
Next I
'construction finale du code...
ChaineXML = DebutXML & XML & FinXML
'et création du fichier XML dans le même dossier que celui du classeur
CreerXML ChaineXML
End Sub
Sub TriSection(Plage As Range)
Dim I As Integer
Dim Concat As String
Dim J As Integer
'tri la plage du plujs petit au plus grand sur la colonne "Hauteur" puis "Epaisseur"
Plage.Sort Plage(1, 3), xlAscending, Plage(1, 4), , xlAscending
'crée les IDSection
For I = 1 To Plage.Rows.Count
If Plage(I, 3).Value & Plage(I, 4).Value <> Concat Then
J = J + 1: Plage(I, 2).Value = J
Concat = Plage(I, 3).Value & Plage(I, 4).Value
Else
Plage(I, 2).Value = J
End If
Next I
End Sub
Sub CreerXML(Chaine As String)
Open ThisWorkbook.Path & "\TestXML.xml" For Output As #1
Print #1, Chaine
Close #1
End Sub
Function DefPlage(Fe As Worksheet, Optional L As Long = 1, Optional C As Long = 1) As Range
On Error GoTo Fin
With Fe
Set DefPlage = .Range(.Cells(L, C), _
.Cells(.Cells.Find("*", .[A1], -4123, , _
1, 2).Row, .Cells.Find("*", .[A1], -4123, , _
2, 2).Column))
End With
Exit Function
Fin:
Set DefPlage = Nothing
End Function
Bonjour Theze,
Je regarde ça à l'instant, étant en déplacement sur des chantiers ce we. C'est tout bonnement mieux que ce que j'attendais !
J'ai voulu faire en sorte que les utilisateurs puissent renommer le fichier en entrant le nom dans une cellule de la feuille 1. Pour ça j'ai rajouté une variable en colonne 8 (=la cellule de la feuille 1 en question) puis recopié :
[codeDebutXML = DebutXML & Space(4) & "<PrgProgram>]" & Tbl(I).Epaisseur & "</PrgProgram>" & vbCrLf[/code]
mais ça ne fonctionne pas. De la même façon, est-ce possible que ce titre soit le nom du fichier sauvé dans le répertoire identique à la feuille xls ?
Encore merci ! En échange, si besoin un jour de conseils dans le calcul / fabrication de structure bois (pas tous les jours que ça se présente !), n'hésite pas !
Bonjour,
Si je comprend bien, tu veux avoir la possibilité de donner un nom particulier au fichier qui soit et dans le XML :
DebutXML = DebutXML & Space(4) & "<PrgProgram>" & Replace(NomFichier, " ", "_") & "</PrgProgram>" & vbCrLf '<--- remplace les espaces par des tirets bas
et être le nom du fichier XML sur le disque du genre "21-01-2018 Test de fichier" dans ce cas, au lancement de la macro un InputBox va demander de donner un nom au fichier, si il comporte des espaces, ils seront remplacés par des tirets bas dans le XML comme ceci :
21-01-2018_Test_de_fichier et l'extension ".xml" sera rajoutée au nom du fichier de cette façon :
21-01-2018 Test de fichier.xml
Je reposte le classeur avec le code modifié !
Royal !
Voici l'interface que j'ai mis en forme pour la version finale.
Le petit TCD sur le côté permet d'avoir une synthèse par section des mètre linéaire nécessaire et pour combien de pièces. Une petite macro permet de le rafraîchir.
J'avais mis au point une petite règle de formatage conditionnelle mais en copie-collant les données depuis le tableau du logiciel dont les cellules sont déjà formatées par un style, ça a complètement désordonné mon tri. Tant pis donc pour ce formatage, les infos arriveront comme elles arriveront.
Néanmoins, peux-tu me donner ton avis sur le degré de protection à rajouter pour éviter les fausses manip ? Et d'expériences, des infos qui peuvent s'avérer utiles des travers dans l'interface ?
Merci (encore) !
Bonjour,
Si ton tableau doit rester comme ça, ma fonction "DefPlage()" ne doit pas être utilisée car, si on prend la feuille "Principale", la plage sera définie de A2 à Kx et donc, il y aura plantage au niveau de la machine car le fichier .xml qui va sortir sera n'importe quoi !
Il te faut remplacer la ligne de code suivante :
Set Plage = DefPlage(Worksheets("Feuil2"), 2, 1)
par celle-ci :
With Worksheets("Principale"): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 6).End(xlUp)): End With
et tu peux supprimer la fonction "DefPlage()". La plage est définie sur les colonnes de A à F sur la feuille "Principale" à partir de A6 à Fx pour ne pas prendre en compte ton TCD.
Concernant la "protection", le mieux serait de récupérer automatiquement par macro les valeurs depuis le fichier source donné par le BE sans qu'il y est intervention de quelqu'un hormis pour le contrôle des valeurs
Bonsoir Hervé,
Derniers petits bugs avant l'utilisation: Les ID section et EJ dont je conditionne l'affiche avec des SI pose problème à la macro. Je viens de m'en rendre compte juste avant d'envoyer la maquette au BE, alors que ça ne causait pas de problème il y a encore une fois lors d'un autre essai...
Je sais qu'il est tard, mais là je ne pige pas...
Ci-joint le fichier
Merci d'avance pour ton aide, bien à toi.
Baptiste.
Bonjour,
C'est la présence des formules dans la colonne J qui pose problème car la plage est définie jusqu'à J11 alors qu'il n'y a aucune valeur ailleurs. Il ne faut pas utiliser de formule dans la zone, faire ça par macro. Voici ton classeur avec les modifications !
Merci mille fois Hervé !
J'ai juste modifié la cellule de sélection pour l'attribution des EJ, qui se fait selon la longueur de la pièce et non la quantité (colonne 7). Ca a l'air de tourner ! Les gars à l'atelier sont refaits de ne plus avoir à recopier les valeurs une par une dans la machine... !
Sur certaines liste de prod, les longueurs apparaissent sous une forme décimale de type 123,111 pour la longueur. J'ai beau modifier le format de la cellule, il ne s'agit que d'un formatage visuel et la longueur apparaît toujours avec autant de décimales dans le xml, ce qui ne plait pas à la machine (qui affiche tout bonnement 0).
Je te joins le fichier type de liste de prod (à copier coller dans le convertisseur) et le convertisseur avec des données et les décimales qui apparaissent dans la dernière colonne.
A l'avenir, pour limiter les actions "humaines", le mieux de créer une macro de demande de sélectionner le fichier source ou un simple userform sous forme de tableau à copier / coller suffirait ? Merci pour ton avis.
Très bon après-midi,
Baptiste.