tableau dynamique et fusionner des cellules?

WoBy
Invité n'ayant pas de compte PHPfrance

09 mai 2005, 08:51

Bijour, j'ai créé un tableau en dur pour faire un planning de rendez-vous avec de colones :
la permiere avec les différents créneaux horaires (8h à 9h..)
la 2e jusqua la 6e representant les jours du Lundi au Vendredi

J'aimerai afficher les rendez-vous qui se trouvent ds ma base selon les heures dans les cases du tableau et le jour. Un rendez-vous ds la base dispose d'un libellé, d'une date, d'une heure de debut et d'une heure de fin.

Et est-il possible lorsque le rendez-vous dure plus d'1H de fusionner des cellules du tableau?

Mammouth du PHP | 19672 Messages

09 mai 2005, 09:02

Salut,
techniquement oui, bien sur que c'est possible. De là à te dire quoi faire et dans quelle partie du script sans voir le moindre bout de code, ça va être difficile.

Mais schématiquement, il faut que tu calcules pour chaque rendez-vous la durée.

Si ta ligne compte par exemple un maximum de huit colonnes, lors de la génération de la ligne, crée un pointeur qui va s'incrémenter à chaque cellule. En partant de 0 et jusqu'à 8 ou jusquà " < $nb_maxi_heures_par_jour". À chaque nouvelle cellule, il faut incrémenter ce pointeur.

Calcule pour chaque cellule la durée du rendez-vous et s'il dépasse une heure, fais générer ta balise td avec un attribut colspan du nombre d'heure obtenue et dans le même temps, fais incrémenter le pointeur de ce même nombre moins 1 pour éviter de construire trop de cellules.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

woBy
Invité n'ayant pas de compte PHPfrance

09 mai 2005, 15:14

C'est quoi exactement unb pointeur?
C'est une variable en fet?

Pour fusionner les cellules , j'ai juste besoin de faire appel a une fonction?

Mammouth du PHP | 19672 Messages

09 mai 2005, 20:47

C'est effectivement une variable que tu définis. Exemple.
<?php
$i = 0;
while($condition = true)
{
    execution_fonction();
    $i++;
}
Ici, le pointeur, c'est la variable $i : je l'initialise comme je veux, ici à 0 pour l'exemple: tant que la condition est vraie, j'exécute le contenu et j'incrément le pointeur $i. Dès que j'arriva à un moment où la condition n'est plus vraie, je n'exécute rien et on sort de la boucle.

Donc quand tu construis tes lignes, tu utilises une boucle pour créer à chaque tour une nouvelle cellule de tableau. Si un des rendez-vous a plus d'une heure, je dois le tester au moment de creer la cellule pour l'étirer en fusionnant sur plus d'une colonne. Je vais tester la longueur du rendez-vous à l'intérieur de la boucle. Si la valeur trouvée est par exemple 3, je vais ajouter dans la balise td un colspan="3". Mais comme je fusionne une cellule sur trois colonnes, il faut que je fasse deux tours de boucles de moins, sinon, j'aurais deux cellules de trop: donc, je vais d'abord incrémenter mon pointeur de la valeur du rendez vous : $i = $i + (3 -1): pourquoi "-1" ? parce que j'incrémente de 1 de toutes façon à la fin de la boucle et si je ne fais pas ça, il me manquera une cellule dans la ligne.

Voilà, comprends tu le principe ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

WoBy
Invité n'ayant pas de compte PHPfrance

11 mai 2005, 08:31

Voila mon code pr l'instant, j'affiche le mot rien ds les cellules.
Le probleme c'est que si un rendez-vous dure 3 h il va prendre 3 cellules alors que j'ai une colonne a gauche pr les creneaux horaires et tout sera faussé non avec une ligne 3 fois plus grande q'une normale ?!
Ou dois-je mettre ma condition avec le pointeur?


