1 <?php
3 /*
4 * Copyleft 2002 Johann Hanne
5 *
6 * This is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this software; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place,
19 * Suite 330, Boston, MA 02111-1307 USA
20 */
22 /*
23 * This is the Spreadsheet::WriteExcel Perl package ported to PHP
24 * Spreadsheet::WriteExcel was written by John McNamara, jmcnamara@cpan.org
25 */
27 class writeexcel_biffwriter {
28 var $byte_order;
29 var $BIFF_version;
30 var $_byte_order;
31 var $_data;
32 var $_datasize;
33 var $_limit;
35 /*
36 * Constructor
37 */
38 function writeexcel_biffwriter() {
40 $this->byte_order = '';
41 $this->BIFF_version = 0x0500;
42 $this->_byte_order = '';
43 $this->_data = false;
44 $this->_datasize = 0;
45 $this->_limit = 2080;
47 $this->_set_byte_order();
48 }
50 /*
51 * Determine the byte order and store it as class data to avoid
52 * recalculating it for each call to new().
53 */
54 function _set_byte_order() {
55 $this->byteorder=0;
56 // Check if "pack" gives the required IEEE 64bit float
57 $teststr = pack("d", 1.2345);
58 $number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
60 if ($number == $teststr) {
61 $this->byte_order = 0; // Little Endian
62 } elseif ($number == strrev($teststr)) {
63 $this->byte_order = 1; // Big Endian
64 } else {
65 // Give up
66 trigger_error("Required floating point format not supported ".
67 "on this platform. See the portability section ".
68 "of the documentation.", E_USER_ERROR);
69 }
71 $this->_byte_order = $this->byte_order;
72 }
74 /*
75 * General storage function
76 */
77 function _prepend($data) {
79 if (func_num_args()>1) {
80 trigger_error("writeexcel_biffwriter::_prepend() ".
81 "called with more than one argument", E_USER_ERROR);
82 }
84 if ($this->_debug) {
85 print "*** writeexcel_biffwriter::_prepend() called:";
86 for ($c=0;$c<strlen($data);$c++) {
87 if ($c%16==0) {
88 print "\n";
89 }
90 printf("%02X ", ord($data[$c]));
91 }
92 print "\n";
93 }
95 if (strlen($data) > $this->_limit) {
96 $data = $this->_add_continue($data);
97 }
99 $this->_data = $data . $this->_data;
100 $this->_datasize += strlen($data);
101 }
103 /*
104 * General storage function
105 */
106 function _append($data) {
108 if (func_num_args()>1) {
109 trigger_error("writeexcel_biffwriter::_append() ".
110 "called with more than one argument", E_USER_ERROR);
111 }
113 if ($this->_debug) {
114 print "*** writeexcel_biffwriter::_append() called:";
115 for ($c=0;$c<strlen($data);$c++) {
116 if ($c%16==0) {
117 print "\n";
118 }
119 printf("%02X ", ord($data[$c]));
120 }
121 print "\n";
122 }
124 if (strlen($data) > $this->_limit) {
125 $data = $this->_add_continue($data);
126 }
128 $this->_data = $this->_data . $data;
129 $this->_datasize += strlen($data);
130 }
132 /*
133 * Writes Excel BOF record to indicate the beginning of a stream or
134 * sub-stream in the BIFF file.
135 *
136 * $type = 0x0005, Workbook
137 * $type = 0x0010, Worksheet
138 */
139 function _store_bof($type) {
141 $record = 0x0809; // Record identifier
142 $length = 0x0008; // Number of bytes to follow
144 $version = $this->BIFF_version;
146 // According to the SDK $build and $year should be set to zero.
147 // However, this throws a warning in Excel 5. So, use these
148 // magic numbers.
149 $build = 0x096C;
150 $year = 0x07C9;
152 $header = pack("vv", $record, $length);
153 $data = pack("vvvv", $version, $type, $build, $year);
155 $this->_prepend($header . $data);
156 }
158 /*
159 * Writes Excel EOF record to indicate the end of a BIFF stream.
160 */
161 function _store_eof() {
163 $record = 0x000A; // Record identifier
164 $length = 0x0000; // Number of bytes to follow
166 $header = pack("vv", $record, $length);
168 $this->_append($header);
169 }
171 /*
172 * Excel limits the size of BIFF records. In Excel 5 the limit is 2084
173 * bytes. In Excel 97 the limit is 8228 bytes. Records that are longer
174 * than these limits must be split up into CONTINUE blocks.
175 *
176 * This function take a long BIFF record and inserts CONTINUE records as
177 * necessary.
178 */
179 function _add_continue($data) {
181 $limit = $this->_limit;
182 $record = 0x003C; // Record identifier
184 // The first 2080/8224 bytes remain intact. However, we have to change
185 // the length field of the record.
186 $tmp = substr($data, 0, $limit);
187 $data = substr($data, $limit);
188 $tmp = substr($tmp, 0, 2) . pack ("v", $limit-4) . substr($tmp, 4);
190 // Strip out chunks of 2080/8224 bytes +4 for the header.
191 while (strlen($data) > $limit) {
192 $header = pack("vv", $record, $limit);
193 $tmp .= $header;
194 $tmp .= substr($data, 0, $limit);
195 $data = substr($data, $limit);
196 }
198 // Mop up the last of the data
199 $header = pack("vv", $record, strlen($data));
200 $tmp .= $header;
201 $tmp .= $data;
203 return $tmp;
204 }
206 }
208 ?>