77239666 by Marty Penner

Promoting r252-r254 to live. refs #1249

1 parent d1749c3b
1 <?php
2 namespace Tz\Wordpress\Tools\ExcelReader;
3
4 define('NUM_BIG_BLOCK_DEPOT_BLOCKS_POS', 0x2c);
5 define('SMALL_BLOCK_DEPOT_BLOCK_POS', 0x3c);
6 define('ROOT_START_BLOCK_POS', 0x30);
7 define('BIG_BLOCK_SIZE', 0x200);
8 define('SMALL_BLOCK_SIZE', 0x40);
9 define('EXTENSION_BLOCK_POS', 0x44);
10 define('NUM_EXTENSION_BLOCK_POS', 0x48);
11 define('PROPERTY_STORAGE_BLOCK_SIZE', 0x80);
12 define('BIG_BLOCK_DEPOT_BLOCKS_POS', 0x4c);
13 define('SMALL_BLOCK_THRESHOLD', 0x1000);
14 // property storage offsets
15 define('SIZE_OF_NAME_POS', 0x40);
16 define('TYPE_POS', 0x42);
17 define('START_BLOCK_POS', 0x74);
18 define('SIZE_POS', 0x78);
19 define('IDENTIFIER_OLE', pack("CCCCCCCC",0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1));
20
21 //echo 'ROOT_START_BLOCK_POS = '.ROOT_START_BLOCK_POS."\n";
22
23 //echo bin2hex($data[ROOT_START_BLOCK_POS])."\n";
24 //echo "a=";
25 //echo $data[ROOT_START_BLOCK_POS];
26 //function log
27
28 function GetInt4d($data, $pos)
29 {
30 $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24);
31 if ($value>=4294967294)
32 {
33 $value=-2;
34 }
35 return $value;
36 }
37
38
39 class OLERead {
40 var $data = '';
41
42
43 function OLERead(){
44
45
46 }
47
48 function read($sFileName){
49
50 // check if file exist and is readable (Darko Miljanovic)
51 if(!is_readable($sFileName)) {
52 $this->error = 1;
53 return false;
54 }
55
56 $this->data = @file_get_contents($sFileName);
57 if (!$this->data) {
58 $this->error = 1;
59 return false;
60 }
61 //echo IDENTIFIER_OLE;
62 //echo 'start';
63 if (substr($this->data, 0, 8) != IDENTIFIER_OLE) {
64 $this->error = 1;
65 return false;
66 }
67 $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
68 $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS);
69 $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS);
70 $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS);
71 $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS);
72
73 /*
74 echo $this->numBigBlockDepotBlocks." ";
75 echo $this->sbdStartBlock." ";
76 echo $this->rootStartBlock." ";
77 echo $this->extensionBlock." ";
78 echo $this->numExtensionBlocks." ";
79 */
80 //echo "sbdStartBlock = $this->sbdStartBlock\n";
81 $bigBlockDepotBlocks = array();
82 $pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
83 // echo "pos = $pos";
84 $bbdBlocks = $this->numBigBlockDepotBlocks;
85
86 if ($this->numExtensionBlocks != 0) {
87 $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
88 }
89
90 for ($i = 0; $i < $bbdBlocks; $i++) {
91 $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos);
92 $pos += 4;
93 }
94
95
96 for ($j = 0; $j < $this->numExtensionBlocks; $j++) {
97 $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE;
98 $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1);
99
100 for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) {
101 $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos);
102 $pos += 4;
103 }
104
105 $bbdBlocks += $blocksToRead;
106 if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
107 $this->extensionBlock = GetInt4d($this->data, $pos);
108 }
109 }
110
111 // var_dump($bigBlockDepotBlocks);
112
113 // readBigBlockDepot
114 $pos = 0;
115 $index = 0;
116 $this->bigBlockChain = array();
117
118 for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) {
119 $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE;
120 //echo "pos = $pos";
121 for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) {
122 $this->bigBlockChain[$index] = GetInt4d($this->data, $pos);
123 $pos += 4 ;
124 $index++;
125 }
126 }
127
128 //var_dump($this->bigBlockChain);
129 //echo '=====2';
130 // readSmallBlockDepot();
131 $pos = 0;
132 $index = 0;
133 $sbdBlock = $this->sbdStartBlock;
134 $this->smallBlockChain = array();
135
136 while ($sbdBlock != -2) {
137
138 $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE;
139
140 for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) {
141 $this->smallBlockChain[$index] = GetInt4d($this->data, $pos);
142 $pos += 4;
143 $index++;
144 }
145
146 $sbdBlock = $this->bigBlockChain[$sbdBlock];
147 }
148
149
150 // readData(rootStartBlock)
151 $block = $this->rootStartBlock;
152 $pos = 0;
153 $this->entry = $this->__readData($block);
154
155 /*
156 while ($block != -2) {
157 $pos = ($block + 1) * BIG_BLOCK_SIZE;
158 $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE);
159 $block = $this->bigBlockChain[$block];
160 }
161 */
162 //echo '==='.$this->entry."===";
163 $this->__readPropertySets();
164
165 }
166
167 function __readData($bl) {
168 $block = $bl;
169 $pos = 0;
170 $data = '';
171
172 while ($block != -2) {
173 $pos = ($block + 1) * BIG_BLOCK_SIZE;
174 $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE);
175 //echo "pos = $pos data=$data\n";
176 $block = $this->bigBlockChain[$block];
177 }
178 return $data;
179 }
180
181 function __readPropertySets(){
182 $offset = 0;
183 //var_dump($this->entry);
184 while ($offset < strlen($this->entry)) {
185 $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE);
186
187 $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8);
188
189 $type = ord($d[TYPE_POS]);
190 //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1;
191
192 $startBlock = GetInt4d($d, START_BLOCK_POS);
193 $size = GetInt4d($d, SIZE_POS);
194
195 $name = '';
196 for ($i = 0; $i < $nameSize ; $i++) {
197 $name .= $d[$i];
198 }
199
200 $name = str_replace("\x00", "", $name);
201
202 $this->props[] = array (
203 'name' => $name,
204 'type' => $type,
205 'startBlock' => $startBlock,
206 'size' => $size);
207
208 if (($name == "Workbook") || ($name == "Book")) {
209 $this->wrkbook = count($this->props) - 1;
210 }
211
212 if ($name == "Root Entry") {
213 $this->rootentry = count($this->props) - 1;
214 }
215
216 //echo "name ==$name=\n";
217
218
219 $offset += PROPERTY_STORAGE_BLOCK_SIZE;
220 }
221
222 }
223
224
225 function getWorkBook(){
226 if ($this->props[$this->wrkbook]['size'] < SMALL_BLOCK_THRESHOLD){
227 // getSmallBlockStream(PropertyStorage ps)
228
229 $rootdata = $this->__readData($this->props[$this->rootentry]['startBlock']);
230
231 $streamData = '';
232 $block = $this->props[$this->wrkbook]['startBlock'];
233 //$count = 0;
234 $pos = 0;
235 while ($block != -2) {
236 $pos = $block * SMALL_BLOCK_SIZE;
237 $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE);
238
239 $block = $this->smallBlockChain[$block];
240 }
241
242 return $streamData;
243
244
245 }else{
246
247 $numBlocks = $this->props[$this->wrkbook]['size'] / BIG_BLOCK_SIZE;
248 if ($this->props[$this->wrkbook]['size'] % BIG_BLOCK_SIZE != 0) {
249 $numBlocks++;
250 }
251
252 if ($numBlocks == 0) return '';
253
254 //echo "numBlocks = $numBlocks\n";
255 //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE];
256 //print_r($this->wrkbook);
257 $streamData = '';
258 $block = $this->props[$this->wrkbook]['startBlock'];
259 //$count = 0;
260 $pos = 0;
261 //echo "block = $block";
262 while ($block != -2) {
263 $pos = ($block + 1) * BIG_BLOCK_SIZE;
264 $streamData .= substr($this->data, $pos, BIG_BLOCK_SIZE);
265 $block = $this->bigBlockChain[$block];
266 }
267 //echo 'stream'.$streamData;
268 return $streamData;
269 }
270 }
271
272 }
273 ?>
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 namespace Tz\Wordpress\Tools\ExcelReader;
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * A class for reading Microsoft Excel Spreadsheets.
7 *
8 * Originally developed by Vadim Tkachenko under the name PHPExcelReader.
9 * (http://sourceforge.net/projects/phpexcelreader)
10 * Based on the Java version by Andy Khan (http://www.andykhan.com). Now
11 * maintained by David Sanders. Reads only Biff 7 and Biff 8 formats.
12 *
13 * PHP versions 4 and 5
14 *
15 * LICENSE: This source file is subject to version 3.0 of the PHP license
16 * that is available through the world-wide-web at the following URI:
17 * http://www.php.net/license/3_0.txt. If you did not receive a copy of
18 * the PHP License and are unable to obtain it through the web, please
19 * send a note to license@php.net so we can mail you a copy immediately.
20 *
21 * @category Spreadsheet
22 * @package Spreadsheet_Excel_Reader
23 * @author Vadim Tkachenko <vt@apachephp.com>
24 * @license http://www.php.net/license/3_0.txt PHP License 3.0
25 * @version CVS: $Id: reader.php 19 2007-03-13 12:42:41Z shangxiao $
26 * @link http://pear.php.net/package/Spreadsheet_Excel_Reader
27 * @see OLE, Spreadsheet_Excel_Writer
28 */
29
30
31 //require_once 'PEAR.php';
32 //require_once 'Spreadsheet/Excel/Reader/OLERead.php';
33 //require_once 'OLE.php';
34 require_once 'oleread.inc';
35
36 define('SPREADSHEET_EXCEL_READER_BIFF8', 0x600);
37 define('SPREADSHEET_EXCEL_READER_BIFF7', 0x500);
38 define('SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS', 0x5);
39 define('SPREADSHEET_EXCEL_READER_WORKSHEET', 0x10);
40
41 define('SPREADSHEET_EXCEL_READER_TYPE_BOF', 0x809);
42 define('SPREADSHEET_EXCEL_READER_TYPE_EOF', 0x0a);
43 define('SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET', 0x85);
44 define('SPREADSHEET_EXCEL_READER_TYPE_DIMENSION', 0x200);
45 define('SPREADSHEET_EXCEL_READER_TYPE_ROW', 0x208);
46 define('SPREADSHEET_EXCEL_READER_TYPE_DBCELL', 0xd7);
47 define('SPREADSHEET_EXCEL_READER_TYPE_FILEPASS', 0x2f);
48 define('SPREADSHEET_EXCEL_READER_TYPE_NOTE', 0x1c);
49 define('SPREADSHEET_EXCEL_READER_TYPE_TXO', 0x1b6);
50 define('SPREADSHEET_EXCEL_READER_TYPE_RK', 0x7e);
51 define('SPREADSHEET_EXCEL_READER_TYPE_RK2', 0x27e);
52 define('SPREADSHEET_EXCEL_READER_TYPE_MULRK', 0xbd);
53 define('SPREADSHEET_EXCEL_READER_TYPE_MULBLANK', 0xbe);
54 define('SPREADSHEET_EXCEL_READER_TYPE_INDEX', 0x20b);
55 define('SPREADSHEET_EXCEL_READER_TYPE_SST', 0xfc);
56 define('SPREADSHEET_EXCEL_READER_TYPE_EXTSST', 0xff);
57 define('SPREADSHEET_EXCEL_READER_TYPE_CONTINUE', 0x3c);
58 define('SPREADSHEET_EXCEL_READER_TYPE_LABEL', 0x204);
59 define('SPREADSHEET_EXCEL_READER_TYPE_LABELSST', 0xfd);
60 define('SPREADSHEET_EXCEL_READER_TYPE_NUMBER', 0x203);
61 define('SPREADSHEET_EXCEL_READER_TYPE_NAME', 0x18);
62 define('SPREADSHEET_EXCEL_READER_TYPE_ARRAY', 0x221);
63 define('SPREADSHEET_EXCEL_READER_TYPE_STRING', 0x207);
64 define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA', 0x406);
65 define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA2', 0x6);
66 define('SPREADSHEET_EXCEL_READER_TYPE_FORMAT', 0x41e);
67 define('SPREADSHEET_EXCEL_READER_TYPE_XF', 0xe0);
68 define('SPREADSHEET_EXCEL_READER_TYPE_BOOLERR', 0x205);
69 define('SPREADSHEET_EXCEL_READER_TYPE_UNKNOWN', 0xffff);
70 define('SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR', 0x22);
71 define('SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS', 0xE5);
72
73 define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS' , 25569);
74 define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904', 24107);
75 define('SPREADSHEET_EXCEL_READER_MSINADAY', 86400);
76 //define('SPREADSHEET_EXCEL_READER_MSINADAY', 24 * 60 * 60);
77
78 //define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%.2f");
79 define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%s");
80
81
82 /*
83 * Place includes, constant defines and $_GLOBAL settings here.
84 * Make sure they have appropriate docblocks to avoid phpDocumentor
85 * construing they are documented by the page-level docblock.
86 */
87
88 /**
89 * A class for reading Microsoft Excel Spreadsheets.
90 *
91 * Originally developed by Vadim Tkachenko under the name PHPExcelReader.
92 * (http://sourceforge.net/projects/phpexcelreader)
93 * Based on the Java version by Andy Khan (http://www.andykhan.com). Now
94 * maintained by David Sanders. Reads only Biff 7 and Biff 8 formats.
95 *
96 * @category Spreadsheet
97 * @package Spreadsheet_Excel_Reader
98 * @author Vadim Tkachenko <vt@phpapache.com>
99 * @copyright 1997-2005 The PHP Group
100 * @license http://www.php.net/license/3_0.txt PHP License 3.0
101 * @version Release: @package_version@
102 * @link http://pear.php.net/package/PackageName
103 * @see OLE, Spreadsheet_Excel_Writer
104 */
105 class Spreadsheet_Excel_Reader
106 {
107 /**
108 * Array of worksheets found
109 *
110 * @var array
111 * @access public
112 */
113 var $boundsheets = array();
114
115 /**
116 * Array of format records found
117 *
118 * @var array
119 * @access public
120 */
121 var $formatRecords = array();
122
123 /**
124 * todo
125 *
126 * @var array
127 * @access public
128 */
129 var $sst = array();
130
131 /**
132 * Array of worksheets
133 *
134 * The data is stored in 'cells' and the meta-data is stored in an array
135 * called 'cellsInfo'
136 *
137 * Example:
138 *
139 * $sheets --> 'cells' --> row --> column --> Interpreted value
140 * --> 'cellsInfo' --> row --> column --> 'type' - Can be 'date', 'number', or 'unknown'
141 * --> 'raw' - The raw data that Excel stores for that data cell
142 *
143 * @var array
144 * @access public
145 */
146 var $sheets = array();
147
148 /**
149 * The data returned by OLE
150 *
151 * @var string
152 * @access public
153 */
154 var $data;
155
156 /**
157 * OLE object for reading the file
158 *
159 * @var OLE object
160 * @access private
161 */
162 var $_ole;
163
164 /**
165 * Default encoding
166 *
167 * @var string
168 * @access private
169 */
170 var $_defaultEncoding;
171
172 /**
173 * Default number format
174 *
175 * @var integer
176 * @access private
177 */
178 var $_defaultFormat = SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT;
179
180 /**
181 * todo
182 * List of formats to use for each column
183 *
184 * @var array
185 * @access private
186 */
187 var $_columnsFormat = array();
188
189 /**
190 * todo
191 *
192 * @var integer
193 * @access private
194 */
195 var $_rowoffset = 1;
196
197 /**
198 * todo
199 *
200 * @var integer
201 * @access private
202 */
203 var $_coloffset = 1;
204
205 /**
206 * List of default date formats used by Excel
207 *
208 * @var array
209 * @access public
210 */
211 var $dateFormats = array (
212 0xe => "d/m/Y",
213 0xf => "d-M-Y",
214 0x10 => "d-M",
215 0x11 => "M-Y",
216 0x12 => "h:i a",
217 0x13 => "h:i:s a",
218 0x14 => "H:i",
219 0x15 => "H:i:s",
220 0x16 => "d/m/Y H:i",
221 0x2d => "i:s",
222 0x2e => "H:i:s",
223 0x2f => "i:s.S");
224
225 /**
226 * Default number formats used by Excel
227 *
228 * @var array
229 * @access public
230 */
231 var $numberFormats = array(
232 0x1 => "%1.0f", // "0"
233 0x2 => "%1.2f", // "0.00",
234 0x3 => "%1.0f", //"#,##0",
235 0x4 => "%1.2f", //"#,##0.00",
236 0x5 => "%1.0f", /*"$#,##0;($#,##0)",*/
237 0x6 => '$%1.0f', /*"$#,##0;($#,##0)",*/
238 0x7 => '$%1.2f', //"$#,##0.00;($#,##0.00)",
239 0x8 => '$%1.2f', //"$#,##0.00;($#,##0.00)",
240 0x9 => '%1.0f%%', // "0%"
241 0xa => '%1.2f%%', // "0.00%"
242 0xb => '%1.2f', // 0.00E00",
243 0x25 => '%1.0f', // "#,##0;(#,##0)",
244 0x26 => '%1.0f', //"#,##0;(#,##0)",
245 0x27 => '%1.2f', //"#,##0.00;(#,##0.00)",
246 0x28 => '%1.2f', //"#,##0.00;(#,##0.00)",
247 0x29 => '%1.0f', //"#,##0;(#,##0)",
248 0x2a => '$%1.0f', //"$#,##0;($#,##0)",
249 0x2b => '%1.2f', //"#,##0.00;(#,##0.00)",
250 0x2c => '$%1.2f', //"$#,##0.00;($#,##0.00)",
251 0x30 => '%1.0f'); //"##0.0E0";
252
253 // }}}
254 // {{{ Spreadsheet_Excel_Reader()
255
256 /**
257 * Constructor
258 *
259 * Some basic initialisation
260 */
261 function Spreadsheet_Excel_Reader()
262 {
263 $this->_ole =& new OLERead();
264 $this->setUTFEncoder('iconv');
265 }
266
267 // }}}
268 // {{{ setOutputEncoding()
269
270 /**
271 * Set the encoding method
272 *
273 * @param string Encoding to use
274 * @access public
275 */
276 function setOutputEncoding($encoding)
277 {
278 $this->_defaultEncoding = $encoding;
279 }
280
281 // }}}
282 // {{{ setUTFEncoder()
283
284 /**
285 * $encoder = 'iconv' or 'mb'
286 * set iconv if you would like use 'iconv' for encode UTF-16LE to your encoding
287 * set mb if you would like use 'mb_convert_encoding' for encode UTF-16LE to your encoding
288 *
289 * @access public
290 * @param string Encoding type to use. Either 'iconv' or 'mb'
291 */
292 function setUTFEncoder($encoder = 'iconv')
293 {
294 $this->_encoderFunction = '';
295
296 if ($encoder == 'iconv') {
297 $this->_encoderFunction = function_exists('iconv') ? 'iconv' : '';
298 } elseif ($encoder == 'mb') {
299 $this->_encoderFunction = function_exists('mb_convert_encoding') ?
300 'mb_convert_encoding' :
301 '';
302 }
303 }
304
305 // }}}
306 // {{{ setRowColOffset()
307
308 /**
309 * todo
310 *
311 * @access public
312 * @param offset
313 */
314 function setRowColOffset($iOffset)
315 {
316 $this->_rowoffset = $iOffset;
317 $this->_coloffset = $iOffset;
318 }
319
320 // }}}
321 // {{{ setDefaultFormat()
322
323 /**
324 * Set the default number format
325 *
326 * @access public
327 * @param Default format
328 */
329 function setDefaultFormat($sFormat)
330 {
331 $this->_defaultFormat = $sFormat;
332 }
333
334 // }}}
335 // {{{ setColumnFormat()
336
337 /**
338 * Force a column to use a certain format
339 *
340 * @access public
341 * @param integer Column number
342 * @param string Format
343 */
344 function setColumnFormat($column, $sFormat)
345 {
346 $this->_columnsFormat[$column] = $sFormat;
347 }
348
349
350 // }}}
351 // {{{ read()
352
353 /**
354 * Read the spreadsheet file using OLE, then parse
355 *
356 * @access public
357 * @param filename
358 * @todo return a valid value
359 */
360 function read($sFileName)
361 {
362 /*
363 require_once 'OLE.php';
364 $ole = new OLE();
365 $ole->read($sFileName);
366
367 foreach ($ole->_list as $i => $pps) {
368 if (($pps->Name == 'Workbook' || $pps->Name == 'Book') &&
369 $pps->Size >= SMALL_BLOCK_THRESHOLD) {
370
371 $this->data = $ole->getData($i, 0, $ole->getDataLength($i));
372 } elseif ($pps->Name == 'Root Entry') {
373 $this->data = $ole->getData($i, 0, $ole->getDataLength($i));
374 }
375 //var_dump(strlen($ole->getData($i, 0, $ole->getDataLength($i))), $pps->Name, md5($this->data), $ole->getDataLength($i));
376 }
377 //exit;
378 $this->_parse();
379
380 return sizeof($this->sheets) > 0;
381 */
382
383 $res = $this->_ole->read($sFileName);
384
385 // oops, something goes wrong (Darko Miljanovic)
386 if($res === false) {
387 // check error code
388 if($this->_ole->error == 1) {
389 // bad file
390 die('The filename ' . $sFileName . ' is not readable');
391 }
392 // check other error codes here (eg bad fileformat, etc...)
393 }
394
395 $this->data = $this->_ole->getWorkBook();
396
397
398 /*
399 $res = $this->_ole->read($sFileName);
400
401 if ($this->isError($res)) {
402 // var_dump($res);
403 return $this->raiseError($res);
404 }
405
406 $total = $this->_ole->ppsTotal();
407 for ($i = 0; $i < $total; $i++) {
408 if ($this->_ole->isFile($i)) {
409 $type = unpack("v", $this->_ole->getData($i, 0, 2));
410 if ($type[''] == 0x0809) { // check if it's a BIFF stream
411 $this->_index = $i;
412 $this->data = $this->_ole->getData($i, 0, $this->_ole->getDataLength($i));
413 break;
414 }
415 }
416 }
417
418 if ($this->_index === null) {
419 return $this->raiseError("$file doesn't seem to be an Excel file");
420 }
421
422 */
423
424 //echo "data =".$this->data;
425 //$this->readRecords();
426 $this->_parse();
427 }
428
429
430 // }}}
431 // {{{ _parse()
432
433 /**
434 * Parse a workbook
435 *
436 * @access private
437 * @return bool
438 */
439 function _parse()
440 {
441 $pos = 0;
442
443 $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8;
444 $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8;
445
446 $version = ord($this->data[$pos + 4]) | ord($this->data[$pos + 5])<<8;
447 $substreamType = ord($this->data[$pos + 6]) | ord($this->data[$pos + 7])<<8;
448 //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n";
449
450 if (($version != SPREADSHEET_EXCEL_READER_BIFF8) &&
451 ($version != SPREADSHEET_EXCEL_READER_BIFF7)) {
452 return false;
453 }
454
455 if ($substreamType != SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS){
456 return false;
457 }
458
459 //print_r($rec);
460 $pos += $length + 4;
461
462 $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8;
463 $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8;
464
465 while ($code != SPREADSHEET_EXCEL_READER_TYPE_EOF) {
466 switch ($code) {
467 case SPREADSHEET_EXCEL_READER_TYPE_SST:
468 //echo "Type_SST\n";
469 $spos = $pos + 4;
470 $limitpos = $spos + $length;
471 $uniqueStrings = $this->_GetInt4d($this->data, $spos+4);
472 $spos += 8;
473 for ($i = 0; $i < $uniqueStrings; $i++) {
474 // Read in the number of characters
475 if ($spos == $limitpos) {
476 $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
477 $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
478 if ($opcode != 0x3c) {
479 return -1;
480 }
481 $spos += 4;
482 $limitpos = $spos + $conlength;
483 }
484 $numChars = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8);
485 //echo "i = $i pos = $pos numChars = $numChars ";
486 $spos += 2;
487 $optionFlags = ord($this->data[$spos]);
488 $spos++;
489 $asciiEncoding = (($optionFlags & 0x01) == 0) ;
490 $extendedString = ( ($optionFlags & 0x04) != 0);
491
492 // See if string contains formatting information
493 $richString = ( ($optionFlags & 0x08) != 0);
494
495 if ($richString) {
496 // Read in the crun
497 $formattingRuns = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8);
498 $spos += 2;
499 }
500
501 if ($extendedString) {
502 // Read in cchExtRst
503 $extendedRunLength = $this->_GetInt4d($this->data, $spos);
504 $spos += 4;
505 }
506
507 $len = ($asciiEncoding)? $numChars : $numChars*2;
508 if ($spos + $len < $limitpos) {
509 $retstr = substr($this->data, $spos, $len);
510 $spos += $len;
511 }else{
512 // found countinue
513 $retstr = substr($this->data, $spos, $limitpos - $spos);
514 $bytesRead = $limitpos - $spos;
515 $charsLeft = $numChars - (($asciiEncoding) ? $bytesRead : ($bytesRead / 2));
516 $spos = $limitpos;
517
518 while ($charsLeft > 0){
519 $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
520 $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
521 if ($opcode != 0x3c) {
522 return -1;
523 }
524 $spos += 4;
525 $limitpos = $spos + $conlength;
526 $option = ord($this->data[$spos]);
527 $spos += 1;
528 if ($asciiEncoding && ($option == 0)) {
529 $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength);
530 $retstr .= substr($this->data, $spos, $len);
531 $charsLeft -= $len;
532 $asciiEncoding = true;
533 }elseif (!$asciiEncoding && ($option != 0)){
534 $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength);
535 $retstr .= substr($this->data, $spos, $len);
536 $charsLeft -= $len/2;
537 $asciiEncoding = false;
538 }elseif (!$asciiEncoding && ($option == 0)) {
539 // Bummer - the string starts off as Unicode, but after the
540 // continuation it is in straightforward ASCII encoding
541 $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength);
542 for ($j = 0; $j < $len; $j++) {
543 $retstr .= $this->data[$spos + $j].chr(0);
544 }
545 $charsLeft -= $len;
546 $asciiEncoding = false;
547 }else{
548 $newstr = '';
549 for ($j = 0; $j < strlen($retstr); $j++) {
550 $newstr = $retstr[$j].chr(0);
551 }
552 $retstr = $newstr;
553 $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength);
554 $retstr .= substr($this->data, $spos, $len);
555 $charsLeft -= $len/2;
556 $asciiEncoding = false;
557 //echo "Izavrat\n";
558 }
559 $spos += $len;
560
561 }
562 }
563 $retstr = ($asciiEncoding) ? $retstr : $this->_encodeUTF16($retstr);
564 // echo "Str $i = $retstr\n";
565 if ($richString){
566 $spos += 4 * $formattingRuns;
567 }
568
569 // For extended strings, skip over the extended string data
570 if ($extendedString) {
571 $spos += $extendedRunLength;
572 }
573 //if ($retstr == 'Derby'){
574 // echo "bb\n";
575 //}
576 $this->sst[]=$retstr;
577 }
578 /*$continueRecords = array();
579 while ($this->getNextCode() == Type_CONTINUE) {
580 $continueRecords[] = &$this->nextRecord();
581 }
582 //echo " 1 Type_SST\n";
583 $this->shareStrings = new SSTRecord($r, $continueRecords);
584 //print_r($this->shareStrings->strings);
585 */
586 // echo 'SST read: '.($time_end-$time_start)."\n";
587 break;
588
589 case SPREADSHEET_EXCEL_READER_TYPE_FILEPASS:
590 return false;
591 break;
592 case SPREADSHEET_EXCEL_READER_TYPE_NAME:
593 //echo "Type_NAME\n";
594 break;
595 case SPREADSHEET_EXCEL_READER_TYPE_FORMAT:
596 $indexCode = ord($this->data[$pos+4]) | ord($this->data[$pos+5]) << 8;
597
598 if ($version == SPREADSHEET_EXCEL_READER_BIFF8) {
599 $numchars = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8;
600 if (ord($this->data[$pos+8]) == 0){
601 $formatString = substr($this->data, $pos+9, $numchars);
602 } else {
603 $formatString = substr($this->data, $pos+9, $numchars*2);
604 }
605 } else {
606 $numchars = ord($this->data[$pos+6]);
607 $formatString = substr($this->data, $pos+7, $numchars*2);
608 }
609
610 $this->formatRecords[$indexCode] = $formatString;
611 // echo "Type.FORMAT\n";
612 break;
613 case SPREADSHEET_EXCEL_READER_TYPE_XF:
614 //global $dateFormats, $numberFormats;
615 $indexCode = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8;
616 //echo "\nType.XF ".count($this->formatRecords['xfrecords'])." $indexCode ";
617 if (array_key_exists($indexCode, $this->dateFormats)) {
618 //echo "isdate ".$dateFormats[$indexCode];
619 $this->formatRecords['xfrecords'][] = array(
620 'type' => 'date',
621 'format' => $this->dateFormats[$indexCode]
622 );
623 }elseif (array_key_exists($indexCode, $this->numberFormats)) {
624 //echo "isnumber ".$this->numberFormats[$indexCode];
625 $this->formatRecords['xfrecords'][] = array(
626 'type' => 'number',
627 'format' => $this->numberFormats[$indexCode]
628 );
629 }else{
630 $isdate = FALSE;
631 if ($indexCode > 0){
632 if (isset($this->formatRecords[$indexCode]))
633 $formatstr = $this->formatRecords[$indexCode];
634 //echo '.other.';
635 //echo "\ndate-time=$formatstr=\n";
636 if ($formatstr)
637 if (preg_match("/[^hmsday\/\-:\s]/i", $formatstr) == 0) { // found day and time format
638 $isdate = TRUE;
639 $formatstr = str_replace('mm', 'i', $formatstr);
640 $formatstr = str_replace('h', 'H', $formatstr);
641 //echo "\ndate-time $formatstr \n";
642 }
643 }
644
645 if ($isdate){
646 $this->formatRecords['xfrecords'][] = array(
647 'type' => 'date',
648 'format' => $formatstr,
649 );
650 }else{
651 $this->formatRecords['xfrecords'][] = array(
652 'type' => 'other',
653 'format' => '',
654 'code' => $indexCode
655 );
656 }
657 }
658 //echo "\n";
659 break;
660 case SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR:
661 //echo "Type.NINETEENFOUR\n";
662 $this->nineteenFour = (ord($this->data[$pos+4]) == 1);
663 break;
664 case SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET:
665 //echo "Type.BOUNDSHEET\n";
666 $rec_offset = $this->_GetInt4d($this->data, $pos+4);
667 $rec_typeFlag = ord($this->data[$pos+8]);
668 $rec_visibilityFlag = ord($this->data[$pos+9]);
669 $rec_length = ord($this->data[$pos+10]);
670
671 if ($version == SPREADSHEET_EXCEL_READER_BIFF8){
672 $chartype = ord($this->data[$pos+11]);
673 if ($chartype == 0){
674 $rec_name = substr($this->data, $pos+12, $rec_length);
675 } else {
676 $rec_name = $this->_encodeUTF16(substr($this->data, $pos+12, $rec_length*2));
677 }
678 }elseif ($version == SPREADSHEET_EXCEL_READER_BIFF7){
679 $rec_name = substr($this->data, $pos+11, $rec_length);
680 }
681 $this->boundsheets[] = array('name'=>$rec_name,
682 'offset'=>$rec_offset);
683
684 break;
685
686 }
687
688 //echo "Code = ".base_convert($r['code'],10,16)."\n";
689 $pos += $length + 4;
690 $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8;
691 $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8;
692
693 //$r = &$this->nextRecord();
694 //echo "1 Code = ".base_convert($r['code'],10,16)."\n";
695 }
696
697 foreach ($this->boundsheets as $key=>$val){
698 $this->sn = $key;
699 $this->_parsesheet($val['offset']);
700 }
701 return true;
702
703 }
704
705 /**
706 * Parse a worksheet
707 *
708 * @access private
709 * @param todo
710 * @todo fix return codes
711 */
712 function _parsesheet($spos)
713 {
714 $cont = true;
715 // read BOF
716 $code = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
717 $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
718
719 $version = ord($this->data[$spos + 4]) | ord($this->data[$spos + 5])<<8;
720 $substreamType = ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8;
721
722 if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && ($version != SPREADSHEET_EXCEL_READER_BIFF7)) {
723 return -1;
724 }
725
726 if ($substreamType != SPREADSHEET_EXCEL_READER_WORKSHEET){
727 return -2;
728 }
729 //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n";
730 $spos += $length + 4;
731 //var_dump($this->formatRecords);
732 //echo "code $code $length";
733 while($cont) {
734 //echo "mem= ".memory_get_usage()."\n";
735 // $r = &$this->file->nextRecord();
736 $lowcode = ord($this->data[$spos]);
737 if ($lowcode == SPREADSHEET_EXCEL_READER_TYPE_EOF) break;
738 $code = $lowcode | ord($this->data[$spos+1])<<8;
739 $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
740 $spos += 4;
741 $this->sheets[$this->sn]['maxrow'] = $this->_rowoffset - 1;
742 $this->sheets[$this->sn]['maxcol'] = $this->_coloffset - 1;
743 //echo "Code=".base_convert($code,10,16)." $code\n";
744 unset($this->rectype);
745 $this->multiplier = 1; // need for format with %
746 switch ($code) {
747 case SPREADSHEET_EXCEL_READER_TYPE_DIMENSION:
748 //echo 'Type_DIMENSION ';
749 if (!isset($this->numRows)) {
750 if (($length == 10) || ($version == SPREADSHEET_EXCEL_READER_BIFF7)){
751 $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+2]) | ord($this->data[$spos+3]) << 8;
752 $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+6]) | ord($this->data[$spos+7]) << 8;
753 } else {
754 $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8;
755 $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+10]) | ord($this->data[$spos+11]) << 8;
756 }
757 }
758 //echo 'numRows '.$this->numRows.' '.$this->numCols."\n";
759 break;
760 case SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS:
761 $cellRanges = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
762 for ($i = 0; $i < $cellRanges; $i++) {
763 $fr = ord($this->data[$spos + 8*$i + 2]) | ord($this->data[$spos + 8*$i + 3])<<8;
764 $lr = ord($this->data[$spos + 8*$i + 4]) | ord($this->data[$spos + 8*$i + 5])<<8;
765 $fc = ord($this->data[$spos + 8*$i + 6]) | ord($this->data[$spos + 8*$i + 7])<<8;
766 $lc = ord($this->data[$spos + 8*$i + 8]) | ord($this->data[$spos + 8*$i + 9])<<8;
767 //$this->sheets[$this->sn]['mergedCells'][] = array($fr + 1, $fc + 1, $lr + 1, $lc + 1);
768 if ($lr - $fr > 0) {
769 $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['rowspan'] = $lr - $fr + 1;
770 }
771 if ($lc - $fc > 0) {
772 $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['colspan'] = $lc - $fc + 1;
773 }
774 }
775 //echo "Merged Cells $cellRanges $lr $fr $lc $fc\n";
776 break;
777 case SPREADSHEET_EXCEL_READER_TYPE_RK:
778 case SPREADSHEET_EXCEL_READER_TYPE_RK2:
779 //echo 'SPREADSHEET_EXCEL_READER_TYPE_RK'."\n";
780 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
781 $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
782 $rknum = $this->_GetInt4d($this->data, $spos + 6);
783 $numValue = $this->_GetIEEE754($rknum);
784 //echo $numValue." ";
785 if ($this->isDate($spos)) {
786 list($string, $raw) = $this->createDate($numValue);
787 }else{
788 $raw = $numValue;
789 if (isset($this->_columnsFormat[$column + 1])){
790 $this->curformat = $this->_columnsFormat[$column + 1];
791 }
792 $string = sprintf($this->curformat, $numValue * $this->multiplier);
793 //$this->addcell(RKRecord($r));
794 }
795 $this->addcell($row, $column, $string, $raw);
796 //echo "Type_RK $row $column $string $raw {$this->curformat}\n";
797 break;
798 case SPREADSHEET_EXCEL_READER_TYPE_LABELSST:
799 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
800 $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
801 $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5])<<8;
802 $index = $this->_GetInt4d($this->data, $spos + 6);
803 //var_dump($this->sst);
804 $this->addcell($row, $column, $this->sst[$index]);
805 //echo "LabelSST $row $column $string\n";
806 break;
807 case SPREADSHEET_EXCEL_READER_TYPE_MULRK:
808 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
809 $colFirst = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
810 $colLast = ord($this->data[$spos + $length - 2]) | ord($this->data[$spos + $length - 1])<<8;
811 $columns = $colLast - $colFirst + 1;
812 $tmppos = $spos+4;
813 for ($i = 0; $i < $columns; $i++) {
814 $numValue = $this->_GetIEEE754($this->_GetInt4d($this->data, $tmppos + 2));
815 if ($this->isDate($tmppos-4)) {
816 list($string, $raw) = $this->createDate($numValue);
817 }else{
818 $raw = $numValue;
819 if (isset($this->_columnsFormat[$colFirst + $i + 1])){
820 $this->curformat = $this->_columnsFormat[$colFirst + $i + 1];
821 }
822 $string = sprintf($this->curformat, $numValue * $this->multiplier);
823 }
824 //$rec['rknumbers'][$i]['xfindex'] = ord($rec['data'][$pos]) | ord($rec['data'][$pos+1]) << 8;
825 $tmppos += 6;
826 $this->addcell($row, $colFirst + $i, $string, $raw);
827 //echo "MULRK $row ".($colFirst + $i)." $string\n";
828 }
829 //MulRKRecord($r);
830 // Get the individual cell records from the multiple record
831 //$num = ;
832
833 break;
834 case SPREADSHEET_EXCEL_READER_TYPE_NUMBER:
835 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
836 $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
837 $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent
838 if ($this->isDate($spos)) {
839 list($string, $raw) = $this->createDate($tmp['double']);
840 // $this->addcell(DateRecord($r, 1));
841 }else{
842 //$raw = $tmp[''];
843 if (isset($this->_columnsFormat[$column + 1])){
844 $this->curformat = $this->_columnsFormat[$column + 1];
845 }
846 $raw = $this->createNumber($spos);
847 $string = sprintf($this->curformat, $raw * $this->multiplier);
848
849 // $this->addcell(NumberRecord($r));
850 }
851 $this->addcell($row, $column, $string, $raw);
852 //echo "Number $row $column $string\n";
853 break;
854 case SPREADSHEET_EXCEL_READER_TYPE_FORMULA:
855 case SPREADSHEET_EXCEL_READER_TYPE_FORMULA2:
856 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
857 $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
858 if ((ord($this->data[$spos+6])==0) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) {
859 //String formula. Result follows in a STRING record
860 //echo "FORMULA $row $column Formula with a string<br>\n";
861 } elseif ((ord($this->data[$spos+6])==1) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) {
862 //Boolean formula. Result is in +2; 0=false,1=true
863 } elseif ((ord($this->data[$spos+6])==2) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) {
864 //Error formula. Error code is in +2;
865 } elseif ((ord($this->data[$spos+6])==3) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) {
866 //Formula result is a null string.
867 } else {
868 // result is a number, so first 14 bytes are just like a _NUMBER record
869 $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent
870 if ($this->isDate($spos)) {
871 list($string, $raw) = $this->createDate($tmp['double']);
872 // $this->addcell(DateRecord($r, 1));
873 }else{
874 //$raw = $tmp[''];
875 if (isset($this->_columnsFormat[$column + 1])){
876 $this->curformat = $this->_columnsFormat[$column + 1];
877 }
878 $raw = $this->createNumber($spos);
879 $string = sprintf($this->curformat, $raw * $this->multiplier);
880
881 // $this->addcell(NumberRecord($r));
882 }
883 $this->addcell($row, $column, $string, $raw);
884 //echo "Number $row $column $string\n";
885 }
886 break;
887 case SPREADSHEET_EXCEL_READER_TYPE_BOOLERR:
888 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
889 $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
890 $string = ord($this->data[$spos+6]);
891 $this->addcell($row, $column, $string);
892 //echo 'Type_BOOLERR '."\n";
893 break;
894 case SPREADSHEET_EXCEL_READER_TYPE_ROW:
895 case SPREADSHEET_EXCEL_READER_TYPE_DBCELL:
896 case SPREADSHEET_EXCEL_READER_TYPE_MULBLANK:
897 break;
898 case SPREADSHEET_EXCEL_READER_TYPE_LABEL:
899 $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8;
900 $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8;
901 $this->addcell($row, $column, substr($this->data, $spos + 8, ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8));
902
903 // $this->addcell(LabelRecord($r));
904 break;
905
906 case SPREADSHEET_EXCEL_READER_TYPE_EOF:
907 $cont = false;
908 break;
909 default:
910 //echo ' unknown :'.base_convert($r['code'],10,16)."\n";
911 break;
912
913 }
914 $spos += $length;
915 }
916
917 if (!isset($this->sheets[$this->sn]['numRows']))
918 $this->sheets[$this->sn]['numRows'] = $this->sheets[$this->sn]['maxrow'];
919 if (!isset($this->sheets[$this->sn]['numCols']))
920 $this->sheets[$this->sn]['numCols'] = $this->sheets[$this->sn]['maxcol'];
921
922 }
923
924 /**
925 * Check whether the current record read is a date
926 *
927 * @param todo
928 * @return boolean True if date, false otherwise
929 */
930 function isDate($spos)
931 {
932 //$xfindex = GetInt2d(, 4);
933 $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8;
934 //echo 'check is date '.$xfindex.' '.$this->formatRecords['xfrecords'][$xfindex]['type']."\n";
935 //var_dump($this->formatRecords['xfrecords'][$xfindex]);
936 if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'date') {
937 $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format'];
938 $this->rectype = 'date';
939 return true;
940 } else {
941 if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'number') {
942 $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format'];
943 $this->rectype = 'number';
944 if (($xfindex == 0x9) || ($xfindex == 0xa)){
945 $this->multiplier = 100;
946 }
947 }else{
948 $this->curformat = $this->_defaultFormat;
949 $this->rectype = 'unknown';
950 }
951 return false;
952 }
953 }
954
955 //}}}
956 //{{{ createDate()
957
958 /**
959 * Convert the raw Excel date into a human readable format
960 *
961 * Dates in Excel are stored as number of seconds from an epoch. On
962 * Windows, the epoch is 30/12/1899 and on Mac it's 01/01/1904
963 *
964 * @access private
965 * @param integer The raw Excel value to convert
966 * @return array First element is the converted date, the second element is number a unix timestamp
967 */
968 function createDate($numValue)
969 {
970 if ($numValue > 1) {
971 $utcDays = $numValue - ($this->nineteenFour ? SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904 : SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS);
972 $utcValue = round(($utcDays+1) * SPREADSHEET_EXCEL_READER_MSINADAY);
973 $string = date ($this->curformat, $utcValue);
974 $raw = $utcValue;
975 } else {
976 $raw = $numValue;
977 $hours = floor($numValue * 24);
978 $mins = floor($numValue * 24 * 60) - $hours * 60;
979 $secs = floor($numValue * SPREADSHEET_EXCEL_READER_MSINADAY) - $hours * 60 * 60 - $mins * 60;
980 $string = date ($this->curformat, mktime($hours, $mins, $secs));
981 }
982
983 return array($string, $raw);
984 }
985
986 function createNumber($spos)
987 {
988 $rknumhigh = $this->_GetInt4d($this->data, $spos + 10);
989 $rknumlow = $this->_GetInt4d($this->data, $spos + 6);
990 //for ($i=0; $i<8; $i++) { echo ord($this->data[$i+$spos+6]) . " "; } echo "<br>";
991 $sign = ($rknumhigh & 0x80000000) >> 31;
992 $exp = ($rknumhigh & 0x7ff00000) >> 20;
993 $mantissa = (0x100000 | ($rknumhigh & 0x000fffff));
994 $mantissalow1 = ($rknumlow & 0x80000000) >> 31;
995 $mantissalow2 = ($rknumlow & 0x7fffffff);
996 $value = $mantissa / pow( 2 , (20- ($exp - 1023)));
997 if ($mantissalow1 != 0) $value += 1 / pow (2 , (21 - ($exp - 1023)));
998 $value += $mantissalow2 / pow (2 , (52 - ($exp - 1023)));
999 //echo "Sign = $sign, Exp = $exp, mantissahighx = $mantissa, mantissalow1 = $mantissalow1, mantissalow2 = $mantissalow2<br>\n";
1000 if ($sign) {$value = -1 * $value;}
1001 return $value;
1002 }
1003
1004 function addcell($row, $col, $string, $raw = '')
1005 {
1006 //echo "ADD cel $row-$col $string\n";
1007 $this->sheets[$this->sn]['maxrow'] = max($this->sheets[$this->sn]['maxrow'], $row + $this->_rowoffset);
1008 $this->sheets[$this->sn]['maxcol'] = max($this->sheets[$this->sn]['maxcol'], $col + $this->_coloffset);
1009 $this->sheets[$this->sn]['cells'][$row + $this->_rowoffset][$col + $this->_coloffset] = $string;
1010 if ($raw)
1011 $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['raw'] = $raw;
1012 if (isset($this->rectype))
1013 $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['type'] = $this->rectype;
1014
1015 }
1016
1017
1018 function _GetIEEE754($rknum)
1019 {
1020 if (($rknum & 0x02) != 0) {
1021 $value = $rknum >> 2;
1022 } else {
1023 //mmp
1024 // first comment out the previously existing 7 lines of code here
1025 // $tmp = unpack("d", pack("VV", 0, ($rknum & 0xfffffffc)));
1026 // //$value = $tmp[''];
1027 // if (array_key_exists(1, $tmp)) {
1028 // $value = $tmp[1];
1029 // } else {
1030 // $value = $tmp[''];
1031 // }
1032 // I got my info on IEEE754 encoding from
1033 // http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html
1034 // The RK format calls for using only the most significant 30 bits of the
1035 // 64 bit floating point value. The other 34 bits are assumed to be 0
1036 // So, we use the upper 30 bits of $rknum as follows...
1037 $sign = ($rknum & 0x80000000) >> 31;
1038 $exp = ($rknum & 0x7ff00000) >> 20;
1039 $mantissa = (0x100000 | ($rknum & 0x000ffffc));
1040 $value = $mantissa / pow( 2 , (20- ($exp - 1023)));
1041 if ($sign) {$value = -1 * $value;}
1042 //end of changes by mmp
1043
1044 }
1045
1046 if (($rknum & 0x01) != 0) {
1047 $value /= 100;
1048 }
1049 return $value;
1050 }
1051
1052 function _encodeUTF16($string)
1053 {
1054 $result = $string;
1055 if ($this->_defaultEncoding){
1056 switch ($this->_encoderFunction){
1057 case 'iconv' : $result = iconv('UTF-16LE', $this->_defaultEncoding, $string);
1058 break;
1059 case 'mb_convert_encoding' : $result = mb_convert_encoding($string, $this->_defaultEncoding, 'UTF-16LE' );
1060 break;
1061 }
1062 }
1063 return $result;
1064 }
1065
1066 function _GetInt4d($data, $pos)
1067 {
1068 $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24);
1069 if ($value>=4294967294)
1070 {
1071 $value=-2;
1072 }
1073 return $value;
1074 }
1075
1076 }
1077
1078 /*
1079 * Local variables:
1080 * tab-width: 4
1081 * c-basic-offset: 4
1082 * c-hanging-comment-ender-p: nil
1083 * End:
1084 */
1085
1086 ?>
...@@ -24,19 +24,19 @@ function select_opts(Array $options, $selected = null, $echo = true) { ...@@ -24,19 +24,19 @@ function select_opts(Array $options, $selected = null, $echo = true) {
24 24
25 function select_opts_provinces($selected = null, $echo = true) { 25 function select_opts_provinces($selected = null, $echo = true) {
26 $return = "<option>Select a State/Province</option>"; 26 $return = "<option>Select a State/Province</option>";
27 27
28 $return .= '<optgroup label="Canada">'; 28 $return .= '<optgroup label="Canada">';
29 $return .= select_opts(Vars::$provinces['CA'], $selected, false); 29 $return .= select_opts(Vars::$provinces['CA'], $selected, false);
30 $return .= '</optgroup>'; 30 $return .= '</optgroup>';
31 31
32 $return .= '<optgroup label="United States">'; 32 $return .= '<optgroup label="United States">';
33 $return .= select_opts(Vars::$provinces['US'], $selected, false); 33 $return .= select_opts(Vars::$provinces['US'], $selected, false);
34 $return .= '</optgroup>'; 34 $return .= '</optgroup>';
35 35
36 $return .= '<optgroup label="Other">'; 36 $return .= '<optgroup label="Other">';
37 $return .= '<option value="other">Outside Canada/USA</option>'; 37 $return .= '<option value="other">Outside Canada/USA</option>';
38 $return .= '</optgroup>'; 38 $return .= '</optgroup>';
39 39
40 return $return; 40 return $return;
41 } 41 }
42 42
...@@ -99,11 +99,11 @@ function validateDate( $date, $format='YYYY-MM-DD') ...@@ -99,11 +99,11 @@ function validateDate( $date, $format='YYYY-MM-DD')
99 default: 99 default:
100 throw new Exception( "Invalid Date Format" ); 100 throw new Exception( "Invalid Date Format" );
101 } 101 }
102 102
103 return checkdate( $m, $d, $y ); 103 return checkdate( $m, $d, $y );
104 104
105 105
106 106
107 } 107 }
108 108
109 function validate_creditcard($cc_num, $type) { 109 function validate_creditcard($cc_num, $type) {
...@@ -114,7 +114,7 @@ function validate_creditcard($cc_num, $type) { ...@@ -114,7 +114,7 @@ function validate_creditcard($cc_num, $type) {
114 $verified = true; 114 $verified = true;
115 } else { 115 } else {
116 $verified = false; 116 $verified = false;
117 } 117 }
118 } elseif ($type == "mc") { 118 } elseif ($type == "mc") {
119 $pattern = "/^([51|52|53|54|55]{2})([0-9]{14})$/"; //Mastercard 119 $pattern = "/^([51|52|53|54|55]{2})([0-9]{14})$/"; //Mastercard
120 if (preg_match($pattern,$cc_num)) { 120 if (preg_match($pattern,$cc_num)) {
...@@ -130,7 +130,7 @@ function validate_creditcard($cc_num, $type) { ...@@ -130,7 +130,7 @@ function validate_creditcard($cc_num, $type) {
130 $verified = false; 130 $verified = false;
131 } 131 }
132 } 132 }
133 133
134 return $verified; 134 return $verified;
135 } 135 }
136 136
...@@ -190,7 +190,7 @@ if ( ! function_exists('form_dropdown')) ...@@ -190,7 +190,7 @@ if ( ! function_exists('form_dropdown'))
190 } 190 }
191 } 191 }
192 192
193 function form_linked_dropdown($name = '', $parent = '', $options = array(), $parent_selected = '', $selected = '', $extra = '') 193 function form_linked_dropdown($name = '', $parent = '', $options = array(), $parent_selected = '', $selected = '', $extra = '', $provide_js = true)
194 { 194 {
195 if ($extra != '') $extra = ' '.$extra; 195 if ($extra != '') $extra = ' '.$extra;
196 196
...@@ -204,23 +204,24 @@ function form_linked_dropdown($name = '', $parent = '', $options = array(), $par ...@@ -204,23 +204,24 @@ function form_linked_dropdown($name = '', $parent = '', $options = array(), $par
204 204
205 $form .= '<option value="'.$key.'"'.$sel.'>'.$val."</option>\n"; 205 $form .= '<option value="'.$key.'"'.$sel.'>'.$val."</option>\n";
206 } 206 }
207 } 207 }
208 208
209 $form .= '</select> 209 if ($provide_js) {
210 $form .= '</select>
210 <script> 211 <script>
211 function update_' . $name . '(value) { 212 function update_' . $name . '(value) {
212 213
213 if (value=="") { 214 if (value=="") {
214 return; 215 return;
215 } 216 }
216 217
217 jQuery("#'.$name.'_custom").attr("disabled","disabled").hide(); 218 jQuery("#' . $name . '_custom").attr("disabled","disabled").hide();
218 jQuery("#'.$name.'").show(); 219 jQuery("#' . $name . '").show();
219 220
220 221
221 var options = new Array(); 222 var options = new Array();
222 var select = document.getElementById("' . $name . '"); 223 var select = document.getElementById("' . $name . '");
223 select.disabled = false; 224 select.disabled = false;
224 while (select.firstChild) 225 while (select.firstChild)
225 select.removeChild(select.firstChild); 226 select.removeChild(select.firstChild);
226 switch (value.toString()) {'; 227 switch (value.toString()) {';
...@@ -230,41 +231,50 @@ function form_linked_dropdown($name = '', $parent = '', $options = array(), $par ...@@ -230,41 +231,50 @@ function form_linked_dropdown($name = '', $parent = '', $options = array(), $par
230 foreach ($v as $value => $content) { 231 foreach ($v as $value => $content) {
231 $form .= '"' . $value . '","' . $content . '",'; 232 $form .= '"' . $value . '","' . $content . '",';
232 } 233 }
233 $form = substr($form,0,-1); 234 $form = substr($form, 0, -1);
234 $form .= '); 235 $form .= ');
235 break;'; 236 break;';
236 } 237 }
237 $form .= 'default: 238 $form .= 'default:
238 select.disabled = true; 239 select.disabled = true;
239 240
240 jQuery("#'.$name.'").after("<input type=\'text\' name=\''.$name.'\' id=\''.$name.'_custom\' class=\'input-field-css input-large\' value=\''.$selected.'\' />").removeAttr("disabled").show(); 241 jQuery("#' . $name . '").after("<input type=\'text\' name=\'' . $name . '\' id=\'' . $name . '_custom\' class=\'input-field-css input-large\' value=\'' . $selected . '\' />").removeAttr("disabled").show();
241 jQuery("#'.$name.'").hide(); 242 jQuery("#' . $name . '").hide();
242 //options = new Array("other","Other"); 243 //options = new Array("other","Other");
243 return; 244 return;
244 } 245 }
245 246
246 var option = document.createElement("option"); 247 var option = document.createElement("option");
247 var val = ""; 248 var val = "";
248 option.val = val; 249 option.val = val;
249 option.innerHTML = "Select..."; 250 option.innerHTML = "Select...";
250 select.appendChild(option); 251 select.appendChild(option);
251 252
252 for(var i = 0; i < options.length;) { 253 for(var i = 0; i < options.length;) {
253 var option = document.createElement("option"); 254 var option = document.createElement("option");
254 var val = options[i++]; 255 var val = options[i++];
255 option.value = val; 256 option.value = val;
256 option.innerHTML = options[i++]; 257 option.innerHTML = options[i++];
257 if (val == "'.$selected.'") { 258 if (val == "' . $selected . '") {
258 option.selected = true; 259 option.selected = true;
259 } 260 }
260 select.appendChild(option); 261 select.appendChild(option);
261 } 262 }
262 263
263 } 264 }
264 update_'.$name.'(document.getElementById("'.$parent.'").value); 265 update_' . $name . '(document.getElementById("' . $parent . '").value);
265 document.getElementById("' . $parent . '").onchange = function() { update_' . $name . '(this.value); } 266 document.getElementById("' . $parent . '").onchange = function() { update_' . $name . '(this.value); }
266 </script> 267 </script>
267 '; 268 ';
269 } else {
270 $form = '';
271 if (array_key_exists($parent_selected, $options)) {
272 foreach ($options[$parent_selected] as $name => $option) {
273 $sel = ($selected == $name) ? ' selected="selected"' : '';
274 $form .= '<option value="' . $name . '"' . $sel . '>' . $option . "</option>\n";
275 }
276 }
277 }
268 278
269 return $form; 279 return $form;
270 } 280 }
...@@ -323,7 +333,7 @@ class Vars { ...@@ -323,7 +333,7 @@ class Vars {
323 , 'Dr.' => 'Dr.' 333 , 'Dr.' => 'Dr.'
324 , 'Prof.' => 'Prof.' 334 , 'Prof.' => 'Prof.'
325 ); 335 );
326 336
327 public static $company_types = Array( 337 public static $company_types = Array(
328 'advisory_firm' => "Advisory Firm" 338 'advisory_firm' => "Advisory Firm"
329 , 'litigation_firm' => "Litigation Firm" 339 , 'litigation_firm' => "Litigation Firm"
...@@ -340,7 +350,7 @@ class Vars { ...@@ -340,7 +350,7 @@ class Vars {
340 , 'mutual_fund_co' => "Mutual Fund Management Company" 350 , 'mutual_fund_co' => "Mutual Fund Management Company"
341 , 'merchant_bank' => "Merchant Bank" 351 , 'merchant_bank' => "Merchant Bank"
342 ); 352 );
343 353
344 public static $countries = Array( 354 public static $countries = Array(
345 'CA' => 'Canada' 355 'CA' => 'Canada'
346 , 'US' => 'United States' 356 , 'US' => 'United States'
...@@ -657,13 +667,13 @@ class Vars { ...@@ -657,13 +667,13 @@ class Vars {
657 , 'WY' => 'Wyoming' 667 , 'WY' => 'Wyoming'
658 ) 668 )
659 ); 669 );
660 670
661 public static $securities = Array( 671 public static $securities = Array(
662 'S01' => "What is your Mother's maiden name?" 672 'S01' => "What is your Mother's maiden name?"
663 , 'S02' => "Who was you childhood hero?" 673 , 'S02' => "Who was you childhood hero?"
664 , 'S03' => "What is/was the name of your first pet?" 674 , 'S03' => "What is/was the name of your first pet?"
665 ); 675 );
666 676
667 public static $creditcards = Array( 677 public static $creditcards = Array(
668 'visa' => "Visa" 678 'visa' => "Visa"
669 , 'mc' => "MasterCard" 679 , 'mc' => "MasterCard"
......