<table width="100%" height="75%" border="6" cellpadding="5" cellspacing="2" table background="images/fond2.gif">
<tr>
<td width="10%">&nbsp;</td><?
//On récupère les jours
for ($i=0; $i<5; $i++) {
?>
<td width="18%" class="colonnetableau">
<? $jour=Array("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi");
$aWeek=$vsem; $aYear=$van;
for ($aDay=0;$aDay<5;$aDay++) {
$adate=datefromweeknr($aYear, $aWeek, $aDay+1);
if ($i==$aDay) {
echo "$jour[$i]";
echo ' '.date('d-m-Y',$adate).'<br>'; }
} ?></td><?
}
?>
</tr>
<?
for ($i=8;$i<18;$i++){
$j=$i+1;
?>
<tr>
td width="10%" class="lignetableau"><? echo "$i"."H"." à "."$j"."H"; ?></td> <!-- On insère les créneaux horaires -->
<?
for ($k=1; $k<6 ; $k++){
?>
<td valign="middle" align="center" width="18%">
<?
echo "<font color=red size=2>Rien</font>";
?>
</td>
<?
}
?>
</tr>
<?
}
?>
</table>

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

11 mai 2005, 10:24

Voici ton code que j'ai redévelopper pour résoudre ton problème avec les RDV qui dépassent 1 heure.
Mais j'ai constaté que t'as pas une vision claire quant à la structure et la construction des tables HTML.

Saches que la construction d'une table HTML est séquentielle sous forme d'un Z : C'est à dire que l'on commence par créer les céllules par ligne en commençant par la gauche.

Pour construire une ligne <tr> on construit ses colonnes <td> ou <th> avant de passer à la ligne suivante.

Autrement dit, on ne peut pas consruire toute une colonne de céllule puis remonter pour en construire d'autres.

Le problème se complique si on a des céllules fiusinnées (en colonnes ou en lignes) celà suppose que le dessinateur du tableau connait à l'avance les céllules qui doivent occuper plusieurs colones ou lignes. Et du coup, éviter de redessiner des céllules déjà consommées par une fusion précédente.

Respectant tous ces principes, le programme que j'ai repris dresse le tableau du planning des RDV en plaçant des céllules fusionnées en lignes (crénneaux horaires) selon la durée du RDV.

Ainsi, si un RDV dure 2 heurs par exemple, la céllule consomme deux lignes (ROWSPAN=2) et la ligne suivante perd une céllule exactement sous celle du RDV plaçé.

Le programme commenté :
<table width="100%" border="6" cellpadding="5" cellspacing="2" table background="images/fond2.gif"> 
<tr><th width="11%"> 
<? 
//La base de données 
$jour=Array("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi"); 
//initialiser  les RDV et leurs durées (à rien et 0 heure par défaut) 
for ($c=0; $c <8; $c++) for ($j=0; $j <5; $j++) $RDV [$c][$j] = "Rien"; 
for ($c=0; $c <8; $c++) for ($j=0; $j <5; $j++) $durées_RDV [$c][$j] = 0; 
//Pour exemple je planifie 2 heures de RDV dans le crénneau 0 (dès 8H) le jour 0 (lundi) 
$RDV [0][0] = "RDV1";   
$durées_RDV [0][0] = 2; 

//Pour exemple je planifie 1 heure de RDV dans le crénneau 1 (dès 9H) le jour 2 (Mercredi) 
$RDV [1][2] = "RDV2";   
$durées_RDV [1][2] = 1;   
   
//Pour exemple je planifie 2 heures de RDV dans le crénneau 4 (dès 14H) le jour 4 (Vendredi) 
$RDV [4][4] = "RDV3";   
$durées_RDV [4][4] = 2;   

//On affiche l'entête du tableau (Les jours) 
for ($j=0; $j<5; $j++) { 
?> 
<th> 
<? 
echo "$jour[$j]"; 
} 

