Hi, 
you find a file attached, which contains my changes for a new class
(formated tables). 
It's a tar file, and it consists of 
1. diff.txt: the diff to the current cvs version (changes in CHANGES and
Documentation.sgml)
2. php/html/fmt_table.inc
3. sgml/05-fmt_tables.sgml
4. stuff/fmt_table.html (sample html output)

Perhaps someone with write access to the repository could commit it for me. 


Thanks to Holger Bahr for help and to Matt Wong for his proposal
(perhaps you could send some details of your solution)


Michael

-- 
GMX - Die Kommunikationsplattform im Internet.
http://www.gmx.net
diff.txt100644
      0      0        3102  7263020534  10603 
0ustar
  
rootroot?
 doc/sgml/05-fmt_table.sgml
? php/html/fmt_table.inc
? stuff/fmt_table.html
Index: CHANGES
===================================================================
RCS file: /repository/php-lib/CHANGES,v
retrieving revision 1.187
diff -u -r1.187 CHANGES
--- CHANGES     2001/01/05 09:30:21     1.187
+++ CHANGES     2001/04/05 07:39:58
@@ -1,5 +1,12 @@
 $Id: CHANGES,v 1.187 2001/01/05 09:30:21 max Exp $
 
+04-Mar-2001
+  - Added class fmt_table.inc; 
+  - added class documentation 05-fmt_table.sgml; 
+  - changed documentation.sgml in order to include fmt_table.sgml; 
+  - put fmt_table.html into stuff directory (sample html output of Fmt_Table)
+
 05-Jan-2001 max
   - Added user4.inc with User class that works with session4* session implementations.
 
Index: doc/sgml/documentation.sgml
===================================================================
RCS file: /repository/php-lib/doc/sgml/documentation.sgml,v
retrieving revision 1.11
diff -u -r1.11 documentation.sgml
--- doc/sgml/documentation.sgml 2000/02/24 23:33:02     1.11
+++ doc/sgml/documentation.sgml 2001/04/05 07:39:59
@@ -36,6 +36,7 @@
   <!ENTITY f05widget       SYSTEM "05-widget.sgml">
   <!ENTITY f05sqlquery     SYSTEM "05-sql_query.sgml">
   <!ENTITY f05table        SYSTEM "05-table.sgml">
+  <!ENTITY f05fmttable     SYSTEM "05-fmt_table.sgml">
   <!ENTITY f05menu         SYSTEM "05-menu.sgml">
   <!ENTITY f05menu2        SYSTEM "05-menu2.sgml">
   <!ENTITY f05form         SYSTEM "05-form.sgml">
@@ -93,6 +94,7 @@
 &f05widget;
 &f05sqlquery;
 &f05table;
+&f05fmttable;
 &f05menu;
 &f05menu2;
 &f05form;






























doc/sgml/05-fmt_table.sgml100644
     44    144       17431  7262646274  14463 
0ustar
  
adabasusers<sect1>Fmt&lowbar;Table
<p>

The Fmt&lowbar;Table class is an extension of Table that allows
you to pass content sensitive formating information to your 
html output. 
<p>
The Fmt&lowbar;Table class can be used to 
<itemize>
<item>span rows, e.g. concatenate all rows with the same
content; 
<item>span columns, e.g. concatenate fields in certain rows; 
<item>wrap the content of a cell with html tags, dependent on
the value of this or other cells in the specific row, e.g. 
if the value is less than the one of the other column, 
you want to show it with red font color; 
<item>put html code into the opening tag of a cell, dependent on 
the value of this or other cells in the specific row, e.g.
you want a different background color for some values. 
</itemize>

For the user the main extension to Table is the function 
<tt/add&lowbar;format()/, which takes the specific 
format conditions and format instructions for a column, an
array of columns or, if desired, for all columns. 

Imagine a table that contains two numerical columns ,'expected' 
and 'obtained'. The following code will assign a different 
font color to those values in the 'obtained' column, which are
less than the values in the 'expected' column. 
<p>

