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_upload_directory('temp/excel');
68 $this->pear_excel_workbook
->setTempDir($CFG->dataroot
.'/temp/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 $textlib = textlib_get_instance();
147 $name = $textlib->substr($name, 0, 31);
150 /// Internally, add one sheet to the workbook
151 $this->pear_excel_worksheet
=& $workbook->addWorksheet($name);
152 $this->latin_output
= $latin_output;
153 /// Set encoding to UTF-16LE
154 if (!$this->latin_output
) { /// Only if don't want to use latin (win1252) stronger output
155 $this->pear_excel_worksheet
->setInputEncoding('UTF-16LE');
160 * Write one string somewhere in the worksheet
162 * @param integer $row Zero indexed row
163 * @param integer $col Zero indexed column
164 * @param string $str The string to write
165 * @param mixed $format The XF format for the cell
167 function write_string($row, $col, $str, $format=null) {
168 /// Calculate the internal PEAR format
169 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
170 /// Loading the textlib singleton instance. We are going to need it.
171 $textlib = textlib_get_instance();
172 /// Convert the text from its original encoding to UTF-16LE
173 if (!$this->latin_output
) { /// Only if don't want to use latin (win1252) stronger output
174 $str = $textlib->convert($str, 'utf-8', 'utf-16le');
175 } else { /// else, convert to latin (win1252)
176 $str = $textlib->convert($str, 'utf-8', 'windows-1252');
178 /// Add the string safely to the PEAR Worksheet
179 $this->pear_excel_worksheet
->writeString($row, $col, $str, $format);
183 * Write one number somewhere in the worksheet
185 * @param integer $row Zero indexed row
186 * @param integer $col Zero indexed column
187 * @param float $num The number to write
188 * @param mixed $format The XF format for the cell
190 function write_number($row, $col, $num, $format=null) {
191 /// Calculate the internal PEAR format
192 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
193 /// Add the number safely to the PEAR Worksheet
194 $this->pear_excel_worksheet
->writeNumber($row, $col, $num, $format);
198 * Write one url somewhere in the worksheet
200 * @param integer $row Zero indexed row
201 * @param integer $col Zero indexed column
202 * @param string $url The url to write
203 * @param mixed $format The XF format for the cell
205 function write_url($row, $col, $url, $format=null) {
206 /// Calculate the internal PEAR format
207 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
208 /// Add the url safely to the PEAR Worksheet
209 $this->pear_excel_worksheet
->writeUrl($row, $col, $url, $format);
213 * Write one date somewhere in the worksheet
214 * @param integer $row Zero indexed row
215 * @param integer $col Zero indexed column
216 * @param string $date The date to write in UNIX timestamp format
217 * @param mixed $format The XF format for the cell
219 function write_date($row, $col, $date, $format=null) {
220 /// Calculate the internal PEAR format
221 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
222 /// Convert the date to Excel format
223 $timezone = get_user_timezone_offset();
224 if ($timezone == 99) {
225 // system timezone offset in seconds
226 $offset = (int)date('Z');
228 $offset = (int)($timezone * HOURSECS
* 2);
230 $value = ((usertime($date) +
$offset) / 86400) +
25569;
231 /// Add the date safely to the PEAR Worksheet
232 $this->pear_excel_worksheet
->writeNumber($row, $col, $value, $format);
236 * Write one formula somewhere in the worksheet
238 * @param integer $row Zero indexed row
239 * @param integer $col Zero indexed column
240 * @param string $formula The formula to write
241 * @param mixed $format The XF format for the cell
243 function write_formula($row, $col, $formula, $format=null) {
244 /// Calculate the internal PEAR format
245 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
246 /// Add the formula safely to the PEAR Worksheet
247 $this->pear_excel_worksheet
->writeFormula($row, $col, $formula, $format);
251 * Write one blanck somewhere in the worksheet
253 * @param integer $row Zero indexed row
254 * @param integer $col Zero indexed column
255 * @param mixed $format The XF format for the cell
257 function write_blank($row, $col, $format=null) {
258 /// Calculate the internal PEAR format
259 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
260 /// Add the blank safely to the PEAR Worksheet
261 $this->pear_excel_worksheet
->writeBlank($row, $col, $format);
265 * Write anything somewhere in the worksheet
266 * Type will be automatically detected
268 * @param integer $row Zero indexed row
269 * @param integer $col Zero indexed column
270 * @param mixed $token What we are writing
271 * @param mixed $format The XF format for the cell
274 function write($row, $col, $token, $format=null) {
276 /// Analyse what are we trying to send
277 if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/", $token)) {
279 return $this->write_number($row, $col, $token, $format);
280 } elseif (preg_match("/^[fh]tt?p:\/\//", $token)) {
281 /// Match http or ftp URL
282 return $this->write_url($row, $col, $token, '', $format);
283 } elseif (preg_match("/^mailto:/", $token)) {
285 return $this->write_url($row, $col, $token, '', $format);
286 } elseif (preg_match("/^(?:in|ex)ternal:/", $token)) {
287 /// Match internal or external sheet link
288 return $this->write_url($row, $col, $token, '', $format);
289 } elseif (preg_match("/^=/", $token)) {
291 return $this->write_formula($row, $col, $token, $format);
292 } elseif (preg_match("/^@/", $token)) {
294 return $this->write_formula($row, $col, $token, $format);
295 } elseif ($token == '') {
297 return $this->write_blank($row, $col, $format);
299 /// Default: match string
300 return $this->write_string($row, $col, $token, $format);
305 * Sets the height (and other settings) of one row
307 * @param integer $row The row to set
308 * @param integer $height Height we are giving to the row (null to set just format withouth setting the height)
309 * @param mixed $format The optional XF format we are giving to the row
310 * @param bool $hidden The optional hidden attribute
311 * @param integer $level The optional outline level (0-7)
313 function set_row ($row, $height, $format = null, $hidden = false, $level = 0) {
314 /// Calculate the internal PEAR format
315 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
316 /// Set the row safely to the PEAR Worksheet
317 $this->pear_excel_worksheet
->setRow($row, $height, $format, $hidden, $level);
321 * Sets the width (and other settings) of one column
323 * @param integer $firstcol first column on the range
324 * @param integer $lastcol last column on the range
325 * @param integer $width width to set
326 * @param mixed $format The optional XF format to apply to the columns
327 * @param integer $hidden The optional hidden atribute
328 * @param integer $level The optional outline level (0-7)
330 function set_column ($firstcol, $lastcol, $width, $format = null, $hidden = false, $level = 0) {
331 /// Calculate the internal PEAR format
332 $format = $this->MoodleExcelFormat2PearExcelFormat($format);
333 /// Set the column safely to the PEAR Worksheet
334 $this->pear_excel_worksheet
->setColumn($firstcol, $lastcol, $width, $format, $hidden, $level);
338 * Set the option to hide gridlines on the printed page.
342 function hide_gridlines() {
343 $this->pear_excel_worksheet
->hideGridLines();
347 * Set the option to hide gridlines on the worksheet (as seen on the screen).
351 function hide_screen_gridlines() {
352 $this->pear_excel_worksheet
->hideScreenGridlines();
356 * Insert a 24bit bitmap image in a worksheet.
359 * @param integer $row The row we are going to insert the bitmap into
360 * @param integer $col The column we are going to insert the bitmap into
361 * @param string $bitmap The bitmap filename
362 * @param integer $x The horizontal position (offset) of the image inside the cell.
363 * @param integer $y The vertical position (offset) of the image inside the cell.
364 * @param integer $scale_x The horizontal scale
365 * @param integer $scale_y The vertical scale
367 function insert_bitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) {
368 /// Add the bitmap safely to the PEAR Worksheet
369 $this->pear_excel_worksheet
->insertBitmap($row, $col, $bitmap, $x, $y, $scale_x, $scale_y);
373 * Merges the area given by its arguments.
374 * This is an Excel97/2000 method. It is required to perform more complicated
375 * merging than the normal setAlign('merge').
378 * @param integer $first_row First row of the area to merge
379 * @param integer $first_col First column of the area to merge
380 * @param integer $last_row Last row of the area to merge
381 * @param integer $last_col Last column of the area to merge
383 function merge_cells($first_row, $first_col, $last_row, $last_col) {
384 /// Merge cells safely to the PEAR Worksheet
385 $this->pear_excel_worksheet
->mergeCells($first_row, $first_col, $last_row, $last_col);
389 * Returns the PEAR Excel Format for one Moodle Excel Format
391 * @param mixed $format MoodleExcelFormat object
392 * @return mixed PEAR Excel Format object
394 function MoodleExcelFormat2PearExcelFormat($format) {
396 return $format->pear_excel_format
;
405 * Define and operate over one Format.
407 * A big part of this class acts as a wrapper over the PEAR
408 * Spreadsheet_Excel_Writer_Workbook and OLE libraries
409 * maintaining Moodle functions isolated from underlying code.
411 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
412 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
413 * @package moodlecore
415 class MoodleExcelFormat
{
417 var $pear_excel_format;
420 * Constructs one Moodle Format.
422 * @param object $workbook The internal PEAR Workbook onject we are creating
423 * @param array $properties
425 function MoodleExcelFormat(&$workbook, $properties = array()) {
426 /// Internally, add one sheet to the workbook
427 $this->pear_excel_format
=& $workbook->addFormat();
428 /// If we have something in the array of properties, compute them
429 foreach($properties as $property => $value) {
430 if(method_exists($this,"set_$property")) {
431 $aux = 'set_'.$property;
438 * Set the size of the text in the format (in pixels).
439 * By default all texts in generated sheets are 10px.
441 * @param integer $size Size of the text (in pixels)
443 function set_size($size) {
444 /// Set the size safely to the PEAR Format
445 $this->pear_excel_format
->setSize($size);
449 * Set weight of the format
451 * @param integer $weight Weight for the text, 0 maps to 400 (normal text),
452 * 1 maps to 700 (bold text). Valid range is: 100-1000.
453 * It's Optional, default is 1 (bold).
455 function set_bold($weight = 1) {
456 /// Set the bold safely to the PEAR Format
457 $this->pear_excel_format
->setBold($weight);
461 * Set underline of the format
463 * @param integer $underline The value for underline. Possible values are:
464 * 1 => underline, 2 => double underline
466 function set_underline($underline) {
467 /// Set the underline safely to the PEAR Format
468 $this->pear_excel_format
->setUnderline($underline);
472 * Set italic of the format
474 function set_italic() {
475 /// Set the italic safely to the PEAR Format
476 $this->pear_excel_format
->setItalic();
480 * Set strikeout of the format
482 function set_strikeout() {
483 /// Set the strikeout safely to the PEAR Format
484 $this->pear_excel_format
->setStrikeOut();
488 * Set outlining of the format
490 function set_outline() {
491 /// Set the outlining safely to the PEAR Format
492 $this->pear_excel_format
->setOutLine();
496 * Set shadow of the format
498 function set_shadow() {
499 /// Set the shadow safely to the PEAR Format
500 $this->pear_excel_format
->setShadow();
504 * Set the script of the text
506 * @param integer $script The value for script type. Possible values are:
507 * 1 => superscript, 2 => subscript
509 function set_script($script) {
510 /// Set the script safely to the PEAR Format
511 $this->pear_excel_format
->setScript($script);
515 * Set color of the format. Used to specify the color of the text to be formatted.
517 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
519 function set_color($color) {
520 /// Set the background color safely to the PEAR Format
521 $this->pear_excel_format
->setColor($color);
525 * Set foreground color (top layer) of the format. About formatting colors note that cells backgrounds
526 * have TWO layers, in order to support patterns and paint them with two diferent colors.
527 * This method set the color of the TOP layer of the background format. So, when filling
528 * cells with plain colors (no patterns) this is the method to use.
530 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
532 function set_fg_color($color) {
533 /// Set the foreground color safely to the PEAR Format
534 $this->pear_excel_format
->setFgColor($color);
538 * Set background color (bottom layer) of the format. About formatting colors note that cells backgrounds
539 * have TWO layers, in order to support patterns and paint them with two diferent colors.
540 * This method set the color of the BOTTOM layer of the background format. So, the color
541 * specified here only will be visible if using patterns. Use set_fg_color() to fill
542 * cells with plain colors (no patterns).
544 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
546 function set_bg_color($color) {
547 /// Set the background color safely to the PEAR Format
548 $this->pear_excel_format
->setBgColor($color);
552 * Set the fill pattern of the format
553 * @param integer Optional. Defaults to 1. Meaningful values are: 0-18
554 * 0 meaning no background.
556 function set_pattern($pattern=1) {
557 /// Set the fill pattern safely to the PEAR Format
558 $this->pear_excel_format
->setPattern($pattern);
562 * Set text wrap of the format
564 function set_text_wrap() {
565 /// Set the shadow safely to the PEAR Format
566 $this->pear_excel_format
->setTextWrap();
570 * Set the cell alignment of the format
572 * @param string $location alignment for the cell ('left', 'right', etc...)
574 function set_align($location) {
575 /// Set the alignment of the cell safely to the PEAR Format
576 $this->pear_excel_format
->setAlign($location);
580 * Set the cell horizontal alignment of the format
582 * @param string $location alignment for the cell ('left', 'right', etc...)
584 function set_h_align($location) {
585 /// Set the alignment of the cell safely to the PEAR Format
586 $this->pear_excel_format
->setHAlign($location);
590 * Set the cell vertical alignment of the format
592 * @param string $location alignment for the cell ('top', 'vleft', etc...)
594 function set_v_align($location) {
595 /// Set the alignment of the cell safely to the PEAR Format
596 $this->pear_excel_format
->setVAlign($location);
600 * Set the top border of the format
602 * @param integer $style style for the cell. 1 => thin, 2 => thick
604 function set_top($style) {
605 /// Set the top border of the cell safely to the PEAR Format
606 $this->pear_excel_format
->setTop($style);
610 * Set the bottom border of the format
612 * @param integer $style style for the cell. 1 => thin, 2 => thick
614 function set_bottom($style) {
615 /// Set the bottom border of the cell safely to the PEAR Format
616 $this->pear_excel_format
->setBottom($style);
620 * Set the left border of the format
622 * @param integer $style style for the cell. 1 => thin, 2 => thick
624 function set_left($style) {
625 /// Set the left border of the cell safely to the PEAR Format
626 $this->pear_excel_format
->setLeft($style);
630 * Set the right border of the format
632 * @param integer $style style for the cell. 1 => thin, 2 => thick
634 function set_right($style) {
635 /// Set the right border of the cell safely to the PEAR Format
636 $this->pear_excel_format
->setRight($style);
640 * Set cells borders to the same style
642 * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
644 function set_border($style) {
645 /// Set all the borders of the cell safely to the PEAR Format
646 $this->pear_excel_format
->setBorder($style);
650 * Set the numerical format of the format
651 * It can be date, time, currency, etc...
653 * @param integer $num_format The numeric format
655 function set_num_format($num_format) {
656 /// Set the numerical format safely to the PEAR Format
657 $this->pear_excel_format
->setNumFormat($num_format);