Zeilen zu Spalten umwandeln

Moin,


ich teste gerade und stehe etwas auf dem Schlauch. Wir haben 2 CSV Dateien, eine enthält die Artikelstammdaten mit Preisen, Name, Beschreibung usw.


Aus JTL kommt nun eine 2. Datei, die die jeweiligen Attribute enthält. Diese sind aber Zeilenweise angeordnet. Damit ich die aber z.B. mit Marktplätzen verknüpfen kann, brauche ich quasi den Attributnamen als Zeile mit dem Attributwert als Wert. Habe nun gedacht das kann man als Master / Child machen, komme da aber nicht wirklich weiter, weil die Werte dann ja in den Zeilen stehen und ich die dann nicht ausgeben kann.


So sehen die Stammdaten aus:


image



dazu kommen jetzt die Attribute die aber Zeilenweise sind, also mehrfach die Artikelnummer mit jeweils Attributname und Attributwert.


image



So, wie kriege ich das jetzt so hin, das die Daten aus der 2. Datei die Zeilenweise angeordnet sind als Spalte mit Attributname als Spaltenname habe, und den Wert als Wert in der Zeile


Würde mich freuen hier eine Hilfestellung zu bekommen.


Klingt komplex.

Vielleicht hilft das KeyValueSpreadsheet Step weiter. Als Key-Spalte sollte man sich künstlich einen Schlüssel bauen aus Artikelnummer-Attributename-Attributewert. In einem SpreadsheetMapper kann man dann darauf zugreifen, um sich die Werte zu holen.





Halloi Hallo,


ein erster Ansatz hier wäre aus den Attributen (oder hier Zeilen JSON Key Value Paare zu machen)

Das heißt in einer neuen Spalte würde das Key Value Paar pro Zeile dann so aussehen: "Marke" : "HEIKO"

Das gruppierst du dann auf Artikelnummernebene und lässt die die neue Spalte Komma Seperiert ausgeben: "Marke" : "Heiko", "Gerätetyp" : "Kühlen und Heizen", ....

Nach dem Gruppieren baust du dann noch die Artikelnummer vor: "Artikelnummer" : "P1", "Marke" : "Heiko", "Gerätetyp" : "Kühlen und Heizen", ....

Die nächste Zeile würde dann so aussehen: "Artikelnummer" : "P2", "Marke" : "Bosch", "Gerätetyp" : "Bohren", .... Damit das dann ein valides JSON-Objekt ist, müssen noch geschweifte Klammern drumherum { ... }

Das gruppierst du dann nochmal so, dass das komplette Dokument in einer Zeile in ener Spalte drin ist. Das muss dann natürlich noch zu einem Array umgewandelt werden, so da dass du dann das hier drin stehen hast:


[
 {
  "Artikelnummer" : "P1",
  "Hersteller" : "Bosch"
 },
 {
  "Artikelnummer" : "P2",
  "Hersteller" : "Heinko"
 }
]

Wenn du Glück hast, kannst du das dann durch nen JSON2Spreadsheet Step jagen.

Du solltest dann auf das gewünschte Ergebnis kommen.


Diese Lösung ist ein riesiger Workaround und ich bin sicher Synesty hat da eine bessere Lösung parat.


Viele Grüße

Stefan

Ja Stefans Gedankengang ist schon gut. Ob es über den JSON-Umweg sein muss, kann man sicher diskutieren. Also es ist vermutlich eine Mischung aus verschiedenen Werkzeugen (Gruppieren, KeyValueSpreadsheet oder Mappingset / Querverweis)

Eine fertige Lösung haben wir nicht. Vermutlich würden wir mit dem TextHTMLWriter Step rangehen (ist ähnlich zu Stefans Ansatz über JSON2Spreadsheet) und vorher die Werte entsprechend zusammen-gruppieren.

Die Schwierigkeit hier ist, dass man erstmal die eindeutigen Attributnamen ermitteln muss (die die es überhaupt gibt), damit man daraus die Kopfzeile der CSV erstellen kann.

Alles nicht trivial. Sie können das gern bei uns als Projektanfrage anfragen oder sich an einen Partner wenden.

Nur noch mal um auch Missverständnissen vorzubeugen:

Könnten Sie nochmal eine Beispielausgabe der Zieldatei posten (so wie oben mit den Quelldaten)?

Nur damit wir hier nicht mutmaßen und am Ende doch etwas anderes sein soll, als wir denken.

Die Frage ist auch: Wieviele Attribute gibt es denn? Ist das eine überschaubare Anzahl oder bei jedem Artikel andere? Weil wenn es eher ein festes Set ist, könnte man evtl. auch pragmatischere Wege finden. Wenn es aber hochdynamisch ist, dann wird es komplizierter.

Moin,


leider ist das dynamisch, es sind unterschiedliche Anzahl von Attributen. Die Zieldatei muss im Prinzip die Daten aus der ersten Datei haben, sowie sämtliche vorhandenen Attribute aus der 2. Datei. Gibt es nicht die Möglichkeit das eventuell mit der Datenbank zu lösen über Master Child? Ich bin dazu noch nicht genug im Thema eingearbeitet. Im Prinzip wären ja die Attributpaare so ähnlich wie Varianten. Es müsste so sein, das die Artikelstammdaten quasi der Master sind, die Attribute die Childs und ich diese dann in einer einzigen Datei ausgeben kann, und zwar Zeilenweise.


Atrikelnummer | Name | Bild | Attributname1 | Attributname2 | Attributname3 |
123456789 | TEST | xxx | Attributwertwert1| Attributwertwert1 | Attributwertwert1|


Wenn es sich nicht dynamisch lösen lässt über die Datenbank wäre es auch möglich es soweit vorzubereiten das sämtliche theoretisch vorkommenen Attributnamen qangelegt werden. Sollten später mal welche dazu kommen, könnten man ja den Flow / Datenbank anpassen und um die weiteren Werte ergänzen....


Schon mal vielen Dank für den Input und die Hilfe, aber falls noch einer weitere Ideen hat.....



Gruß


Michael

Hallo Michael,


du würdest das zwar über in einen Datastore reinbekommen, leider aber nicht wie gewünscht abgreifen können. Hierbei scheitert es einfach beim Transponieren.

Meine JSON Lösung wäre zum Beispiel Dynamisch.

Am Besten wäre es aber, wenn du, wie bereits von Synesty Angefordert, deine zwei Dateien hier ablegst.

Dann kann man sich das mal genauer anschauen.


Viele Grüße

Ich habe hier mal beide Dateien mit fiktiven Werten angehängt. Habe nun noch einiges gelesen, wird aber wohl komplizierter als ich mir dachte......

Hallo Michael,


schau mal hier ob der angehangene Flow funktioniert.


Grüße

Stefan

wow, ich habe es jetzt mal schnell getestet, und es werden mir zumindest die Attribute mit den jeweiligen Werten in einer Zeile angezeigt. Jetzt muss ich nur noch die Artikellstammdaten dazu bekommen und dann könnte das so funktionieren. Ich muss mir den Flow gleich mal in Ruhe ansehen um zu verstehen was da überhaupt passiert :-)

ok, ich verstehe nicht alles davon, aber es scheint jetzt soweit zu funktionieren wie ich es benötige. Ich habe die Artikeldaten sowieso in der Datenbank, und nehme dann für das Outputfile leere Spalten, mit Querverweis aus der Datenbank, das scheint soweit zu funktionieren. Cooler wäre natürlich wenn ich nicht den Umweg über die DB gehen müsste und er aus den beiden Files eines generiert, aber so geht es auch. Wofür ist denn die 1. Variable in der ich die Artikeldaten abrufe? Ich kann aus keinen Spreadsheet auf diese zugreifen oder habe ich etwas übersehen. Erstmal echt vielen Dank.

Hallo Michael,


ich hatte die Artikeldaten Datei am Anfang nur da rein geworfen um zu schauen, was da so drin ist.


Ich muss hier wohl folgende Bemerkungen hinzufügen:

Ich habe am Anfang die Attribut Werte HTMLEscaped, das heißt, du musst die entsprechend wieder unEscapen damit der Original Text da drin steht.

Achte bitte, dass du eindeutige Attributnamen hast. Zum Beispiel gibt es hier für beide Artikel in der Attribut-Datei das Attribut "British thermal unit BTU" und "British thermal unit (BTU)". Von Synesty werden die identisch interpretiert. Das führt hintenrum zu Fehlern. Das sollte also vorher abgefangen werden oder einfach nicht in der Datei mit drin sein. Das selbe gilt für das Attribut "Schalldruckpegel Außen dB(A)".

Damit das hier funktioniert habe ich die doppelten Attribute vorher abgefangen.

Weiterhin war komischerweise in der Attribut Datei von dir ganz am Anfang ein Steuerzeichen drin.Ich hab das leider nicht raus bekommen, also habe ich hier die Datei ohne Header eingelesen.


Letzten Endes brauchst du hier keinen Datastore um die Daten zu verheiraten.

Über Spreadsheet Append und Gruppieren geht das auch.

Im Anhang der geupdatete Flow.


Grüße

Stefan

vielen Dank, das mit dem unescapen habe ich bereits mitbekommen, ebenso mit der Interpretierung der doppelten Werte. Anscheinend nimmt Synesty beim Namen Sonderzeichen heraus, zumindest Klammern usw. Ist aber kein Problem, ich habe damals beim Export einfach mal alle vorhandenen und früher gepflegten Werte genommen, das wird gerade eh überarbeitet und optimiert. Mir ging es um die Machbarkeit da wir von einem anderen Anbieter weg wollen. So wie es aussieht klappt das und ich werde morgen mal versuchen mit einem Testartikel einen Export für einen unserer Marktplätze zu machen um das dort zu listen. Mit dem Steuerzeichen hatte ich keine Probleme, habe die Originaldateien eben nochmal getestet, war problemlos, keine Ahnung warum das da drin war. Ich werde weiter testen und mich hier melden wenn es wieder Probleme und Fragen gibt. Danke nochmal!!!


Gruß


Michael

Hallo zusammen,


ich hänge mich mal dran und möchte vorab Stefan Helme für die super Vorarbeit danken! Ich stehe aktuell vor dem gleichen Problem wie Michael und konnte es anhand von Stefans Hilfe beinahe lösen.

Jedoch habe ich noch ein Problem:


Der JSONReader liest nur die Keys der ersten Zeile aus und schreibt diese als Spalten. Bereits ab der zweiten Zeile habe ich andere Keys und somit andere potentielle Spalten. Diese werden jedoch nicht mehr berücksichtigt. Ich habe das Gefühl als dass ich noch irgendwas um die Liste spannen muss, komm jedoch nicht darauf.


<#assign row = target.addRow()>
<#list json as j >
<#assign row = target.addRow()>
${addColumns(row, j,"",{"autoExpand":"asColumns"})}
</#list>

Das ist das erste JSON-Objekt, dessen Keys zu Columns werden:


[{ "SUPPLIER_PID" : "5150904", "FNAME" : { "farbe":"klar","norm":"EN 166/EN 170/CAT II","bezeichnung":"Schutzbrille Oklahoma","eshop-synonyme":"1000315, tp1000315, tp1000315","standardnormen166":"ja","uv-schutzen170":"99,9 %","sonnenschutzen172":"nein","material":"Polycarbonat","beschlagfrei":"nein","kratzfest":"ja","bruchsicherheit":"45 m/Sek.","duosphärischescheibe":"nein","vollsichtbrille":"nein","fürkorrekturbrillenträger":"ja" } }]

Und dies das zweite, hier werden die Keys schon nicht mehr zu Columns:


[{ "SUPPLIER_PID" : "4938028", "FNAME" : { "inhalt":"200 ml","bezeichnung":"Augenspülflasche ph-neutral","produkt-typ":"Flasche","eshop-synonyme":"3015102, tp3015102, tp3015102" } }]


Hallo Ludwig,


hattest du schon mal versucht die beiden JSONs zu kombinieren?

Das sollte dann so aussehen:

[{ "SUPPLIER_PID" : "5150904", 
"FNAME" : { "farbe":"klar","norm":"EN 166/EN 170/CAT II","bezeichnung":"Schutzbrille Oklahoma","eshop-synonyme":"1000315, tp1000315, tp1000315","standardnormen166":"ja","uv-schutzen170":"99,9 %","sonnenschutzen172":"nein","material":"Polycarbonat","beschlagfrei":"nein","kratzfest":"ja","bruchsicherheit":"45 m/Sek.","duosphärischescheibe":"nein","vollsichtbrille":"nein","fürkorrekturbrillenträger":"ja" } 
}, 
{ "SUPPLIER_PID" : "4938028", 
"FNAME" : { "inhalt":"200 ml","bezeichnung":"Augenspülflasche ph-neutral","produkt-typ":"Flasche","eshop-synonyme":"3015102, tp3015102, tp3015102" } 
}
] 

Dann sollte das Script eigentlich funktionieren.

Normalerweise sollte man das Script aber auch so bauen können, dass der mit mehreren Zeilen klar kommt, ich weiß aber leider aus dem Stehgreif gerade nicht wie.


Viele Grüße

Stefan

Hallo Stefan und danke für deine zügige Antwort.


Dein Vorschlag wäre eine statische Lösung. Da bei mir jedoch theoretisch in jeder Zeile andere Keys vorkommen können (wir haben knapp 340 potentielle Attribute) muss die Abfrage hochdynamisch bleiben. Es muss in jeder Zeile neu geprüft werden ob die Column aus dem JSON noch nicht existiert und daher durch "autoExpand" hinzugefügt wird.


Ich habe dein Konzept eigentlich so verstanden, dass genau das so hiermit funktioniert?


<#assign row = target.addRow()>
<#list json as j >
<#assign row = target.addRow()>
${addColumns(row, j,"",{"autoExpand":"asColumns"})}
</#list>


