204 &$str_total, &$str_unique, &$str_table, &$colors,
208 parent::__construct();
211 $this->_biffsize = 0;
212 $this->_palette =
array();
213 $this->_country_code = -1;
215 $this->_str_total = &$str_total;
216 $this->_str_unique = &$str_unique;
217 $this->_str_table = &$str_table;
218 $this->_colors = &$colors;
221 $this->_phpExcel = $phpExcel;
225 $this->_codepage = 0x04B0;
228 $countSheets = $phpExcel->getSheetCount();
229 for ($i = 0; $i < $countSheets; ++$i) {
230 $phpSheet = $phpExcel->getSheet($i);
232 $this->_parser->setExtSheet($phpSheet->getTitle(), $i);
234 $supbook_index = 0x00;
235 $ref = pack(
'vvv', $supbook_index, $i, $i);
236 $this->_parser->_references[] = $ref;
239 if ($phpSheet->isTabColorSet()) {
240 $this->
_addColor($phpSheet->getTabColor()->getRGB());
256 $xfWriter->setIsStyleXf($isStyleXf);
262 $xfWriter->setFontIndex($fontIndex);
265 $xfWriter->setFgColor($this->
_addColor(
$style->getFill()->getStartColor()->getRGB()));
266 $xfWriter->setBgColor($this->
_addColor(
$style->getFill()->getEndColor()->getRGB()));
267 $xfWriter->setBottomColor($this->
_addColor(
$style->getBorders()->getBottom()->getColor()->getRGB()));
268 $xfWriter->setTopColor($this->
_addColor(
$style->getBorders()->getTop()->getColor()->getRGB()));
269 $xfWriter->setRightColor($this->
_addColor(
$style->getBorders()->getRight()->getColor()->getRGB()));
270 $xfWriter->setLeftColor($this->
_addColor(
$style->getBorders()->getLeft()->getColor()->getRGB()));
271 $xfWriter->setDiagColor($this->
_addColor(
$style->getBorders()->getDiagonal()->getColor()->getRGB()));
274 if (
$style->getNumberFormat()->getBuiltInFormatCode() ===
false) {
275 $numberFormatHashCode =
$style->getNumberFormat()->getHashCode();
277 if (isset($this->_addedNumberFormats[$numberFormatHashCode])) {
278 $numberFormatIndex = $this->_addedNumberFormats[$numberFormatHashCode];
280 $numberFormatIndex = 164 + count($this->_numberFormats);
281 $this->_numberFormats[$numberFormatIndex] =
$style->getNumberFormat();
282 $this->_addedNumberFormats[$numberFormatHashCode] = $numberFormatIndex;
285 $numberFormatIndex = (int)
$style->getNumberFormat()->getBuiltInFormatCode();
289 $xfWriter->setNumberFormatIndex($numberFormatIndex);
291 $this->_xfWriters[] = $xfWriter;
293 $xfIndex = count($this->_xfWriters) - 1;
306 if(isset($this->_addedFonts[$fontHashCode])){
307 $fontIndex = $this->_addedFonts[$fontHashCode];
309 $countFonts = count($this->_fontWriters);
310 $fontIndex = ($countFonts < 4) ? $countFonts : $countFonts + 1;
314 $this->_fontWriters[] = $fontWriter;
316 $this->_addedFonts[$fontHashCode] = $fontIndex;
328 if (!isset($this->_colors[$rgb])) {
329 if (count($this->_colors) < 57) {
331 $colorIndex = 8 + count($this->_colors);
332 $this->_palette[$colorIndex] =
334 hexdec(substr($rgb, 0, 2)),
335 hexdec(substr($rgb, 2, 2)),
336 hexdec(substr($rgb, 4)),
339 $this->_colors[$rgb] = $colorIndex;
346 $colorIndex = $this->_colors[$rgb];
359 $this->_palette =
array(
360 0x08 =>
array(0x00, 0x00, 0x00, 0x00),
361 0x09 =>
array(0xff, 0xff, 0xff, 0x00),
362 0x0A =>
array(0xff, 0x00, 0x00, 0x00),
363 0x0B =>
array(0x00, 0xff, 0x00, 0x00),
364 0x0C =>
array(0x00, 0x00, 0xff, 0x00),
365 0x0D =>
array(0xff, 0xff, 0x00, 0x00),
366 0x0E =>
array(0xff, 0x00, 0xff, 0x00),
367 0x0F =>
array(0x00, 0xff, 0xff, 0x00),
368 0x10 =>
array(0x80, 0x00, 0x00, 0x00),
369 0x11 =>
array(0x00, 0x80, 0x00, 0x00),
370 0x12 =>
array(0x00, 0x00, 0x80, 0x00),
371 0x13 =>
array(0x80, 0x80, 0x00, 0x00),
372 0x14 =>
array(0x80, 0x00, 0x80, 0x00),
373 0x15 =>
array(0x00, 0x80, 0x80, 0x00),
374 0x16 =>
array(0xc0, 0xc0, 0xc0, 0x00),
375 0x17 =>
array(0x80, 0x80, 0x80, 0x00),
376 0x18 =>
array(0x99, 0x99, 0xff, 0x00),
377 0x19 =>
array(0x99, 0x33, 0x66, 0x00),
378 0x1A =>
array(0xff, 0xff, 0xcc, 0x00),
379 0x1B =>
array(0xcc, 0xff, 0xff, 0x00),
380 0x1C =>
array(0x66, 0x00, 0x66, 0x00),
381 0x1D =>
array(0xff, 0x80, 0x80, 0x00),
382 0x1E =>
array(0x00, 0x66, 0xcc, 0x00),
383 0x1F =>
array(0xcc, 0xcc, 0xff, 0x00),
384 0x20 =>
array(0x00, 0x00, 0x80, 0x00),
385 0x21 =>
array(0xff, 0x00, 0xff, 0x00),
386 0x22 =>
array(0xff, 0xff, 0x00, 0x00),
387 0x23 =>
array(0x00, 0xff, 0xff, 0x00),
388 0x24 =>
array(0x80, 0x00, 0x80, 0x00),
389 0x25 =>
array(0x80, 0x00, 0x00, 0x00),
390 0x26 =>
array(0x00, 0x80, 0x80, 0x00),
391 0x27 =>
array(0x00, 0x00, 0xff, 0x00),
392 0x28 =>
array(0x00, 0xcc, 0xff, 0x00),
393 0x29 =>
array(0xcc, 0xff, 0xff, 0x00),
394 0x2A =>
array(0xcc, 0xff, 0xcc, 0x00),
395 0x2B =>
array(0xff, 0xff, 0x99, 0x00),
396 0x2C =>
array(0x99, 0xcc, 0xff, 0x00),
397 0x2D =>
array(0xff, 0x99, 0xcc, 0x00),
398 0x2E =>
array(0xcc, 0x99, 0xff, 0x00),
399 0x2F =>
array(0xff, 0xcc, 0x99, 0x00),
400 0x30 =>
array(0x33, 0x66, 0xff, 0x00),
401 0x31 =>
array(0x33, 0xcc, 0xcc, 0x00),
402 0x32 =>
array(0x99, 0xcc, 0x00, 0x00),
403 0x33 =>
array(0xff, 0xcc, 0x00, 0x00),
404 0x34 =>
array(0xff, 0x99, 0x00, 0x00),
405 0x35 =>
array(0xff, 0x66, 0x00, 0x00),
406 0x36 =>
array(0x66, 0x66, 0x99, 0x00),
407 0x37 =>
array(0x96, 0x96, 0x96, 0x00),
408 0x38 =>
array(0x00, 0x33, 0x66, 0x00),
409 0x39 =>
array(0x33, 0x99, 0x66, 0x00),
410 0x3A =>
array(0x00, 0x33, 0x00, 0x00),
411 0x3B =>
array(0x33, 0x33, 0x00, 0x00),
412 0x3C =>
array(0x99, 0x33, 0x00, 0x00),
413 0x3D =>
array(0x99, 0x33, 0x66, 0x00),
414 0x3E =>
array(0x33, 0x33, 0x99, 0x00),
415 0x3F =>
array(0x33, 0x33, 0x33, 0x00),
428 $this->_worksheetSizes = $pWorksheetSizes;
432 $total_worksheets = $this->_phpExcel->getSheetCount();
448 if ($this->_country_code != -1) {
465 for ($i = 0; $i < $total_worksheets; ++$i) {
466 $this->
_writeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]);
470 $this->_data .= $part3;
482 $boundsheet_length = 10;
488 $total_worksheets = count($this->_phpExcel->getAllSheets());
489 foreach ($this->_phpExcel->getWorksheetIterator() as $sheet) {
494 for ($i = 0; $i < $total_worksheets; ++$i) {
495 $this->_worksheetOffsets[$i] = $offset;
496 $offset += $this->_worksheetSizes[$i];
498 $this->_biffsize = $offset;
506 foreach ($this->_fontWriters as $fontWriter) {
507 $this->
_append($fontWriter->writeFont());
516 foreach ($this->_numberFormats as $numberFormatIndex => $numberFormat) {
517 $this->
_writeNumFormat($numberFormat->getFormatCode(), $numberFormatIndex);
526 foreach ($this->_xfWriters as $xfWriter) {
527 $this->
_append($xfWriter->writeXf());
545 $countSheets = $this->_phpExcel->getSheetCount();
550 for ($i = 0; $i < $countSheets; ++$i) {
561 $total_worksheets = $this->_phpExcel->getSheetCount();
564 for ($i = 0; $i < $total_worksheets; ++$i) {
565 $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup();
567 if ($sheetSetup->isPrintAreaSet()) {
570 $printArea = $printArea[0];
574 $print_rowmin = $printArea[0][1] - 1;
575 $print_rowmax = $printArea[1][1] - 1;
591 for ($i = 0; $i < $total_worksheets; ++$i) {
592 $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup();
595 if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) {
596 $repeat = $sheetSetup->getColumnsToRepeatAtLeft();
600 $repeat = $sheetSetup->getRowsToRepeatAtTop();
601 $rowmin = $repeat[0] - 1;
602 $rowmax = $repeat[1] - 1;
614 }
else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) {
617 if ($sheetSetup->isColumnsToRepeatAtLeftSet()) {
618 $repeat = $sheetSetup->getColumnsToRepeatAtLeft();
627 if ($sheetSetup->isRowsToRepeatAtTopSet()) {
628 $repeat = $sheetSetup->getRowsToRepeatAtTop();
629 $rowmin = $repeat[0] - 1;
630 $rowmax = $repeat[1] - 1;
657 if (count($this->_phpExcel->getNamedRanges()) > 0) {
659 $namedRanges = $this->_phpExcel->getNamedRanges();
660 foreach ($namedRanges as $namedRange) {
664 for ($i = 0; $i < count($range); $i++) {
665 $range[$i][0] =
'\'' . str_replace(
"'",
"''", $namedRange->getWorksheet()->getTitle()) .
'\'!
' . PHPExcel_Cell::absoluteCoordinate($range[$i][0]); 666 if (isset($range[$i][1])) { 667 $range[$i][1] = PHPExcel_Cell::absoluteCoordinate($range[$i][1]); 670 $range = PHPExcel_Cell::buildRange($range); // e.g. Sheet1!$A$1:$B$2 674 $error = $this->_parser->parse($range); 675 $formulaData = $this->_parser->toReversePolish(); 677 // make sure tRef3d is of type tRef3dR (0x3A) 678 if (isset($formulaData{0}) and ($formulaData{0} == "\x7A" or $formulaData{0} == "\x5A")) { 679 $formulaData = "\x3A" . substr($formulaData, 1); 682 if ($namedRange->getLocalOnly()) { 684 $scope = $this->_phpExcel->getIndex($namedRange->getScope()) + 1; 689 $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, $scope, false)); 691 } catch(PHPExcel_Exception $e) { 697 // total number of sheets 698 $total_worksheets = $this->_phpExcel->getSheetCount(); 700 // write the print titles (repeating rows, columns), if any 701 for ($i = 0; $i < $total_worksheets; ++$i) { 702 $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); 703 // simultaneous repeatColumns repeatRows 704 if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { 705 $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); 706 $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; 707 $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; 709 $repeat = $sheetSetup->getRowsToRepeatAtTop(); 710 $rowmin = $repeat[0] - 1; 711 $rowmax = $repeat[1] - 1; 713 // construct formula data manually 714 $formulaData = pack('Cv
', 0x29, 0x17); // tMemFunc 715 $formulaData .= pack('Cvvvvv
', 0x3B, $i, 0, 65535, $colmin, $colmax); // tArea3d 716 $formulaData .= pack('Cvvvvv
', 0x3B, $i, $rowmin, $rowmax, 0, 255); // tArea3d 717 $formulaData .= pack('C', 0x10); // tList 719 // store the DEFINEDNAME record 720 $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); 722 // (exclusive) either repeatColumns or repeatRows 723 } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { 726 if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { 727 $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); 728 $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; 729 $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; 735 if ($sheetSetup->isRowsToRepeatAtTopSet()) { 736 $repeat = $sheetSetup->getRowsToRepeatAtTop(); 737 $rowmin = $repeat[0] - 1; 738 $rowmax = $repeat[1] - 1; 744 // construct formula data manually because parser does not recognize absolute 3d cell references 745 $formulaData = pack('Cvvvvv
', 0x3B, $i, $rowmin, $rowmax, $colmin, $colmax); 747 // store the DEFINEDNAME record 748 $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); 752 // write the print areas, if any 753 for ($i = 0; $i < $total_worksheets; ++$i) { 754 $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); 755 if ($sheetSetup->isPrintAreaSet()) { 756 // Print area, e.g. A3:J6,H1:X20 757 $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); 758 $countPrintArea = count($printArea); 761 for ($j = 0; $j < $countPrintArea; ++$j) { 762 $printAreaRect = $printArea[$j]; // e.g. A3:J6 763 $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); 764 $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); 766 $print_rowmin = $printAreaRect[0][1] - 1; 767 $print_rowmax = $printAreaRect[1][1] - 1; 768 $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; 769 $print_colmax = PHPExcel_Cell::columnIndexFromString($printAreaRect[1][0]) - 1; 771 // construct formula data manually because parser does not recognize absolute 3d cell references 772 $formulaData .= pack('Cvvvvv
', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); 775 $formulaData .= pack('C', 0x10); // list operator token ',
' 779 // store the DEFINEDNAME record 780 $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C
', 0x06), $formulaData, $i + 1, true)); 784 // write autofilters, if any 785 for ($i = 0; $i < $total_worksheets; ++$i) { 786 $sheetAutoFilter = $this->_phpExcel->getSheet($i)->getAutoFilter(); 787 $autoFilterRange = $sheetAutoFilter->getRange(); 788 if(!empty($autoFilterRange)) { 789 $rangeBounds = PHPExcel_Cell::rangeBoundaries($autoFilterRange); 791 //Autofilter built in name 792 $name = pack('C
', 0x0D); 794 $chunk .= $this->writeData($this->_writeShortNameBiff8($name, $i + 1, $rangeBounds, true)); 810 private function _writeDefinedNameBiff8($name, $formulaData, $sheetIndex = 0, $isBuiltIn = false) 815 $options = $isBuiltIn ? 0x20 : 0x00; 817 // length of the name, character count 818 $nlen = PHPExcel_Shared_String::CountCharacters($name); 820 // name with stripped length field 821 $name = substr(PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($name), 2); 823 // size of the formula (in bytes) 824 $sz = strlen($formulaData); 827 $data = pack('vCCvvvCCCC
', $options, 0, $nlen, $sz, 0, $sheetIndex, 0, 0, 0, 0) 828 . $name . $formulaData; 829 $length = strlen($data); 831 $header = pack('vv
', $record, $length); 833 return $header . $data; 845 private function _writeShortNameBiff8($name, $sheetIndex = 0, $rangeBounds, $isHidden = false){ 849 $options = ($isHidden ? 0x21 : 0x00); 851 $extra = pack('Cvvvvv
', 854 $rangeBounds[0][1] - 1, 855 $rangeBounds[1][1] - 1, 856 $rangeBounds[0][0] - 1, 857 $rangeBounds[1][0] - 1); 859 // size of the formula (in bytes) 860 $sz = strlen($extra); 863 $data = pack('vCCvvvCCCCC
', $options, 0, 1, $sz, 0, $sheetIndex, 0, 0, 0, 0, 0) 865 $length = strlen($data); 867 $header = pack('vv
', $record, $length); 869 return $header . $data; 875 private function _writeCodepage() 877 $record = 0x0042; // Record identifier 878 $length = 0x0002; // Number of bytes to follow 879 $cv = $this->_codepage; // The code page 881 $header = pack('vv
', $record, $length); 882 $data = pack('v
', $cv); 884 $this->_append($header . $data); 890 private function _writeWindow1() 892 $record = 0x003D; // Record identifier 893 $length = 0x0012; // Number of bytes to follow 895 $xWn = 0x0000; // Horizontal position of window 896 $yWn = 0x0000; // Vertical position of window 897 $dxWn = 0x25BC; // Width of window 898 $dyWn = 0x1572; // Height of window 900 $grbit = 0x0038; // Option flags 902 // not supported by PHPExcel, so there is only one selected sheet, the active 903 $ctabsel = 1; // Number of workbook tabs selected 905 $wTabRatio = 0x0258; // Tab to scrollbar ratio 907 // not supported by PHPExcel, set to 0 908 $itabFirst = 0; // 1st displayed worksheet 909 $itabCur = $this->_phpExcel->getActiveSheetIndex(); // Active worksheet 911 $header = pack("vv", $record, $length); 912 $data = pack("vvvvvvvvv", $xWn, $yWn, $dxWn, $dyWn, 914 $itabCur, $itabFirst, 915 $ctabsel, $wTabRatio); 916 $this->_append($header . $data); 925 private function _writeBoundsheet($sheet, $offset) 927 $sheetname = $sheet->getTitle(); 928 $record = 0x0085; // Record identifier 931 switch ($sheet->getSheetState()) { 932 case PHPExcel_Worksheet::SHEETSTATE_VISIBLE: $ss = 0x00; break; 933 case PHPExcel_Worksheet::SHEETSTATE_HIDDEN: $ss = 0x01; break; 934 case PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN: $ss = 0x02; break; 935 default: $ss = 0x00; break; 941 $grbit = 0x0000; // Visibility and sheet type 943 $data = pack("VCC", $offset, $ss, $st); 944 $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheetname); 946 $length = strlen($data); 947 $header = pack("vv", $record, $length); 948 $this->_append($header . $data); 954 private function _writeSupbookInternal() 956 $record = 0x01AE; // Record identifier 957 $length = 0x0004; // Bytes to follow 959 $header = pack("vv", $record, $length); 960 $data = pack("vv", $this->_phpExcel->getSheetCount(), 0x0401); 961 return $this->writeData($header . $data); 969 private function _writeExternsheetBiff8() 971 $total_references = count($this->_parser->_references); 972 $record = 0x0017; // Record identifier 973 $length = 2 + 6 * $total_references; // Number of bytes to follow 975 $supbook_index = 0; // FIXME: only using internal SUPBOOK record 976 $header = pack("vv", $record, $length); 977 $data = pack('v
', $total_references); 978 for ($i = 0; $i < $total_references; ++$i) { 979 $data .= $this->_parser->_references[$i]; 981 return $this->writeData($header . $data); 987 private function _writeStyle() 989 $record = 0x0293; // Record identifier 990 $length = 0x0004; // Bytes to follow 992 $ixfe = 0x8000; // Index to cell style XF 993 $BuiltIn = 0x00; // Built-in style 994 $iLevel = 0xff; // Outline style level 996 $header = pack("vv", $record, $length); 997 $data = pack("vCC", $ixfe, $BuiltIn, $iLevel); 998 $this->_append($header . $data); 1007 private function _writeNumFormat($format, $ifmt) 1009 $record = 0x041E; // Record identifier 1011 $numberFormatString = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($format); 1012 $length = 2 + strlen($numberFormatString); // Number of bytes to follow 1015 $header = pack("vv", $record, $length); 1016 $data = pack("v", $ifmt) . $numberFormatString; 1017 $this->_append($header . $data); 1023 private function _writeDatemode() 1025 $record = 0x0022; // Record identifier 1026 $length = 0x0002; // Bytes to follow 1028 $f1904 = (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) ? 1029 1 : 0; // Flag for 1904 date system 1031 $header = pack("vv", $record, $length); 1032 $data = pack("v", $f1904); 1033 $this->_append($header . $data); 1048 private function _writeExterncount($cxals) 1050 $record = 0x0016; // Record identifier 1051 $length = 0x0002; // Number of bytes to follow 1053 $header = pack("vv", $record, $length); 1054 $data = pack("v", $cxals); 1055 $this->_append($header . $data); 1067 private function _writeExternsheet($sheetname) 1069 $record = 0x0017; // Record identifier 1070 $length = 0x02 + strlen($sheetname); // Number of bytes to follow 1072 $cch = strlen($sheetname); // Length of sheet name 1073 $rgch = 0x03; // Filename encoding 1075 $header = pack("vv", $record, $length); 1076 $data = pack("CC", $cch, $rgch); 1077 $this->_append($header . $data . $sheetname); 1091 private function _writeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax) 1093 $record = 0x0018; // Record identifier 1094 $length = 0x0024; // Number of bytes to follow 1096 $grbit = 0x0020; // Option flags 1097 $chKey = 0x00; // Keyboard shortcut 1098 $cch = 0x01; // Length of text name 1099 $cce = 0x0015; // Length of text definition 1100 $ixals = $index + 1; // Sheet index 1101 $itab = $ixals; // Equal to ixals 1102 $cchCustMenu = 0x00; // Length of cust menu text 1103 $cchDescription = 0x00; // Length of description text 1104 $cchHelptopic = 0x00; // Length of help topic text 1105 $cchStatustext = 0x00; // Length of status bar text 1106 $rgch = $type; // Built-in name type 1109 $unknown04 = 0xffff-$index; 1110 $unknown05 = 0x0000; 1111 $unknown06 = 0x0000; 1112 $unknown07 = 0x1087; 1113 $unknown08 = 0x8005; 1115 $header = pack("vv", $record, $length); 1116 $data = pack("v", $grbit); 1117 $data .= pack("C", $chKey); 1118 $data .= pack("C", $cch); 1119 $data .= pack("v", $cce); 1120 $data .= pack("v", $ixals); 1121 $data .= pack("v", $itab); 1122 $data .= pack("C", $cchCustMenu); 1123 $data .= pack("C", $cchDescription); 1124 $data .= pack("C", $cchHelptopic); 1125 $data .= pack("C", $cchStatustext); 1126 $data .= pack("C", $rgch); 1127 $data .= pack("C", $unknown03); 1128 $data .= pack("v", $unknown04); 1129 $data .= pack("v", $unknown05); 1130 $data .= pack("v", $unknown06); 1131 $data .= pack("v", $unknown07); 1132 $data .= pack("v", $unknown08); 1133 $data .= pack("v", $index); 1134 $data .= pack("v", $index); 1135 $data .= pack("v", $rowmin); 1136 $data .= pack("v", $rowmax); 1137 $data .= pack("C", $colmin); 1138 $data .= pack("C", $colmax); 1139 $this->_append($header . $data); 1155 private function _writeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax) 1157 $record = 0x0018; // Record identifier 1158 $length = 0x003d; // Number of bytes to follow 1159 $grbit = 0x0020; // Option flags 1160 $chKey = 0x00; // Keyboard shortcut 1161 $cch = 0x01; // Length of text name 1162 $cce = 0x002e; // Length of text definition 1163 $ixals = $index + 1; // Sheet index 1164 $itab = $ixals; // Equal to ixals 1165 $cchCustMenu = 0x00; // Length of cust menu text 1166 $cchDescription = 0x00; // Length of description text 1167 $cchHelptopic = 0x00; // Length of help topic text 1168 $cchStatustext = 0x00; // Length of status bar text 1169 $rgch = $type; // Built-in name type 1172 $unknown02 = 0x002b; 1174 $unknown04 = 0xffff-$index; 1175 $unknown05 = 0x0000; 1176 $unknown06 = 0x0000; 1177 $unknown07 = 0x1087; 1178 $unknown08 = 0x8008; 1180 $header = pack("vv", $record, $length); 1181 $data = pack("v", $grbit); 1182 $data .= pack("C", $chKey); 1183 $data .= pack("C", $cch); 1184 $data .= pack("v", $cce); 1185 $data .= pack("v", $ixals); 1186 $data .= pack("v", $itab); 1187 $data .= pack("C", $cchCustMenu); 1188 $data .= pack("C", $cchDescription); 1189 $data .= pack("C", $cchHelptopic); 1190 $data .= pack("C", $cchStatustext); 1191 $data .= pack("C", $rgch); 1192 $data .= pack("C", $unknown01); 1193 $data .= pack("v", $unknown02); 1194 // Column definition 1195 $data .= pack("C", $unknown03); 1196 $data .= pack("v", $unknown04); 1197 $data .= pack("v", $unknown05); 1198 $data .= pack("v", $unknown06); 1199 $data .= pack("v", $unknown07); 1200 $data .= pack("v", $unknown08); 1201 $data .= pack("v", $index); 1202 $data .= pack("v", $index); 1203 $data .= pack("v", 0x0000); 1204 $data .= pack("v", 0x3fff); 1205 $data .= pack("C", $colmin); 1206 $data .= pack("C", $colmax); 1208 $data .= pack("C", $unknown03); 1209 $data .= pack("v", $unknown04); 1210 $data .= pack("v", $unknown05); 1211 $data .= pack("v", $unknown06); 1212 $data .= pack("v", $unknown07); 1213 $data .= pack("v", $unknown08); 1214 $data .= pack("v", $index); 1215 $data .= pack("v", $index); 1216 $data .= pack("v", $rowmin); 1217 $data .= pack("v", $rowmax); 1218 $data .= pack("C", 0x00); 1219 $data .= pack("C", 0xff); 1221 $data .= pack("C", 0x10); 1222 $this->_append($header . $data); 1230 private function _writeCountry() 1232 $record = 0x008C; // Record identifier 1233 $length = 4; // Number of bytes to follow 1235 $header = pack('vv
', $record, $length); 1236 /* using the same country code always for simplicity */ 1237 $data = pack('vv
', $this->_country_code, $this->_country_code); 1238 //$this->_append($header . $data); 1239 return $this->writeData($header . $data); 1247 private function _writeRecalcId() 1249 $record = 0x01C1; // Record identifier 1250 $length = 8; // Number of bytes to follow 1252 $header = pack('vv
', $record, $length); 1254 // by inspection of real Excel files, MS Office Excel 2007 writes this 1255 $data = pack('VV
', 0x000001C1, 0x00001E667); 1257 return $this->writeData($header . $data); 1263 private function _writePalette() 1265 $aref = $this->_palette; 1267 $record = 0x0092; // Record identifier 1268 $length = 2 + 4 * count($aref); // Number of bytes to follow 1269 $ccv = count($aref); // Number of RGB values to follow 1270 $data = ''; // The RGB data 1272 // Pack the RGB data 1273 foreach ($aref as $color) { 1274 foreach ($color as $byte) { 1275 $data .= pack("C",$byte); 1279 $header = pack("vvv", $record, $length, $ccv); 1280 $this->_append($header . $data); 1297 private function _writeSharedStringsTable() 1299 // maximum size of record data (excluding record header) 1300 $continue_limit = 8224; 1302 // initialize array of record data blocks 1303 $recordDatas = array(); 1305 // start SST record data block with total number of strings, total number of unique strings 1306 $recordData = pack("VV", $this->_str_total, $this->_str_unique); 1308 // loop through all (unique) strings in shared strings table 1309 foreach (array_keys($this->_str_table) as $string) { 1311 // here $string is a BIFF8 encoded string 1313 // length = character count 1314 $headerinfo = unpack("vlength/Cencoding", $string); 1316 // currently, this is always 1 = uncompressed 1317 $encoding = $headerinfo["encoding"]; 1319 // initialize finished writing current $string 1322 while ($finished === false) { 1324 // normally, there will be only one cycle, but if string cannot immediately be written as is 1325 // there will be need for more than one cylcle, if string longer than one record data block, there 1326 // may be need for even more cycles 1328 if (strlen($recordData) + strlen($string) <= $continue_limit) { 1329 // then we can write the string (or remainder of string) without any problems 1330 $recordData .= $string; 1332 if (strlen($recordData) + strlen($string) == $continue_limit) { 1333 // we close the record data block, and initialize a new one 1334 $recordDatas[] = $recordData; 1338 // we are finished writing this string 1341 // special treatment writing the string (or remainder of the string) 1342 // If the string is very long it may need to be written in more than one CONTINUE record. 1344 // check how many bytes more there is room for in the current record 1345 $space_remaining = $continue_limit - strlen($recordData); 1347 // minimum space needed 1348 // uncompressed: 2 byte string length length field + 1 byte option flags + 2 byte character 1349 // compressed: 2 byte string length length field + 1 byte option flags + 1 byte character 1350 $min_space_needed = ($encoding == 1) ? 5 : 4; 1352 // We have two cases 1353 // 1. space remaining is less than minimum space needed 1354 // here we must waste the space remaining and move to next record data block 1355 // 2. space remaining is greater than or equal to minimum space needed 1356 // here we write as much as we can in the current block, then move to next record data block 1358 // 1. space remaining is less than minimum space needed 1359 if ($space_remaining < $min_space_needed) { 1360 // we close the block, store the block data 1361 $recordDatas[] = $recordData; 1363 // and start new record data block where we start writing the string 1366 // 2. space remaining is greater than or equal to minimum space needed 1368 // initialize effective remaining space, for Unicode strings this may need to be reduced by 1, see below 1369 $effective_space_remaining = $space_remaining; 1371 // for uncompressed strings, sometimes effective space remaining is reduced by 1 1372 if ( $encoding == 1 && (strlen($string) - $space_remaining) % 2 == 1 ) { 1373 --$effective_space_remaining; 1376 // one block fininshed, store the block data 1377 $recordData .= substr($string, 0, $effective_space_remaining); 1379 $string = substr($string, $effective_space_remaining); // for next cycle in while loop 1380 $recordDatas[] = $recordData; 1382 // start new record data block with the repeated option flags 1383 $recordData = pack('C
', $encoding); 1389 // Store the last record data block unless it is empty 1390 // if there was no need for any continue records, this will be the for SST record data block itself 1391 if (strlen($recordData) > 0) { 1392 $recordDatas[] = $recordData; 1395 // combine into one chunk with all the blocks SST, CONTINUE,... 1397 foreach ($recordDatas as $i => $recordData) { 1398 // first block should have the SST record header, remaing should have CONTINUE header 1399 $record = ($i == 0) ? 0x00FC : 0x003C; 1401 $header = pack("vv", $record, strlen($recordData)); 1402 $data = $header . $recordData; 1404 $chunk .= $this->writeData($data); 1413 private function _writeMsoDrawingGroup() 1415 // write the Escher stream if necessary 1416 if (isset($this->_escher)) { 1417 $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); 1418 $data = $writer->close(); 1421 $length = strlen($data); 1422 $header = pack("vv", $record, $length); 1424 return $this->writeData($header . $data); 1436 public function getEscher() 1438 return $this->_escher; 1446 public function setEscher(PHPExcel_Shared_Escher $pValue = null) 1448 $this->_escher = $pValue;
static splitRange($pRange='A1:A1')
Split range into coordinate strings.
static coordinateFromString($pCoordinateString='A1')
Coordinate from string.
_append($data)
General storage function.
addXfWriter($style, $isStyleXf=false)
Add a new XF writer.
_writeSupbookInternal()
Write Internal SUPBOOK record.
_writeCountry()
Stores the COUNTRY record for localization.
_writeAllXfs()
Write all XF records.
_writeRecalcId()
Write the RECALCID record.
_writeExterncount($cxals)
Write BIFF record EXTERNCOUNT to indicate the number of external sheet references in the workbook...
_writeBoundsheet($sheet, $offset)
Writes Excel BIFF BOUNDSHEET record.
_storeBof($type)
Writes Excel BOF record to indicate the beginning of a stream or sub-stream in the BIFF file...
_writeDatemode()
Write DATEMODE record to indicate the date system in use (1904 or 1900).
_writeAllNumFormats()
Store user defined numerical formats i.e.
_writeAllDefinedNamesBiff8()
Writes all the DEFINEDNAME records (BIFF8).
__construct(PHPExcel $phpExcel=null, &$str_total, &$str_unique, &$str_table, &$colors, $parser)
Class constructor.
_setPaletteXl97()
Sets the colour palette to the Excel 97+ default.
writeEof()
Writes Excel EOF record to indicate the end of a BIFF stream.
_writeExternsheetBiff8()
Writes the Excel BIFF EXTERNSHEET record.
_writeMsoDrawingGroup()
Writes the MSODRAWINGGROUP record if needed.
_addFont(PHPExcel_Style_Font $font)
Add a font to added fonts.
static UTF8toBIFF8UnicodeShort($value, $arrcRuns=array())
Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length) Writes the string using ...
_writeCodepage()
Stores the CODEPAGE biff record.
getHashCode()
Get hash code.
Create styles array
The data for the language used.
_writeStyle()
Write Excel BIFF STYLE records.
_writeExterns()
Write the EXTERNCOUNT and EXTERNSHEET records.
static columnIndexFromString($pString='A')
Column index from string.
_writeWindow1()
Write Excel BIFF WINDOW1 record.
_writeSharedStringsTable()
Handling of the SST continue blocks is complicated by the need to include an additional continuation ...
writeWorkbook($pWorksheetSizes=null)
Assemble worksheets into a workbook and send the BIFF data to an OLE storage.
_calcSheetOffsets()
Calculate offsets for Worksheet BOF records.
_writePalette()
Stores the PALETTE biff record.
_writeExternsheet($sheetname)
Writes the Excel BIFF EXTERNSHEET record.
_writeNumFormat($format, $ifmt)
Writes Excel FORMAT record for non "built-in" numerical formats.
_writeAllStyles()
Write all STYLE records.
_writeNames()
Write the NAME record to define the print area and the repeat rows and cols.
_writeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax)
Store the NAME record in the long format that is used for storing the repeat rows and columns when bo...
_addColor($rgb)
Alter color palette adding a custom color.
_writeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax)
Store the NAME record in the short format that is used for storing the print area, repeat rows only and repeat columns only.
_writeAllFonts()
Store the Excel FONT records.