3 // This file is part of Moodle - http://moodle.org/
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
21 * @copyright (C) 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com}
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') ||
die();
29 /** setup.php includes our hacked pear libs first */
30 require_once 'Spreadsheet/Excel/Writer.php';
33 * Define and operate over one Moodle Workbook.
35 * A big part of this class acts as a wrapper over the PEAR
36 * Spreadsheet_Excel_Writer_Workbook and OLE libraries
37 * maintaining Moodle functions isolated from underlying code.
39 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 class MoodleExcelWorkbook
{
45 var $pear_excel_workbook;
50 * Constructs one Moodle Workbook.
53 * @param string $filename The name of the file
55 function MoodleExcelWorkbook($filename) {
57 /// Internally, create one PEAR Spreadsheet_Excel_Writer_Workbook class
58 $this->pear_excel_workbook
= new Spreadsheet_Excel_Writer($filename);
59 /// Prepare it to accept UTF-16LE data and to encode it properly
60 if (empty($CFG->latinexcelexport
)) { /// Only if don't want to use latin (win1252) stronger output
61 $this->pear_excel_workbook
->setVersion(8);
62 $this->latin_output
= false;
63 } else { /// We want latin (win1252) output
64 $this->latin_output
= true;
66 /// Choose our temporary directory - see MDL-7176, found by paulo.matos
67 make_temp_directory('excel');
68 $this->pear_excel_workbook
->setTempDir($CFG->tempdir
.'/excel');
72 * Create one Moodle Worksheet
74 * @param string $name Name of the sheet
75 * @return object MoodleExcelWorksheet
77 function &add_worksheet($name = '') {
78 /// Create the Moodle Worksheet. Returns one pointer to it
79 $ws = new MoodleExcelWorksheet ($name, $this->pear_excel_workbook
, $this->latin_output
);
84 * Create one Moodle Format
86 * @param array $properties array of properties [name]=value;
87 * valid names are set_XXXX existing
88 * functions without the set_ part
89 * i.e: [bold]=1 for set_bold(1)...Optional!
90 * @return object MoodleExcelFormat
92 function &add_format($properties = array()) {
93 /// Create the Moodle Format. Returns one pointer to it
94 $ft = new MoodleExcelFormat ($this->pear_excel_workbook
, $properties);
99 * Close the Moodle Workbook
102 $this->pear_excel_workbook
->close();
106 * Write the correct HTTP headers
108 * @param string $filename Name of the downloaded file
110 function send($filename) {
111 $this->pear_excel_workbook
->send($filename);
116 * Define and operate over one Worksheet.
118 * A big part of this class acts as a wrapper over the PEAR
119 * Spreadsheet_Excel_Writer_Workbook and OLE libraries
120 * maintaining Moodle functions isolated from underlying code.
122 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
123 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
124 * @package moodlecore
126 class MoodleExcelWorksheet
{
128 var $pear_excel_worksheet;
129 /** @var bool Only if don't want to use latin (win1252) stronger output */
133 * Constructs one Moodle Worksheet.
135 * @param string $filename The name of the file
136 * @param object $workbook The internal PEAR Workbook onject we are creating
137 * @param bool $latin_output Only if don't want to use latin (win1252) stronger output
139 function MoodleExcelWorksheet($name, &$workbook, $latin_output=false) {
141 if (strlen($name) > 31) {
142 // Excel does not seem able to cope with sheet names > 31 chars.
143 // With $latin_output = false, it does not cope at all.
144 // With $latin_output = true it is supposed to work, but in our experience,
145 // it doesn't. Therefore, truncate in all circumstances.
146 $name = textlib
::substr($name, 0, 31);
149 /// Internally, add one sheet to the workbook
150 $this->pear_excel_worksheet
=& $workbook->addWorksheet($name);
151 $this->latin_output
= $latin_output;
152 /// Set encoding to UTF-16LE
153 if (!$this->latin_output
) { /// Only if don't want to use latin (win1252) stronger output
154 $this->pear_excel_worksheet
->setInputEncoding('UTF-16LE');
159 * Write one string somewhere in the worksheet
161 * @param integer $row Zero indexed row
162 * @param integer $col Zero indexed column
163 * @param string $str The string to write
164 * @param mixed $format The XF format for the cell
166 function write_string($row, $col, $str, $format=null) {
167 /// Calculate the internal PEAR format
168 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
169 /// Convert the text from its original encoding to UTF-16LE
170 if (!$this->latin_output
) { /// Only if don't want to use latin (win1252) stronger output
171 $str = textlib
::convert($str, 'utf-8', 'utf-16le');
172 } else { /// else, convert to latin (win1252)
173 $str = textlib
::convert($str, 'utf-8', 'windows-1252');
175 /// Add the string safely to the PEAR Worksheet
176 $this->pear_excel_worksheet
->writeString($row, $col, $str, $format);
180 * Write one number somewhere in the worksheet
182 * @param integer $row Zero indexed row
183 * @param integer $col Zero indexed column
184 * @param float $num The number to write
185 * @param mixed $format The XF format for the cell
187 function write_number($row, $col, $num, $format=null) {
188 /// Calculate the internal PEAR format
189 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
190 /// Add the number safely to the PEAR Worksheet
191 $this->pear_excel_worksheet
->writeNumber($row, $col, $num, $format);
195 * Write one url somewhere in the worksheet
197 * @param integer $row Zero indexed row
198 * @param integer $col Zero indexed column
199 * @param string $url The url to write
200 * @param mixed $format The XF format for the cell
202 function write_url($row, $col, $url, $format=null) {
203 /// Calculate the internal PEAR format
204 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
205 /// Add the url safely to the PEAR Worksheet
206 $this->pear_excel_worksheet
->writeUrl($row, $col, $url, $format);
210 * Write one date somewhere in the worksheet
211 * @param integer $row Zero indexed row
212 * @param integer $col Zero indexed column
213 * @param string $date The date to write in UNIX timestamp format
214 * @param mixed $format The XF format for the cell
216 function write_date($row, $col, $date, $format=null) {
217 /// Calculate the internal PEAR format
218 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
219 /// Convert the date to Excel format
220 $timezone = get_user_timezone_offset();
221 if ($timezone == 99) {
222 // system timezone offset in seconds
223 $offset = (int)date('Z');
225 $offset = (int)($timezone * HOURSECS
* 2);
227 $value = ((usertime($date) +
$offset) / 86400) +
25569;
228 /// Add the date safely to the PEAR Worksheet
229 $this->pear_excel_worksheet
->writeNumber($row, $col, $value, $format);
233 * Write one formula somewhere in the worksheet
235 * @param integer $row Zero indexed row
236 * @param integer $col Zero indexed column
237 * @param string $formula The formula to write
238 * @param mixed $format The XF format for the cell
240 function write_formula($row, $col, $formula, $format=null) {
241 /// Calculate the internal PEAR format
242 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
243 /// Add the formula safely to the PEAR Worksheet
244 $this->pear_excel_worksheet
->writeFormula($row, $col, $formula, $format);
248 * Write one blanck somewhere in the worksheet
250 * @param integer $row Zero indexed row
251 * @param integer $col Zero indexed column
252 * @param mixed $format The XF format for the cell
254 function write_blank($row, $col, $format=null) {
255 /// Calculate the internal PEAR format
256 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
257 /// Add the blank safely to the PEAR Worksheet
258 $this->pear_excel_worksheet
->writeBlank($row, $col, $format);
262 * Write anything somewhere in the worksheet
263 * Type will be automatically detected
265 * @param integer $row Zero indexed row
266 * @param integer $col Zero indexed column
267 * @param mixed $token What we are writing
268 * @param mixed $format The XF format for the cell
271 function write($row, $col, $token, $format=null) {
273 /// Analyse what are we trying to send
274 if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/", $token)) {
276 return $this->write_number($row, $col, $token, $format);
277 } elseif (preg_match("/^[fh]tt?p:\/\//", $token)) {
278 /// Match http or ftp URL
279 return $this->write_url($row, $col, $token, '', $format);
280 } elseif (preg_match("/^mailto:/", $token)) {
282 return $this->write_url($row, $col, $token, '', $format);
283 } elseif (preg_match("/^(?:in|ex)ternal:/", $token)) {
284 /// Match internal or external sheet link
285 return $this->write_url($row, $col, $token, '', $format);
286 } elseif (preg_match("/^=/", $token)) {
288 return $this->write_formula($row, $col, $token, $format);
289 } elseif (preg_match("/^@/", $token)) {
291 return $this->write_formula($row, $col, $token, $format);
292 } elseif ($token == '') {
294 return $this->write_blank($row, $col, $format);
296 /// Default: match string
297 return $this->write_string($row, $col, $token, $format);
302 * Sets the height (and other settings) of one row
304 * @param integer $row The row to set
305 * @param integer $height Height we are giving to the row (null to set just format withouth setting the height)
306 * @param mixed $format The optional XF format we are giving to the row
307 * @param bool $hidden The optional hidden attribute
308 * @param integer $level The optional outline level (0-7)
310 function set_row ($row, $height, $format = null, $hidden = false, $level = 0) {
311 /// Calculate the internal PEAR format
312 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
313 /// Set the row safely to the PEAR Worksheet
314 $this->pear_excel_worksheet
->setRow($row, $height, $format, $hidden, $level);
318 * Sets the width (and other settings) of one column
320 * @param integer $firstcol first column on the range
321 * @param integer $lastcol last column on the range
322 * @param integer $width width to set
323 * @param mixed $format The optional XF format to apply to the columns
324 * @param integer $hidden The optional hidden atribute
325 * @param integer $level The optional outline level (0-7)
327 function set_column ($firstcol, $lastcol, $width, $format = null, $hidden = false, $level = 0) {
328 /// Calculate the internal PEAR format
329 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
330 /// Set the column safely to the PEAR Worksheet
331 $this->pear_excel_worksheet
->setColumn($firstcol, $lastcol, $width, $format, $hidden, $level);
335 * Set the option to hide gridlines on the printed page.
339 function hide_gridlines() {
340 $this->pear_excel_worksheet
->hideGridLines();
344 * Set the option to hide gridlines on the worksheet (as seen on the screen).
348 function hide_screen_gridlines() {
349 $this->pear_excel_worksheet
->hideScreenGridlines();
353 * Insert a 24bit bitmap image in a worksheet.
356 * @param integer $row The row we are going to insert the bitmap into
357 * @param integer $col The column we are going to insert the bitmap into
358 * @param string $bitmap The bitmap filename
359 * @param integer $x The horizontal position (offset) of the image inside the cell.
360 * @param integer $y The vertical position (offset) of the image inside the cell.
361 * @param integer $scale_x The horizontal scale
362 * @param integer $scale_y The vertical scale
364 function insert_bitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) {
365 /// Add the bitmap safely to the PEAR Worksheet
366 $this->pear_excel_worksheet
->insertBitmap($row, $col, $bitmap, $x, $y, $scale_x, $scale_y);
370 * Merges the area given by its arguments.
371 * This is an Excel97/2000 method. It is required to perform more complicated
372 * merging than the normal setAlign('merge').
375 * @param integer $first_row First row of the area to merge
376 * @param integer $first_col First column of the area to merge
377 * @param integer $last_row Last row of the area to merge
378 * @param integer $last_col Last column of the area to merge
380 function merge_cells($first_row, $first_col, $last_row, $last_col) {
381 /// Merge cells safely to the PEAR Worksheet
382 $this->pear_excel_worksheet
->mergeCells($first_row, $first_col, $last_row, $last_col);
386 * Returns the PEAR Excel Format for one Moodle Excel Format
388 * @param mixed $format MoodleExcelFormat object
389 * @return mixed PEAR Excel Format object
391 function MoodleExcelFormat2PearExcelFormat($format) {
393 return $format->pear_excel_format
;
402 * Define and operate over one Format.
404 * A big part of this class acts as a wrapper over the PEAR
405 * Spreadsheet_Excel_Writer_Workbook and OLE libraries
406 * maintaining Moodle functions isolated from underlying code.
408 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
409 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
410 * @package moodlecore
412 class MoodleExcelFormat
{
414 var $pear_excel_format;
417 * Constructs one Moodle Format.
419 * @param object $workbook The internal PEAR Workbook onject we are creating
420 * @param array $properties
422 function MoodleExcelFormat(&$workbook, $properties = array()) {
423 /// Internally, add one sheet to the workbook
424 $this->pear_excel_format
=& $workbook->addFormat();
425 /// If we have something in the array of properties, compute them
426 foreach($properties as $property => $value) {
427 if(method_exists($this,"set_$property")) {
428 $aux = 'set_'.$property;
435 * Set the size of the text in the format (in pixels).
436 * By default all texts in generated sheets are 10px.
438 * @param integer $size Size of the text (in pixels)
440 function set_size($size) {
441 /// Set the size safely to the PEAR Format
442 $this->pear_excel_format
->setSize($size);
446 * Set weight of the format
448 * @param integer $weight Weight for the text, 0 maps to 400 (normal text),
449 * 1 maps to 700 (bold text). Valid range is: 100-1000.
450 * It's Optional, default is 1 (bold).
452 function set_bold($weight = 1) {
453 /// Set the bold safely to the PEAR Format
454 $this->pear_excel_format
->setBold($weight);
458 * Set underline of the format
460 * @param integer $underline The value for underline. Possible values are:
461 * 1 => underline, 2 => double underline
463 function set_underline($underline) {
464 /// Set the underline safely to the PEAR Format
465 $this->pear_excel_format
->setUnderline($underline);
469 * Set italic of the format
471 function set_italic() {
472 /// Set the italic safely to the PEAR Format
473 $this->pear_excel_format
->setItalic();
477 * Set strikeout of the format
479 function set_strikeout() {
480 /// Set the strikeout safely to the PEAR Format
481 $this->pear_excel_format
->setStrikeOut();
485 * Set outlining of the format
487 function set_outline() {
488 /// Set the outlining safely to the PEAR Format
489 $this->pear_excel_format
->setOutLine();
493 * Set shadow of the format
495 function set_shadow() {
496 /// Set the shadow safely to the PEAR Format
497 $this->pear_excel_format
->setShadow();
501 * Set the script of the text
503 * @param integer $script The value for script type. Possible values are:
504 * 1 => superscript, 2 => subscript
506 function set_script($script) {
507 /// Set the script safely to the PEAR Format
508 $this->pear_excel_format
->setScript($script);
512 * Set color of the format. Used to specify the color of the text to be formatted.
514 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
516 function set_color($color) {
517 /// Set the background color safely to the PEAR Format
518 $this->pear_excel_format
->setColor($color);
522 * Set foreground color (top layer) of the format. About formatting colors note that cells backgrounds
523 * have TWO layers, in order to support patterns and paint them with two diferent colors.
524 * This method set the color of the TOP layer of the background format. So, when filling
525 * cells with plain colors (no patterns) this is the method to use.
527 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
529 function set_fg_color($color) {
530 /// Set the foreground color safely to the PEAR Format
531 $this->pear_excel_format
->setFgColor($color);
535 * Set background color (bottom layer) of the format. About formatting colors note that cells backgrounds
536 * have TWO layers, in order to support patterns and paint them with two diferent colors.
537 * This method set the color of the BOTTOM layer of the background format. So, the color
538 * specified here only will be visible if using patterns. Use set_fg_color() to fill
539 * cells with plain colors (no patterns).
541 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
543 function set_bg_color($color) {
544 /// Set the background color safely to the PEAR Format
545 $this->pear_excel_format
->setBgColor($color);
549 * Set the fill pattern of the format
550 * @param integer Optional. Defaults to 1. Meaningful values are: 0-18
551 * 0 meaning no background.
553 function set_pattern($pattern=1) {
554 /// Set the fill pattern safely to the PEAR Format
555 $this->pear_excel_format
->setPattern($pattern);
559 * Set text wrap of the format
561 function set_text_wrap() {
562 /// Set the shadow safely to the PEAR Format
563 $this->pear_excel_format
->setTextWrap();
567 * Set the cell alignment of the format
569 * @param string $location alignment for the cell ('left', 'right', etc...)
571 function set_align($location) {
572 /// Set the alignment of the cell safely to the PEAR Format
573 $this->pear_excel_format
->setAlign($location);
577 * Set the cell horizontal alignment of the format
579 * @param string $location alignment for the cell ('left', 'right', etc...)
581 function set_h_align($location) {
582 /// Set the alignment of the cell safely to the PEAR Format
583 $this->pear_excel_format
->setHAlign($location);
587 * Set the cell vertical alignment of the format
589 * @param string $location alignment for the cell ('top', 'vleft', etc...)
591 function set_v_align($location) {
592 /// Set the alignment of the cell safely to the PEAR Format
593 $this->pear_excel_format
->setVAlign($location);
597 * Set the top border of the format
599 * @param integer $style style for the cell. 1 => thin, 2 => thick
601 function set_top($style) {
602 /// Set the top border of the cell safely to the PEAR Format
603 $this->pear_excel_format
->setTop($style);
607 * Set the bottom border of the format
609 * @param integer $style style for the cell. 1 => thin, 2 => thick
611 function set_bottom($style) {
612 /// Set the bottom border of the cell safely to the PEAR Format
613 $this->pear_excel_format
->setBottom($style);
617 * Set the left border of the format
619 * @param integer $style style for the cell. 1 => thin, 2 => thick
621 function set_left($style) {
622 /// Set the left border of the cell safely to the PEAR Format
623 $this->pear_excel_format
->setLeft($style);
627 * Set the right border of the format
629 * @param integer $style style for the cell. 1 => thin, 2 => thick
631 function set_right($style) {
632 /// Set the right border of the cell safely to the PEAR Format
633 $this->pear_excel_format
->setRight($style);
637 * Set cells borders to the same style
639 * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
641 function set_border($style) {
642 /// Set all the borders of the cell safely to the PEAR Format
643 $this->pear_excel_format
->setBorder($style);
647 * Set the numerical format of the format
648 * It can be date, time, currency, etc...
650 * @param integer $num_format The numeric format
652 function set_num_format($num_format) {
653 /// Set the numerical format safely to the PEAR Format
654 $this->pear_excel_format
->setNumFormat($num_format);