Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / lib / pear / Spreadsheet / Excel / Writer / BIFFwriter.php
blob64885f25d192dfc7d55099ea311f29e246d15440
1 <?php
2 /*
3 * Module written/ported by Xavier Noguer <xnoguer@php.net>
5 * The majority of this is _NOT_ my code. I simply ported it from the
6 * PERL Spreadsheet::WriteExcel module.
8 * The author of the Spreadsheet::WriteExcel module is John McNamara
9 * <jmcnamara@cpan.org>
11 * I _DO_ maintain this code, and John McNamara has nothing to do with the
12 * porting of this code to PHP. Any questions directly related to this
13 * class library should be directed to me.
15 * License Information:
17 * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
18 * Copyright (c) 2002-2003 Xavier Noguer xnoguer@php.net
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 require_once 'PEAR.php';
37 /**
38 * Class for writing Excel BIFF records.
40 * From "MICROSOFT EXCEL BINARY FILE FORMAT" by Mark O'Brien (Microsoft Corporation):
42 * BIFF (BInary File Format) is the file format in which Excel documents are
43 * saved on disk. A BIFF file is a complete description of an Excel document.
44 * BIFF files consist of sequences of variable-length records. There are many
45 * different types of BIFF records. For example, one record type describes a
46 * formula entered into a cell; one describes the size and location of a
47 * window into a document; another describes a picture format.
49 * @author Xavier Noguer <xnoguer@php.net>
50 * @category FileFormats
51 * @package Spreadsheet_Excel_Writer
54 class Spreadsheet_Excel_Writer_BIFFwriter extends PEAR
56 /**
57 * The BIFF/Excel version (5).
58 * @var integer
60 var $_BIFF_version = 0x0500;
62 /**
63 * The byte order of this architecture. 0 => little endian, 1 => big endian
64 * @var integer
66 var $_byte_order;
68 /**
69 * The string containing the data of the BIFF stream
70 * @var string
72 var $_data;
74 /**
75 * The size of the data in bytes. Should be the same as strlen($this->_data)
76 * @var integer
78 var $_datasize;
80 /**
81 * The maximun length for a BIFF record. See _addContinue()
82 * @var integer
83 * @see _addContinue()
85 var $_limit;
87 /**
88 * Constructor
90 * @access public
92 function Spreadsheet_Excel_Writer_BIFFwriter()
94 $this->_byte_order = '';
95 $this->_data = '';
96 $this->_datasize = 0;
97 $this->_limit = 2080;
98 // Set the byte order
99 $this->_setByteOrder();
103 * Determine the byte order and store it as class data to avoid
104 * recalculating it for each call to new().
106 * @access private
108 function _setByteOrder()
110 // Check if "pack" gives the required IEEE 64bit float
111 $teststr = pack("d", 1.2345);
112 $number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
113 if ($number == $teststr) {
114 $byte_order = 0; // Little Endian
115 } elseif ($number == strrev($teststr)){
116 $byte_order = 1; // Big Endian
117 } else {
118 // Give up. I'll fix this in a later version.
119 return $this->raiseError("Required floating point format ".
120 "not supported on this platform.");
122 $this->_byte_order = $byte_order;
126 * General storage function
128 * @param string $data binary data to prepend
129 * @access private
131 function _prepend($data)
133 if (strlen($data) > $this->_limit) {
134 $data = $this->_addContinue($data);
136 $this->_data = $data.$this->_data;
137 $this->_datasize += strlen($data);
141 * General storage function
143 * @param string $data binary data to append
144 * @access private
146 function _append($data)
148 if (strlen($data) > $this->_limit) {
149 $data = $this->_addContinue($data);
151 $this->_data = $this->_data.$data;
152 $this->_datasize += strlen($data);
156 * Writes Excel BOF record to indicate the beginning of a stream or
157 * sub-stream in the BIFF file.
159 * @param integer $type Type of BIFF file to write: 0x0005 Workbook,
160 * 0x0010 Worksheet.
161 * @access private
163 function _storeBof($type)
165 $record = 0x0809; // Record identifier
167 // According to the SDK $build and $year should be set to zero.
168 // However, this throws a warning in Excel 5. So, use magic numbers.
169 if ($this->_BIFF_version == 0x0500) {
170 $length = 0x0008;
171 $unknown = '';
172 $build = 0x096C;
173 $year = 0x07C9;
174 } elseif ($this->_BIFF_version == 0x0600) {
175 $length = 0x0010;
176 $unknown = pack("VV", 0x00000041, 0x00000006); //unknown last 8 bytes for BIFF8
177 $build = 0x0DBB;
178 $year = 0x07CC;
180 $version = $this->_BIFF_version;
182 $header = pack("vv", $record, $length);
183 $data = pack("vvvv", $version, $type, $build, $year);
184 $this->_prepend($header . $data . $unknown);
188 * Writes Excel EOF record to indicate the end of a BIFF stream.
190 * @access private
192 function _storeEof()
194 $record = 0x000A; // Record identifier
195 $length = 0x0000; // Number of bytes to follow
196 $header = pack("vv", $record, $length);
197 $this->_append($header);
201 * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
202 * Excel 97 the limit is 8228 bytes. Records that are longer than these limits
203 * must be split up into CONTINUE blocks.
205 * This function takes a long BIFF record and inserts CONTINUE records as
206 * necessary.
208 * @param string $data The original binary data to be written
209 * @return string A very convenient string of continue blocks
210 * @access private
212 function _addContinue($data)
214 $limit = $this->_limit;
215 $record = 0x003C; // Record identifier
217 // The first 2080/8224 bytes remain intact. However, we have to change
218 // the length field of the record.
219 $tmp = substr($data, 0, 2).pack("v", $limit-4).substr($data, 4, $limit - 4);
221 $header = pack("vv", $record, $limit); // Headers for continue records
223 // Retrieve chunks of 2080/8224 bytes +4 for the header.
224 $data_length = strlen($data);
225 for ($i = $limit; $i < ($data_length - $limit); $i += $limit) {
226 $tmp .= $header;
227 $tmp .= substr($data, $i, $limit);
230 // Retrieve the last chunk of data
231 $header = pack("vv", $record, strlen($data) - $i);
232 $tmp .= $header;
233 $tmp .= substr($data, $i, strlen($data) - $i);
235 return $tmp;