Code

1523d3710b1f496588b62999d0021e306e0b83e2
[gosa.git] / class.writeexcel_format.inc.php
1 <?php
3 /*
4  * Copyleft 2002 Johann Hanne
5  *
6  * This is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this software; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place,
19  * Suite 330, Boston, MA  02111-1307 USA
20  */
22 /*
23  * This is the Spreadsheet::WriteExcel Perl package ported to PHP
24  * Spreadsheet::WriteExcel was written by John McNamara, jmcnamara@cpan.org
25  */
27 class writeexcel_format {
29     var $_xf_index;
30     var $_font_index;
31     var $_font;
32     var $_size;
33     var $_bold;
34     var $_italic;
35     var $_color;
36     var $_underline;
37     var $_font_strikeout;
38     var $_font_outline;
39     var $_font_shadow;
40     var $_font_script;
41     var $_font_family;
42     var $_font_charset;
43     var $_num_format;
44     var $_hidden;
45     var $_locked;
46     var $_text_h_align;
47     var $_text_wrap;
48     var $_text_v_align;
49     var $_text_justlast;
50     var $_rotation;
51     var $_fg_color;
52     var $_bg_color;
53     var $_pattern;
54     var $_bottom;
55     var $_top;
56     var $_left;
57     var $_right;
58     var $_bottom_color;
59     var $_top_color;
60     var $_left_color;
61     var $_right_color;
63     /*
64      * Constructor
65      */
66     function writeexcel_format() {
67         $_=func_get_args();
69         $this->_xf_index       = (sizeof($_)>0) ? array_shift($_) : 0;
71         $this->_font_index     = 0;
72         $this->_font           = 'Arial';
73         $this->_size           = 10;
74         $this->_bold           = 0x0190;
75         $this->_italic         = 0;
76         $this->_color          = 0x7FFF;
77         $this->_underline      = 0;
78         $this->_font_strikeout = 0;
79         $this->_font_outline   = 0;
80         $this->_font_shadow    = 0;
81         $this->_font_script    = 0;
82         $this->_font_family    = 0;
83         $this->_font_charset   = 0;
85         $this->_num_format     = 0;
87         $this->_hidden         = 0;
88         $this->_locked         = 1;
90         $this->_text_h_align   = 0;
91         $this->_text_wrap      = 0;
92         $this->_text_v_align   = 2;
93         $this->_text_justlast  = 0;
94         $this->_rotation       = 0;
96         $this->_fg_color       = 0x40;
97         $this->_bg_color       = 0x41;
99         $this->_pattern        = 0;
101         $this->_bottom         = 0;
102         $this->_top            = 0;
103         $this->_left           = 0;
104         $this->_right          = 0;
106         $this->_bottom_color   = 0x40;
107         $this->_top_color      = 0x40;
108         $this->_left_color     = 0x40;
109         $this->_right_color    = 0x40;
111         // Set properties passed to writeexcel_workbook::addformat()
112         if (sizeof($_)>0) {
113             call_user_method_array('set_properties', $this, $_);
114         }
115     }
117     /*
118      * Copy the attributes of another writeexcel_format object.
119      */
120     function copy($other) {
121         $xf = $this->_xf_index;   // Backup XF index
122         $this = $other;           // Copy properties
123         $this->_xf_index = $xf;   // Restore XF index
124     }
126     /*
127      * Generate an Excel BIFF XF record.
128      */
129     function get_xf() {
131         $_=func_get_args();
133         // $record    Record identifier
134         // $length    Number of bytes to follow
136         // $ifnt      Index to FONT record
137         // $ifmt      Index to FORMAT record
138         // $style     Style and other options
139         // $align     Alignment
140         // $icv       fg and bg pattern colors
141         // $fill      Fill and border line style
142         // $border1   Border line style and color
143         // $border2   Border color
145         // Set the type of the XF record and some of the attributes.
146         if ($_[0] == "style") {
147             $style = 0xFFF5;
148         } else {
149             $style   = $this->_locked;
150             $style  |= $this->_hidden << 1;
151         }
153         // Flags to indicate if attributes have been set.
154         $atr_num     = ($this->_num_format != 0) ? 1 : 0;
155         $atr_fnt     = ($this->_font_index != 0) ? 1 : 0;
156         $atr_alc     =  $this->_text_wrap ? 1 : 0;
157         $atr_bdr     = ($this->_bottom   ||
158                         $this->_top      ||
159                         $this->_left     ||
160                         $this->_right) ? 1 : 0;
161         $atr_pat     = ($this->_fg_color != 0x41 ||
162                         $this->_bg_color != 0x41 ||
163                         $this->_pattern  != 0x00) ? 1 : 0;
164         $atr_prot    = 0;
166         // Reset the default colors for the non-font properties
167         if ($this->_fg_color     == 0x7FFF) $this->_fg_color     = 0x40;
168         if ($this->_bg_color     == 0x7FFF) $this->_bg_color     = 0x41;
169         if ($this->_bottom_color == 0x7FFF) $this->_bottom_color = 0x41;
170         if ($this->_top_color    == 0x7FFF) $this->_top_color    = 0x41;
171         if ($this->_left_color   == 0x7FFF) $this->_left_color   = 0x41;
172         if ($this->_right_color  == 0x7FFF) $this->_right_color  = 0x41;
174         // Zero the default border colour if the border has not been set.
175         if ($this->_bottom == 0) {
176             $this->_bottom_color = 0;
177         }
178         if ($this->_top    == 0) {
179             $this->_top_color    = 0;
180         }
181         if ($this->_right  == 0) {
182             $this->_right_color  = 0;
183         }
184         if ($this->_left   == 0) {
185             $this->_left_color   = 0;
186         }
188         // The following 2 logical statements take care of special cases in 
189         // relation to cell colors and patterns:
190         // 1. For a solid fill (_pattern == 1) Excel reverses the role of
191         //    foreground and background colors
192         // 2. If the user specifies a foreground or background color
193         //    without a pattern they probably wanted a solid fill, so we
194         //    fill in the defaults.
195         if ($this->_pattern <= 0x01 && 
196             $this->_bg_color != 0x41 && 
197             $this->_fg_color == 0x40 )
198         {
199             $this->_fg_color = $this->_bg_color;
200             $this->_bg_color = 0x40;
201             $this->_pattern  = 1;
202         }
204         if ($this->_pattern <= 0x01 &&
205             $this->_bg_color == 0x41 &&
206             $this->_fg_color != 0x40 )
207         {
208             $this->_bg_color = 0x40;
209             $this->_pattern  = 1;
210         }
212         $record         = 0x00E0;
213         $length         = 0x0010;
215         $ifnt           = $this->_font_index;
216         $ifmt           = $this->_num_format;
218         $align          = $this->_text_h_align;
219         $align         |= $this->_text_wrap     << 3;
220         $align         |= $this->_text_v_align  << 4;
221         $align         |= $this->_text_justlast << 7;
222         $align         |= $this->_rotation      << 8;
223         $align         |= $atr_num              << 10;
224         $align         |= $atr_fnt              << 11;
225         $align         |= $atr_alc              << 12;
226         $align         |= $atr_bdr              << 13;
227         $align         |= $atr_pat              << 14;
228         $align         |= $atr_prot             << 15;
230         $icv            = $this->_fg_color;
231         $icv           |= $this->_bg_color      << 7;
233         $fill           = $this->_pattern;
234         $fill          |= $this->_bottom        << 6;
235         $fill          |= $this->_bottom_color  << 9;
237         $border1        = $this->_top;
238         $border1       |= $this->_left          << 3;
239         $border1       |= $this->_right         << 6;
240         $border1       |= $this->_top_color     << 9;
242         $border2        = $this->_left_color;
243         $border2       |= $this->_right_color   << 7;
245         $header      = pack("vv",       $record, $length);
246         $data        = pack("vvvvvvvv", $ifnt, $ifmt, $style, $align,
247                                         $icv, $fill,
248                                         $border1, $border2);
250         return($header . $data);
251     }
253     /*
254      * Generate an Excel BIFF FONT record.
255      */
256     function get_font() {
258         // $record     Record identifier
259         // $length     Record length
261         // $dyHeight   Height of font (1/20 of a point)
262         // $grbit      Font attributes
263         // $icv        Index to color palette
264         // $bls        Bold style
265         // $sss        Superscript/subscript
266         // $uls        Underline
267         // $bFamily    Font family
268         // $bCharSet   Character set
269         // $reserved   Reserved
270         // $cch        Length of font name
271         // $rgch       Font name
273         $dyHeight   = $this->_size * 20;
274         $icv        = $this->_color;
275         $bls        = $this->_bold;
276         $sss        = $this->_font_script;
277         $uls        = $this->_underline;
278         $bFamily    = $this->_font_family;
279         $bCharSet   = $this->_font_charset;
280         $rgch       = $this->_font;
282         $cch        = strlen($rgch);
283         $record     = 0x31;
284         $length     = 0x0F + $cch;
285         $reserved   = 0x00;
287         $grbit      = 0x00;
289         if ($this->_italic) {
290             $grbit     |= 0x02;
291         }
293         if ($this->_font_strikeout) {
294             $grbit     |= 0x08;
295         }
297         if ($this->_font_outline) {
298             $grbit     |= 0x10;
299         }
301         if ($this->_font_shadow) {
302             $grbit     |= 0x20;
303         }
305         $header  = pack("vv",         $record, $length);
306         $data    = pack("vvvvvCCCCC", $dyHeight, $grbit, $icv, $bls,
307                                       $sss, $uls, $bFamily,
308                                       $bCharSet, $reserved, $cch);
310         return($header . $data . $this->_font);
311     }
313     /*
314      * Returns a unique hash key for a font.
315      * Used by writeexcel_workbook::_store_all_fonts()
316      */
317     function get_font_key() {
319         # The following elements are arranged to increase the probability of
320         # generating a unique key. Elements that hold a large range of numbers
321         # eg. _color are placed between two binary elements such as _italic
322         #
323         $key  = $this->_font.$this->_size.
324                 $this->_font_script.$this->_underline.
325                 $this->_font_strikeout.$this->_bold.$this->_font_outline.
326                 $this->_font_family.$this->_font_charset.
327                 $this->_font_shadow.$this->_color.$this->_italic;
329         $key = preg_replace('/ /', '_', $key); # Convert the key to a single word
331         return $key;
332     }
334     /*
335      * Returns the used by Worksheet->_XF()
336      */
337     function get_xf_index() {
338         return $this->_xf_index;
339     }
341     /*
342      * Used in conjunction with the set_xxx_color methods to convert a color
343      * string into a number. Color range is 0..63 but we will restrict it
344      * to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
345      */
346     function _get_color($color=false) {
348         $colors = array(
349                         'aqua'    => 0x0F,
350                         'cyan'    => 0x0F,
351                         'black'   => 0x08,
352                         'blue'    => 0x0C,
353                         'brown'   => 0x10,
354                         'magenta' => 0x0E,
355                         'fuchsia' => 0x0E,
356                         'gray'    => 0x17,
357                         'grey'    => 0x17,
358                         'green'   => 0x11,
359                         'lime'    => 0x0B,
360                         'navy'    => 0x12,
361                         'orange'  => 0x35,
362                         'purple'  => 0x14,
363                         'red'     => 0x0A,
364                         'silver'  => 0x16,
365                         'white'   => 0x09,
366                         'yellow'  => 0x0D
367                        );
369         // Return the default color, 0x7FFF, if undef,
370         if ($color===false) {
371             return 0x7FFF;
372         }
374         // or the color string converted to an integer,
375         if (isset($colors[strtolower($color)])) {
376             return $colors[strtolower($color)];
377         }
379         // or the default color if string is unrecognised,
380         if (preg_match('/\D/', $color)) {
381             return 0x7FFF;
382         }
384         // or an index < 8 mapped into the correct range,
385         if ($color<8) {
386             return $color + 8;
387         }
389         // or the default color if arg is outside range,
390         if ($color>63) {
391             return 0x7FFF;
392         }
394         // or an integer in the valid range
395         return $color;
396     }
398     /*
399      * Set cell alignment.
400      */
401     function set_align($location) {
403         // Ignore numbers
404         if (preg_match('/\d/', $location)) {
405             return;
406         }
408         $location = strtolower($location);
410         switch ($location) {
412         case 'left':
413             $this->set_text_h_align(1);
414             break;
416         case 'centre':
417         case 'center':
418             $this->set_text_h_align(2);
419             break;
421         case 'right':
422             $this->set_text_h_align(3);
423             break;
425         case 'fill':
426             $this->set_text_h_align(4);
427             break;
429         case 'justify':
430             $this->set_text_h_align(5);
431             break;
433         case 'merge':
434             $this->set_text_h_align(6);
435             break;
437         case 'equal_space':
438             $this->set_text_h_align(7);
439             break;
441         case 'top':
442             $this->set_text_v_align(0);
443             break;
445         case 'vcentre':
446         case 'vcenter':
447             $this->set_text_v_align(1);
448             break;
449             break;
451         case 'bottom':
452             $this->set_text_v_align(2);
453             break;
455         case 'vjustify':
456             $this->set_text_v_align(3);
457             break;
459         case 'vequal_space':
460             $this->set_text_v_align(4);
461             break;
462         }
463     }
465     /*
466      * Set vertical cell alignment. This is required by the set_properties()
467      * method to differentiate between the vertical and horizontal properties.
468      */
469     function set_valign($location) {
470         $this->set_align($location);
471     }
473     /*
474      * This is an alias for the unintuitive set_align('merge')
475      */
476     function set_merge() {
477         $this->set_text_h_align(6);
478     }
480     /*
481      * Bold has a range 0x64..0x3E8.
482      * 0x190 is normal. 0x2BC is bold.
483      */
484     function set_bold($weight=1) {
486         if ($weight == 1) {
487             // Bold text
488             $weight = 0x2BC;
489         }
491         if ($weight == 0) {
492             // Normal text
493             $weight = 0x190;
494         }
496         if ($weight < 0x064) {
497             // Lower bound
498             $weight = 0x190;
499         }
501         if ($weight > 0x3E8) {
502             // Upper bound
503             $weight = 0x190;
504         }
506         $this->_bold = $weight;
507     }
509     /*
510      * Set all cell borders (bottom, top, left, right) to the same style
511      */
512     function set_border($style) {
513         $this->set_bottom($style);
514         $this->set_top($style);
515         $this->set_left($style);
516         $this->set_right($style);
517     }
519     /*
520      * Set all cell borders (bottom, top, left, right) to the same color
521      */
522     function set_border_color($color) {
523         $this->set_bottom_color($color);
524         $this->set_top_color($color);
525         $this->set_left_color($color);
526         $this->set_right_color($color);
527     }
529     /*
530      * Convert hashes of properties to method calls.
531      */
532     function set_properties() {
534         $_=func_get_args();
536         $properties=array();
537         foreach($_ as $props) {
538             if (is_array($props)) {
539                 $properties=array_merge($properties, $props);
540             } else {
541                 $properties[]=$props;
542             }
543         }
545         foreach ($properties as $key=>$value) {
547             // Strip leading "-" from Tk style properties eg. -color => 'red'.
548             $key = preg_replace('/^-/', '', $key);
550             /* Make sure method names are alphanumeric characters only, in
551                case tainted data is passed to the eval(). */
552             if (preg_match('/\W/', $key)) {
553                 trigger_error("Unknown property: $key.",
554                               E_USER_ERROR);
555             }
557             /* Evaling all $values as a strings gets around the problem of
558                some numerical format strings being evaluated as numbers, for
559                example "00000" for a zip code. */
560             if (is_int($key)) {
561                 eval("\$this->set_$value();");
562             } else {
563                 eval("\$this->set_$key('$value');");
564             }
566         }
567     }
569     function set_font($font) {
570         $this->_font=$font;
571     }
573     function set_size($size) {
574         $this->_size=$size;
575     }
577     function set_italic($italic=1) {
578         $this->_italic=$italic;
579     }
581     function set_color($color) {
582         $this->_color=$this->_get_color($color);
583     }
585     function set_underline($underline=1) {
586         $this->_underline=$underline;
587     }
589     function set_font_strikeout($font_strikeout=1) {
590         $this->_font_strikeout=$font_strikeout;
591     }
593     function set_font_outline($font_outline=1) {
594         $this->_font_outline=$font_outline;
595     }
597     function set_font_shadow($font_shadow=1) {
598         $this->_font_shadow=$font_shadow;
599     }
601     function set_font_script($font_script=1) {
602         $this->_font_script=$font_script;
603     }
605     /* Undocumented */
606     function set_font_family($font_family=1) {
607         $this->_font_family=$font_family;
608     }
610     /* Undocumented */
611     function set_font_charset($font_charset=1) {
612         $this->_font_charset=$font_charset;
613     }
615     function set_num_format($num_format=1) {
616         $this->_num_format=$num_format;
617     }
619     function set_hidden($hidden=1) {
620         $this->_hidden=$hidden;
621     }
623     function set_locked($locked=1) {
624         $this->_locked=$locked;
625     }
627     function set_text_h_align($align) {
628         $this->_text_h_align=$align;
629     }
631     function set_text_wrap($wrap=1) {
632         $this->_text_wrap=$wrap;
633     }
635     function set_text_v_align($align) {
636         $this->_text_v_align=$align;
637     }
639     function set_text_justlast($text_justlast=1) {
640         $this->_text_justlast=$text_justlast;
641     }
643     function set_rotation($rotation=1) {
644         $this->_rotation=$rotation;
645     }
647     function set_fg_color($color) {
648         $this->_fg_color=$this->_get_color($color);
649     }
651     function set_bg_color($color) {
652         $this->_bg_color=$this->_get_color($color);
653     }
655     function set_pattern($pattern=1) {
656         $this->_pattern=$pattern;
657     }
659     function set_bottom($bottom=1) {
660         $this->_bottom=$bottom;
661     }
663     function set_top($top=1) {
664         $this->_top=$top;
665     }
667     function set_left($left=1) {
668         $this->_left=$left;
669     }
671     function set_right($right=1) {
672          $this->_right=$right;
673     }
675     function set_bottom_color($color) {
676         $this->_bottom_color=$this->_get_color($color);
677     }
679     function set_top_color($color) {
680         $this->_top_color=$this->_get_color($color);
681     }
683     function set_left_color($color) {
684         $this->_left_color=$this->_get_color($color);
685     }
687     function set_right_color($color) {
688         $this->_right_color=$this->_get_color($color);
689     }
693 ?>