<tscreen><code>
$t-&gt;add_format(array('cols'=&gt;'obtained' , 
                     'conds'=&gt;"([expected] &gt; [])", 
                     'formats'=&gt;"&lt;font color='red'&gt;[]&lt;/font&gt;")); 
</code></tscreen>
<p>
An empty pair of square brackets is a placeholder for the value 
of the column in question ( resp. for the html presentation of this
value). 

The <tt/cols/ key of the format array also takes an array with 
a collection of column names or the special value <tt/ALL_COLUMNS/. 
If several columns are concerned, the placeholder always points to the
value of each single column, which is traversed. 
<p>
The <tt/conds/ key also might contain an array with several conditional 
expressions. In that case an array with a fitting number of
format instructions has to be assigned to the <tt/formats/ key. 
Please see the example below. 
<p>
The default for the <tt/conds/ key is <tt/true/, that means, all rows
will hit. 
<p>
The <tt/formats/ value(s) can contain the special <tt/met/ tag (my escape tag) for 
those values, that are directed to the cell opening tag. For example, a
<tt/&lt;met colspan=2&gt;/ will span two columns together. In that case you need to 
apply the special expression <tt/&lt;met MET_SKIP&gt;/ in the column to be skipped, in 
order to assure a fitting number of columns in the row, where the 
<tt/colspan/ is applied. 
<p>
The <tt/met/ tag is also the right place for text alignment and background color 
information. 

<p>

<sect2>Additional instance variables
<p>
<table>
<tabular ca="">
extrahtml<colsep>Takes html assignments for the table opening tag.<rowsep>
suppress&lowbar;empty<colsep>If set true, empty cells are filled with the 
<tt/&amp;nbsp;/ special char (some explorers neglect the  cell frame for empty cells). 
Default is <tt/false/<rowsep>
row&lowbar;span<colsep>Takes a field name or an array of field names which are 
concatenated (in case of identical values in consecutive rows).<rowsep>
</tabular>
<caption>Additional accessible instance variables.Only variables and 
functions additional to the Table class are listed. 
Please refer to the Table class documentation for further information. 
</caption>
</table>

<sect2>Additional instance methods
<p>

<descrip>

<tag>add&lowbar;format($ary)</tag> 
<p> 
Will add format conditions and format instructions to the table. 
The array <tt/$ary/ shall consist of the keys 
<itemize>
<item><tt/cols/ (value is a 
field name, an array of field names or the special value <tt/ALL_COLUMNS/), 
<item><tt/conds/ (value is a conditional expression or an array of conditional 
expressions, which probably will involve the value of the cell(s), for which
the format applies) and finally 
<item><tt/formats/, which will contain a format 
instruction (or an array of format instructions), which is applied to the cell
in case of succesful validation of <tt/conds/. 
</itemize>


<sect2>Example
<p>
Since the functionality of this class is best explained with approbiate
data, the data objects for this example are outlined. 

The example makes use of the DB&lowbar;Sql class of phplib. 

<p>
<tscreen><code>
// sql, that goes into the database first; 
// your sql-loader might expect a semi-colon after each command
//
drop table sales
//
create table sales (
category varchar (32),
product varchar (32),
expected fixed (5,2), 
obtained fixed (5,2)
)
//
insert into sales values ('sports','hoola hoops',103.56, 0)
//
insert into sales values ('sports','mountain bikes',155.88, 87.22)
//
insert into sales values ('sports','surf boards',106.56, 106.56)
//
insert into sales values ('entertainment','books',75.65, 109.44)
//
insert into sales values ('entertainment','videos',99.88, 82.34)
//
create view sales_view as
select 10 as order1,
       10 as order2,
       category, 
       product,
       expected,
       obtained,
       obtained - expected as difference
from   sales
union
select 10 as order1, 
       20 as order2,      
       category, 
       '' as product, 
       sum (expected) as expected, 
       sum (obtained) as obtained, 
       sum (obtained - expected) as difference
from   sales
group by category
union
select 20 as order1, 
       10 as order2,
       '' as category, 
       '' as product, 
       sum (expected) as expected, 
       sum (obtained) as obtained, 
       sum (obtained - expected) as difference