//En suite on affiche les 8 lignes correspondants aux crénneaux allant de 8H à 12H et de 14H à 18H 
//Les 8 crénneau peuvent être calculés automatiquement à partir de 8H 
$hd = 8; //Heure de départ des crénneaux d'un jour 
for ($c=0; $c<8 ; $c++){ 
//La première colonne de la ligne contient le crénneau calculé à partir de $hd 
?> 
<tr> 
<th> 
<? 
//La durée affichée d'un crénneau est toujour 1 heure 
$hf = $hd +1; //par exemple $hf contient 9H si $hd contient 8H 
echo "$hd"."H"." à "."$hf"."H"; 

//Préparer le crénneau suivant 
$hd += 1; 
//Correction pour le passage de midi à l'après-midi 
if ($hf == 12) $hd = 14; 

//La deuxieme partie de la ligne affichée contient les RDV des 5 jours 
for ($j=0; $j<5 ; $j++){ 
//Attention: ne pas créer de céllule si le crénneau précédent l'a déjà consommée à cause d'une durée qui dépasse 1 heure 
//$c : le n° du crénneau et $j celui du jour du RDV 
if (!($c>0 && $durées_RDV[$c-1][$j]>1)) { 
//la céllule qui s'affiche peut consommer plusieurs lignes selon la durée du RDV planifié (c'est ROWSPAN qui s'en charge) 
//BGCOLOR permet de peindre le fond si le RDV existe 
//COLOR change de couleur de texte si le RDV existe 
?> 
<td valign="middle" align="center" width="18%" rowspan=<? echo $durées_RDV[$c][$j]; ?> 
bgcolor="<? echo $durées_RDV[$c][$j]>0?"silver":""; ?>" style="color:<? echo $RDV[$c][$j]=="Rien"?"":"red"; ?>"> 
<? 
echo $RDV[$c][$j]; 
}//fin if 
}//fin for $j 
}//fin for $c 
?> 
</table> 
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

WoBy
Invité n'ayant pas de compte PHPfrance

11 mai 2005, 14:48

Ok c cool ca marche bien le code qu'on ma gentiment fait mais je fais un truc plus compliké.
En effet, je vais chercher le libellé des rendez-vous dans une base. Et en fonction du jour (car en fait, une fonction me trouve les 5 dates de la semaine selon le numero de semaine sur laquelle on a cliqué à la page précédente), je veux que le libellé s'insère dans la bonne colonne pour le bon jour.
il faut arriver a faire une comparaison entre la date du rdv et celui en entete et ensuite l'afficher dans la colonne correspondante en trouvant la variable j, voila mon pb.
Merci ca fait deja des jours que je galere sur ce plannning... :cry:


<!-- On construit et génère le tableau -->
<table width="100%" height="75%" border="6" cellpadding="5" cellspacing="2" table background="images/fond2.gif">
<tr><th width="10%">
<?
//La base de données
$jour=Array("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi");

//initialiser les RDV et leurs durées (à rien et 0 heure par défaut)
for ($c=0; $c <10; $c++) for ($j=0; $j <5; $j++) $RDV [$c][$j] = "Rien";
for ($c=0; $c <10; $c++) for ($j=0; $j <5; $j++) $durées_RDV [$c][$j] = 0;

//Pour exemple et pour test je planifie 2 heures de RDV dans le crénneau 0 (dès 8H) le jour 0 (lundi)
$RDV [0][0] = "RDV1";
$durées_RDV [0][0] = 2;


//On affiche l'entête du tableau (Les jours)
for ($j=0; $j<5; $j++) {
?>
<th width="18%" class="colonnetableau">
<?
$aWeek=$vsem; $aYear=$van;
for ($aDay=0;$aDay<5;$aDay++) {
$adate=datefromweeknr($aYear, $aWeek, $aDay+1);
if ($j==$aDay) {
echo "$jour[$j]";
echo ' '.date('d-m-Y',$adate).'<br>';}
}
}
require('config/myConnexion.php');
require('config/connect.php');

$query2 = 'SELECT libelle_rdv as lib, heure_deb, heure_fin, date FROM rendezvous, avoir WHERE avoir.code_rdv=rendezvous.code_rdv AND code_util="'.$vnom.'" ';
$result2 = mysql_query ($query2) or die (" La requête pour la recherche des rendez-vous a échouée ");
while ($row_Resul2=mysql_fetch_assoc($result2)) {
$c = $row_Resul2['heure_deb']-8 ;
//$j = 3;
$RDV [$c][$j] = $row_Resul2['lib'];
$durées_RDV [$c][$j] = $row_Resul2['heure_fin']-$row_Resul2['heure_deb'];
}
mysql_close();