Hallo Ludwig,


normalerweise sollte es möglich sein, die beiden JSONs dynamisch zu kombinieren in dem du alles in eine Zeile gruppierst. Dein Trennzeichen ist hier ein Komma. Erst nach dem abschließenden Gruppieren solltest du dann die Array Klammern '[ ... ]' drum herum machen.


Das heißt, dass würde dann so aussehen:


Zeile1:


{ "SUPPLIER_PID" : "5150904", "FNAME" : { "farbe":"klar","norm":"EN 166/EN 170/CAT II","bezeichnung":"Schutzbrille Oklahoma","eshop-synonyme":"1000315, tp1000315, tp1000315","standardnormen166":"ja","uv-schutzen170":"99,9 %","sonnenschutzen172":"nein","material":"Polycarbonat","beschlagfrei":"nein","kratzfest":"ja","bruchsicherheit":"45 m/Sek.","duosphärischescheibe":"nein","vollsichtbrille":"nein","fürkorrekturbrillenträger":"ja" }}

Zeile 2:

{ "SUPPLIER_PID" : "4938028", "FNAME" : { "inhalt":"200 ml","bezeichnung":"Augenspülflasche ph-neutral","produkt-typ":"Flasche","eshop-synonyme":"3015102, tp3015102, tp3015102" } }

Gruppiert:

Zeile1, Zeile2

{ "SUPPLIER_PID" : "5150904", 
"FNAME" : { "farbe":"klar","norm":"EN 166/EN 170/CAT II","bezeichnung":"Schutzbrille Oklahoma","eshop-synonyme":"1000315, tp1000315, tp1000315","standardnormen166":"ja","uv-schutzen170":"99,9 %","sonnenschutzen172":"nein","material":"Polycarbonat","beschlagfrei":"nein","kratzfest":"ja","bruchsicherheit":"45 m/Sek.","duosphärischescheibe":"nein","vollsichtbrille":"nein","fürkorrekturbrillenträger":"ja" } 
}, 
{ "SUPPLIER_PID" : "4938028", 
"FNAME" : { "inhalt":"200 ml","bezeichnung":"Augenspülflasche ph-neutral","produkt-typ":"Flasche","eshop-synonyme":"3015102, tp3015102, tp3015102" } 
}

Klammern:

[ Zeile1, Zeile2]

[{ "SUPPLIER_PID" : "5150904", 
"FNAME" : { "farbe":"klar","norm":"EN 166/EN 170/CAT II","bezeichnung":"Schutzbrille Oklahoma","eshop-synonyme":"1000315, tp1000315, tp1000315","standardnormen166":"ja","uv-schutzen170":"99,9 %","sonnenschutzen172":"nein","material":"Polycarbonat","beschlagfrei":"nein","kratzfest":"ja","bruchsicherheit":"45 m/Sek.","duosphärischescheibe":"nein","vollsichtbrille":"nein","fürkorrekturbrillenträger":"ja" } 
}, 
{ "SUPPLIER_PID" : "4938028", 
"FNAME" : { "inhalt":"200 ml","bezeichnung":"Augenspülflasche ph-neutral","produkt-typ":"Flasche","eshop-synonyme":"3015102, tp3015102, tp3015102" } 
}
] 


Der erste Aufruf von <#assign row = target.addRow()> fügt eine leere Kopfzeile an dein Ausgabe-spreadsheet an. Das braucht Synesty, damit dort später die einzelnen Spalten hinzugefügt werden können. Das muss initial immer gemacht werden.


Mit den [ ] klammern werden ja in JSON Arrays definiert. Ein Array ist eine Liste von Objekten (in dem Fall deine Zeilen). Diese Objekte sind immer Komma getrennt.

Mit dem <#list json as j> sagst du also "Gehe durch alle Zeilen in der JSON-Liste (Array) und benenne mir die momentane Zeile (Objekt) als 'j'.

Der nächste Aufruf <#assign row = target.addRow()> bedeutet nun: "Füge für jede Zeile (Objekt) in der Liste (Array) eine leere Zeile zu dem Ausgabe-Spreadsheet hinzu."


Dann kommt der Aufruf:

${addColumns(row, j,"",{"autoExpand":"asColumns"})}

Hier werden alle JSON Attribute aus dem dem Objekt j zu der Spreadsheet Zeile "row" hinzugefügt.

Das autoexpand bewirkt dabei, dass automatisch alle hierarchischen Attribute mit in eigene Spalten kommen.

Diese Funktion beachtet dabei von alleine ob eine Spalte bereits besteht oder nicht.


An sonsten kannst du ja, wenn du willst deinen Flow hier anhängen und ich schaue mal drüber :)


Viele Grüße

Stefan