from   sales
//
grant select on sales_view to wwwrun
//
commit
</code></tscreen>
<p>
A view object is used for the computation of our provisional and 
final results. 
Here also the help fields <tt/order1/ and <tt/order2/ are introduced, that 
will constitute the proper order of details and results and will serve as an
hook to some format conditions. 

The user <tt/wwwrun/ is the database user account for the 
DB&lowbar;Sql class to access the database. 

The dedicated part of your php script may look like this: 

<tscreen><code>
require("fmt_table.inc"); 

$db = new DB_Sql_1; 

$q = 
" select * from sales_view " . 
" order by order1, category, order2, product"; 
$db-&gt;query($q); 

$t = new Fmt_Table; 
$t-&gt;heading = "on"; 
$t-&gt;suppress_empty = true; 
$t-&gt;extrahtml = "border width = 100%"; 

$t-&gt;fields=array("category","product","expected","obtained","difference"); 


$t-&gt;add_format(array('cols'=&gt;"obtained" , 
                     'conds'=&gt;array("(([]==0)or([expected]==[]))",
                                    "([expected] &lt; [])",
                                    "([expected] &gt; [])"), 
                     'formats'=&gt;array("&lt;font color='blue'&gt;[]&lt;/font&gt;",
                                      "&lt;font color='green'&gt;[]&lt;/font&gt;",
                                      "&lt;font color='red'&gt;[]&lt;/font&gt;"))); 


$t-&gt;add_format(array('cols'=&gt;"category", 
                     'conds'=&gt;"[order1] == 20", 
                     'formats'=&gt;"&lt;met colspan=2 align='right'&gt;Overall sum:"));

$t-&gt;add_format(array('cols'=&gt;"product", 
                     'conds'=&gt;"[order1] == 20", 
                     'formats'=&gt;"&lt;met MET_SKIP&gt;")); 


$t-&gt;add_format(array('cols'=&gt;"product", 
                     'conds'=&gt;"[order2] == 20", 
                     'formats'=&gt;"&lt;met align='right'&gt;Sum of [category]:")); 


$t-&gt;add_format(array('cols'=&gt;"difference", 
               'conds'=&gt;"[obtained] == 0", 
               'formats'=&gt;"&lt;i&gt;No Sales&lt;/i&gt;")); 


$t-&gt;add_format(array('cols'=&gt;"ALL_COLUMNS", 
                     'conds'=&gt;"[order1] == 20", 
                     'formats'=&gt;"&lt;met 
bgcolor='pink'&gt;&lt;b&gt;[]&lt;/b&gt;")); 


$t-&gt;add_format(array("cols"=&gt;"ALL_COLUMNS", 
                     "conds"=&gt;"[order2] == 20", 
                     "formats"=&gt;"&lt;met 
bgcolor='lightyellow'&gt;&lt;b&gt;[]&lt;/b&gt;")); 

$t-&gt;row_span = "category"; 

$t-&gt;show_result($db); 

</code></tscreen>

For an impression on how the html output does look like, see the file 
<tt/fmt_table.html/ in the <tt/stuff/ directory of the php-lib installation. 



php/html/fmt_table.inc100644
     44    144       26117  7262632704  14066 
0ustar
  
adabasusers<?php

/************************************************************************
*  class Fmt_Table extends Table {
*  extra functionality for content sensitive formating of cells; 
*  all additional formating information is done in html instead of css; 
*  Copyright (c) 2000,2001 by Michael Kuehne [EMAIL PROTECTED]
*  
************************************************************************/

class Fmt_Table extends Table {

  var $extrahtml; 
  var $col_func = array(); 
  var $suppress_empty=false; 
  var $row_span = false; 
  var $span_ary = array(); 
  var $headline_wrap;


  /************************************************************************
   *  function show_headline($headline){
   *  extra function for display of a headline above the table
   *
   ************************************************************************/

  function show_headline($headline){
    printf ($this->headline_wrap, $headline); 
  }

  /************************************************************************
   *  function table_open($class=""){
   *  prints table header with extra html
   *
   ************************************************************************/

  function table_open($class=""){
    printf("<table $this->extrahtml %s>\n", $class?" class=$class":""); 
  }

  /************************************************************************
   *  function show_info($db, $class =""){
   *  shows a query result (only 1 dataset allowed) as rotated table;  
   *  usefull for header information in 1:n - relations
   *
   ************************************************************************/

  function show_info($db, $class =""){
    if ($db->num_rows() > 1) {
      echo ("error in function show_info: more than 1 dataset!"); 
      return; 
    }
    $db->next_record(); 
    $ary = array(); 
    $ary_inv = array(); 
    $ary[] = $db->Record; 
    while(list($key,$val) = each($ary[0])){
      if (is_numeric($key)){continue;}
      if ($this->verify_array($this->map_cols)){
        reset($this->map_cols);
        while(list($mkey, $name) = each($this->map_cols)) {
          if ($mkey == $key){
            $key = $name;
            $found = 1;
            break;
          }
        }
      }
      $t_ary["Attrib"] = $key; 
      $t_ary["Value"] = $val; 
      $ary_inv[] = $t_ary; 
    }      
    $this->show($ary_inv, $class);
  }

  /************************************************************************
   *  function load_into_array($db) 
   *  loads query result into array; necessary, since we work here 
   *  with the table::show() function instead of table::show_result()
   *
   ************************************************************************/

  function load_into_array($db) 
    {
      if (!$this->verify_db($db))
        return 0;

      $ary = array(); 
    
      while ($db->next_record()){
        $ary[] = $db->Record; 
      }
    
      reset ($ary); 
      return $ary;
    }

  /************************************************************************
   *  function span ($ary) {
   *  checks results in the row(s) to span and prepares an array with
   *  the approbiate spanning information
   *
   ************************************************************************/

  function span ($ary) {
    if (!$this->row_span) { return 0 ; }
    
    $cols =  is_array ($this->row_span) ? 
      $this->row_span : array ($this->row_span); 

    $this->span_ary = $ary; 
    while (list ($colkey, $col) = each ($cols)){
      reset ($this->span_ary); 
      $distval = ""; 
      $distkey = 0; 
      $num_distrow = 0; 
      $row = 0; 

      while (list ($rowkey, $rowval) = each ($this->span_ary)) {
        $row++; 
        $num_distrow++; 
        if ($rowval [$col] == $distval) {
          $this->span_ary[$rowkey][$col] = -1; 
        }
        else {
          $this->span_ary [$distkey] [$col] = $num_distrow; 
          $num_distrow = 0; 
          $distkey = $row - 1; 
          $distval = $rowval [$col]; 
        }
      }
    }
  }

  /************************************************************************
   *  function add_format ($ary) {
   *  used for passing format information to the col_func - array
   *
   ************************************************************************/

  function add_format ($ary) {
    if (!is_array($ary))
      return false; 
    $ary['conds']=$ary['conds']?$ary['conds']:true; 
    $this->col_func[] = $ary; 
  }

  /************************************************************************
   *  function show_result($db, $class="") {
   *  similar functionality like table::show_result
   *
   ************************************************************************/

  function show_result($db, $class="") {

    if (!$this->verify_db($db))
      return 0;

    $ary = $this->load_into_array($db); 
    
    $this->show($ary, $class); 
  }     


  /************************************************************************
   *  function show($ary, $class=""){
   *  contains additional functionality; calls table::show()
   *
   ************************************************************************/

  function show($ary, $class=""){

    if (!$this->verify_2d_array($ary))
      return 0;

    $this->span ($ary); 

    while (list($rowkey, $rowval) = each ($ary)){

      while (list ($cellkey, $cellval) = each ($rowval)){

        if (is_array($this->col_func)){
          reset($this->col_func); 

          while (list($funckey,$funcval) = each($this->col_func)){
            if (($cellkey != '0') and (($funcval['cols'] == "ALL_COLUMNS") or
                   (strcmp($cellkey,$funcval['cols'])== 0)  or
                   (is_array($funcval['cols']) 
                    and in_array($cellkey, $funcval['cols'])))){
              $AryCondition = $funcval['conds'];
              $AryFormatExpression  = $funcval['formats']; 

              if (!is_array($AryCondition)){
                $AryCondition = array($AryCondition);
                $AryFormatExpression  = array($AryFormatExpression); 
              }

              while (list($condkey, $Condition) = each ($AryCondition)){
                $Condition = ereg_replace ("\[\]", '$cellval', $Condition); 
                if (ereg("(\[(.*)\])",$Condition, $regs))
                  $Condition = ereg_replace ("(\[.*\])",
                                             $rowval[$regs[2]],
                                             $Condition); 

                eval("\$f = ($Condition);"); 

                if ($f){
                  $expstr = "\"$AryFormatExpression[$condkey]\""; 
                  $expstr = ereg_replace ("\[\]", "\$cellval", $expstr); 
                  if (ereg("(\[(.*)\])",$expstr, $regs))
                    $expstr = ereg_replace ("(\[.*\])",
                                            $rowval[$regs[2]],
                                            $expstr); 

                    eval("\$cellval = ($expstr);");  
                    break; 
                }
              }
            }
          }
          $ary[$rowkey][$cellkey] = sprintf("%s", $cellval);     
        }
        if ($this->suppress_empty and strlen(strip_tags($cellval)) == 0){
          $ary[$rowkey][$cellkey].= sprintf("&nbsp;" ); 
        }
      }
    }
    reset ($ary); 

    $rows = 0;

    $this->table_open($class);
    if ($this->show_table_heading_row($ary, $class))
      $rows = $this->show_table_rows($ary, $class);
    $this->table_close($class);
    
    return $rows;
  }


  /************************************************************************
   *  function table_cell($row, $col, $key, $val, $class="") 
   *  contains additional functionality; calls table::table_cell()
   *
   ************************************************************************/

  function table_cell($row, $col, $key, $val, $class="") 
    {

      if ($this->row_span) {
        $cols =  is_array ($this->row_span) ? 
          $this->row_span : array ($this->row_span); 
      
        if (in_array ($key, $cols)) {
          $nbrows = $this->span_ary [$row] [$key]; 
          if ($nbrows == -1) 
            return; 
          else {
            $extra .= " rowspan=$nbrows valign=top ";
          }
        }
      }

      if (preg_match_all("|<met(.*)>|Ui",$val, $regs, PREG_PATTERN_ORDER)){
        while (list($regkey, $regval) = each($regs[1])){
          if (ereg('MET_SKIP',$regval)) {
            return; 
          }
          $extra .= " $regval"; 
        }
      }

      $this->table_cell_open($class, $extra);
      printf("%s", $val);
      $this->table_cell_close($class);

    }

  /************************************************************************
   *  function table_cell_open($class="", $extra="")
   *  outputs html tag for table cell open + additional html
   *
   ************************************************************************/

  function table_cell_open($class="", $extra="")
    {
      printf("  <td %s%s>", $extra, 
              $class?" class=$class":"");
    }

  /************************************************************************
   *  function table_heading_cell($col, $val, $class="") {
   *  checks whether column will be shown, outputs html for 
   *  table heading cell + extra html
   *
   ************************************************************************/

  function table_heading_cell($col, $val, $class="") {

  
    //Check for column name remapping
    if ($this->verify_array($this->map_cols))
      {
        reset($this->map_cols);
        while(list($key, $name) = each($this->map_cols)) 
          {
            if ($key == $val)
              {
                $val = $name;
                $found = 1;
                break;
              }
          }
      }

    if (preg_match_all("|<met(.*)>|Ui",$val, $regs, PREG_PATTERN_ORDER)){
      while (list($regkey, $regval) = each($regs[1])){
        if (ereg('MET_SKIP',$regval)) {
          return; 
        }
        $extra .= "$regval"; 
      }
    }

    $this->table_heading_cell_open($class, $extra);
    printf("%s", $val);
    $this->table_heading_cell_close($class);
  }


  /************************************************************************
   *  function table_heading_cell_open($class="", $extra="") {
   *  outputs opening tag for table heading cell  + extra html
   *
   ************************************************************************/

  function table_heading_cell_open($class="", $extra="") {
    printf("  <th %s%s>", $extra, 
            $class?" class=$class":"");
  }
    

  /************************************************************************
   *  function table_heading_row_add_extra($data, $class=""){
   *  outputs an additional heading cell 
   *  overload
   ************************************************************************/

  function table_heading_row_add_extra($data, $class=""){
    $this->table_heading_cell(0, "&nbsp;", $class);
  }



  /************************************************************************
   *  function table_row_add_extra($row, $row_key, $data, $class=""){
   *  outputs an additional cell
   *  overload
   ************************************************************************/

  function table_row_add_extra($row, $row_key, $data, $class=""){
    $this->table_cell($row, $col, $key, $data, $class=""); 
  }


}

?>stuff/fmt_table.html100644
     44    144        4075  7262646654  13645 
0ustar
  
adabasusers<html>
<head><title>Sample report with fmt_table.inc</title>
</head>
<BODY BGCOLOR="#FFFFFF">
<h1>
Sample output of Fmt_Table
</h1>

<table border width = 100%s>
 <tr>
  <th >category</th>
  <th >product</th>
  <th >expected</th>
  <th >obtained</th>
  <th >difference</th>
 </tr>
 <tr>
  <td  rowspan=3 valign=top >entertainment</td>
  <td >books</td>
  <td >75.65</td>
  <td ><font color='green'>109.44</font></td>
  <td >33.79</td>
 </tr>
 <tr>
  <td >videos</td>
  <td >99.88</td>
  <td ><font color='red'>82.34</font></td>
  <td >-17.54</td>
 </tr>
 <tr>
  <td   bgcolor='lightyellow'  align='right'><met bgcolor='lightyellow'><b><met 
align='right'>Sum of entertainment:</b></td>
  <td   bgcolor='lightyellow'><met bgcolor='lightyellow'><b>175.53</b></td>
  <td   bgcolor='lightyellow'><met bgcolor='lightyellow'><b><font 
color='green'>191.78</font></b></td>
  <td   bgcolor='lightyellow'><met bgcolor='lightyellow'><b>16.25</b></td>
 </tr>
 <tr>
  <td  rowspan=4 valign=top >sports</td>
  <td >hoola hoops</td>
  <td >103.56</td>
  <td ><font color='blue'>0</font></td>
  <td ><i>No Sales</i></td>
 </tr>
 <tr>
  <td >mountain bikes</td>
  <td >155.88</td>
  <td ><font color='red'>87.22</font></td>
  <td >-68.66</td>
 </tr>
 <tr>
  <td >surf boards</td>
  <td >106.56</td>
  <td ><font color='blue'>106.56</font></td>
  <td >0</td>
 </tr>
 <tr>
  <td   bgcolor='lightyellow'  align='right'><met bgcolor='lightyellow'><b><met 
align='right'>Sum of sports:</b></td>
  <td   bgcolor='lightyellow'><met bgcolor='lightyellow'><b>366</b></td>
  <td   bgcolor='lightyellow'><met bgcolor='lightyellow'><b><font 
color='red'>193.78</font></b></td>
  <td   bgcolor='lightyellow'><met bgcolor='lightyellow'><b>-172.22</b></td>
 </tr>
 <tr>
  <td  rowspan= valign=top   bgcolor='pink'  colspan=2 align='right'><met 
bgcolor='pink'><b><met colspan=2 align='right'>Overall sum:</b></td>
  <td   bgcolor='pink'><met bgcolor='pink'><b>541.53</b></td>
  <td   bgcolor='pink'><met bgcolor='pink'><b><font color='red'>385.56</font></b></td>
  <td   bgcolor='pink'><met bgcolor='pink'><b>-155.97</b></td>
 </tr>
</table>



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to