//En suite on affiche les 10 lignes correspondants aux crénneaux allant de 8H à 18H
//Les 8 crénneau peuvent être calculés automatiquement à partir de 8H
$hd = 8; //Heure de départ des crénneaux d'un jour
for ($c=0; $c<10 ; $c++){
//La première colonne de la ligne contient le crénneau calculé à partir de $hd
?>
<tr>
<th width="10%" class="lignetableau">
<?
//La durée affichée d'un crénneau est toujour 1 heure
$hf = $hd +1; //par exemple $hf contient 9H si $hd contient 8H
echo "$hd"."H"." à "."$hf"."H";

//Préparer le crénneau suivant
$hd += 1;

//La deuxieme partie de la ligne affichée contient les RDV des 5 jours
for ($j=0; $j<5 ; $j++){
//Attention: ne pas créer de céllule si le crénneau précédent l'a déjà consommée à cause d'une durée qui dépasse 1 heure
//$c : le n° du crénneau et $j celui du jour du RDV
if (!($c>0 && $durées_RDV[$c-1][$j]>1)) {
//la céllule qui s'affiche peut consommer plusieurs lignes selon la durée du RDV planifié (c'est ROWSPAN qui s'en charge)
//BGCOLOR permet de peindre le fond si le RDV existe
//COLOR change de couleur de texte si le RDV existe

?>
<td valign="middle" align="center" width="18%" rowspan=<? echo $durées_RDV[$c][$j]; ?>
bgcolor="<? echo $durées_RDV[$c][$j]>0?"silver":""; ?>" color="<? echo $RDV[$c][$j]=="Rien"?"":"RED"; ?>">
<?
echo $RDV[$c][$j];
}//fin if
}//fin for $j
}//fin for $c
?>
</table>

WoBy
Invité n'ayant pas de compte PHPfrance

11 mai 2005, 15:38

C bon ce code marche bien mais j'ai piti souci.
Tout s'affiche correnctement ds la bonne colone et sur la ou les bonnes lignes. Mes cellules ou il y a pa de rdv affichent un ".". Mais certaines de ces cellules avec "." apparaissent completment a droite ds une colone apres le vendredi alors kils nont pas lieu d etre. Je sai pa pourkoi puisque ma variable j va juska 5 seulement !


<!-- On construit et génère le tableau -->
<table width="100%" height="75%" border="6" cellpadding="5" cellspacing="2" table background="images/fond2.gif">
<tr><th width="10%">
<?
//La base de données
$jour=Array("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi");
//initialiser les RDV et leurs durées (à rien et 0 heure par défaut)
for ($c=0; $c <10; $c++) for ($j=0; $j <5; $j++) $RDV [$c][$j] = ".";
for ($c=0; $c <10; $c++) for ($j=0; $j <5; $j++) $durées_RDV [$c][$j] = 0;

//On affiche l'entête du tableau (Les jours)
for ($j=0; $j<5; $j++) {
?>
<th width="18%" class="colonnetableau">
<?
$aWeek=$vsem; $aYear=$van;
for ($aDay=0;$aDay<5;$aDay++) {
$adate=datefromweeknr($aYear, $aWeek, $aDay+1);
if ($j==$aDay) {
echo "$jour[$j]";
$datentete = date('Y-m-d',$adate);
echo ' '.date('d-m-Y',$adate).'<br>';

require('config/myConnexion.php');
require('config/connect.php');

$query2 = 'SELECT libelle_rdv as lib, heure_deb, heure_fin, date FROM rendezvous, avoir WHERE avoir.code_rdv=rendezvous.code_rdv AND code_util="'.$vnom.'" and date="'.$datentete.'"';
$result2 = mysql_query ($query2) or die (" La requête pour la recherche des rendez-vous a échouée ");
while ($row_Resul2=mysql_fetch_assoc($result2)) {
if ($row_Resul2['date'] == $datentete) {
$c = $row_Resul2['heure_deb']-8 ;
$j = $aDay;
$RDV [$c][$j] = $row_Resul2['lib'];
$durées_RDV [$c][$j] = $row_Resul2['heure_fin']-$row_Resul2['heure_deb']; }
}
mysql_close();}
}
}


