ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
Excel5.php
Go to the documentation of this file.
1 <?php
37 {
43  private $_phpExcel;
44 
50  private $_str_total = 0;
51 
57  private $_str_unique = 0;
58 
64  private $_str_table = array();
65 
71  private $_colors;
72 
78  private $_parser;
79 
85  private $_IDCLs;
86 
93 
100 
106  public function __construct(PHPExcel $phpExcel) {
107  $this->_phpExcel = $phpExcel;
108 
109  $this->_parser = new PHPExcel_Writer_Excel5_Parser();
110  }
111 
118  public function save($pFilename = null) {
119 
120  // garbage collect
121  $this->_phpExcel->garbageCollect();
122 
123  $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog();
124  PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE);
127 
128  // initialize colors array
129  $this->_colors = array();
130 
131  // Initialise workbook writer
132  $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel,
133  $this->_str_total, $this->_str_unique, $this->_str_table,
134  $this->_colors, $this->_parser);
135 
136  // Initialise worksheet writers
137  $countSheets = $this->_phpExcel->getSheetCount();
138  for ($i = 0; $i < $countSheets; ++$i) {
139  $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_str_total, $this->_str_unique,
140  $this->_str_table, $this->_colors,
141  $this->_parser,
142  $this->_preCalculateFormulas,
143  $this->_phpExcel->getSheet($i));
144  }
145 
146  // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
147  $this->_buildWorksheetEschers();
148  $this->_buildWorkbookEscher();
149 
150  // add 15 identical cell style Xfs
151  // for now, we use the first cellXf instead of cellStyleXf
152  $cellXfCollection = $this->_phpExcel->getCellXfCollection();
153  for ($i = 0; $i < 15; ++$i) {
154  $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true);
155  }
156 
157  // add all the cell Xfs
158  foreach ($this->_phpExcel->getCellXfCollection() as $style) {
159  $this->_writerWorkbook->addXfWriter($style, false);
160  }
161 
162  // add fonts from rich text eleemnts
163  for ($i = 0; $i < $countSheets; ++$i) {
164  foreach ($this->_writerWorksheets[$i]->_phpSheet->getCellCollection() as $cellID) {
165  $cell = $this->_writerWorksheets[$i]->_phpSheet->getCell($cellID);
166  $cVal = $cell->getValue();
167  if ($cVal instanceof PHPExcel_RichText) {
168  $elements = $cVal->getRichTextElements();
169  foreach ($elements as $element) {
170  if ($element instanceof PHPExcel_RichText_Run) {
171  $font = $element->getFont();
172  $this->_writerWorksheets[$i]->_fntHashIndex[$font->getHashCode()] = $this->_writerWorkbook->_addFont($font);
173  }
174  }
175  }
176  }
177  }
178 
179  // initialize OLE file
180  $workbookStreamName = 'Workbook';
181  $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName));
182 
183  // Write the worksheet streams before the global workbook stream,
184  // because the byte sizes of these are needed in the global workbook stream
185  $worksheetSizes = array();
186  for ($i = 0; $i < $countSheets; ++$i) {
187  $this->_writerWorksheets[$i]->close();
188  $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize;
189  }
190 
191  // add binary data for global workbook stream
192  $OLE->append($this->_writerWorkbook->writeWorkbook($worksheetSizes));
193 
194  // add binary data for sheet streams
195  for ($i = 0; $i < $countSheets; ++$i) {
196  $OLE->append($this->_writerWorksheets[$i]->getData());
197  }
198 
199  $this->_documentSummaryInformation = $this->_writeDocumentSummaryInformation();
200  // initialize OLE Document Summary Information
201  if(isset($this->_documentSummaryInformation) && !empty($this->_documentSummaryInformation)){
202  $OLE_DocumentSummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'DocumentSummaryInformation'));
203  $OLE_DocumentSummaryInformation->append($this->_documentSummaryInformation);
204  }
205 
206  $this->_summaryInformation = $this->_writeSummaryInformation();
207  // initialize OLE Summary Information
208  if(isset($this->_summaryInformation) && !empty($this->_summaryInformation)){
209  $OLE_SummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'SummaryInformation'));
210  $OLE_SummaryInformation->append($this->_summaryInformation);
211  }
212 
213  // define OLE Parts
214  $arrRootData = array($OLE);
215  // initialize OLE Properties file
216  if(isset($OLE_SummaryInformation)){
217  $arrRootData[] = $OLE_SummaryInformation;
218  }
219  // initialize OLE Extended Properties file
220  if(isset($OLE_DocumentSummaryInformation)){
221  $arrRootData[] = $OLE_DocumentSummaryInformation;
222  }
223 
224  $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), $arrRootData);
225  // save the OLE file
226  $res = $root->save($pFilename);
227 
229  PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog);
230  }
231 
240  public function setTempDir($pValue = '') {
241  return $this;
242  }
243 
248  private function _buildWorksheetEschers()
249  {
250  // 1-based index to BstoreContainer
251  $blipIndex = 0;
252  $lastReducedSpId = 0;
253  $lastSpId = 0;
254 
255  foreach ($this->_phpExcel->getAllsheets() as $sheet) {
256  // sheet index
257  $sheetIndex = $sheet->getParent()->getIndex($sheet);
258 
259  $escher = null;
260 
261  // check if there are any shapes for this sheet
262  $filterRange = $sheet->getAutoFilter()->getRange();
263  if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) {
264  continue;
265  }
266 
267  // create intermediate Escher object
268  $escher = new PHPExcel_Shared_Escher();
269 
270  // dgContainer
271  $dgContainer = new PHPExcel_Shared_Escher_DgContainer();
272 
273  // set the drawing index (we use sheet index + 1)
274  $dgId = $sheet->getParent()->getIndex($sheet) + 1;
275  $dgContainer->setDgId($dgId);
276  $escher->setDgContainer($dgContainer);
277 
278  // spgrContainer
280  $dgContainer->setSpgrContainer($spgrContainer);
281 
282  // add one shape which is the group shape
284  $spContainer->setSpgr(true);
285  $spContainer->setSpType(0);
286  $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
287  $spgrContainer->addChild($spContainer);
288 
289  // add the shapes
290 
291  $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet
292 
293  foreach ($sheet->getDrawingCollection() as $drawing) {
294  ++$blipIndex;
295 
296  ++$countShapes[$sheetIndex];
297 
298  // add the shape
300 
301  // set the shape type
302  $spContainer->setSpType(0x004B);
303  // set the shape flag
304  $spContainer->setSpFlag(0x02);
305 
306  // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
307  $reducedSpId = $countShapes[$sheetIndex];
308  $spId = $reducedSpId
309  | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
310  $spContainer->setSpId($spId);
311 
312  // keep track of last reducedSpId
313  $lastReducedSpId = $reducedSpId;
314 
315  // keep track of last spId
316  $lastSpId = $spId;
317 
318  // set the BLIP index
319  $spContainer->setOPT(0x4104, $blipIndex);
320 
321  // set coordinates and offsets, client anchor
322  $coordinates = $drawing->getCoordinates();
323  $offsetX = $drawing->getOffsetX();
324  $offsetY = $drawing->getOffsetY();
325  $width = $drawing->getWidth();
326  $height = $drawing->getHeight();
327 
328  $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
329 
330  $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
331  $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
332  $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
333  $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
334  $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
335  $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
336 
337  $spgrContainer->addChild($spContainer);
338  }
339 
340  // AutoFilters
341  if(!empty($filterRange)){
342  $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange);
343  $iNumColStart = $rangeBounds[0][0];
344  $iNumColEnd = $rangeBounds[1][0];
345 
346  $iInc = $iNumColStart;
347  while($iInc <= $iNumColEnd){
348  ++$countShapes[$sheetIndex];
349 
350  // create an Drawing Object for the dropdown
351  $oDrawing = new PHPExcel_Worksheet_BaseDrawing();
352  // get the coordinates of drawing
353  $cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1];
354  $oDrawing->setCoordinates($cDrawing);
355  $oDrawing->setWorksheet($sheet);
356 
357  // add the shape
359  // set the shape type
360  $spContainer->setSpType(0x00C9);
361  // set the shape flag
362  $spContainer->setSpFlag(0x01);
363 
364  // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
365  $reducedSpId = $countShapes[$sheetIndex];
366  $spId = $reducedSpId
367  | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
368  $spContainer->setSpId($spId);
369 
370  // keep track of last reducedSpId
371  $lastReducedSpId = $reducedSpId;
372 
373  // keep track of last spId
374  $lastSpId = $spId;
375 
376  $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
377  $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
378  $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
379  $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
380  $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint
381 
382  // set coordinates and offsets, client anchor
384  $endCoordinates .= $rangeBounds[0][1] + 1;
385 
386  $spContainer->setStartCoordinates($cDrawing);
387  $spContainer->setStartOffsetX(0);
388  $spContainer->setStartOffsetY(0);
389  $spContainer->setEndCoordinates($endCoordinates);
390  $spContainer->setEndOffsetX(0);
391  $spContainer->setEndOffsetY(0);
392 
393  $spgrContainer->addChild($spContainer);
394  $iInc++;
395  }
396  }
397 
398  // identifier clusters, used for workbook Escher object
399  $this->_IDCLs[$dgId] = $lastReducedSpId;
400 
401  // set last shape index
402  $dgContainer->setLastSpId($lastSpId);
403 
404  // set the Escher object
405  $this->_writerWorksheets[$sheetIndex]->setEscher($escher);
406  }
407  }
408 
412  private function _buildWorkbookEscher()
413  {
414  $escher = null;
415 
416  // any drawings in this workbook?
417  $found = false;
418  foreach ($this->_phpExcel->getAllSheets() as $sheet) {
419  if (count($sheet->getDrawingCollection()) > 0) {
420  $found = true;
421  break;
422  }
423  }
424 
425  // nothing to do if there are no drawings
426  if (!$found) {
427  return;
428  }
429 
430  // if we reach here, then there are drawings in the workbook
431  $escher = new PHPExcel_Shared_Escher();
432 
433  // dggContainer
434  $dggContainer = new PHPExcel_Shared_Escher_DggContainer();
435  $escher->setDggContainer($dggContainer);
436 
437  // set IDCLs (identifier clusters)
438  $dggContainer->setIDCLs($this->_IDCLs);
439 
440  // this loop is for determining maximum shape identifier of all drawing
441  $spIdMax = 0;
442  $totalCountShapes = 0;
443  $countDrawings = 0;
444 
445  foreach ($this->_phpExcel->getAllsheets() as $sheet) {
446  $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
447 
448  if (count($sheet->getDrawingCollection()) > 0) {
449  ++$countDrawings;
450 
451  foreach ($sheet->getDrawingCollection() as $drawing) {
452  ++$sheetCountShapes;
453  ++$totalCountShapes;
454 
455  $spId = $sheetCountShapes
456  | ($this->_phpExcel->getIndex($sheet) + 1) << 10;
457  $spIdMax = max($spId, $spIdMax);
458  }
459  }
460  }
461 
462  $dggContainer->setSpIdMax($spIdMax + 1);
463  $dggContainer->setCDgSaved($countDrawings);
464  $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
465 
466  // bstoreContainer
468  $dggContainer->setBstoreContainer($bstoreContainer);
469 
470  // the BSE's (all the images)
471  foreach ($this->_phpExcel->getAllsheets() as $sheet) {
472  foreach ($sheet->getDrawingCollection() as $drawing) {
473  if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
474 
475  $filename = $drawing->getPath();
476 
477  list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);
478 
479  switch ($imageFormat) {
480 
481  case 1: // GIF, not supported by BIFF8, we convert to PNG
483  ob_start();
484  imagepng(imagecreatefromgif($filename));
485  $blipData = ob_get_contents();
486  ob_end_clean();
487  break;
488 
489  case 2: // JPEG
491  $blipData = file_get_contents($filename);
492  break;
493 
494  case 3: // PNG
496  $blipData = file_get_contents($filename);
497  break;
498 
499  case 6: // Windows DIB (BMP), we convert to PNG
501  ob_start();
503  $blipData = ob_get_contents();
504  ob_end_clean();
505  break;
506 
507  default: continue 2;
508 
509  }
510 
512  $blip->setData($blipData);
513 
515  $BSE->setBlipType($blipType);
516  $BSE->setBlip($blip);
517 
518  $bstoreContainer->addBSE($BSE);
519 
520  } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {
521 
522  switch ($drawing->getRenderingFunction()) {
523 
526  $renderingFunction = 'imagejpeg';
527  break;
528 
533  $renderingFunction = 'imagepng';
534  break;
535 
536  }
537 
538  ob_start();
539  call_user_func($renderingFunction, $drawing->getImageResource());
540  $blipData = ob_get_contents();
541  ob_end_clean();
542 
544  $blip->setData($blipData);
545 
547  $BSE->setBlipType($blipType);
548  $BSE->setBlip($blip);
549 
550  $bstoreContainer->addBSE($BSE);
551  }
552  }
553  }
554 
555  // Set the Escher object
556  $this->_writerWorkbook->setEscher($escher);
557  }
558 
564 
565  // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
566  $data = pack('v', 0xFFFE);
567  // offset: 2; size: 2;
568  $data .= pack('v', 0x0000);
569  // offset: 4; size: 2; OS version
570  $data .= pack('v', 0x0106);
571  // offset: 6; size: 2; OS indicator
572  $data .= pack('v', 0x0002);
573  // offset: 8; size: 16
574  $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
575  // offset: 24; size: 4; section count
576  $data .= pack('V', 0x0001);
577 
578  // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae
579  $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9);
580  // offset: 44; size: 4; offset of the start
581  $data .= pack('V', 0x30);
582 
583  // SECTION
584  $dataSection = array();
585  $dataSection_NumProps = 0;
586  $dataSection_Summary = '';
587  $dataSection_Content = '';
588 
589  // GKPIDDSI_CODEPAGE: CodePage
590  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01),
591  'offset' => array('pack' => 'V'),
592  'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer
593  'data' => array('data' => 1252));
594  $dataSection_NumProps++;
595 
596  // GKPIDDSI_CATEGORY : Category
597  if($this->_phpExcel->getProperties()->getCategory()){
598  $dataProp = $this->_phpExcel->getProperties()->getCategory();
599  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02),
600  'offset' => array('pack' => 'V'),
601  'type' => array('pack' => 'V', 'data' => 0x1E),
602  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
603  $dataSection_NumProps++;
604  }
605  // GKPIDDSI_VERSION :Version of the application that wrote the property storage
606  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x17),
607  'offset' => array('pack' => 'V'),
608  'type' => array('pack' => 'V', 'data' => 0x03),
609  'data' => array('pack' => 'V', 'data' => 0x000C0000));
610  $dataSection_NumProps++;
611  // GKPIDDSI_SCALE : FALSE
612  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0B),
613  'offset' => array('pack' => 'V'),
614  'type' => array('pack' => 'V', 'data' => 0x0B),
615  'data' => array('data' => false));
616  $dataSection_NumProps++;
617  // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application
618  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x10),
619  'offset' => array('pack' => 'V'),
620  'type' => array('pack' => 'V', 'data' => 0x0B),
621  'data' => array('data' => false));
622  $dataSection_NumProps++;
623  // GKPIDDSI_SHAREDOC : FALSE
624  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13),
625  'offset' => array('pack' => 'V'),
626  'type' => array('pack' => 'V', 'data' => 0x0B),
627  'data' => array('data' => false));
628  $dataSection_NumProps++;
629  // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application
630  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x16),
631  'offset' => array('pack' => 'V'),
632  'type' => array('pack' => 'V', 'data' => 0x0B),
633  'data' => array('data' => false));
634  $dataSection_NumProps++;
635 
636  // GKPIDDSI_DOCSPARTS
637  // MS-OSHARED p75 (2.3.3.2.2.1)
638  // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9)
639  // cElements
640  $dataProp = pack('v', 0x0001);
641  $dataProp .= pack('v', 0x0000);
642  // array of UnalignedLpstr
643  // cch
644  $dataProp .= pack('v', 0x000A);
645  $dataProp .= pack('v', 0x0000);
646  // value
647  $dataProp .= 'Worksheet'.chr(0);
648 
649  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D),
650  'offset' => array('pack' => 'V'),
651  'type' => array('pack' => 'V', 'data' => 0x101E),
652  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
653  $dataSection_NumProps++;
654 
655  // GKPIDDSI_HEADINGPAIR
656  // VtVecHeadingPairValue
657  // cElements
658  $dataProp = pack('v', 0x0002);
659  $dataProp .= pack('v', 0x0000);
660  // Array of vtHeadingPair
661  // vtUnalignedString - headingString
662  // stringType
663  $dataProp .= pack('v', 0x001E);
664  // padding
665  $dataProp .= pack('v', 0x0000);
666  // UnalignedLpstr
667  // cch
668  $dataProp .= pack('v', 0x0013);
669  $dataProp .= pack('v', 0x0000);
670  // value
671  $dataProp .= 'Feuilles de calcul';
672  // vtUnalignedString - headingParts
673  // wType : 0x0003 = 32 bit signed integer
674  $dataProp .= pack('v', 0x0300);
675  // padding
676  $dataProp .= pack('v', 0x0000);
677  // value
678  $dataProp .= pack('v', 0x0100);
679  $dataProp .= pack('v', 0x0000);
680  $dataProp .= pack('v', 0x0000);
681  $dataProp .= pack('v', 0x0000);
682 
683  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C),
684  'offset' => array('pack' => 'V'),
685  'type' => array('pack' => 'V', 'data' => 0x100C),
686  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
687  $dataSection_NumProps++;
688 
689  // 4 Section Length
690  // 4 Property count
691  // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4))
692  $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
693  foreach ($dataSection as $dataProp){
694  // Summary
695  $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
696  // Offset
697  $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
698  // DataType
699  $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
700  // Data
701  if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer
702  $dataSection_Content .= pack('V', $dataProp['data']['data']);
703 
704  $dataSection_Content_Offset += 4 + 4;
705  }
706  elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer
707  $dataSection_Content .= pack('V', $dataProp['data']['data']);
708 
709  $dataSection_Content_Offset += 4 + 4;
710  }
711  elseif($dataProp['type']['data'] == 0x0B){ // Boolean
712  if($dataProp['data']['data'] == false){
713  $dataSection_Content .= pack('V', 0x0000);
714  } else {
715  $dataSection_Content .= pack('V', 0x0001);
716  }
717  $dataSection_Content_Offset += 4 + 4;
718  }
719  elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length
720  // Null-terminated string
721  $dataProp['data']['data'] .= chr(0);
722  $dataProp['data']['length'] += 1;
723  // Complete the string with null string for being a %4
724  $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4));
725  $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
726 
727  $dataSection_Content .= pack('V', $dataProp['data']['length']);
728  $dataSection_Content .= $dataProp['data']['data'];
729 
730  $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
731  }
732  elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
733  $dataSection_Content .= $dataProp['data']['data'];
734 
735  $dataSection_Content_Offset += 4 + 8;
736  }
737  else {
738  // Data Type Not Used at the moment
739  $dataSection_Content .= $dataProp['data']['data'];
740 
741  $dataSection_Content_Offset += 4 + $dataProp['data']['length'];
742  }
743  }
744  // Now $dataSection_Content_Offset contains the size of the content
745 
746  // section header
747  // offset: $secOffset; size: 4; section length
748  // + x Size of the content (summary + content)
749  $data .= pack('V', $dataSection_Content_Offset);
750  // offset: $secOffset+4; size: 4; property count
751  $data .= pack('V', $dataSection_NumProps);
752  // Section Summary
753  $data .= $dataSection_Summary;
754  // Section Content
755  $data .= $dataSection_Content;
756 
757  return $data;
758  }
759 
764  private function _writeSummaryInformation(){
765  // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
766  $data = pack('v', 0xFFFE);
767  // offset: 2; size: 2;
768  $data .= pack('v', 0x0000);
769  // offset: 4; size: 2; OS version
770  $data .= pack('v', 0x0106);
771  // offset: 6; size: 2; OS indicator
772  $data .= pack('v', 0x0002);
773  // offset: 8; size: 16
774  $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
775  // offset: 24; size: 4; section count
776  $data .= pack('V', 0x0001);
777 
778  // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9
779  $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3);
780  // offset: 44; size: 4; offset of the start
781  $data .= pack('V', 0x30);
782 
783  // SECTION
784  $dataSection = array();
785  $dataSection_NumProps = 0;
786  $dataSection_Summary = '';
787  $dataSection_Content = '';
788 
789  // CodePage : CP-1252
790  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01),
791  'offset' => array('pack' => 'V'),
792  'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer
793  'data' => array('data' => 1252));
794  $dataSection_NumProps++;
795 
796  // Title
797  if($this->_phpExcel->getProperties()->getTitle()){
798  $dataProp = $this->_phpExcel->getProperties()->getTitle();
799  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02),
800  'offset' => array('pack' => 'V'),
801  'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length
802  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
803  $dataSection_NumProps++;
804  }
805  // Subject
806  if($this->_phpExcel->getProperties()->getSubject()){
807  $dataProp = $this->_phpExcel->getProperties()->getSubject();
808  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x03),
809  'offset' => array('pack' => 'V'),
810  'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length
811  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
812  $dataSection_NumProps++;
813  }
814  // Author (Creator)
815  if($this->_phpExcel->getProperties()->getCreator()){
816  $dataProp = $this->_phpExcel->getProperties()->getCreator();
817  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x04),
818  'offset' => array('pack' => 'V'),
819  'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length
820  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
821  $dataSection_NumProps++;
822  }
823  // Keywords
824  if($this->_phpExcel->getProperties()->getKeywords()){
825  $dataProp = $this->_phpExcel->getProperties()->getKeywords();
826  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x05),
827  'offset' => array('pack' => 'V'),
828  'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length
829  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
830  $dataSection_NumProps++;
831  }
832  // Comments (Description)
833  if($this->_phpExcel->getProperties()->getDescription()){
834  $dataProp = $this->_phpExcel->getProperties()->getDescription();
835  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x06),
836  'offset' => array('pack' => 'V'),
837  'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length
838  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
839  $dataSection_NumProps++;
840  }
841  // Last Saved By (LastModifiedBy)
842  if($this->_phpExcel->getProperties()->getLastModifiedBy()){
843  $dataProp = $this->_phpExcel->getProperties()->getLastModifiedBy();
844  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x08),
845  'offset' => array('pack' => 'V'),
846  'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length
847  'data' => array('data' => $dataProp, 'length' => strlen($dataProp)));
848  $dataSection_NumProps++;
849  }
850  // Created Date/Time
851  if($this->_phpExcel->getProperties()->getCreated()){
852  $dataProp = $this->_phpExcel->getProperties()->getCreated();
853  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C),
854  'offset' => array('pack' => 'V'),
855  'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
856  'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp)));
857  $dataSection_NumProps++;
858  }
859  // Modified Date/Time
860  if($this->_phpExcel->getProperties()->getModified()){
861  $dataProp = $this->_phpExcel->getProperties()->getModified();
862  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D),
863  'offset' => array('pack' => 'V'),
864  'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
865  'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp)));
866  $dataSection_NumProps++;
867  }
868  // Security
869  $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13),
870  'offset' => array('pack' => 'V'),
871  'type' => array('pack' => 'V', 'data' => 0x03), // 4 byte signed integer
872  'data' => array('data' => 0x00));
873  $dataSection_NumProps++;
874 
875 
876  // 4 Section Length
877  // 4 Property count
878  // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4))
879  $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
880  foreach ($dataSection as $dataProp){
881  // Summary
882  $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
883  // Offset
884  $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
885  // DataType
886  $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
887  // Data
888  if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer
889  $dataSection_Content .= pack('V', $dataProp['data']['data']);
890 
891  $dataSection_Content_Offset += 4 + 4;
892  }
893  elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer
894  $dataSection_Content .= pack('V', $dataProp['data']['data']);
895 
896  $dataSection_Content_Offset += 4 + 4;
897  }
898  elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length
899  // Null-terminated string
900  $dataProp['data']['data'] .= chr(0);
901  $dataProp['data']['length'] += 1;
902  // Complete the string with null string for being a %4
903  $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4));
904  $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
905 
906  $dataSection_Content .= pack('V', $dataProp['data']['length']);
907  $dataSection_Content .= $dataProp['data']['data'];
908 
909  $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
910  }
911  elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
912  $dataSection_Content .= $dataProp['data']['data'];
913 
914  $dataSection_Content_Offset += 4 + 8;
915  }
916  else {
917  // Data Type Not Used at the moment
918  }
919  }
920  // Now $dataSection_Content_Offset contains the size of the content
921 
922  // section header
923  // offset: $secOffset; size: 4; section length
924  // + x Size of the content (summary + content)
925  $data .= pack('V', $dataSection_Content_Offset);
926  // offset: $secOffset+4; size: 4; property count
927  $data .= pack('V', $dataSection_NumProps);
928  // Section Summary
929  $data .= $dataSection_Summary;
930  // Section Content
931  $data .= $dataSection_Content;
932 
933  return $data;
934  }
935 }
static Asc2Ucs($ascii)
Utility function to transform ASCII text to Unicode.
Definition: OLE.php:446
__construct(PHPExcel $phpExcel)
Create a new PHPExcel_Writer_Excel5.
Definition: Excel5.php:106
_buildWorksheetEschers()
Build the Worksheet Escher objects.
Definition: Excel5.php:248
$style
Definition: example_012.php:70
save($pFilename=null)
Save PHPExcel to file.
Definition: Excel5.php:118
static rangeBoundaries($pRange='A1:A1')
Calculate range boundaries.
Definition: Cell.php:707
static oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height)
Convert 1-cell anchor coordinates to 2-cell anchor coordinates This function is ported from PEAR Spre...
Definition: Excel5.php:245
static imagecreatefrombmp($p_sFile)
Create a new image from file.
Definition: Drawing.php:179
Create styles array
The data for the language used.
_buildWorkbookEscher()
Build the Escher object corresponding to the MSODRAWINGGROUP record.
Definition: Excel5.php:412
static setReturnDateType($returnDateType)
Definition: Functions.php:155
static getInstance(PHPExcel $workbook=NULL)
Get an instance of this class.
static stringFromColumnIndex($pColumnIndex=0)
String from columnindex.
Definition: Cell.php:825
setTempDir($pValue='')
Set temporary storage directory.
Definition: Excel5.php:240
_writeSummaryInformation()
Build the OLE Part for Summary Information.
Definition: Excel5.php:764
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
_writeDocumentSummaryInformation()
Build the OLE Part for DocumentSummary Information.
Definition: Excel5.php:563
static LocalDate2OLE($date=null)
Utility function Returns a string for the OLE container with the date given.
Definition: OLE.php:464