Schwierig! HTML Tabelle ausgeben

Hi zusammen

Ich würd gern mit PHP ein mehrdimensionales Array als HTML-Tabelle (Crosstable) ausgeben.

Beispiel:

Die Tabelle soll links die Länder und die dazugehörigen Kunden enthalten. Oben sollen Produktgruppen angezeigt werden. In der Mitte sollen die Stückzahlen und Umsätze angezeigt werden.

 Kunden Produktgruppe
\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_P1\_\_\_\_\_P2\_\_
Deutschland | Kunde A | Stück | 1000 | 500 |
 | | Umsatz | 3000 | 200 |
 | Kunde B | Stück | 2000 | 300 |
 | | Umsatz | 4000 | 200 |
Frankreich | Kunde C | Stück | 500 | 600 |
 | | Umsatz | 3000 | 700 |
 | Kunde D | Stück | 500 | 900 |
 | | Umsatz | 3000 | 100 |

Das Array wäre bei obiger Tabelle folgendermassen aufgebaut:

$crosstable[countryname][customername][productgroup][datatype] = value;
$zeilentitel = "countryname, customername";
$spaltentitel = "productgroup";

Wichtig ist, dass die Anzahl der einzelnen Bereiche (Zeilentitel / Spaltentitel / Datentitel) dynamisch sein muss; entsprechend könnte das Array auch anders aufgebaut sein, z.b.

$crosstable[continent][country][town][sex][age\_group][datatype] = value;
$zeilentitel = "continent, country, town";
$spaltentitel = "sex, age\_group";

Wie kann ich das Array als HTML-Tabelle rausschreiben?

Liebe Grüsse
Janosh

Hi…

Wenn Du im Topic schon eine selbsteinschätzung gibst, dann deutet das für mich darauf hin, dass Du durchaus php „sprichst“, richtig?
Du brauchst damit also keine Komplettlösung sondern nur die herangehensweise…?

Ich würd gern mit PHP ein mehrdimensionales Array als
HTML-Tabelle (Crosstable) ausgeben.

ich weiss nicht genau was Du mit Crosstable meinst - aber ich würde Dir ineinander verschachtelte Tabellen empfehlen, weils sonst zu schwierig wird das mit php zu lösen bzw zu komplex um das hier zu beschreiben…

Beispiel:
Die Tabelle soll links die Länder und die dazugehörigen Kunden
enthalten. Oben sollen Produktgruppen angezeigt werden. In der
Mitte sollen die Stückzahlen und Umsätze angezeigt
werden.

wenn ich Dich recht verstehe ist der array-key dabei der inhalt, oder?
deswegen nimmst Du z.b.
$keys = array_keys($crosstable);
danach gehst Du durch mit
echo „“;
for ($i = 0; $i $keys[$i]
(…)
echo "
}
echo „“;
durch…

da wo jetzt (…) steht musst Du dann die nächste behandlung machen
also quasi ein
$nextkeys = array_keys($crosstable[$keys[$i]]);
da das wahrscheinlich nicht geht musst Du $keys[$i] in einer zwischenvariable speichern…
dann bekommst Du die Kunden und dann im nächsten Schritt die untegeordneten Daten.
Könnte man evtl rekursiv lösen, aber bei 2 Ebenen in denen das genutzt wird (danach ist ja die Formatierung anders wenn ichs richtig sehe) lohnt das kaum…

Wichtig ist, dass die Anzahl der einzelnen Bereiche
(Zeilentitel / Spaltentitel / Datentitel) dynamisch
sein muss; entsprechend könnte das Array auch anders aufgebaut
sein, z.b.

$crosstable[continent][country][town][sex][age_group][datatype]
= value;
$zeilentitel = „continent, country, town“;
$spaltentitel = „sex, age_group“;

das schreit dann schon wieder nach einer rekursiven Funktion…
aber dafür halte ich die Struktur Deiner Daten eher unpraktisch.
Ich hab mir mal eine klasse gebaut in der ich solche mehrdimensionalen Arrays anzeigen hab lassen - hab ich nur nicht auf diesem Rechner und erfüllt auch nicht die Anforderung mit den Überschriften…

Hi MunichFreak

Meiner Ansicht nach muss es rekursiv gelöst werden, um die Anzahl der Dimensionen dynamisch zu haben. Aber genau damit hab ich echt Mühe.