//En suite on affiche les 10 lignes correspondants aux crénneaux allant de 8H à 18H
//Les 8 crénneau peuvent être calculés automatiquement à partir de 8H
$hd = 8; //Heure de départ des crénneaux d'un jour
for ($c=0; $c<10 ; $c++){
//La première colonne de la ligne contient le crénneau calculé à partir de $hd
?>
<tr>
<th width="10%" class="lignetableau">
<?
//La durée affichée d'un crénneau est toujour 1 heure
$hf = $hd +1; //par exemple $hf contient 9H si $hd contient 8H
echo "$hd"."H"." à "."$hf"."H";

//Préparer le crénneau suivant
$hd += 1;

//La deuxieme partie de la ligne affichée contient les RDV des 5 jours
for ($j=0; $j<5 ; $j++){
//Attention: ne pas créer de céllule si le crénneau précédent l'a déjà consommée à cause d'une durée qui dépasse 1 heure
//$c : le n° du crénneau et $j celui du jour du RDV
if (!($c>0 && $durées_RDV[$c-1][$j]>1)) {
//la céllule qui s'affiche peut consommer plusieurs lignes selon la durée du RDV planifié (c'est ROWSPAN qui s'en charge)
//BGCOLOR permet de peindre le fond si le RDV existe
//COLOR change de couleur de texte si le RDV existe

?>
<td valign="middle" align="center" width="18%" rowspan=<? echo $durées_RDV[$c][$j]; ?>
bgcolor="<? echo $durées_RDV[$c][$j]>0?"silver":""; ?>" color="<? echo $RDV[$c][$j]=="."?"":"red"; ?>">
<?
echo $RDV[$c][$j];
}//fin if
}//fin for $j
}//fin for $c
?>
</table>

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

12 mai 2005, 13:04

J'avoue que je ne comprends pas pourquoi tu exécute ta requête dans la boucle des jours :
...
for ($j=0; $j<5; $j++) { 

?> 
<th width="18%" class="colonnetableau"> 
<? 
$aWeek=$vsem; $aYear=$van; 
for ($aDay=0;$aDay<5;$aDay++) { 
$adate=datefromweeknr($aYear, $aWeek, $aDay+1); 
if ($j==$aDay) { 
echo "$jour[$j]"; 
$datentete = date('Y-m-d',$adate); 
echo ' '.date('d-m-Y',$adate).'<br>'; 

require('config/myConnexion.php'); 
require('config/connect.php'); 

$query2 = 'SELECT libelle_rdv as lib, heure_deb, heure_fin, date FROM rendezvous, avoir WHERE avoir.code_rdv=rendezvous.code_rdv AND code_util="'.$vnom.'" and date="'.$datentete.'"'; 
$result2 = mysql_query ($query2) or die (" La requête pour la recherche des rendez-vous a échouée "); 
while ($row_Resul2=mysql_fetch_assoc($result2)) { 
if ($row_Resul2['date'] == $datentete) { 
$c = $row_Resul2['heure_deb']-8 ; 
$j = $aDay; 
$RDV [$c][$j] = $row_Resul2['lib']; 
$durées_RDV [$c][$j] = $row_Resul2['heure_fin']-$row_Resul2['heure_deb']; } 
} 
mysql_close();} 
} 
}
...
Et pourquoi le test : if ($j==$aDay) { ?
Et le test : if ($row_Resul2['date'] == $datentete) { si t'as le $j = $aDay; ?

Mais je suis sur que ce bloc peut être simplifié puisqu'au lieu de faire une boucle $aDay (5 fois) qui se trouve dans une boucle $j (5 fois) tu peux simplifier en éliminant soit $aDay soit $j.

Tu peux aussi éliminer les tests sur $aDay et $datentete en les intégrant dans la clause WHERE de SQL (ce qui est déjà fait pour $datentete.

Je vois que tu exécute la requête 5 fois évite alors de répeter le code de connexion dans la boucle.
Une autre idée consiste à éviter de repeter aussi la réexécution de la requête en la programmant pour retounrer tous les RDV de la semaine en utilisant le n° de la semaine et l'année comme paramètres de selection et en la sortant de la boucle des jours.

Simplifie d'abord ton code et suite on verra les petits de bugs.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène