PageRenderTime 1324ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/excel/Format.php

http://github.com/moodle/moodle
PHP | 637 lines | 343 code | 64 blank | 230 comment | 61 complexity | cf668c1d31ca76a38c79a7dbba60302d MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /*
  3. * Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
  4. *
  5. * The majority of this is _NOT_ my code. I simply ported it from the
  6. * PERL Spreadsheet::WriteExcel module.
  7. *
  8. * The author of the Spreadsheet::WriteExcel module is John McNamara
  9. * <jmcnamara@cpan.org>
  10. *
  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.
  14. *
  15. * License Information:
  16. *
  17. * Spreadsheet::WriteExcel: A library for generating Excel Spreadsheets
  18. * Copyright (C) 2002 Xavier Noguer xnoguer@rezebra.com
  19. *
  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.
  24. *
  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.
  29. *
  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
  33. */
  34. /**
  35. * Class for generating Excel XF records (formats)
  36. *
  37. * @author Xavier Noguer <xnoguer@rezebra.com>
  38. * @package Spreadsheet_WriteExcel
  39. */
  40. class Format
  41. {
  42. /**
  43. * Constructor
  44. *
  45. * @access public
  46. * @param integer $index the XF index for the format.
  47. * @param array $properties array with properties to be set on initialization.
  48. */
  49. function Format($index = 0,$properties = array())
  50. {
  51. $this->xf_index = $index;
  52. $this->font_index = 0;
  53. $this->font = 'Arial';
  54. $this->size = 10;
  55. $this->bold = 0x0190;
  56. $this->_italic = 0;
  57. $this->color = 0x7FFF;
  58. $this->_underline = 0;
  59. $this->font_strikeout = 0;
  60. $this->font_outline = 0;
  61. $this->font_shadow = 0;
  62. $this->font_script = 0;
  63. $this->font_family = 0;
  64. $this->font_charset = 0;
  65. $this->_num_format = 0;
  66. $this->hidden = 0;
  67. $this->locked = 1;
  68. $this->_text_h_align = 0;
  69. $this->_text_wrap = 0;
  70. $this->text_v_align = 2;
  71. $this->text_justlast = 0;
  72. $this->rotation = 0;
  73. $this->fg_color = 0x40;
  74. $this->bg_color = 0x41;
  75. $this->pattern = 0;
  76. $this->bottom = 0;
  77. $this->top = 0;
  78. $this->left = 0;
  79. $this->right = 0;
  80. $this->bottom_color = 0x40;
  81. $this->top_color = 0x40;
  82. $this->left_color = 0x40;
  83. $this->right_color = 0x40;
  84. // Set properties passed to Workbook::add_format()
  85. foreach($properties as $property => $value)
  86. {
  87. if(method_exists($this,"set_$property"))
  88. {
  89. $aux = 'set_'.$property;
  90. $this->$aux($value);
  91. }
  92. }
  93. }
  94. /**
  95. * Generate an Excel BIFF XF record (style or cell).
  96. *
  97. * @param string $style The type of the XF record ('style' or 'cell').
  98. * @return string The XF record
  99. */
  100. function get_xf($style)
  101. {
  102. // Set the type of the XF record and some of the attributes.
  103. if ($style == "style") {
  104. $style = 0xFFF5;
  105. }
  106. else {
  107. $style = $this->locked;
  108. $style |= $this->hidden << 1;
  109. }
  110. // Flags to indicate if attributes have been set.
  111. $atr_num = ($this->_num_format != 0)?1:0;
  112. $atr_fnt = ($this->font_index != 0)?1:0;
  113. $atr_alc = ($this->_text_wrap)?1:0;
  114. $atr_bdr = ($this->bottom ||
  115. $this->top ||
  116. $this->left ||
  117. $this->right)?1:0;
  118. $atr_pat = (($this->fg_color != 0x40) ||
  119. ($this->bg_color != 0x41) ||
  120. $this->pattern)?1:0;
  121. $atr_prot = 0;
  122. // Zero the default border colour if the border has not been set.
  123. if ($this->bottom == 0) {
  124. $this->bottom_color = 0;
  125. }
  126. if ($this->top == 0) {
  127. $this->top_color = 0;
  128. }
  129. if ($this->right == 0) {
  130. $this->right_color = 0;
  131. }
  132. if ($this->left == 0) {
  133. $this->left_color = 0;
  134. }
  135. $record = 0x00E0; // Record identifier
  136. $length = 0x0010; // Number of bytes to follow
  137. $ifnt = $this->font_index; // Index to FONT record
  138. $ifmt = $this->_num_format; // Index to FORMAT record
  139. $align = $this->_text_h_align; // Alignment
  140. $align |= $this->_text_wrap << 3;
  141. $align |= $this->text_v_align << 4;
  142. $align |= $this->text_justlast << 7;
  143. $align |= $this->rotation << 8;
  144. $align |= $atr_num << 10;
  145. $align |= $atr_fnt << 11;
  146. $align |= $atr_alc << 12;
  147. $align |= $atr_bdr << 13;
  148. $align |= $atr_pat << 14;
  149. $align |= $atr_prot << 15;
  150. $icv = $this->fg_color; // fg and bg pattern colors
  151. $icv |= $this->bg_color << 7;
  152. $fill = $this->pattern; // Fill and border line style
  153. $fill |= $this->bottom << 6;
  154. $fill |= $this->bottom_color << 9;
  155. $border1 = $this->top; // Border line style and color
  156. $border1 |= $this->left << 3;
  157. $border1 |= $this->right << 6;
  158. $border1 |= $this->top_color << 9;
  159. $border2 = $this->left_color; // Border color
  160. $border2 |= $this->right_color << 7;
  161. $header = pack("vv", $record, $length);
  162. $data = pack("vvvvvvvv", $ifnt, $ifmt, $style, $align,
  163. $icv, $fill,
  164. $border1, $border2);
  165. return($header.$data);
  166. }
  167. /**
  168. * Generate an Excel BIFF FONT record.
  169. *
  170. * @see Workbook::_store_all_fonts()
  171. * @return string The FONT record
  172. */
  173. function get_font()
  174. {
  175. $dyHeight = $this->size * 20; // Height of font (1/20 of a point)
  176. $icv = $this->color; // Index to color palette
  177. $bls = $this->bold; // Bold style
  178. $sss = $this->font_script; // Superscript/subscript
  179. $uls = $this->_underline; // Underline
  180. $bFamily = $this->font_family; // Font family
  181. $bCharSet = $this->font_charset; // Character set
  182. $rgch = $this->font; // Font name
  183. $cch = strlen($rgch); // Length of font name
  184. $record = 0x31; // Record identifier
  185. $length = 0x0F + $cch; // Record length
  186. $reserved = 0x00; // Reserved
  187. $grbit = 0x00; // Font attributes
  188. if ($this->_italic) {
  189. $grbit |= 0x02;
  190. }
  191. if ($this->font_strikeout) {
  192. $grbit |= 0x08;
  193. }
  194. if ($this->font_outline) {
  195. $grbit |= 0x10;
  196. }
  197. if ($this->font_shadow) {
  198. $grbit |= 0x20;
  199. }
  200. $header = pack("vv", $record, $length);
  201. $data = pack("vvvvvCCCCC", $dyHeight, $grbit, $icv, $bls,
  202. $sss, $uls, $bFamily,
  203. $bCharSet, $reserved, $cch);
  204. return($header . $data. $this->font);
  205. }
  206. /**
  207. * Returns a unique hash key for a font. Used by Workbook->_store_all_fonts()
  208. *
  209. * The elements that form the key are arranged to increase the probability of
  210. * generating a unique key. Elements that hold a large range of numbers
  211. * (eg. _color) are placed between two binary elements such as _italic
  212. *
  213. * @return string A key for this font
  214. */
  215. function get_font_key()
  216. {
  217. $key = "$this->font$this->size";
  218. $key .= "$this->font_script$this->_underline";
  219. $key .= "$this->font_strikeout$this->bold$this->font_outline";
  220. $key .= "$this->font_family$this->font_charset";
  221. $key .= "$this->font_shadow$this->color$this->_italic";
  222. $key = str_replace(" ","_",$key);
  223. return ($key);
  224. }
  225. /**
  226. * Returns the index used by Worksheet->_XF()
  227. *
  228. * @return integer The index for the XF record
  229. */
  230. function get_xf_index()
  231. {
  232. return($this->xf_index);
  233. }
  234. /**
  235. * Used in conjunction with the set_xxx_color methods to convert a color
  236. * string into a number. Color range is 0..63 but we will restrict it
  237. * to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
  238. *
  239. * @param string $name_color name of the color (i.e.: 'blue', 'red', etc..). Optional.
  240. * @return integer The color index
  241. */
  242. function _get_color($name_color = '')
  243. {
  244. $colors = array(
  245. 'aqua' => 0x0F,
  246. 'cyan' => 0x0F,
  247. 'black' => 0x08,
  248. 'blue' => 0x0C,
  249. 'brown' => 0x10,
  250. 'magenta' => 0x0E,
  251. 'fuchsia' => 0x0E,
  252. 'gray' => 0x17,
  253. 'grey' => 0x17,
  254. 'green' => 0x11,
  255. 'lime' => 0x0B,
  256. 'navy' => 0x12,
  257. 'orange' => 0x35,
  258. 'purple' => 0x14,
  259. 'red' => 0x0A,
  260. 'silver' => 0x16,
  261. 'white' => 0x09,
  262. 'yellow' => 0x0D
  263. );
  264. // Return the default color, 0x7FFF, if undef,
  265. if($name_color == '') {
  266. return(0x7FFF);
  267. }
  268. // or the color string converted to an integer,
  269. if(isset($colors[$name_color])) {
  270. return($colors[$name_color]);
  271. }
  272. // or the default color if string is unrecognised,
  273. if(preg_match("/\D/",$name_color)) {
  274. return(0x7FFF);
  275. }
  276. // or an index < 8 mapped into the correct range,
  277. if($name_color < 8) {
  278. return($name_color + 8);
  279. }
  280. // or the default color if arg is outside range,
  281. if($name_color > 63) {
  282. return(0x7FFF);
  283. }
  284. // or an integer in the valid range
  285. return($name_color);
  286. }
  287. /**
  288. * Set cell alignment.
  289. *
  290. * @access public
  291. * @param string $location alignment for the cell ('left', 'right', etc...).
  292. */
  293. function set_align($location)
  294. {
  295. if (preg_match("/\d/",$location)) {
  296. return; // Ignore numbers
  297. }
  298. $location = strtolower($location);
  299. if ($location == 'left')
  300. $this->_text_h_align = 1;
  301. if ($location == 'centre')
  302. $this->_text_h_align = 2;
  303. if ($location == 'center')
  304. $this->_text_h_align = 2;
  305. if ($location == 'right')
  306. $this->_text_h_align = 3;
  307. if ($location == 'fill')
  308. $this->_text_h_align = 4;
  309. if ($location == 'justify')
  310. $this->_text_h_align = 5;
  311. if ($location == 'merge')
  312. $this->_text_h_align = 6;
  313. if ($location == 'equal_space') // For T.K.
  314. $this->_text_h_align = 7;
  315. if ($location == 'top')
  316. $this->text_v_align = 0;
  317. if ($location == 'vcentre')
  318. $this->text_v_align = 1;
  319. if ($location == 'vcenter')
  320. $this->text_v_align = 1;
  321. if ($location == 'bottom')
  322. $this->text_v_align = 2;
  323. if ($location == 'vjustify')
  324. $this->text_v_align = 3;
  325. if ($location == 'vequal_space') // For T.K.
  326. $this->text_v_align = 4;
  327. }
  328. /**
  329. * This is an alias for the unintuitive set_align('merge')
  330. *
  331. * @access public
  332. */
  333. function set_merge()
  334. {
  335. $this->set_align('merge');
  336. }
  337. /**
  338. * Bold has a range 0x64..0x3E8.
  339. * 0x190 is normal. 0x2BC is bold.
  340. *
  341. * @access public
  342. * @param integer $weight Weight for the text, 0 maps to 0x190, 1 maps to 0x2BC.
  343. It's Optional, default is 1 (bold).
  344. */
  345. function set_bold($weight = 1)
  346. {
  347. if($weight == 1) {
  348. $weight = 0x2BC; // Bold text
  349. }
  350. if($weight == 0) {
  351. $weight = 0x190; // Normal text
  352. }
  353. if($weight < 0x064) {
  354. $weight = 0x190; // Lower bound
  355. }
  356. if($weight > 0x3E8) {
  357. $weight = 0x190; // Upper bound
  358. }
  359. $this->bold = $weight;
  360. }
  361. /************************************
  362. * FUNCTIONS FOR SETTING CELLS BORDERS
  363. */
  364. /**
  365. * Sets the bottom border of the cell
  366. *
  367. * @access public
  368. * @param integer $style style of the cell border. 1 => thin, 2 => thick.
  369. */
  370. function set_bottom($style)
  371. {
  372. $this->bottom = $style;
  373. }
  374. /**
  375. * Sets the top border of the cell
  376. *
  377. * @access public
  378. * @param integer $style style of the cell top border. 1 => thin, 2 => thick.
  379. */
  380. function set_top($style)
  381. {
  382. $this->top = $style;
  383. }
  384. /**
  385. * Sets the left border of the cell
  386. *
  387. * @access public
  388. * @param integer $style style of the cell left border. 1 => thin, 2 => thick.
  389. */
  390. function set_left($style)
  391. {
  392. $this->left = $style;
  393. }
  394. /**
  395. * Sets the right border of the cell
  396. *
  397. * @access public
  398. * @param integer $style style of the cell right border. 1 => thin, 2 => thick.
  399. */
  400. function set_right($style)
  401. {
  402. $this->right = $style;
  403. }
  404. /**
  405. * Set cells borders to the same style
  406. *
  407. * @access public
  408. * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
  409. */
  410. function set_border($style)
  411. {
  412. $this->set_bottom($style);
  413. $this->set_top($style);
  414. $this->set_left($style);
  415. $this->set_right($style);
  416. }
  417. /*******************************************
  418. * FUNCTIONS FOR SETTING CELLS BORDERS COLORS
  419. */
  420. /**
  421. * Sets all the cell's borders to the same color
  422. *
  423. * @access public
  424. * @param mixed $color The color we are setting. Either a string (like 'blue'),
  425. * or an integer (like 0x41).
  426. */
  427. function set_border_color($color)
  428. {
  429. $this->set_bottom_color($color);
  430. $this->set_top_color($color);
  431. $this->set_left_color($color);
  432. $this->set_right_color($color);
  433. }
  434. /**
  435. * Sets the cell's bottom border color
  436. *
  437. * @access public
  438. * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
  439. */
  440. function set_bottom_color($color)
  441. {
  442. $value = $this->_get_color($color);
  443. $this->bottom_color = $value;
  444. }
  445. /**
  446. * Sets the cell's top border color
  447. *
  448. * @access public
  449. * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
  450. */
  451. function set_top_color($color)
  452. {
  453. $value = $this->_get_color($color);
  454. $this->top_color = $value;
  455. }
  456. /**
  457. * Sets the cell's left border color
  458. *
  459. * @access public
  460. * @param mixed $color either a string (like 'blue'), or an integer (like 0x41).
  461. */
  462. function set_left_color($color)
  463. {
  464. $value = $this->_get_color($color);
  465. $this->left_color = $value;
  466. }
  467. /**
  468. * Sets the cell's right border color
  469. *
  470. * @access public
  471. * @param mixed $color either a string (like 'blue'), or an integer (like 0x41).
  472. */
  473. function set_right_color($color)
  474. {
  475. $value = $this->_get_color($color);
  476. $this->right_color = $value;
  477. }
  478. /**
  479. * Sets the cell's foreground color
  480. *
  481. * @access public
  482. * @param mixed $color either a string (like 'blue'), or an integer (like 0x41).
  483. */
  484. function set_fg_color($color)
  485. {
  486. $value = $this->_get_color($color);
  487. $this->fg_color = $value;
  488. }
  489. /**
  490. * Sets the cell's background color
  491. *
  492. * @access public
  493. * @param mixed $color either a string (like 'blue'), or an integer (like 0x41).
  494. */
  495. function set_bg_color($color)
  496. {
  497. $value = $this->_get_color($color);
  498. $this->bg_color = $value;
  499. }
  500. /**
  501. * Sets the cell's color
  502. *
  503. * @access public
  504. * @param mixed $color either a string (like 'blue'), or an integer (like 0x41).
  505. */
  506. function set_color($color)
  507. {
  508. $value = $this->_get_color($color);
  509. $this->color = $value;
  510. }
  511. /**
  512. * Sets the pattern attribute of a cell
  513. *
  514. * @access public
  515. * @param integer $arg Optional. Defaults to 1.
  516. */
  517. function set_pattern($arg = 1)
  518. {
  519. $this->pattern = $arg;
  520. }
  521. /**
  522. * Sets the underline of the text
  523. *
  524. * @access public
  525. * @param integer $underline The value for underline. Possible values are:
  526. * 1 => underline, 2 => double underline.
  527. */
  528. function set_underline($underline)
  529. {
  530. $this->_underline = $underline;
  531. }
  532. /**
  533. * Sets the font style as italic
  534. *
  535. * @access public
  536. */
  537. function set_italic()
  538. {
  539. $this->_italic = 1;
  540. }
  541. /**
  542. * Sets the font size
  543. *
  544. * @access public
  545. * @param integer $size The font size (in pixels I think).
  546. */
  547. function set_size($size)
  548. {
  549. $this->size = $size;
  550. }
  551. /**
  552. * Sets the num format
  553. *
  554. * @access public
  555. * @param integer $num_format The num format.
  556. */
  557. function set_num_format($num_format)
  558. {
  559. $this->_num_format = $num_format;
  560. }
  561. /**
  562. * Sets text wrapping
  563. *
  564. * @access public
  565. * @param integer $text_wrap Optional. 0 => no text wrapping, 1 => text wrapping.
  566. * Defaults to 1.
  567. */
  568. function set_text_wrap($text_wrap = 1)
  569. {
  570. $this->_text_wrap = $text_wrap;
  571. }
  572. }
  573. ?>