Das Array wird mit folgender Funktion aufgebaut:

 function storeRow($db\_row) {
 $temp = & $this-\>tbl;
 foreach ($this-\>dbRowFields as $rf) {
 $temp = & $temp[$db\_row[$rf]];
 }
 foreach ($this-\>dbColFields as $cf) {
 $temp = & $temp[$db\_row[$cf]];
 }
 foreach ($this-\>dbDatFields as $df) {
 if (!isset($temp[$df])) $temp[$df] = 0;
 $temp[$df] += $db\_row[$df];
 }
 }

Welche Array-Struktur wäre denn deiner Meinung nach für die Rekursion und die anschliessende HTML-Ausgabe praktischer?

Danke für deine Hilfe

Gruss
Janosh

moinmoin

Meiner Ansicht nach muss es rekursiv gelöst werden, um die
Anzahl der Dimensionen dynamisch zu haben. Aber genau damit
hab ich echt Mühe.

ja, wenn es dynamisch wird wird es auch schwieriger…

Das Array wird mit folgender Funktion aufgebaut:

function storeRow($db_row) {
$temp = & $this->tbl;
foreach ($this->dbRowFields as $rf) {
$temp = & $temp[$db_row[$rf]];
}
foreach ($this->dbColFields as $cf) {
$temp = & $temp[$db_row[$cf]];
}
foreach ($this->dbDatFields as $df) {
if (!isset($temp[$df])) $temp[$df] = 0;
$temp[$df] += $db_row[$df];
}
}

Welche Array-Struktur wäre denn deiner Meinung nach für die
Rekursion und die anschliessende HTML-Ausgabe praktischer?

naja - ich verstehe nicht ganz wie die unterste Ebene in Deinem Array aufgebaut ist und wie Du die Arrays erstellst…
Wenn Du selbst abfangen kannst wie das array zusammengestellt wird dann wäre evtl eine zweidimensionale Lösung wesentlich leichter.
$array[id][country] = $country;
$array[id][kundenname] = $name;
$array[id][ort] = $ort;

