3 ///////////////////////////////////////////////////////////////////////////
5 // NOTICE OF COPYRIGHT //
7 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
8 // http://moodle.com //
10 // Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
11 // (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
12 // (C) 2001-3001 Petr Skoda (skodak) //
14 // This program is free software; you can redistribute it and/or modify //
15 // it under the terms of the GNU General Public License as published by //
16 // the Free Software Foundation; either version 2 of the License, or //
17 // (at your option) any later version. //
19 // This program is distributed in the hope that it will be useful, //
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
22 // GNU General Public License for more details: //
24 // http://www.gnu.org/copyleft/gpl.html //
26 ///////////////////////////////////////////////////////////////////////////
29 * The xml used here is derived from output of KSpread 1.6.1
32 * - missing formatting
33 * - write_date() works fine in OOo, but it does not work in KOffice - it knows only date or time but not both :-(
36 class MoodleODSWorkbook
{
37 var $worksheets = array();
40 function MoodleODSWorkbook($filename) {
41 $this->filename
= $filename;
44 /* Create one Moodle Worksheet
45 * @param string $name Name of the sheet
47 function &add_worksheet($name = '') {
48 /// Create the Moodle Worksheet. Returns one pointer to it
49 $ws =& new MoodleODSWorksheet($name);
50 $this->worksheets
[] =& $ws;
54 /* Create one Moodle Format
55 * @param array $properties array of properties [name]=value;
56 * valid names are set_XXXX existing
57 * functions without the set_ part
58 * i.e: [bold]=1 for set_bold(1)...Optional!
60 function &add_format($properties = array()) {
61 $format = new MoodleODSFormat($properties);
65 /* Close the Moodle Workbook
69 require_once($CFG->libdir
.'/filelib.php');
71 $dir = 'temp/ods/'.time();
72 make_upload_directory($dir, false);
73 make_upload_directory($dir.'/META-INF', false);
74 $dir = "$CFG->dataroot/$dir";
77 $handle = fopen("$dir/mimetype", 'w');
78 fwrite($handle, get_ods_mimetype());
79 $files[] = "$dir/mimetype";
81 $handle = fopen("$dir/content.xml", 'w');
82 fwrite($handle, get_ods_content($this->worksheets
));
83 $files[] = "$dir/content.xml";
85 $handle = fopen("$dir/meta.xml", 'w');
86 fwrite($handle, get_ods_meta());
87 $files[] = "$dir/meta.xml";
89 $handle = fopen("$dir/styles.xml", 'w');
90 fwrite($handle, get_ods_styles());
91 $files[] = "$dir/styles.xml";
93 $handle = fopen("$dir/META-INF/manifest.xml", 'w');
94 fwrite($handle, get_ods_manifest());
95 $files[] = "$dir/META-INF";
97 $filename = "$dir/result.ods";
98 zip_files($files, $filename);
100 $handle = fopen($filename, 'rb');
101 $contents = fread($handle, filesize($filename));
104 remove_dir($dir); // cleanup the temp directory
106 send_file($contents, $this->filename
, 0, 0, true, true, 'application/vnd.oasis.opendocument.spreadsheet');
109 /* Not required to use
110 * @param string $name Name of the downloaded file
112 function send($filename) {
113 $this->filename
= $filename;
118 class MoodleODSWorksheet
{
120 var $columns = array();
125 /* Constructs one Moodle Worksheet.
126 * @param string $filename The name of the file
128 function MoodleODSWorksheet($name) {
132 /* Write one string somewhere in the worksheet
133 * @param integer $row Zero indexed row
134 * @param integer $col Zero indexed column
135 * @param string $str The string to write
136 * @param mixed $format The XF format for the cell
138 function write_string($row, $col, $str, $format=0) {
139 if (!array_key_exists($row, $this->data
)) {
140 $this->data
[$row] = array();
142 $this->data
[$row][$col] = new object();
143 $this->data
[$row][$col]->value
= $str;
144 $this->data
[$row][$col]->type
= 'string';
145 $this->data
[$row][$col]->format
= $format;
148 /* Write one number somewhere in the worksheet
149 * @param integer $row Zero indexed row
150 * @param integer $col Zero indexed column
151 * @param float $num The number to write
152 * @param mixed $format The XF format for the cell
154 function write_number($row, $col, $num, $format=0) {
155 if (!array_key_exists($row, $this->data
)) {
156 $this->data
[$row] = array();
158 $this->data
[$row][$col] = new object();
159 $this->data
[$row][$col]->value
= $num;
160 $this->data
[$row][$col]->type
= 'float';
161 $this->data
[$row][$col]->format
= $format;
164 /* Write one url somewhere in the worksheet
165 * @param integer $row Zero indexed row
166 * @param integer $col Zero indexed column
167 * @param string $url The url to write
168 * @param mixed $format The XF format for the cell
170 function write_url($row, $col, $url, $format=0) {
171 if (!array_key_exists($row, $this->data
)) {
172 $this->data
[$row] = array();
174 $this->data
[$row][$col] = new object();
175 $this->data
[$row][$col]->value
= $url;
176 $this->data
[$row][$col]->type
= 'string';
177 $this->data
[$row][$col]->format
= $format;
180 /* Write one date somewhere in the worksheet
181 * @param integer $row Zero indexed row
182 * @param integer $col Zero indexed column
183 * @param string $url The url to write
184 * @param mixed $format The XF format for the cell
186 function write_date($row, $col, $date, $format=0) {
187 if (!array_key_exists($row, $this->data
)) {
188 $this->data
[$row] = array();
190 $this->data
[$row][$col] = new object();
191 $this->data
[$row][$col]->value
= $date;
192 $this->data
[$row][$col]->type
= 'date';
193 $this->data
[$row][$col]->format
= $format;
197 * Write one formula somewhere in the worksheet
199 * @param integer $row Zero indexed row
200 * @param integer $col Zero indexed column
201 * @param string $formula The formula to write
202 * @param mixed $format The XF format for the cell
204 function write_formula($row, $col, $formula, $format=null) {
208 /* Write one blanck somewhere in the worksheet
209 * @param integer $row Zero indexed row
210 * @param integer $col Zero indexed column
211 * @param mixed $format The XF format for the cell
213 function write_blank($row, $col, $format=0) {
214 if (array_key_exists($row, $this->data
)) {
215 unset($this->data
[$row][$col]);
219 /* Write anything somewhere in the worksheet
220 * Type will be automatically detected
221 * @param integer $row Zero indexed row
222 * @param integer $col Zero indexed column
223 * @param mixed $token What we are writing
224 * @param mixed $format The XF format for the cell
226 function write($row, $col, $token, $format=0) {
228 /// Analyse what are we trying to send
229 if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/", $token)) {
231 return $this->write_number($row, $col, $token, $format);
232 } elseif (preg_match("/^[fh]tt?p:\/\//", $token)) {
233 /// Match http or ftp URL
234 return $this->write_url($row, $col, $token, '', $format);
235 } elseif (preg_match("/^mailto:/", $token)) {
237 return $this->write_url($row, $col, $token, '', $format);
238 } elseif (preg_match("/^(?:in|ex)ternal:/", $token)) {
239 /// Match internal or external sheet link
240 return $this->write_url($row, $col, $token, '', $format);
241 } elseif (preg_match("/^=/", $token)) {
243 return $this->write_formula($row, $col, $token, $format);
244 } elseif (preg_match("/^@/", $token)) {
246 return $this->write_formula($row, $col, $token, $format);
247 } elseif ($token == '') {
249 return $this->write_blank($row, $col, $format);
251 /// Default: match string
252 return $this->write_string($row, $col, $token, $format);
256 /* Sets the height (and other settings) of one row
257 * @param integer $row The row to set
258 * @param integer $height Height we are giving to the row (null to set just format withouth setting the height)
259 * @param mixed $format The optional XF format we are giving to the row
260 * @param bool $hidden The optional hidden attribute
261 * @param integer $level The optional outline level (0-7)
263 function set_row($row, $height, $format = 0, $hidden = false, $level = 0) {
264 $this->rows
[$row] = new object();
265 $this->rows
[$row]->height
= $height;
266 //$this->rows[$row]->format = $format; // TODO: fix and enable
267 $this->rows
[$row]->hidden
= $hidden;
270 /* Sets the width (and other settings) of one column
271 * @param integer $firstcol first column on the range
272 * @param integer $lastcol last column on the range
273 * @param integer $width width to set
274 * @param mixed $format The optional XF format to apply to the columns
275 * @param integer $hidden The optional hidden atribute
276 * @param integer $level The optional outline level (0-7)
278 function set_column($firstcol, $lastcol, $width, $format = 0, $hidden = false, $level = 0) {
279 for($i=$firstcol; $i<=$lastcol; $i++
) {
280 $this->columns
[$i] = new object();
281 $this->columns
[$i]->width
= $width;
282 //$this->columns[$i]->format = $format; // TODO: fix and enable
283 $this->columns
[$i]->hidden
= $hidden;
289 * Set the option to hide gridlines on the printed page.
293 function hide_gridlines() {
298 * Set the option to hide gridlines on the worksheet (as seen on the screen).
302 function hide_screen_gridlines() {
307 * Insert a 24bit bitmap image in a worksheet.
310 * @param integer $row The row we are going to insert the bitmap into
311 * @param integer $col The column we are going to insert the bitmap into
312 * @param string $bitmap The bitmap filename
313 * @param integer $x The horizontal position (offset) of the image inside the cell.
314 * @param integer $y The vertical position (offset) of the image inside the cell.
315 * @param integer $scale_x The horizontal scale
316 * @param integer $scale_y The vertical scale
318 function insert_bitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) {
322 * Merges the area given by its arguments.
323 * merging than the normal setAlign('merge').
326 * @param integer $first_row First row of the area to merge
327 * @param integer $first_col First column of the area to merge
328 * @param integer $last_row Last row of the area to merge
329 * @param integer $last_col Last column of the area to merge
331 function merge_cells($first_row, $first_col, $last_row, $last_col) {
337 * Define and operate over one Format.
339 class MoodleODSFormat
{
343 /* Constructs one Moodle Format.
344 * @param object $workbook The internal PEAR Workbook onject we are creating
346 function MoodleODSFormat($properties = array()) {
351 foreach($properties as $property => $value) {
352 if(method_exists($this,"set_$property")) {
353 $aux = 'set_'.$property;
359 /* Set weight of the format
360 * @param integer $weight Weight for the text, 0 maps to 400 (normal text),
361 * 1 maps to 700 (bold text). Valid range is: 100-1000.
362 * It's Optional, default is 1 (bold).
364 function set_bold($weight = 1) {
365 $this->properties
['bold'] = $weight;
368 /* Set underline of the format
369 * @param integer $underline The value for underline. Possible values are:
370 * 1 => underline, 2 => double underline
372 function set_underline($underline = 1) {
373 $this->properties
['underline'] = $underline;
376 /* Set italic of the format
378 function set_italic() {
379 $this->properties
['italic'] = true;
382 /* Set strikeout of the format
384 function set_strikeout() {
385 $this->properties
['strikeout'] = true;
388 /* Set outlining of the format
390 function set_outline() {
393 /* Set shadow of the format
395 function set_shadow() {
398 /* Set the script of the text
399 * @param integer $script The value for script type. Possible values are:
400 * 1 => superscript, 2 => subscript
402 function set_script($script) {
405 /* Set color of the format
406 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
408 function set_color($color) {
409 $this->properties
['color'] = $this->_get_color($color);
412 /* Set foreground color of the format
413 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
415 function set_fg_color($color) {
418 /* Set background color of the format
419 * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63])
421 function set_bg_color($color) {
422 $this->properties
['bg_color'] = $this->_get_color($color);
425 /* Set the fill pattern of the format
426 * @param integer Optional. Defaults to 1. Meaningful values are: 0-18
427 * 0 meaning no background.
429 function set_pattern($pattern=1) {
432 /* Set text wrap of the format
434 function set_text_wrap() {
437 /* Set the cell alignment of the format
438 * @param string $location alignment for the cell ('left', 'right', etc...)
440 function set_align($location) {
444 $this->properties
['align'] = 'start';
447 $this->properties
['align'] = 'center';
451 $this->properties
['align'] = 'end';
454 //ignore the rest == start
458 /* Set the cell horizontal alignment of the format
459 * @param string $location alignment for the cell ('left', 'right', etc...)
461 function set_h_align($location) {
462 set_align($location);
465 /* Set the cell vertical alignment of the format
466 * @param string $location alignment for the cell ('top', 'vleft', etc...)
468 function set_v_align($location) {
471 $this->properties
['v_align'] = 'top';
474 $this->properties
['v_align'] = 'bottom';
477 //ignore the rest == middle
481 /* Set the top border of the format
482 * @param integer $style style for the cell. 1 => thin, 2 => thick
484 function set_top($style) {
487 /* Set the bottom border of the format
488 * @param integer $style style for the cell. 1 => thin, 2 => thick
490 function set_bottom($style) {
493 /* Set the left border of the format
494 * @param integer $style style for the cell. 1 => thin, 2 => thick
496 function set_left($style) {
499 /* Set the right border of the format
500 * @param integer $style style for the cell. 1 => thin, 2 => thick
502 function set_right($style) {
506 * Set cells borders to the same style
507 * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
509 function set_border($style) {
512 /* Set the numerical format of the format
513 * It can be date, time, currency, etc...
514 /* Set the numerical format of the format
515 * It can be date, time, currency, etc...
516 * @param integer $num_format The numeric format
518 function set_num_format($num_format) {
521 function _get_color($name_color = '') {
522 if (strpos($name_color, '#') === 0) {
523 return $name_color; // no conversion needed
526 $colors = array('aqua' => '#00FFFF',
528 'black' => '#FFFFFF',
530 'brown' => '#A52A2A',
531 'magenta' => '#FF00FF',
532 'fuchsia' => '#FF00FF',
535 'green' => '#00FF00',
538 'orange' => '#FF8000',
539 'purple' => '#800080',
541 'silver' => '#DCDCDC',
542 'white' => '#FFFFFF',
543 'yellow' => '#FFFF00');
545 if(array_key_exists($name_color, $colors)) {
546 return $colors[$name_color];
554 //=============================
555 // OpenDocument XML functions
556 //=============================
557 function get_ods_content(&$worksheets) {
560 // find out the size of worksheets and used styles
566 foreach($worksheets as $wsnum=>$ws) {
567 $worksheets[$wsnum]->maxr
= 0;
568 $worksheets[$wsnum]->maxc
= 0;
569 foreach($ws->data
as $rnum=>$row) {
570 if ($rnum > $worksheets[$wsnum]->maxr
) {
571 $worksheets[$wsnum]->maxr
= $rnum;
573 foreach($row as $cnum=>$cell) {
574 if ($cnum > $worksheets[$wsnum]->maxc
) {
575 $worksheets[$wsnum]->maxc
= $cnum;
577 if (!empty($cell->format
)) {
578 if (!array_key_exists($cell->format
->id
, $formats)) {
579 $formats[$cell->format
->id
] = $cell->format
;
585 foreach($ws->rows
as $rnum=>$row) {
586 if (!empty($row->format
)) {
587 if (!array_key_exists($row->format
->id
, $formats)) {
588 $formats[$row->format
->id
] = $row->format
;
591 if ($rnum > $worksheets[$wsnum]->maxr
) {
592 $worksheets[$wsnum]->maxr
= $rnum;
594 //define all column styles
595 if (!empty($ws->rows
[$rnum])) {
597 <style:style style:name="ws'.$wsnum.'ro'.$rnum.'" style:family="table-row">
598 <style:table-row-properties style:row-height="'.$row->height
.'pt"/>
603 foreach($ws->columns
as $cnum=>$col) {
604 if (!empty($col->format
)) {
605 if (!array_key_exists($col->format
->id
, $formats)) {
606 $formats[$col->format
->id
] = $col->format
;
609 if ($cnum > $worksheets[$wsnum]->maxc
) {
610 $worksheets[$wsnum]->maxc
= $cnum;
612 //define all column styles
613 if (!empty($ws->columns
[$cnum])) {
615 <style:style style:name="ws'.$wsnum.'co'.$cnum.'" style:family="table-column">
616 <style:table-column-properties style:column-width="'.$col->width
.'pt"/>
622 foreach($formats as $format) {
626 foreach($format->properties
as $pname=>$pvalue) {
629 if (!empty($pvalue)) {
630 $textprop .= ' fo:font-weight="bold"';
634 if (!empty($pvalue)) {
635 $textprop .= ' fo:font-style="italic"';
639 if (!empty($pvalue)) {
640 $textprop .= ' style:text-underline-color="font-color" style:text-underline-style="solid" style:text-underline-width="auto"';
644 if (!empty($pvalue)) {
645 $textprop .= ' style:text-line-through-style="solid"';
649 if ($pvalue !== false) {
650 $textprop .= ' fo:color="'.$pvalue.'"';
654 if ($pvalue !== false) {
655 $cellprop .= ' fo:background-color="'.$pvalue.'"';
659 $parprop .= ' fo:text-align="'.$pvalue.'"';
662 $cellprop .= ' style:vertical-align="'.$pvalue.'"';
666 if (!empty($textprop)) {
668 <style:text-properties'.$textprop.'/>';
671 if (!empty($cellprop)) {
673 <style:table-cell-properties'.$cellprop.'/>';
676 if (!empty($parprop)) {
678 <style:paragraph-properties'.$parprop.'/>';
682 <style:style style:name="format'.$format->id
.'" style:family="table-cell">'.$textprop.$cellprop.$parprop.'
688 '<?xml version="1.0" encoding="UTF-8"?>
689 <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">
690 <office:automatic-styles>
691 <style:style style:name="ta1" style:family="table" style:master-page-name="Standard1">
692 <style:table-properties table:display="true"/>
694 <style:style style:name="date0" style:family="table-cell"/>';
696 $buffer .= $formatstyles;
697 $buffer .= $rowstyles;
698 $buffer .= $colstyles;
701 </office:automatic-styles>
706 foreach($worksheets as $wsnum=>$ws) {
709 $buffer .= '<table:table table:name="' . htmlspecialchars($ws->name
) . '" table:style-name="ta1">'."\n";
711 // define column properties
712 for($c=0; $c<=$ws->maxc
; $c++
) {
713 if (array_key_exists($c, $ws->columns
)) {
715 if (!empty($ws->columns
[$c]->format
)) {
716 $extra .= ' table:default-cell-style-name="format'.$ws->columns
[$c]->format
->id
.'"';
718 if ($ws->columns
[$c]->hidden
) {
719 $extra .= ' table:visibility="collapse"';
721 $buffer .= '<table:table-column table:style-name="ws'.$wsnum.'co'.$c.'"'.$extra.'/>'."\n";
723 $buffer .= '<table:table-column/>'."\n";
728 for($r=0; $r<=$ws->maxr
; $r++
) {
729 if (array_key_exists($r, $ws->rows
)) {
731 if (!empty($ws->rows
[$r]->format
)) {
732 $extra .= ' table:default-cell-style-name="format'.$ws->rows
[$r]->format
->id
.'"';
734 if ($ws->rows
[$r]->hidden
) {
735 $extra .= ' table:visibility="collapse"';
737 $buffer .= '<table:table-row table:style-name="ws'.$wsnum.'ro'.$r.'"'.$extra.'>'."\n";
739 $buffer .= '<table:table-row>'."\n";
741 for($c=0; $c<=$ws->maxc
; $c++
) {
742 if (isset($ws->data
[$r][$c])) {
743 $cell = $ws->data
[$r][$c];
745 if (!empty($cell->format
)) {
746 $extra = ' table:style-name="format'.$cell->format
->id
.'"';
748 if ($cell->type
== 'date') {
749 $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.'>'
750 . '<text:p>' . strftime('%Y-%m-%dT%H:%M:%S', $cell->value
) . '</text:p>'
751 . '</table:table-cell>'."\n";
752 } else if ($cell->type
== 'float') {
753 $buffer .= '<table:table-cell office:value-type="float" office:value="' . htmlspecialchars($cell->value
) . '"'.$extra.'>'
754 . '<text:p>' . htmlspecialchars($cell->value
) . '</text:p>'
755 . '</table:table-cell>'."\n";
756 } else if ($cell->type
== 'string') {
757 $buffer .= '<table:table-cell office:value-type="string" office:string-value="' . htmlspecialchars($cell->value
) . '"'.$extra.'>'
758 . '<text:p>' . htmlspecialchars($cell->value
) . '</text:p>'
759 . '</table:table-cell>'."\n";
761 $buffer .= '<table:table-cell office:value-type="string"'.$extra.'>'
762 . '<text:p>!!Error - unknown type!!</text:p>'
763 . '</table:table-cell>'."\n";
766 $buffer .= '<table:table-cell/>'."\n";
769 $buffer .= '</table:table-row>'."\n";
772 $buffer .= '</table:table>'."\n";
778 ' </office:spreadsheet>
780 </office:document-content>';
785 function get_ods_mimetype() {
786 return 'application/vnd.oasis.opendocument.spreadsheet';
789 function get_ods_meta() {
793 '<?xml version="1.0" encoding="UTF-8"?>
794 <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">
796 <meta:generator>Moodle '.$CFG->version
.'</meta:generator>
797 <meta:initial-creator>'.fullname($USER, true).'</meta:initial-creator>
798 <meta:editing-cycles>1</meta:editing-cycles>
799 <meta:creation-date>'.strftime('%Y-%m-%dT%H:%M:%S').'</meta:creation-date>
800 <dc:date>'.strftime('%Y-%m-%dT%H:%M:%S').'</dc:date>
801 <dc:creator>'.fullname($USER, true).'</dc:creator>
803 </office:document-meta>';
806 function get_ods_styles() {
808 '<?xml version="1.0" encoding="UTF-8"?>
809 <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">
811 <style:default-style style:family="table-column">
812 <style:table-column-properties style:column-width="75pt"/>
813 </style:default-style>
814 <style:default-style style:family="table-row">
815 <style:table-row-properties style:row-height="15pt"/>
816 </style:default-style>
817 <style:default-style style:family="table-cell">
818 <style:table-cell-properties fo:background-color="#ffffff" style:cell-protect="protected" style:vertical-align="middle"/>
819 <style:text-properties fo:color="#000000" fo:font-family="Arial" fo:font-size="12pt"/>
820 </style:default-style>
822 <office:automatic-styles>
823 <style:page-layout style:name="pm1">
824 <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"/>
826 </office:automatic-styles>
827 <office:master-styles>
828 <style:master-page style:name="Standard1" style:page-layout-name="pm1">
831 <text:sheet-name>???</text:sheet-name>
833 </style:header><style:footer>
835 <text:sheet-name>Page </text:sheet-name>
836 <text:page-number>1</text:page-number>
840 </office:master-styles>
841 </office:document-styles>
845 function get_ods_manifest() {
847 '<?xml version="1.0" encoding="UTF-8"?>
848 <manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
849 <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/>
850 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
851 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
852 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
853 </manifest:manifest>';