3 * Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
5 * The majority of this is _NOT_ my code. I simply ported it from the
6 * PERL Spreadsheet::WriteExcel module.
8 * The author of the Spreadsheet::WriteExcel module is John McNamara
11 * I _DO_ maintain this code, and John McNamara has nothing to do with the
12 * porting of this code to PHP. Any questions directly related to this
13 * class library should be directed to me.
15 * License Information:
17 * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
18 * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 require_once 'PEAR.php';
38 * Class for generating Excel XF records (formats)
40 * @author Xavier Noguer <xnoguer@rezebra.com>
41 * @category FileFormats
42 * @package Spreadsheet_Excel_Writer
45 class Spreadsheet_Excel_Writer_Format
extends PEAR
48 * The index given by the workbook when creating a new format.
54 * Index to the FONT record.
60 * The font name (ASCII).
66 * Height of font (1/20 of a point)
78 * Bit specifiying if the font is italic.
84 * Index to the cell's color
90 * The text underline property
96 * Bit specifiying if the font has strikeout.
102 * Bit specifiying if the font has outline.
108 * Bit specifiying if the font has shadow.
114 * 2 bytes specifiying the script type for the font.
120 * Byte specifiying the font family.
126 * Byte specifiying the font charset.
132 * An index (2 bytes) to a FORMAT record (number format).
138 * Bit specifying if formulas are hidden.
144 * Bit specifying if the cell is locked.
150 * The three bits specifying the text horizontal alignment.
156 * Bit specifying if the text is wrapped at the right border.
162 * The three bits specifying the text vertical alignment.
168 * 1 bit, apparently not used.
174 * The two bits specifying the text rotation.
180 * The cell's foreground color.
186 * The cell's background color.
192 * The cell's background fill pattern.
198 * Style of the bottom border of the cell
204 * Color of the bottom border of the cell.
210 * Style of the top border of the cell
216 * Color of the top border of the cell.
222 * Style of the left border of the cell
228 * Color of the left border of the cell.
234 * Style of the right border of the cell
240 * Color of the right border of the cell.
249 * @param integer $index the XF index for the format.
250 * @param array $properties array with properties to be set on initialization.
252 function Spreadsheet_Excel_Writer_Format($BIFF_version, $index = 0, $properties = array())
254 $this->_xf_index
= $index;
255 $this->_BIFF_version
= $BIFF_version;
256 $this->font_index
= 0;
257 $this->_font_name
= 'Arial';
259 $this->_bold
= 0x0190;
261 $this->_color
= 0x7FFF;
262 $this->_underline
= 0;
263 $this->_font_strikeout
= 0;
264 $this->_font_outline
= 0;
265 $this->_font_shadow
= 0;
266 $this->_font_script
= 0;
267 $this->_font_family
= 0;
268 $this->_font_charset
= 0;
270 $this->_num_format
= 0;
275 $this->_text_h_align
= 0;
276 $this->_text_wrap
= 0;
277 $this->_text_v_align
= 2;
278 $this->_text_justlast
= 0;
279 $this->_rotation
= 0;
281 $this->_fg_color
= 0x40;
282 $this->_bg_color
= 0x41;
292 $this->_bottom_color
= 0x40;
293 $this->_top_color
= 0x40;
294 $this->_left_color
= 0x40;
295 $this->_right_color
= 0x40;
296 $this->_diag_color
= 0x40;
298 // Set properties passed to Spreadsheet_Excel_Writer_Workbook::addFormat()
299 foreach ($properties as $property => $value)
301 if (method_exists($this, 'set'.ucwords($property))) {
302 $method_name = 'set'.ucwords($property);
303 $this->$method_name($value);
310 * Generate an Excel BIFF XF record (style or cell).
312 * @param string $style The type of the XF record ('style' or 'cell').
313 * @return string The XF record
315 function getXf($style)
317 // Set the type of the XF record and some of the attributes.
318 if ($style == 'style') {
321 $style = $this->_locked
;
322 $style |
= $this->_hidden
<< 1;
325 // Flags to indicate if attributes have been set.
326 $atr_num = ($this->_num_format
!= 0)?
1:0;
327 $atr_fnt = ($this->font_index
!= 0)?
1:0;
328 $atr_alc = ($this->_text_wrap
)?
1:0;
329 $atr_bdr = ($this->_bottom ||
333 $atr_pat = (($this->_fg_color
!= 0x40) ||
334 ($this->_bg_color
!= 0x41) ||
335 $this->_pattern
)?
1:0;
336 $atr_prot = $this->_locked |
$this->_hidden
;
338 // Zero the default border colour if the border has not been set.
339 if ($this->_bottom
== 0) {
340 $this->_bottom_color
= 0;
342 if ($this->_top
== 0) {
343 $this->_top_color
= 0;
345 if ($this->_right
== 0) {
346 $this->_right_color
= 0;
348 if ($this->_left
== 0) {
349 $this->_left_color
= 0;
351 if ($this->_diag
== 0) {
352 $this->_diag_color
= 0;
355 $record = 0x00E0; // Record identifier
356 if ($this->_BIFF_version
== 0x0500) {
357 $length = 0x0010; // Number of bytes to follow
359 if ($this->_BIFF_version
== 0x0600) {
363 $ifnt = $this->font_index
; // Index to FONT record
364 $ifmt = $this->_num_format
; // Index to FORMAT record
365 if ($this->_BIFF_version
== 0x0500) {
366 $align = $this->_text_h_align
; // Alignment
367 $align |
= $this->_text_wrap
<< 3;
368 $align |
= $this->_text_v_align
<< 4;
369 $align |
= $this->_text_justlast
<< 7;
370 $align |
= $this->_rotation
<< 8;
371 $align |
= $atr_num << 10;
372 $align |
= $atr_fnt << 11;
373 $align |
= $atr_alc << 12;
374 $align |
= $atr_bdr << 13;
375 $align |
= $atr_pat << 14;
376 $align |
= $atr_prot << 15;
378 $icv = $this->_fg_color
; // fg and bg pattern colors
379 $icv |
= $this->_bg_color
<< 7;
381 $fill = $this->_pattern
; // Fill and border line style
382 $fill |
= $this->_bottom
<< 6;
383 $fill |
= $this->_bottom_color
<< 9;
385 $border1 = $this->_top
; // Border line style and color
386 $border1 |
= $this->_left
<< 3;
387 $border1 |
= $this->_right
<< 6;
388 $border1 |
= $this->_top_color
<< 9;
390 $border2 = $this->_left_color
; // Border color
391 $border2 |
= $this->_right_color
<< 7;
393 $header = pack("vv", $record, $length);
394 $data = pack("vvvvvvvv", $ifnt, $ifmt, $style, $align,
397 } elseif ($this->_BIFF_version
== 0x0600) {
398 $align = $this->_text_h_align
; // Alignment
399 $align |
= $this->_text_wrap
<< 3;
400 $align |
= $this->_text_v_align
<< 4;
401 $align |
= $this->_text_justlast
<< 7;
403 $used_attrib = $atr_num << 2;
404 $used_attrib |
= $atr_fnt << 3;
405 $used_attrib |
= $atr_alc << 4;
406 $used_attrib |
= $atr_bdr << 5;
407 $used_attrib |
= $atr_pat << 6;
408 $used_attrib |
= $atr_prot << 7;
410 $icv = $this->_fg_color
; // fg and bg pattern colors
411 $icv |
= $this->_bg_color
<< 7;
413 $border1 = $this->_left
; // Border line style and color
414 $border1 |
= $this->_right
<< 4;
415 $border1 |
= $this->_top
<< 8;
416 $border1 |
= $this->_bottom
<< 12;
417 $border1 |
= $this->_left_color
<< 16;
418 $border1 |
= $this->_right_color
<< 23;
419 $diag_tl_to_rb = 0; // FIXME: add method
420 $diag_tr_to_lb = 0; // FIXME: add method
421 $border1 |
= $diag_tl_to_rb << 30;
422 $border1 |
= $diag_tr_to_lb << 31;
424 $border2 = $this->_top_color
; // Border color
425 $border2 |
= $this->_bottom_color
<< 7;
426 $border2 |
= $this->_diag_color
<< 14;
427 $border2 |
= $this->_diag
<< 21;
428 $border2 |
= $this->_pattern
<< 26;
430 $header = pack("vv", $record, $length);
433 $biff8_options = 0x00;
434 $data = pack("vvvC", $ifnt, $ifmt, $style, $align);
435 $data .= pack("CCC", $rotation, $biff8_options, $used_attrib);
436 $data .= pack("VVv", $border1, $border2, $icv);
439 return($header . $data);
443 * Generate an Excel BIFF FONT record.
445 * @return string The FONT record
449 $dyHeight = $this->_size
* 20; // Height of font (1/20 of a point)
450 $icv = $this->_color
; // Index to color palette
451 $bls = $this->_bold
; // Bold style
452 $sss = $this->_font_script
; // Superscript/subscript
453 $uls = $this->_underline
; // Underline
454 $bFamily = $this->_font_family
; // Font family
455 $bCharSet = $this->_font_charset
; // Character set
456 $encoding = 0; // TODO: Unicode support
458 $cch = strlen($this->_font_name
); // Length of font name
459 $record = 0x31; // Record identifier
460 if ($this->_BIFF_version
== 0x0500) {
461 $length = 0x0F +
$cch; // Record length
462 } elseif ($this->_BIFF_version
== 0x0600) {
463 $length = 0x10 +
$cch;
465 $reserved = 0x00; // Reserved
466 $grbit = 0x00; // Font attributes
467 if ($this->_italic
) {
470 if ($this->_font_strikeout
) {
473 if ($this->_font_outline
) {
476 if ($this->_font_shadow
) {
480 $header = pack("vv", $record, $length);
481 if ($this->_BIFF_version
== 0x0500) {
482 $data = pack("vvvvvCCCCC", $dyHeight, $grbit, $icv, $bls,
483 $sss, $uls, $bFamily,
484 $bCharSet, $reserved, $cch);
485 } elseif ($this->_BIFF_version
== 0x0600) {
486 $data = pack("vvvvvCCCCCC", $dyHeight, $grbit, $icv, $bls,
487 $sss, $uls, $bFamily,
488 $bCharSet, $reserved, $cch, $encoding);
490 return($header . $data . $this->_font_name
);
494 * Returns a unique hash key for a font.
495 * Used by Spreadsheet_Excel_Writer_Workbook::_storeAllFonts()
497 * The elements that form the key are arranged to increase the probability of
498 * generating a unique key. Elements that hold a large range of numbers
499 * (eg. _color) are placed between two binary elements such as _italic
501 * @return string A key for this font
503 function getFontKey()
505 $key = "$this->_font_name$this->_size";
506 $key .= "$this->_font_script$this->_underline";
507 $key .= "$this->_font_strikeout$this->_bold$this->_font_outline";
508 $key .= "$this->_font_family$this->_font_charset";
509 $key .= "$this->_font_shadow$this->_color$this->_italic";
510 $key = str_replace(' ', '_', $key);
515 * Returns the index used by Spreadsheet_Excel_Writer_Worksheet::_XF()
517 * @return integer The index for the XF record
519 function getXfIndex()
521 return($this->_xf_index
);
525 * Used in conjunction with the set_xxx_color methods to convert a color
526 * string into a number. Color range is 0..63 but we will restrict it
527 * to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
530 * @param string $name_color name of the color (i.e.: 'blue', 'red', etc..). Optional.
531 * @return integer The color index
533 function _getColor($name_color = '')
556 // Return the default color, 0x7FFF, if undef,
557 if ($name_color == '') {
561 // or the color string converted to an integer,
562 if (isset($colors[$name_color])) {
563 return($colors[$name_color]);
566 // or the default color if string is unrecognised,
567 if (preg_match("/\D/",$name_color)) {
571 // or an index < 8 mapped into the correct range,
572 if ($name_color < 8) {
573 return($name_color +
8);
576 // or the default color if arg is outside range,
577 if ($name_color > 63) {
581 // or an integer in the valid range
586 * Set cell alignment.
589 * @param string $location alignment for the cell ('left', 'right', etc...).
591 function setAlign($location)
593 if (preg_match("/\d/",$location)) {
594 return; // Ignore numbers
597 $location = strtolower($location);
599 if ($location == 'left') {
600 $this->_text_h_align
= 1;
602 if ($location == 'centre') {
603 $this->_text_h_align
= 2;
605 if ($location == 'center') {
606 $this->_text_h_align
= 2;
608 if ($location == 'right') {
609 $this->_text_h_align
= 3;
611 if ($location == 'fill') {
612 $this->_text_h_align
= 4;
614 if ($location == 'justify') {
615 $this->_text_h_align
= 5;
617 if ($location == 'merge') {
618 $this->_text_h_align
= 6;
620 if ($location == 'equal_space') { // For T.K.
621 $this->_text_h_align
= 7;
623 if ($location == 'top') {
624 $this->_text_v_align
= 0;
626 if ($location == 'vcentre') {
627 $this->_text_v_align
= 1;
629 if ($location == 'vcenter') {
630 $this->_text_v_align
= 1;
632 if ($location == 'bottom') {
633 $this->_text_v_align
= 2;
635 if ($location == 'vjustify') {
636 $this->_text_v_align
= 3;
638 if ($location == 'vequal_space') { // For T.K.
639 $this->_text_v_align
= 4;
644 * Set cell horizontal alignment.
647 * @param string $location alignment for the cell ('left', 'right', etc...).
649 function setHAlign($location)
651 if (preg_match("/\d/",$location)) {
652 return; // Ignore numbers
655 $location = strtolower($location);
657 if ($location == 'left') {
658 $this->_text_h_align
= 1;
660 if ($location == 'centre') {
661 $this->_text_h_align
= 2;
663 if ($location == 'center') {
664 $this->_text_h_align
= 2;
666 if ($location == 'right') {
667 $this->_text_h_align
= 3;
669 if ($location == 'fill') {
670 $this->_text_h_align
= 4;
672 if ($location == 'justify') {
673 $this->_text_h_align
= 5;
675 if ($location == 'merge') {
676 $this->_text_h_align
= 6;
678 if ($location == 'equal_space') { // For T.K.
679 $this->_text_h_align
= 7;
684 * Set cell vertical alignment.
687 * @param string $location alignment for the cell ('top', 'vleft', 'vright', etc...).
689 function setVAlign($location)
691 if (preg_match("/\d/",$location)) {
692 return; // Ignore numbers
695 $location = strtolower($location);
697 if ($location == 'top') {
698 $this->_text_v_align
= 0;
700 if ($location == 'vcentre') {
701 $this->_text_v_align
= 1;
703 if ($location == 'vcenter') {
704 $this->_text_v_align
= 1;
706 if ($location == 'bottom') {
707 $this->_text_v_align
= 2;
709 if ($location == 'vjustify') {
710 $this->_text_v_align
= 3;
712 if ($location == 'vequal_space') { // For T.K.
713 $this->_text_v_align
= 4;
718 * This is an alias for the unintuitive setAlign('merge')
724 $this->setAlign('merge');
728 * Sets the boldness of the text.
729 * Bold has a range 100..1000.
730 * 0 (400) is normal. 1 (700) is bold.
733 * @param integer $weight Weight for the text, 0 maps to 400 (normal text),
734 1 maps to 700 (bold text). Valid range is: 100-1000.
735 It's Optional, default is 1 (bold).
737 function setBold($weight = 1)
740 $weight = 0x2BC; // Bold text
743 $weight = 0x190; // Normal text
745 if ($weight < 0x064) {
746 $weight = 0x190; // Lower bound
748 if ($weight > 0x3E8) {
749 $weight = 0x190; // Upper bound
751 $this->_bold
= $weight;
755 /************************************
756 * FUNCTIONS FOR SETTING CELLS BORDERS
760 * Sets the width for the bottom border of the cell
763 * @param integer $style style of the cell border. 1 => thin, 2 => thick.
765 function setBottom($style)
767 $this->_bottom
= $style;
771 * Sets the width for the top border of the cell
774 * @param integer $style style of the cell top border. 1 => thin, 2 => thick.
776 function setTop($style)
778 $this->_top
= $style;
782 * Sets the width for the left border of the cell
785 * @param integer $style style of the cell left border. 1 => thin, 2 => thick.
787 function setLeft($style)
789 $this->_left
= $style;
793 * Sets the width for the right border of the cell
796 * @param integer $style style of the cell right border. 1 => thin, 2 => thick.
798 function setRight($style)
800 $this->_right
= $style;
805 * Set cells borders to the same style
808 * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
810 function setBorder($style)
812 $this->setBottom($style);
813 $this->setTop($style);
814 $this->setLeft($style);
815 $this->setRight($style);
819 /*******************************************
820 * FUNCTIONS FOR SETTING CELLS BORDERS COLORS
824 * Sets all the cell's borders to the same color
827 * @param mixed $color The color we are setting. Either a string (like 'blue'),
828 * or an integer (range is [8...63]).
830 function setBorderColor($color)
832 $this->setBottomColor($color);
833 $this->setTopColor($color);
834 $this->setLeftColor($color);
835 $this->setRightColor($color);
839 * Sets the cell's bottom border color
842 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
844 function setBottomColor($color)
846 $value = $this->_getColor($color);
847 $this->_bottom_color
= $value;
851 * Sets the cell's top border color
854 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
856 function setTopColor($color)
858 $value = $this->_getColor($color);
859 $this->_top_color
= $value;
863 * Sets the cell's left border color
866 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
868 function setLeftColor($color)
870 $value = $this->_getColor($color);
871 $this->_left_color
= $value;
875 * Sets the cell's right border color
878 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
880 function setRightColor($color)
882 $value = $this->_getColor($color);
883 $this->_right_color
= $value;
888 * Sets the cell's foreground color
891 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
893 function setFgColor($color)
895 $value = $this->_getColor($color);
896 $this->_fg_color
= $value;
897 if ($this->_pattern
== 0) { // force color to be seen
903 * Sets the cell's background color
906 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
908 function setBgColor($color)
910 $value = $this->_getColor($color);
911 $this->_bg_color
= $value;
912 if ($this->_pattern
== 0) { // force color to be seen
918 * Sets the cell's color
921 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
923 function setColor($color)
925 $value = $this->_getColor($color);
926 $this->_color
= $value;
930 * Sets the fill pattern attribute of a cell
933 * @param integer $arg Optional. Defaults to 1. Meaningful values are: 0-18,
934 * 0 meaning no background.
936 function setPattern($arg = 1)
938 $this->_pattern
= $arg;
942 * Sets the underline of the text
945 * @param integer $underline The value for underline. Possible values are:
946 * 1 => underline, 2 => double underline.
948 function setUnderline($underline)
950 $this->_underline
= $underline;
954 * Sets the font style as italic
967 * @param integer $size The font size (in pixels I think).
969 function setSize($size)
971 $this->_size
= $size;
979 function setTextWrap()
981 $this->_text_wrap
= 1;
985 * Sets the orientation of the text
988 * @param integer $angle The rotation angle for the text (clockwise). Possible
989 values are: 0, 90, 270 and -1 for stacking top-to-bottom.
991 function setTextRotation($angle)
996 $this->_rotation
= 0;
999 $this->_rotation
= 3;
1002 $this->_rotation
= 2;
1005 $this->_rotation
= 1;
1008 return $this->raiseError("Invalid value for angle.".
1009 " Possible values are: 0, 90, 270 and -1 ".
1010 "for stacking top-to-bottom.");
1011 $this->_rotation
= 0;
1017 * Sets the numeric format.
1018 * It can be date, time, currency, etc...
1021 * @param integer $num_format The numeric format.
1023 function setNumFormat($num_format)
1025 $this->_num_format
= $num_format;
1029 * Sets font as strikeout.
1033 function setStrikeOut()
1035 $this->_font_strikeout
= 1;
1039 * Sets outlining for a font.
1043 function setOutLine()
1045 $this->_font_outline
= 1;
1049 * Sets font as shadow.
1053 function setShadow()
1055 $this->_font_shadow
= 1;
1059 * Sets the script type of the text
1062 * @param integer $script The value for script type. Possible values are:
1063 * 1 => superscript, 2 => subscript.
1065 function setScript($script)
1067 $this->_font_script
= $script;
1075 function setLocked()
1081 * Unlocks a cell. Useful for unprotecting particular cells of a protected sheet.
1085 function setUnLocked()
1091 * Sets the font family name.
1094 * @param string $fontfamily The font family name. Possible values are:
1095 * 'Times New Roman', 'Arial', 'Courier'.
1097 function setFontFamily($font_family)
1099 $this->_font_name
= $font_family;