sortierung wesentlich einfacher - so brauchst Du „nur“ abfragen, ob der Inhalt der Zeile zu der darüber sich geändert hat und wenn das der Fall ist den neuen Wert ausgeben…
(if ($array[$i][country] == $array[$i-1][country]) $eingabe = „“;
else $eingabe = $array[$i][country];
wobei country natürlich wieder $key[$i] sein muss damits dynamisch bleibt…

das einzige was man dazu sagen muss ist dass Deine id’s halt passen müssen und dass die Daten richtig sortiert ankommen…

hoffe dass das verständlich war…?
Munich

Hello again…

naja - ich verstehe nicht ganz wie die unterste Ebene in
Deinem Array aufgebaut ist und wie Du die Arrays erstellst…

Im Datenbereich der Tabelle können pro Schnittpunkt Kunde/Produktgruppe mehrere Werte vorhanden sein. (Siehe Beispiel oben: Stück und Umsatz). Die unterste Array-Ebene wird entsprechend gespeichert:
$array[…]…[‚Stück‘] = 10;
$array[…]…[‚Umsatz‘] = 20;

Wenn Du selbst abfangen kannst wie das array zusammengestellt
wird dann wäre evtl eine zweidimensionale Lösung wesentlich
leichter.
$array[id][country] = $country;
$array[id][kundenname] = $name;
$array[id][ort] = $ort;

Ja, das kann ich abfangen, nur die DB-Abfrage ist fix gegeben.
Als ID wäre die Kombination aus allen Zeilenattributen denkbar, also ID = $country."_"."_".$town."_".$customername;

Ich verstehe noch nicht, wie ich in der zweidimensionalen Lösung den „Spaltenbaum“ abbilden und ausgeben könnte (siehe 2. Beispiel oben: [‚Geschlecht‘][‚Altersgruppe‘] im Spaltenbereich)

Und generell ist die Ausgabe der Werte des Datenbereichs in der richtigen Spalte nicht ganz simpel. Oder kennst du eine einfache Möglichkeit?

Gruss,
Janosh

Moin

naja - ich verstehe nicht ganz wie die unterste Ebene in
Deinem Array aufgebaut ist und wie Du die Arrays erstellst…

Im Datenbereich der Tabelle können pro Schnittpunkt
Kunde/Produktgruppe mehrere Werte vorhanden sein. (Siehe
Beispiel oben: Stück und Umsatz). Die unterste Array-Ebene
wird entsprechend gespeichert:
$array[…]…[‚Stück‘] = 10;
$array[…]…[‚Umsatz‘] = 20;

ja, aber warum?

Wenn Du selbst abfangen kannst wie das array zusammengestellt
wird dann wäre evtl eine zweidimensionale Lösung wesentlich
leichter.
$array[id][country] = $country;
$array[id][kundenname] = $name;
$array[id][ort] = $ort;

Ja, das kann ich abfangen, nur die DB-Abfrage ist fix gegeben.
Als ID wäre die Kombination aus allen Zeilenattributen
denkbar, also ID = $country."_"."_".$town."_".$customername;

warum einfach wenns auch kompliziert geht?
$id = $id++;

Ich verstehe noch nicht, wie ich in der zweidimensionalen
Lösung den „Spaltenbaum“ abbilden und ausgeben könnte (siehe
2. Beispiel oben: [‚Geschlecht‘][‚Altersgruppe‘] im
Spaltenbereich)

Spaltenbaum:
$spaltennamen[$spaltennummer1] = „Alter“;
$spaltennamen[$spaltennummer2] = „Geschlecht“;

Und generell ist die Ausgabe der Werte des Datenbereichs in
der richtigen Spalte nicht ganz simpel. Oder kennst du eine
einfache Möglichkeit?

wenn ich Deinem Problem besser folgen könnte, aber besonders viel mühe bei der schilderung des Problems scheinst Du Dir nicht zu geben

Gruss,
Munich

Guten Morgen, Munich! Gut geschlafen?

ja, aber warum?

Die Werte aus der DB werden dadurch konsolidiert. Wenn ein Kunde mehrere Einträge hat, werden diese zu einem zusammengefasst.

Gut, nun hätte ich also ein Array mit dem „neuen“ Aufbau, z.b. wie folgt:

**Zeilenbaum:**
$array[1]['continent'] = "Europa";
$array[1]['country'] = "Deutschland";
$array[1]['customer'] = "Kunde A";

**Spaltenbaum:**
$spaltennamen[1] = "Produktgruppe K";
$spaltennamen[2] = "Produkt K-2";

**Datenbereich:**
Werte für Produkt K-2:
$array[1]['pieces'] = 100
$array[1]['intake'] = 300

Natürlich gebe ich mir Mühe, das Problem zu beschreiben! Wir haben hier eine Verbindung zwischen Datenbereich und Zeilenbereich (durch die ID-Nummer). Die Verbindung zum Spaltenbereich fehlt noch. Muss allenfalls doch eine 3. Dimension eingeführt werden?

Die weitere Frage ist, wie ich dieses „neue“ Array nun auf eine einfache Art als HTML rausschreiben könnte. Ich stelle mir in etwa sowas vor:

foreach ($array as $row) {
 echo "";
 foreach ($row as $val) echo "$val";
 echo "";
}

Das Problem dabei ist jedoch, dass die Werte auf die richtigen Spalten verteilt werden müssen. Wie im vorherigen Array-Beispiel kann es ja dann pro Produktgruppe mehrere Produkte haben, welche jeweils ihre eigenen Werte (Pieces / Intake) beinhalten. In obiger foreach-Schleife ist diese Funktionalität noch nicht enthalten.

Eine weitere, wichtige Funktionalität wird dann zusätzlich noch sein, verschiedene Spalten/Zeilen zu totalisieren. Aber vielleicht lassen wir das momentan mal aussen vor.

Gruss,
Janosh

Guten Morgen, Munich! Gut geschlafen?

gut ja, aber zu kurz -.-

Gut, nun hätte ich also ein Array mit dem „neuen“ Aufbau, z.b.
wie folgt:

Zeilenbaum:
$array[1][‚continent‘] = „Europa“;
$array[1][‚country‘] = „Deutschland“;
$array[1][‚customer‘] = „Kunde A“;

Frage dazu: ist der Aufbau IMMER gleich oder kanns sein dass die Datensätze sich in der anzahl unterscheiden sprich dass ein
$array[1][‚customer‘] auf einmal nicht gesetzt ist?

Spaltenbaum:
$spaltennamen[1] = „Produktgruppe K“;
$spaltennamen[2] = „Produkt K-2“;

Datenbereich:
Werte für Produkt K-2:
$array[1][‚pieces‘] = 100
$array[1][‚intake‘] = 300

Frage auch hier: Ist pieces und intake immer gegeben oder auch mal nur eins davon?

Natürlich gebe ich mir Mühe, das Problem zu beschreiben! Wir
haben hier eine Verbindung zwischen Datenbereich und
Zeilenbereich (durch die ID-Nummer). Die Verbindung zum
Spaltenbereich fehlt noch. Muss allenfalls doch eine 3.
Dimension eingeführt werden?

nein. Ich sehe ehrlich gesagt da keine Unterschiede zwischen Beschriftungsdaten und Inhaltsdaten.

Die weitere Frage ist, wie ich dieses „neue“ Array nun auf
eine einfache Art als HTML rausschreiben könnte. Ich stelle
mir in etwa sowas vor:

foreach ($array as $row) {
echo „“;
foreach ($row as $val) echo „$val“;
echo „“;
}

Das Problem dabei ist jedoch, dass die Werte auf die richtigen
Spalten verteilt werden müssen. Wie im vorherigen
Array-Beispiel kann es ja dann pro Produktgruppe mehrere
Produkte haben, welche jeweils ihre eigenen Werte (Pieces /
Intake) beinhalten. In obiger foreach-Schleife ist diese
Funktionalität noch nicht enthalten.

ermittle erst mal, wieviele Spalten Du brauchst also ein
$anzahl = count($array[1]); wobei natürlich die 1 immer da sein muss…

anschliessend weisst Du wie oft Du machen musst…
den Tabllenkopf gehste dann mit einer for schleife durch und prüfst immer auf
if (isset($spaltennamen[$i])) echo „$spaltennamen[$i]“;
else echo " ";

anschliessend geht das mit Deinen Inhaltsdaten genauso.
Natürlich musst Du Dir erst Deine Array-Keys wieder auslesen lassen.
Achtung - wenn Du die beiden Keys immer hast für Stück und Umsatz und die untereinander haben willst dann solltest Du entweder einen eigenen Array-Datensatz dafür bauen oder innerhalb der Schleife die beiden (bzw nur einen) Keys ausklammern und an der vorgesehenen Stelle dann eine neue Tabelle erzeugen…

Eine weitere, wichtige Funktionalität wird dann zusätzlich
noch sein, verschiedene Spalten/Zeilen zu totalisieren. Aber
vielleicht lassen wir das momentan mal aussen vor.

ist im Prinzip doch nicht sooo schwer…
zumindest wenn ich mich recht daran erinnere dass man mit
${$variablenname} = ${$variablenname} + $x;
variable variablennamen erstellen kann - der Name ist dann wieder der array-key…

nu musste aber langsam mal selbst auf nen grünen Zweig kommen :wink:

Frage dazu: ist der Aufbau IMMER gleich oder kanns sein dass
die Datensätze sich in der anzahl unterscheiden sprich dass
ein $array[1][‚customer‘] auf einmal nicht gesetzt ist?

Aus der DB kommt immer ein Wert, allenfalls ein Leerstring. Sollte es sich dabei um ein Zahlenfeld handeln, müsste es einfach als 0 interpretiert werden. (verhält sich auch bei pieces/intake so)

Ich habe mal die beiden functions gemäss deiner Idee angefangen:

function storeRow($db\_row, $zeilenfelder="", $spaltenfelder="") {
 $this-\>id++;
 $zeilenfelder = explode(",","country,customer,quantity,unitprice");
 foreach ($zeilenfelder as $dbfeld) $this-\>tbl\_zeilen[$this-\>id][$dbfeld] = $db\_row[$dbfeld];
 $spaltenfelder = explode(",","productcategory");
 foreach ($spaltenfelder as $dbfeld) $this-\>tbl\_spalten[$db\_row[$dbfeld]] = true;
}

function showTable() {
 $anzahl\_spalten = count($this-\>tbl\_spalten);

 echo "

";
(.??.)
echo „“;
}

Irgendwie komme ich aber nicht weiter. Wie kann ich nun die Werte in der richtigen Spalte rausschreiben? Wie werden überhaupt die Werte nach Produktgruppe/Produkt pro Kunde gespeichert?

Ich sehe noch keinen grünen Zweig… :frowning:

Grüsse nach München

Janosh

sorry aber entweder Du kommentierst Deinen code oder Du musst schon selbst damit klar kommen - ich hab keine Lust mir die funktion der Funktionen am inhalt zusammenzureimen…

Ausserdem verwendest Du ja offensichtlich Klassen und dann sind Deine Codeschnipsel wirklich nur ein kleiner Bereich…

Also, ich hab zwei Funktionen:

Die erste heisst storeRow() und baut das Array auf. Sie wird durch eine while($row = fetch($db_conn)) Schleife pro DB-Zeile aufgerufen. Sie müsste eigentlich auch die Werte konsolidieren; also wenn ein Kunde 2 Bestellungen in der DB hat, dass dann die Werte der beiden Bestellungen zusammengezählt werden.

Die zweite Funktion heisst showTable() und soll das Array in HTML ausgeben. Ich hab das Array $this->tbl benannt, aber das spielt ja keine Rolle. Die HTML Tabelle soll oben die Spaltentitel zeigen, link die Zeilentitel und in der Mitte die Werte an den richtigen Schnittpunkten.

Sorry für die undokumentierten Code-Schnipsel.

Gruss,
Janosh

Die erste heisst storeRow() und baut das Array auf. Sie wird
durch eine while($row = fetch($db_conn)) Schleife pro DB-Zeile
aufgerufen. Sie müsste eigentlich auch die Werte
konsolidieren; also wenn ein Kunde 2 Bestellungen in der DB
hat, dass dann die Werte der beiden Bestellungen
zusammengezählt werden.

ok, die lass ich dann aussenvor - ich geh davon aus, dass Dein array richtig aufgebaut wird aber gibs mal mit print_r($array); aus und kontrolliere das…

Die zweite Funktion heisst showTable() und soll das Array in
HTML ausgeben. Ich hab das Array $this->tbl benannt, aber
das spielt ja keine Rolle. Die HTML Tabelle soll oben die
Spaltentitel zeigen, link die Zeilentitel und in der Mitte die
Werte an den richtigen Schnittpunkten.

function showTable() {
 $anzahl\_spalten = count($this-\>tbl\_spalten);

 echo "

„;
$arraykeys = array_keys($this->tbl_spalten[1]);
//Tabellenheader erzeugen
echo „“;
for($i=1;$i$spaltenheaders[$i]“;
else echo " ";
}
echo „“;

//tabelleninhalt

for ($i = 1; $i tbl_zeilen; $i++)
{
echo „“;

for ($j = 1; $j $this->tbl_zeilen[$currentkey]";
}

echo „“;
}

echo „“;
}

verständlicher?

Hi Munich

Ja, jetzt ist es verständlicher.

for ($j = 1; $j $this->tbl_zeilen[$currentkey]";
}

Diese innere for-Schleife unter dem ‚Tabelleninhalt‘ funktioniert aber nicht so. $j müsste doch bei 0 beginnen und bis tbl_zeilen[] ja nur der „Zeilentitel“ gespeichert und nicht die Werte zum entsprechenden Titel in der entsprechenden Spalte. Oder wie wolltest du die Werte in diesem Array tbl_zeilen[] gespeichert haben?

Gruss,
Janosh

Ja, jetzt ist es verständlicher.

gut

for ($j = 1; $j $this->tbl_zeilen[$currentkey]";
}

Diese innere for-Schleife unter dem ‚Tabelleninhalt‘
funktioniert aber nicht so. $j müsste doch bei 0 beginnen und
bis id++; gesetzt und damit auf 1.

d.h. Dein Array fängt mit 1 an und nicht mit 0.

Ausserdem ist in
$this->tbl_zeilen[] ja nur der „Zeilentitel“ gespeichert
und nicht die Werte zum entsprechenden Titel in der
entsprechenden Spalte. Oder wie wolltest du die Werte in
diesem Array tbl_zeilen[] gespeichert haben?

das ist mir ziemlich egal :wink:
Du wirst das jetzt schon hinkriegen *g*

d.h. Dein Array fängt mit 1 an und nicht mit 0.

ok, klar.

das ist mir ziemlich egal :wink:
Du wirst das jetzt schon hinkriegen *g*

Der Thread ist ja mittlerweile schon sehr umfangreich geworden. Ich werd an dem Ansatz jetzt noch weitermachen, bis es (hoffentlich) klappt.

Vielen Dank für deine Mühen!

Grüsse,
Janosh

viel Erfolg owT
:wink: