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/>.
20 * - Eloy Lafuente (stronk7) {@link http://contiento.com}
21 * - Petr Skoda (skodak)
25 * @copyright (C) 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com}
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29 defined('MOODLE_INTERNAL') ||
die();
32 * The xml used here is derived from output of KSpread 1.6.1
35 * - missing formatting
36 * - write_date() works fine in OOo, but it does not work in KOffice - it knows only date or time but not both :-(
39 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42 class MoodleODSWorkbook
{
43 var $worksheets = array();
46 function MoodleODSWorkbook($filename) {
47 $this->filename
= $filename;
50 /* Create one Moodle Worksheet
51 * @param string $name Name of the sheet
53 function &add_worksheet($name = '') {
54 /// Create the Moodle Worksheet. Returns one pointer to it
55 $ws = new MoodleODSWorksheet($name);
56 $this->worksheets
[] =& $ws;
60 /* Create one Moodle Format
61 * @param array $properties array of properties [name]=value;
62 * valid names are set_XXXX existing
63 * functions without the set_ part
64 * i.e: [bold]=1 for set_bold(1)...Optional!
66 function &add_format($properties = array()) {
67 $format = new MoodleODSFormat($properties);
71 /* Close the Moodle Workbook
75 require_once($CFG->libdir
.'/filelib.php');
78 make_temp_directory($dir);
79 make_temp_directory($dir.'/META-INF');
80 $dir = "$CFG->tempdir/$dir";
83 $handle = fopen("$dir/mimetype", 'w');
84 fwrite($handle, get_ods_mimetype());
85 $files[] = "$dir/mimetype";
87 $handle = fopen("$dir/content.xml", 'w');
88 fwrite($handle, get_ods_content($this->worksheets
));
89 $files[] = "$dir/content.xml";
91 $handle = fopen("$dir/meta.xml", 'w');
92 fwrite($handle, get_ods_meta());
93 $files[] = "$dir/meta.xml";
95 $handle = fopen("$dir/styles.xml", 'w');
96 fwrite($handle, get_ods_styles());
97 $files[] = "$dir/styles.xml";
99 $handle = fopen("$dir/META-INF/manifest.xml", 'w');
100 fwrite($handle, get_ods_manifest());
101 $files[] = "$dir/META-INF";
103 $filename = "$dir/result.ods";
104 zip_files($files, $filename);
106 $handle = fopen($filename, 'rb');
107 $contents = fread($handle, filesize($filename));
110 remove_dir($dir); // cleanup the temp directory
112 send_file($contents, $this->filename
, 0, 0, true, true, 'application/vnd.oasis.opendocument.spreadsheet');
115 /* Not required to use
116 * @param string $name Name of the downloaded file
118 function send($filename) {
119 $this->filename
= $filename;
126 * @package moodlecore
127 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
128 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
130 class MoodleODSWorksheet
{
132 var $columns = array();
137 /* Constructs one Moodle Worksheet.
138 * @param string $filename The name of the file
140 function MoodleODSWorksheet($name) {
144 /* Write one string somewhere in the worksheet
145 * @param integer $row Zero indexed row
146 * @param integer $col Zero indexed column
147 * @param string $str The string to write
148 * @param mixed $format The XF format for the cell
150 function write_string($row, $col, $str, $format=0) {
151 if (!array_key_exists($row, $this->data
)) {
152 $this->data
[$row] = array();
154 $this->data
[$row][$col] = new stdClass();
155 $this->data
[$row][$col]->value
= $str;
156 $this->data
[$row][$col]->type
= 'string';
157 $this->data
[$row][$col]->format
= $format;
160 /* Write one number somewhere in the worksheet
161 * @param integer $row Zero indexed row
162 * @param integer $col Zero indexed column
163 * @param float $num The number to write
164 * @param mixed $format The XF format for the cell
166 function write_number($row, $col, $num, $format=0) {
167 if (!array_key_exists($row, $this->data
)) {
168 $this->data
[$row] = array();
170 $this->data
[$row][$col] = new stdClass();
171 $this->data
[$row][$col]->value
= $num;
172 $this->data
[$row][$col]->type
= 'float';
173 $this->data
[$row][$col]->format
= $format;
176 /* Write one url somewhere in the worksheet
177 * @param integer $row Zero indexed row
178 * @param integer $col Zero indexed column
179 * @param string $url The url to write
180 * @param mixed $format The XF format for the cell
182 function write_url($row, $col, $url, $format=0) {
183 if (!array_key_exists($row, $this->data
)) {
184 $this->data
[$row] = array();
186 $this->data
[$row][$col] = new stdClass();
187 $this->data
[$row][$col]->value
= $url;
188 $this->data
[$row][$col]->type
= 'string';
189 $this->data
[$row][$col]->format
= $format;
192 /* Write one date somewhere in the worksheet
193 * @param integer $row Zero indexed row
194 * @param integer $col Zero indexed column
195 * @param string $url The url to write
196 * @param mixed $format The XF format for the cell
198 function write_date($row, $col, $date, $format=0) {
199 if (!array_key_exists($row, $this->data
)) {
200 $this->data
[$row] = array();
202 $this->data
[$row][$col] = new stdClass();
203 $this->data
[$row][$col]->value
= $date;
204 $this->data
[$row][$col]->type
= 'date';
205 $this->data
[$row][$col]->format
= $format;
209 * Write one formula somewhere in the worksheet
211 * @param integer $row Zero indexed row
212 * @param integer $col Zero indexed column
213 * @param string $formula The formula to write
214 * @param mixed $format The XF format for the cell
216 function write_formula($row, $col, $formula, $format=null) {
220 /* Write one blanck somewhere in the worksheet
221 * @param integer $row Zero indexed row
222 * @param integer $col Zero indexed column
223 * @param mixed $format The XF format for the cell
225 function write_blank($row, $col, $format=0) {
226 if (array_key_exists($row, $this->data
)) {
227 unset($this->data
[$row][$col]);
231 /* Write anything somewhere in the worksheet
232 * Type will be automatically detected
233 * @param integer $row Zero indexed row
234 * @param integer $col Zero indexed column
235 * @param mixed $token What we are writing
236 * @param mixed $format The XF format for the cell
238 function write($row, $col, $token, $format=0) {
240 /// Analyse what are we trying to send
241 if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/", $token)) {
243 return $this->write_number($row, $col, $token, $format);
244 } elseif (preg_match("/^[fh]tt?p:\/\//", $token)) {
245 /// Match http or ftp URL
246 return $this->write_url($row, $col, $token, '', $format);
247 } elseif (preg_match("/^mailto:/", $token)) {
249 return $this->write_url($row, $col, $token, '', $format);
250 } elseif (preg_match("/^(?:in|ex)ternal:/", $token)) {
251 /// Match internal or external sheet link
252 return $this->write_url($row, $col, $token, '', $format);
253 } elseif (preg_match("/^=/", $token)) {
255 return $this->write_formula($row, $col, $token, $format);
256 } elseif (preg_match("/^@/", $token)) {
258 return $this->write_formula($row, $col, $token, $format);
259 } elseif ($token == '') {
261 return $this->write_blank($row, $col, $format);
263 /// Default: match string
264 return $this->write_string($row, $col, $token, $format);
268 /* Sets the height (and other settings) of one row
269 * @param integer $row The row to set
270 * @param integer $height Height we are giving to the row (null to set just format withouth setting the height)
271 * @param mixed $format The optional XF format we are giving to the row
272 * @param bool $hidden The optional hidden attribute
273 * @param integer $level The optional outline level (0-7)
275 function set_row($row, $height, $format = 0, $hidden = false, $level = 0) {
276 $this->rows
[$row] = new stdClass();
277 $this->rows
[$row]->height
= $height;
278 //$this->rows[$row]->format = $format; // TODO: fix and enable
279 $this->rows
[$row]->hidden
= $hidden;
282 /* Sets the width (and other settings) of one column
283 * @param integer $firstcol first column on the range
284 * @param integer $lastcol last column on the range
285 * @param integer $width width to set
286 * @param mixed $format The optional XF format to apply to the columns
287 * @param integer $hidden The optional hidden atribute
288 * @param integer $level The optional outline level (0-7)
290 function set_column($firstcol, $lastcol, $width, $format = 0, $hidden = false, $level = 0) {
291 for($i=$firstcol; $i<=$lastcol; $i++
) {
292 $this->columns
[$i] = new stdClass();
293 $this->columns
[$i]->width
= $width;
294 //$this->columns[$i]->format = $format; // TODO: fix and enable
295 $this->columns
[$i]->hidden
= $hidden;
301 * Set the option to hide gridlines on the printed page.
305 function hide_gridlines() {
310 * Set the option to hide gridlines on the worksheet (as seen on the screen).
314 function hide_screen_gridlines() {
319 * Insert a 24bit bitmap image in a worksheet.
322 * @param integer $row The row we are going to insert the bitmap into
323 * @param integer $col The column we are going to insert the bitmap into
324 * @param string $bitmap The bitmap filename
325 * @param integer $x The horizontal position (offset) of the image inside the cell.
326 * @param integer $y The vertical position (offset) of the image inside the cell.
327 * @param integer $scale_x The horizontal scale
328 * @param integer $scale_y The vertical scale
330 function insert_bitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) {
334 * Merges the area given by its arguments.
335 * merging than the normal setAlign('merge').
338 * @param integer $first_row First row of the area to merge
339 * @param integer $first_col First column of the area to merge
340 * @param integer $last_row Last row of the area to merge
341 * @param integer $last_col Last column of the area to merge
343 function merge_cells($first_row, $first_col, $last_row, $last_col) {
348 * Define and operate over one Format.
350 * @package moodlecore
351 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
352 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
354 class MoodleODSFormat
{
358 /* Constructs one Moodle Format.
359 * @param object $workbook The internal PEAR Workbook onject we are creating
361 function MoodleODSFormat($properties = array()) {
366 foreach($properties as $property => $value) {
367 if(method_exists($this,"set_$property")) {
368 $aux = 'set_'.$property;
374 /* Set weight of the format
375 * @param integer $weight Weight for the text, 0 maps to 400 (normal text),
376 * 1 maps to 700 (bold text). Valid range is: 100-1000.
377 * It's Optional, default is 1 (bold).
379 function set_bold($weight = 1) {
380 $this->properties
['bold'] = $weight;
383 /* Set underline of the format
384 * @param integer $underline The value for underline. Possible values are:
385 * 1 => underline, 2 => double underline
387 function set_underline($underline = 1) {
388 $this->properties
['underline'] = $underline;
391 /* Set italic of the format
393 function set_italic() {
394 $this->properties
['italic'] = true;
397 /* Set strikeout of the format
399 function set_strikeout() {
400 $this->properties
['strikeout'] = true;
403 /* Set outlining of the format
405 function set_outline() {
408 /* Set shadow of the format
410 function set_shadow() {
413 /* Set the script of the text
414 * @param integer $script The value for script type. Possible values are:
415 * 1 => superscript, 2 => subscript
417 function set_script($script) {
420 /* Set color of the format
421 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
423 function set_color($color) {
424 $this->properties
['color'] = $this->_get_color($color);
427 /* Set foreground color of the format
428 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
430 function set_fg_color($color) {
433 /* Set background color of the format
434 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
436 function set_bg_color($color) {
437 $this->properties
['bg_color'] = $this->_get_color($color);
440 /* Set the fill pattern of the format
441 * @param integer Optional. Defaults to 1. Meaningful values are: 0-18
442 * 0 meaning no background.
444 function set_pattern($pattern=1) {
447 /* Set text wrap of the format
449 function set_text_wrap() {
452 /* Set the cell alignment of the format
453 * @param string $location alignment for the cell ('left', 'right', etc...)
455 function set_align($location) {
459 $this->properties
['align'] = 'start';
462 $this->properties
['align'] = 'center';
466 $this->properties
['align'] = 'end';
469 //ignore the rest == start
473 /* Set the cell horizontal alignment of the format
474 * @param string $location alignment for the cell ('left', 'right', etc...)
476 function set_h_align($location) {
477 $this->set_align($location);
480 /* Set the cell vertical alignment of the format
481 * @param string $location alignment for the cell ('top', 'vleft', etc...)
483 function set_v_align($location) {
486 $this->properties
['v_align'] = 'top';
489 $this->properties
['v_align'] = 'bottom';
492 //ignore the rest == middle
496 /* Set the top border of the format
497 * @param integer $style style for the cell. 1 => thin, 2 => thick
499 function set_top($style) {
502 /* Set the bottom border of the format
503 * @param integer $style style for the cell. 1 => thin, 2 => thick
505 function set_bottom($style) {
508 /* Set the left border of the format
509 * @param integer $style style for the cell. 1 => thin, 2 => thick
511 function set_left($style) {
514 /* Set the right border of the format
515 * @param integer $style style for the cell. 1 => thin, 2 => thick
517 function set_right($style) {
521 * Set cells borders to the same style
522 * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
524 function set_border($style) {
527 /* Set the numerical format of the format
528 * It can be date, time, currency, etc...
529 /* Set the numerical format of the format
530 * It can be date, time, currency, etc...
531 * @param integer $num_format The numeric format
533 function set_num_format($num_format) {
536 function _get_color($name_color = '') {
537 if (strpos($name_color, '#') === 0) {
538 return $name_color; // no conversion needed
541 $colors = array('aqua' => '#00FFFF',
543 'black' => '#FFFFFF',
545 'brown' => '#A52A2A',
546 'magenta' => '#FF00FF',
547 'fuchsia' => '#FF00FF',
550 'green' => '#00FF00',
553 'orange' => '#FF8000',
554 'purple' => '#800080',
556 'silver' => '#DCDCDC',
557 'white' => '#FFFFFF',
558 'yellow' => '#FFFF00');
560 if(array_key_exists($name_color, $colors)) {
561 return $colors[$name_color];
569 //=============================
570 // OpenDocument XML functions
571 //=============================
572 function get_ods_content(&$worksheets) {
575 // find out the size of worksheets and used styles
581 foreach($worksheets as $wsnum=>$ws) {
582 $worksheets[$wsnum]->maxr
= 0;
583 $worksheets[$wsnum]->maxc
= 0;
584 foreach($ws->data
as $rnum=>$row) {
585 if ($rnum > $worksheets[$wsnum]->maxr
) {
586 $worksheets[$wsnum]->maxr
= $rnum;
588 foreach($row as $cnum=>$cell) {
589 if ($cnum > $worksheets[$wsnum]->maxc
) {
590 $worksheets[$wsnum]->maxc
= $cnum;
592 if (!empty($cell->format
)) {
593 if (!array_key_exists($cell->format
->id
, $formats)) {
594 $formats[$cell->format
->id
] = $cell->format
;
600 foreach($ws->rows
as $rnum=>$row) {
601 if (!empty($row->format
)) {
602 if (!array_key_exists($row->format
->id
, $formats)) {
603 $formats[$row->format
->id
] = $row->format
;
606 if ($rnum > $worksheets[$wsnum]->maxr
) {
607 $worksheets[$wsnum]->maxr
= $rnum;
609 //define all column styles
610 if (!empty($ws->rows
[$rnum])) {
612 <style:style style:name="ws'.$wsnum.'ro'.$rnum.'" style:family="table-row">
613 <style:table-row-properties style:row-height="'.$row->height
.'pt"/>
618 foreach($ws->columns
as $cnum=>$col) {
619 if (!empty($col->format
)) {
620 if (!array_key_exists($col->format
->id
, $formats)) {
621 $formats[$col->format
->id
] = $col->format
;
624 if ($cnum > $worksheets[$wsnum]->maxc
) {
625 $worksheets[$wsnum]->maxc
= $cnum;
627 //define all column styles
628 if (!empty($ws->columns
[$cnum])) {
630 <style:style style:name="ws'.$wsnum.'co'.$cnum.'" style:family="table-column">
631 <style:table-column-properties style:column-width="'.$col->width
.'pt"/>
637 foreach($formats as $format) {
641 foreach($format->properties
as $pname=>$pvalue) {
644 if (!empty($pvalue)) {
645 $textprop .= ' fo:font-weight="bold"';
649 if (!empty($pvalue)) {
650 $textprop .= ' fo:font-style="italic"';
654 if (!empty($pvalue)) {
655 $textprop .= ' style:text-underline-color="font-color" style:text-underline-style="solid" style:text-underline-width="auto"';
659 if (!empty($pvalue)) {
660 $textprop .= ' style:text-line-through-style="solid"';
664 if ($pvalue !== false) {
665 $textprop .= ' fo:color="'.$pvalue.'"';
669 if ($pvalue !== false) {
670 $cellprop .= ' fo:background-color="'.$pvalue.'"';
674 $parprop .= ' fo:text-align="'.$pvalue.'"';
677 $cellprop .= ' style:vertical-align="'.$pvalue.'"';
681 if (!empty($textprop)) {
683 <style:text-properties'.$textprop.'/>';
686 if (!empty($cellprop)) {
688 <style:table-cell-properties'.$cellprop.'/>';
691 if (!empty($parprop)) {
693 <style:paragraph-properties'.$parprop.'/>';
697 <style:style style:name="format'.$format->id
.'" style:family="table-cell">'.$textprop.$cellprop.$parprop.'
703 '<?xml version="1.0" encoding="UTF-8"?>
704 <office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink">
705 <office:automatic-styles>
706 <style:style style:name="ta1" style:family="table" style:master-page-name="Standard1">
707 <style:table-properties table:display="true"/>
709 <style:style style:name="date0" style:family="table-cell"/>';
711 $buffer .= $formatstyles;
712 $buffer .= $rowstyles;
713 $buffer .= $colstyles;
716 </office:automatic-styles>
721 foreach($worksheets as $wsnum=>$ws) {
724 $buffer .= '<table:table table:name="' . htmlspecialchars($ws->name
) . '" table:style-name="ta1">'."\n";
726 // define column properties
727 for($c=0; $c<=$ws->maxc
; $c++
) {
728 if (array_key_exists($c, $ws->columns
)) {
730 if (!empty($ws->columns
[$c]->format
)) {
731 $extra .= ' table:default-cell-style-name="format'.$ws->columns
[$c]->format
->id
.'"';
733 if ($ws->columns
[$c]->hidden
) {
734 $extra .= ' table:visibility="collapse"';
736 $buffer .= '<table:table-column table:style-name="ws'.$wsnum.'co'.$c.'"'.$extra.'/>'."\n";
738 $buffer .= '<table:table-column/>'."\n";
743 for($r=0; $r<=$ws->maxr
; $r++
) {
744 if (array_key_exists($r, $ws->rows
)) {
746 if (!empty($ws->rows
[$r]->format
)) {
747 $extra .= ' table:default-cell-style-name="format'.$ws->rows
[$r]->format
->id
.'"';
749 if ($ws->rows
[$r]->hidden
) {
750 $extra .= ' table:visibility="collapse"';
752 $buffer .= '<table:table-row table:style-name="ws'.$wsnum.'ro'.$r.'"'.$extra.'>'."\n";
754 $buffer .= '<table:table-row>'."\n";
756 for($c=0; $c<=$ws->maxc
; $c++
) {
757 if (isset($ws->data
[$r][$c])) {
758 $cell = $ws->data
[$r][$c];
760 if (!empty($cell->format
)) {
761 $extra = ' table:style-name="format'.$cell->format
->id
.'"';
763 if ($cell->type
== 'date') {
764 $buffer .= '<table:table-cell office:value-type="date" table:style-name="date0" office:date-value="' . strftime('%Y-%m-%dT%H:%M:%S', $cell->value
) . '"'.$extra.'>'
765 . '<text:p>' . strftime('%Y-%m-%dT%H:%M:%S', $cell->value
) . '</text:p>'
766 . '</table:table-cell>'."\n";
767 } else if ($cell->type
== 'float') {
768 $buffer .= '<table:table-cell office:value-type="float" office:value="' . htmlspecialchars($cell->value
) . '"'.$extra.'>'
769 . '<text:p>' . htmlspecialchars($cell->value
) . '</text:p>'
770 . '</table:table-cell>'."\n";
771 } else if ($cell->type
== 'string') {
772 $buffer .= '<table:table-cell office:value-type="string" office:string-value="' . htmlspecialchars($cell->value
) . '"'.$extra.'>'
773 . '<text:p>' . htmlspecialchars($cell->value
) . '</text:p>'
774 . '</table:table-cell>'."\n";
776 $buffer .= '<table:table-cell office:value-type="string"'.$extra.'>'
777 . '<text:p>!!Error - unknown type!!</text:p>'
778 . '</table:table-cell>'."\n";
781 $buffer .= '<table:table-cell/>'."\n";
784 $buffer .= '</table:table-row>'."\n";
787 $buffer .= '</table:table>'."\n";
793 ' </office:spreadsheet>
795 </office:document-content>';
800 function get_ods_mimetype() {
801 return 'application/vnd.oasis.opendocument.spreadsheet';
804 function get_ods_meta() {
808 '<?xml version="1.0" encoding="UTF-8"?>
809 <office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink">
811 <meta:generator>Moodle '.$CFG->version
.'</meta:generator>
812 <meta:initial-creator>'.fullname($USER, true).'</meta:initial-creator>
813 <meta:editing-cycles>1</meta:editing-cycles>
814 <meta:creation-date>'.strftime('%Y-%m-%dT%H:%M:%S').'</meta:creation-date>
815 <dc:date>'.strftime('%Y-%m-%dT%H:%M:%S').'</dc:date>
816 <dc:creator>'.fullname($USER, true).'</dc:creator>
818 </office:document-meta>';
821 function get_ods_styles() {
823 '<?xml version="1.0" encoding="UTF-8"?>
824 <office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink">
826 <style:default-style style:family="table-column">
827 <style:table-column-properties style:column-width="75pt"/>
828 </style:default-style>
829 <style:default-style style:family="table-row">
830 <style:table-row-properties style:row-height="15pt"/>
831 </style:default-style>
832 <style:default-style style:family="table-cell">
833 <style:table-cell-properties fo:background-color="#ffffff" style:cell-protect="protected" style:vertical-align="middle"/>
834 <style:text-properties fo:color="#000000" fo:font-family="Arial" fo:font-size="12pt"/>
835 </style:default-style>
837 <office:automatic-styles>
838 <style:page-layout style:name="pm1">
839 <style:page-layout-properties fo:margin-bottom="56.6930116pt" fo:margin-left="56.6930116pt" fo:margin-right="56.6930116pt" fo:margin-top="56.6930116pt" fo:page-height="841.89122226pt" fo:page-width="595.2766218pt" style:print="objects charts drawings zero-values" style:print-orientation="portrait"/>
841 </office:automatic-styles>
842 <office:master-styles>
843 <style:master-page style:name="Standard1" style:page-layout-name="pm1">
846 <text:sheet-name>???</text:sheet-name>
848 </style:header><style:footer>
850 <text:sheet-name>Page </text:sheet-name>
851 <text:page-number>1</text:page-number>
855 </office:master-styles>
856 </office:document-styles>
860 function get_ods_manifest() {
862 '<?xml version="1.0" encoding="UTF-8"?>
863 <manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
864 <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/>
865 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
866 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
867 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
868 </manifest:manifest>';