ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
PhpOffice\PhpSpreadsheet\Writer\Xls Class Reference
+ Inheritance diagram for PhpOffice\PhpSpreadsheet\Writer\Xls:
+ Collaboration diagram for PhpOffice\PhpSpreadsheet\Writer\Xls:

Public Member Functions

 __construct (Spreadsheet $spreadsheet)
 Create a new Xls Writer. More...
 
 save ($pFilename)
 Save Spreadsheet to file. More...
 
- Public Member Functions inherited from PhpOffice\PhpSpreadsheet\Writer\BaseWriter
 getIncludeCharts ()
 Write charts in workbook? If this is true, then the Writer will write definitions for any charts that exist in the PhpSpreadsheet object. More...
 
 setIncludeCharts ($pValue)
 Set write charts in workbook Set to true, to advise the Writer to include any charts that exist in the PhpSpreadsheet object. More...
 
 getPreCalculateFormulas ()
 Get Pre-Calculate Formulas flag If this is true (the default), then the writer will recalculate all formulae in a workbook when saving, so that the pre-calculated values are immediately available to MS Excel or other office spreadsheet viewer when opening the file If false, then formulae are not calculated on save. More...
 
 setPreCalculateFormulas ($pValue)
 Set Pre-Calculate Formulas Set to true (the default) to advise the Writer to calculate all formulae on save Set to false to prevent precalculation of formulae on save. More...
 
 getUseDiskCaching ()
 Get use disk caching where possible? More...
 
 setUseDiskCaching ($pValue, $pDirectory=null)
 Set use disk caching where possible? More...
 
 getDiskCachingDirectory ()
 Get disk caching directory. More...
 
 openFileHandle ($filename)
 Open file handle. More...
 

Private Member Functions

 buildWorksheetEschers ()
 Build the Worksheet Escher objects. More...
 
 processMemoryDrawing (BstoreContainer &$bstoreContainer, MemoryDrawing $drawing, string $renderingFunctionx)
 
 processDrawing (BstoreContainer &$bstoreContainer, Drawing $drawing)
 
 processBaseDrawing (BstoreContainer &$bstoreContainer, BaseDrawing $drawing)
 
 checkForDrawings ()
 
 buildWorkbookEscher ()
 Build the Escher object corresponding to the MSODRAWINGGROUP record. More...
 
 writeDocumentSummaryInformation ()
 Build the OLE Part for DocumentSummary Information. More...
 
 writeSummaryPropOle ($dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata)
 
 writeSummaryProp (string $dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata)
 
 writeSummaryInformation ()
 Build the OLE Part for Summary Information. More...
 

Private Attributes

 $spreadsheet
 
 $strTotal = 0
 
 $strUnique = 0
 
 $strTable = []
 
 $colors
 
 $parser
 
 $IDCLs
 
 $summaryInformation
 
 $documentSummaryInformation
 
 $writerWorkbook
 
 $writerWorksheets
 

Additional Inherited Members

- Protected Member Functions inherited from PhpOffice\PhpSpreadsheet\Writer\BaseWriter
 maybeCloseFileHandle ()
 Close file handle only if we opened it ourselves. More...
 
- Protected Attributes inherited from PhpOffice\PhpSpreadsheet\Writer\BaseWriter
 $includeCharts = false
 
 $preCalculateFormulas = true
 
 $fileHandle
 

Detailed Description

Definition at line 30 of file Xls.php.

Constructor & Destructor Documentation

◆ __construct()

PhpOffice\PhpSpreadsheet\Writer\Xls::__construct ( Spreadsheet  $spreadsheet)

Create a new Xls Writer.

Parameters
Spreadsheet$spreadsheetPhpSpreadsheet object

Implements PhpOffice\PhpSpreadsheet\Writer\IWriter.

Definition at line 110 of file Xls.php.

References PhpOffice\PhpSpreadsheet\Writer\Xls\$spreadsheet.

111  {
112  $this->spreadsheet = $spreadsheet;
113 
114  $this->parser = new Xls\Parser($spreadsheet);
115  }

Member Function Documentation

◆ buildWorkbookEscher()

PhpOffice\PhpSpreadsheet\Writer\Xls::buildWorkbookEscher ( )
private

Build the Escher object corresponding to the MSODRAWINGGROUP record.

Definition at line 500 of file Xls.php.

References PhpOffice\PhpSpreadsheet\Writer\Xls\checkForDrawings(), and PhpOffice\PhpSpreadsheet\Writer\Xls\processBaseDrawing().

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\save().

500  : void
501  {
502  // nothing to do if there are no drawings
503  if (!$this->checkForDrawings()) {
504  return;
505  }
506 
507  // if we reach here, then there are drawings in the workbook
508  $escher = new Escher();
509 
510  // dggContainer
511  $dggContainer = new DggContainer();
512  $escher->setDggContainer($dggContainer);
513 
514  // set IDCLs (identifier clusters)
515  $dggContainer->setIDCLs($this->IDCLs);
516 
517  // this loop is for determining maximum shape identifier of all drawing
518  $spIdMax = 0;
519  $totalCountShapes = 0;
520  $countDrawings = 0;
521 
522  foreach ($this->spreadsheet->getAllsheets() as $sheet) {
523  $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
524 
525  $addCount = 0;
526  foreach ($sheet->getDrawingCollection() as $drawing) {
527  $addCount = 1;
528  ++$sheetCountShapes;
529  ++$totalCountShapes;
530 
531  $spId = $sheetCountShapes | ($this->spreadsheet->getIndex($sheet) + 1) << 10;
532  $spIdMax = max($spId, $spIdMax);
533  }
534  $countDrawings += $addCount;
535  }
536 
537  $dggContainer->setSpIdMax($spIdMax + 1);
538  $dggContainer->setCDgSaved($countDrawings);
539  $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
540 
541  // bstoreContainer
542  $bstoreContainer = new BstoreContainer();
543  $dggContainer->setBstoreContainer($bstoreContainer);
544 
545  // the BSE's (all the images)
546  foreach ($this->spreadsheet->getAllsheets() as $sheet) {
547  foreach ($sheet->getDrawingCollection() as $drawing) {
548  $this->processBaseDrawing($bstoreContainer, $drawing);
549  }
550  }
551 
552  // Set the Escher object
553  $this->writerWorkbook->setEscher($escher);
554  }
processBaseDrawing(BstoreContainer &$bstoreContainer, BaseDrawing $drawing)
Definition: Xls.php:473
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildWorksheetEschers()

PhpOffice\PhpSpreadsheet\Writer\Xls::buildWorksheetEschers ( )
private

Build the Worksheet Escher objects.

Definition at line 236 of file Xls.php.

References PhpOffice\PhpSpreadsheet\Shared\Xls\oneAnchor2twoAnchor(), PhpOffice\PhpSpreadsheet\Cell\Coordinate\rangeBoundaries(), and PhpOffice\PhpSpreadsheet\Cell\Coordinate\stringFromColumnIndex().

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\save().

236  : void
237  {
238  // 1-based index to BstoreContainer
239  $blipIndex = 0;
240  $lastReducedSpId = 0;
241  $lastSpId = 0;
242 
243  foreach ($this->spreadsheet->getAllsheets() as $sheet) {
244  // sheet index
245  $sheetIndex = $sheet->getParent()->getIndex($sheet);
246 
247  $escher = null;
248 
249  // check if there are any shapes for this sheet
250  $filterRange = $sheet->getAutoFilter()->getRange();
251  if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) {
252  continue;
253  }
254 
255  // create intermediate Escher object
256  $escher = new Escher();
257 
258  // dgContainer
259  $dgContainer = new DgContainer();
260 
261  // set the drawing index (we use sheet index + 1)
262  $dgId = $sheet->getParent()->getIndex($sheet) + 1;
263  $dgContainer->setDgId($dgId);
264  $escher->setDgContainer($dgContainer);
265 
266  // spgrContainer
267  $spgrContainer = new SpgrContainer();
268  $dgContainer->setSpgrContainer($spgrContainer);
269 
270  // add one shape which is the group shape
271  $spContainer = new SpContainer();
272  $spContainer->setSpgr(true);
273  $spContainer->setSpType(0);
274  $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
275  $spgrContainer->addChild($spContainer);
276 
277  // add the shapes
278 
279  $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet
280 
281  foreach ($sheet->getDrawingCollection() as $drawing) {
282  ++$blipIndex;
283 
284  ++$countShapes[$sheetIndex];
285 
286  // add the shape
287  $spContainer = new SpContainer();
288 
289  // set the shape type
290  $spContainer->setSpType(0x004B);
291  // set the shape flag
292  $spContainer->setSpFlag(0x02);
293 
294  // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
295  $reducedSpId = $countShapes[$sheetIndex];
296  $spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
297  $spContainer->setSpId($spId);
298 
299  // keep track of last reducedSpId
300  $lastReducedSpId = $reducedSpId;
301 
302  // keep track of last spId
303  $lastSpId = $spId;
304 
305  // set the BLIP index
306  $spContainer->setOPT(0x4104, $blipIndex);
307 
308  // set coordinates and offsets, client anchor
309  $coordinates = $drawing->getCoordinates();
310  $offsetX = $drawing->getOffsetX();
311  $offsetY = $drawing->getOffsetY();
312  $width = $drawing->getWidth();
313  $height = $drawing->getHeight();
314 
315  $twoAnchor = \PhpOffice\PhpSpreadsheet\Shared\Xls::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
316 
317  $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
318  $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
319  $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
320  $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
321  $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
322  $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
323 
324  $spgrContainer->addChild($spContainer);
325  }
326 
327  // AutoFilters
328  if (!empty($filterRange)) {
329  $rangeBounds = Coordinate::rangeBoundaries($filterRange);
330  $iNumColStart = $rangeBounds[0][0];
331  $iNumColEnd = $rangeBounds[1][0];
332 
333  $iInc = $iNumColStart;
334  while ($iInc <= $iNumColEnd) {
335  ++$countShapes[$sheetIndex];
336 
337  // create an Drawing Object for the dropdown
338  $oDrawing = new BaseDrawing();
339  // get the coordinates of drawing
340  $cDrawing = Coordinate::stringFromColumnIndex($iInc) . $rangeBounds[0][1];
341  $oDrawing->setCoordinates($cDrawing);
342  $oDrawing->setWorksheet($sheet);
343 
344  // add the shape
345  $spContainer = new SpContainer();
346  // set the shape type
347  $spContainer->setSpType(0x00C9);
348  // set the shape flag
349  $spContainer->setSpFlag(0x01);
350 
351  // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
352  $reducedSpId = $countShapes[$sheetIndex];
353  $spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
354  $spContainer->setSpId($spId);
355 
356  // keep track of last reducedSpId
357  $lastReducedSpId = $reducedSpId;
358 
359  // keep track of last spId
360  $lastSpId = $spId;
361 
362  $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
363  $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
364  $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
365  $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
366  $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint
367 
368  // set coordinates and offsets, client anchor
369  $endCoordinates = Coordinate::stringFromColumnIndex($iInc);
370  $endCoordinates .= $rangeBounds[0][1] + 1;
371 
372  $spContainer->setStartCoordinates($cDrawing);
373  $spContainer->setStartOffsetX(0);
374  $spContainer->setStartOffsetY(0);
375  $spContainer->setEndCoordinates($endCoordinates);
376  $spContainer->setEndOffsetX(0);
377  $spContainer->setEndOffsetY(0);
378 
379  $spgrContainer->addChild($spContainer);
380  ++$iInc;
381  }
382  }
383 
384  // identifier clusters, used for workbook Escher object
385  $this->IDCLs[$dgId] = $lastReducedSpId;
386 
387  // set last shape index
388  $dgContainer->setLastSpId($lastSpId);
389 
390  // set the Escher object
391  $this->writerWorksheets[$sheetIndex]->setEscher($escher);
392  }
393  }
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: Xls.php:210
static rangeBoundaries($pRange)
Calculate range boundaries.
Definition: Coordinate.php:187
static stringFromColumnIndex($columnIndex)
String from column index.
Definition: Coordinate.php:313
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkForDrawings()

PhpOffice\PhpSpreadsheet\Writer\Xls::checkForDrawings ( )
private

Definition at line 482 of file Xls.php.

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\buildWorkbookEscher().

482  : bool
483  {
484  // any drawings in this workbook?
485  $found = false;
486  foreach ($this->spreadsheet->getAllSheets() as $sheet) {
487  if (count($sheet->getDrawingCollection()) > 0) {
488  $found = true;
489 
490  break;
491  }
492  }
493 
494  return $found;
495  }
+ Here is the caller graph for this function:

◆ processBaseDrawing()

PhpOffice\PhpSpreadsheet\Writer\Xls::processBaseDrawing ( BstoreContainer $bstoreContainer,
BaseDrawing  $drawing 
)
private

Definition at line 473 of file Xls.php.

References PhpOffice\PhpSpreadsheet\Writer\Xls\processDrawing(), and PhpOffice\PhpSpreadsheet\Writer\Xls\processMemoryDrawing().

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\buildWorkbookEscher().

473  : void
474  {
475  if ($drawing instanceof Drawing) {
476  $this->processDrawing($bstoreContainer, $drawing);
477  } elseif ($drawing instanceof MemoryDrawing) {
478  $this->processMemoryDrawing($bstoreContainer, $drawing, $drawing->getRenderingFunction());
479  }
480  }
processDrawing(BstoreContainer &$bstoreContainer, Drawing $drawing)
Definition: Xls.php:425
processMemoryDrawing(BstoreContainer &$bstoreContainer, MemoryDrawing $drawing, string $renderingFunctionx)
Definition: Xls.php:395
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ processDrawing()

PhpOffice\PhpSpreadsheet\Writer\Xls::processDrawing ( BstoreContainer $bstoreContainer,
Drawing  $drawing 
)
private

Definition at line 425 of file Xls.php.

References $filename, PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\addBSE(), PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\BLIPTYPE_JPEG, PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\BLIPTYPE_PNG, and PhpOffice\PhpSpreadsheet\Worksheet\Drawing\getPath().

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\processBaseDrawing().

425  : void
426  {
427  $blipType = null;
428  $blipData = '';
429  $filename = $drawing->getPath();
430 
431  [$imagesx, $imagesy, $imageFormat] = getimagesize($filename);
432 
433  switch ($imageFormat) {
434  case 1: // GIF, not supported by BIFF8, we convert to PNG
435  $blipType = BSE::BLIPTYPE_PNG;
436  ob_start();
437  imagepng(imagecreatefromgif($filename));
438  $blipData = ob_get_contents();
439  ob_end_clean();
440 
441  break;
442  case 2: // JPEG
443  $blipType = BSE::BLIPTYPE_JPEG;
444  $blipData = file_get_contents($filename);
445 
446  break;
447  case 3: // PNG
448  $blipType = BSE::BLIPTYPE_PNG;
449  $blipData = file_get_contents($filename);
450 
451  break;
452  case 6: // Windows DIB (BMP), we convert to PNG
453  $blipType = BSE::BLIPTYPE_PNG;
454  ob_start();
455  imagepng(SharedDrawing::imagecreatefrombmp($filename));
456  $blipData = ob_get_contents();
457  ob_end_clean();
458 
459  break;
460  }
461  if ($blipData) {
462  $blip = new Blip();
463  $blip->setData($blipData);
464 
465  $BSE = new BSE();
466  $BSE->setBlipType($blipType);
467  $BSE->setBlip($blip);
468 
469  $bstoreContainer->addBSE($BSE);
470  }
471  }
$filename
Definition: buildRTE.php:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ processMemoryDrawing()

PhpOffice\PhpSpreadsheet\Writer\Xls::processMemoryDrawing ( BstoreContainer $bstoreContainer,
MemoryDrawing  $drawing,
string  $renderingFunctionx 
)
private

Definition at line 395 of file Xls.php.

References PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\addBSE(), PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\BLIPTYPE_JPEG, PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\BLIPTYPE_PNG, PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing\getImageResource(), and PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing\RENDERING_JPEG.

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\processBaseDrawing().

395  : void
396  {
397  switch ($renderingFunctionx) {
399  $blipType = BSE::BLIPTYPE_JPEG;
400  $renderingFunction = 'imagejpeg';
401 
402  break;
403  default:
404  $blipType = BSE::BLIPTYPE_PNG;
405  $renderingFunction = 'imagepng';
406 
407  break;
408  }
409 
410  ob_start();
411  call_user_func($renderingFunction, $drawing->getImageResource());
412  $blipData = ob_get_contents();
413  ob_end_clean();
414 
415  $blip = new Blip();
416  $blip->setData($blipData);
417 
418  $BSE = new BSE();
419  $BSE->setBlipType($blipType);
420  $BSE->setBlip($blip);
421 
422  $bstoreContainer->addBSE($BSE);
423  }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save()

PhpOffice\PhpSpreadsheet\Writer\Xls::save (   $pFilename)

Save Spreadsheet to file.

Parameters
resource | string$pFilename

Implements PhpOffice\PhpSpreadsheet\Writer\IWriter.

Definition at line 122 of file Xls.php.

References $i, $root, $style, $time, PhpOffice\PhpSpreadsheet\Shared\OLE\ascToUcs(), PhpOffice\PhpSpreadsheet\Writer\Xls\buildWorkbookEscher(), PhpOffice\PhpSpreadsheet\Writer\Xls\buildWorksheetEschers(), PhpOffice\PhpSpreadsheet\Calculation\Calculation\getInstance(), PhpOffice\PhpSpreadsheet\Calculation\Functions\getReturnDateType(), PhpOffice\PhpSpreadsheet\Writer\BaseWriter\maybeCloseFileHandle(), PhpOffice\PhpSpreadsheet\Writer\BaseWriter\openFileHandle(), PhpOffice\PhpSpreadsheet\Calculation\Functions\RETURNDATE_EXCEL, PhpOffice\PhpSpreadsheet\Calculation\Functions\setReturnDateType(), PhpOffice\PhpSpreadsheet\Writer\Xls\writeDocumentSummaryInformation(), and PhpOffice\PhpSpreadsheet\Writer\Xls\writeSummaryInformation().

122  : void
123  {
124  // garbage collect
125  $this->spreadsheet->garbageCollect();
126 
127  $saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
128  Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
129  $saveDateReturnType = Functions::getReturnDateType();
131 
132  // initialize colors array
133  $this->colors = [];
134 
135  // Initialise workbook writer
136  $this->writerWorkbook = new Xls\Workbook($this->spreadsheet, $this->strTotal, $this->strUnique, $this->strTable, $this->colors, $this->parser);
137 
138  // Initialise worksheet writers
139  $countSheets = $this->spreadsheet->getSheetCount();
140  for ($i = 0; $i < $countSheets; ++$i) {
141  $this->writerWorksheets[$i] = new Xls\Worksheet($this->strTotal, $this->strUnique, $this->strTable, $this->colors, $this->parser, $this->preCalculateFormulas, $this->spreadsheet->getSheet($i));
142  }
143 
144  // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
145  $this->buildWorksheetEschers();
146  $this->buildWorkbookEscher();
147 
148  // add 15 identical cell style Xfs
149  // for now, we use the first cellXf instead of cellStyleXf
150  $cellXfCollection = $this->spreadsheet->getCellXfCollection();
151  for ($i = 0; $i < 15; ++$i) {
152  $this->writerWorkbook->addXfWriter($cellXfCollection[0], true);
153  }
154 
155  // add all the cell Xfs
156  foreach ($this->spreadsheet->getCellXfCollection() as $style) {
157  $this->writerWorkbook->addXfWriter($style, false);
158  }
159 
160  // add fonts from rich text eleemnts
161  for ($i = 0; $i < $countSheets; ++$i) {
162  foreach ($this->writerWorksheets[$i]->phpSheet->getCoordinates() as $coordinate) {
163  $cell = $this->writerWorksheets[$i]->phpSheet->getCell($coordinate);
164  $cVal = $cell->getValue();
165  if ($cVal instanceof RichText) {
166  $elements = $cVal->getRichTextElements();
167  foreach ($elements as $element) {
168  if ($element instanceof Run) {
169  $font = $element->getFont();
170  $this->writerWorksheets[$i]->fontHashIndex[$font->getHashCode()] = $this->writerWorkbook->addFont($font);
171  }
172  }
173  }
174  }
175  }
176 
177  // initialize OLE file
178  $workbookStreamName = 'Workbook';
179  $OLE = new File(OLE::ascToUcs($workbookStreamName));
180 
181  // Write the worksheet streams before the global workbook stream,
182  // because the byte sizes of these are needed in the global workbook stream
183  $worksheetSizes = [];
184  for ($i = 0; $i < $countSheets; ++$i) {
185  $this->writerWorksheets[$i]->close();
186  $worksheetSizes[] = $this->writerWorksheets[$i]->_datasize;
187  }
188 
189  // add binary data for global workbook stream
190  $OLE->append($this->writerWorkbook->writeWorkbook($worksheetSizes));
191 
192  // add binary data for sheet streams
193  for ($i = 0; $i < $countSheets; ++$i) {
194  $OLE->append($this->writerWorksheets[$i]->getData());
195  }
196 
197  $this->documentSummaryInformation = $this->writeDocumentSummaryInformation();
198  // initialize OLE Document Summary Information
199  if (isset($this->documentSummaryInformation) && !empty($this->documentSummaryInformation)) {
200  $OLE_DocumentSummaryInformation = new File(OLE::ascToUcs(chr(5) . 'DocumentSummaryInformation'));
201  $OLE_DocumentSummaryInformation->append($this->documentSummaryInformation);
202  }
203 
204  $this->summaryInformation = $this->writeSummaryInformation();
205  // initialize OLE Summary Information
206  if (isset($this->summaryInformation) && !empty($this->summaryInformation)) {
207  $OLE_SummaryInformation = new File(OLE::ascToUcs(chr(5) . 'SummaryInformation'));
208  $OLE_SummaryInformation->append($this->summaryInformation);
209  }
210 
211  // define OLE Parts
212  $arrRootData = [$OLE];
213  // initialize OLE Properties file
214  if (isset($OLE_SummaryInformation)) {
215  $arrRootData[] = $OLE_SummaryInformation;
216  }
217  // initialize OLE Extended Properties file
218  if (isset($OLE_DocumentSummaryInformation)) {
219  $arrRootData[] = $OLE_DocumentSummaryInformation;
220  }
221 
222  $time = $this->spreadsheet->getProperties()->getModified();
223  $root = new Root($time, $time, $arrRootData);
224  // save the OLE file
225  $this->openFileHandle($pFilename);
226  $root->save($this->fileHandle);
227  $this->maybeCloseFileHandle();
228 
229  Functions::setReturnDateType($saveDateReturnType);
230  Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
231  }
$style
Definition: example_012.php:70
static getReturnDateType()
Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object).
Definition: Functions.php:133
static ascToUcs($ascii)
Utility function to transform ASCII text to Unicode.
Definition: OLE.php:478
writeDocumentSummaryInformation()
Build the OLE Part for DocumentSummary Information.
Definition: Xls.php:561
static setReturnDateType($returnDateType)
Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric o...
Definition: Functions.php:109
$time
Definition: cron.php:21
writeSummaryInformation()
Build the OLE Part for Summary Information.
Definition: Xls.php:803
$root
Definition: sabredav.php:45
static getInstance(?Spreadsheet $spreadsheet=null)
Get an instance of this class.
$i
Definition: disco.tpl.php:19
buildWorkbookEscher()
Build the Escher object corresponding to the MSODRAWINGGROUP record.
Definition: Xls.php:500
openFileHandle($filename)
Open file handle.
Definition: BaseWriter.php:102
buildWorksheetEschers()
Build the Worksheet Escher objects.
Definition: Xls.php:236
maybeCloseFileHandle()
Close file handle only if we opened it ourselves.
Definition: BaseWriter.php:123
+ Here is the call graph for this function:

◆ writeDocumentSummaryInformation()

PhpOffice\PhpSpreadsheet\Writer\Xls::writeDocumentSummaryInformation ( )
private

Build the OLE Part for DocumentSummary Information.

Returns
string

Definition at line 561 of file Xls.php.

References $data.

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\save().

562  {
563  // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
564  $data = pack('v', 0xFFFE);
565  // offset: 2; size: 2;
566  $data .= pack('v', 0x0000);
567  // offset: 4; size: 2; OS version
568  $data .= pack('v', 0x0106);
569  // offset: 6; size: 2; OS indicator
570  $data .= pack('v', 0x0002);
571  // offset: 8; size: 16
572  $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
573  // offset: 24; size: 4; section count
574  $data .= pack('V', 0x0001);
575 
576  // 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
577  $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9);
578  // offset: 44; size: 4; offset of the start
579  $data .= pack('V', 0x30);
580 
581  // SECTION
582  $dataSection = [];
583  $dataSection_NumProps = 0;
584  $dataSection_Summary = '';
585  $dataSection_Content = '';
586 
587  // GKPIDDSI_CODEPAGE: CodePage
588  $dataSection[] = [
589  'summary' => ['pack' => 'V', 'data' => 0x01],
590  'offset' => ['pack' => 'V'],
591  'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
592  'data' => ['data' => 1252],
593  ];
594  ++$dataSection_NumProps;
595 
596  // GKPIDDSI_CATEGORY : Category
597  $dataProp = $this->spreadsheet->getProperties()->getCategory();
598  if ($dataProp) {
599  $dataSection[] = [
600  'summary' => ['pack' => 'V', 'data' => 0x02],
601  'offset' => ['pack' => 'V'],
602  'type' => ['pack' => 'V', 'data' => 0x1E],
603  'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
604  ];
605  ++$dataSection_NumProps;
606  }
607  // GKPIDDSI_VERSION :Version of the application that wrote the property storage
608  $dataSection[] = [
609  'summary' => ['pack' => 'V', 'data' => 0x17],
610  'offset' => ['pack' => 'V'],
611  'type' => ['pack' => 'V', 'data' => 0x03],
612  'data' => ['pack' => 'V', 'data' => 0x000C0000],
613  ];
614  ++$dataSection_NumProps;
615  // GKPIDDSI_SCALE : FALSE
616  $dataSection[] = [
617  'summary' => ['pack' => 'V', 'data' => 0x0B],
618  'offset' => ['pack' => 'V'],
619  'type' => ['pack' => 'V', 'data' => 0x0B],
620  'data' => ['data' => false],
621  ];
622  ++$dataSection_NumProps;
623  // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application
624  $dataSection[] = [
625  'summary' => ['pack' => 'V', 'data' => 0x10],
626  'offset' => ['pack' => 'V'],
627  'type' => ['pack' => 'V', 'data' => 0x0B],
628  'data' => ['data' => false],
629  ];
630  ++$dataSection_NumProps;
631  // GKPIDDSI_SHAREDOC : FALSE
632  $dataSection[] = [
633  'summary' => ['pack' => 'V', 'data' => 0x13],
634  'offset' => ['pack' => 'V'],
635  'type' => ['pack' => 'V', 'data' => 0x0B],
636  'data' => ['data' => false],
637  ];
638  ++$dataSection_NumProps;
639  // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application
640  $dataSection[] = [
641  'summary' => ['pack' => 'V', 'data' => 0x16],
642  'offset' => ['pack' => 'V'],
643  'type' => ['pack' => 'V', 'data' => 0x0B],
644  'data' => ['data' => false],
645  ];
646  ++$dataSection_NumProps;
647 
648  // GKPIDDSI_DOCSPARTS
649  // MS-OSHARED p75 (2.3.3.2.2.1)
650  // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9)
651  // cElements
652  $dataProp = pack('v', 0x0001);
653  $dataProp .= pack('v', 0x0000);
654  // array of UnalignedLpstr
655  // cch
656  $dataProp .= pack('v', 0x000A);
657  $dataProp .= pack('v', 0x0000);
658  // value
659  $dataProp .= 'Worksheet' . chr(0);
660 
661  $dataSection[] = [
662  'summary' => ['pack' => 'V', 'data' => 0x0D],
663  'offset' => ['pack' => 'V'],
664  'type' => ['pack' => 'V', 'data' => 0x101E],
665  'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
666  ];
667  ++$dataSection_NumProps;
668 
669  // GKPIDDSI_HEADINGPAIR
670  // VtVecHeadingPairValue
671  // cElements
672  $dataProp = pack('v', 0x0002);
673  $dataProp .= pack('v', 0x0000);
674  // Array of vtHeadingPair
675  // vtUnalignedString - headingString
676  // stringType
677  $dataProp .= pack('v', 0x001E);
678  // padding
679  $dataProp .= pack('v', 0x0000);
680  // UnalignedLpstr
681  // cch
682  $dataProp .= pack('v', 0x0013);
683  $dataProp .= pack('v', 0x0000);
684  // value
685  $dataProp .= 'Feuilles de calcul';
686  // vtUnalignedString - headingParts
687  // wType : 0x0003 = 32 bit signed integer
688  $dataProp .= pack('v', 0x0300);
689  // padding
690  $dataProp .= pack('v', 0x0000);
691  // value
692  $dataProp .= pack('v', 0x0100);
693  $dataProp .= pack('v', 0x0000);
694  $dataProp .= pack('v', 0x0000);
695  $dataProp .= pack('v', 0x0000);
696 
697  $dataSection[] = [
698  'summary' => ['pack' => 'V', 'data' => 0x0C],
699  'offset' => ['pack' => 'V'],
700  'type' => ['pack' => 'V', 'data' => 0x100C],
701  'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
702  ];
703  ++$dataSection_NumProps;
704 
705  // 4 Section Length
706  // 4 Property count
707  // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4))
708  $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
709  foreach ($dataSection as $dataProp) {
710  // Summary
711  $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
712  // Offset
713  $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
714  // DataType
715  $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
716  // Data
717  if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
718  $dataSection_Content .= pack('V', $dataProp['data']['data']);
719 
720  $dataSection_Content_Offset += 4 + 4;
721  } elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
722  $dataSection_Content .= pack('V', $dataProp['data']['data']);
723 
724  $dataSection_Content_Offset += 4 + 4;
725  } elseif ($dataProp['type']['data'] == 0x0B) { // Boolean
726  $dataSection_Content .= pack('V', (int) $dataProp['data']['data']);
727  $dataSection_Content_Offset += 4 + 4;
728  } elseif ($dataProp['type']['data'] == 0x1E) { // null-terminated string prepended by dword string length
729  // Null-terminated string
730  $dataProp['data']['data'] .= chr(0);
731  // @phpstan-ignore-next-line
732  ++$dataProp['data']['length'];
733  // Complete the string with null string for being a %4
734  $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
735  $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
736 
737  $dataSection_Content .= pack('V', $dataProp['data']['length']);
738  $dataSection_Content .= $dataProp['data']['data'];
739 
740  $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
741  // Condition below can never be true
742  //} elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
743  // $dataSection_Content .= $dataProp['data']['data'];
744 
745  // $dataSection_Content_Offset += 4 + 8;
746  } else {
747  $dataSection_Content .= $dataProp['data']['data'];
748 
749  // @phpstan-ignore-next-line
750  $dataSection_Content_Offset += 4 + $dataProp['data']['length'];
751  }
752  }
753  // Now $dataSection_Content_Offset contains the size of the content
754 
755  // section header
756  // offset: $secOffset; size: 4; section length
757  // + x Size of the content (summary + content)
758  $data .= pack('V', $dataSection_Content_Offset);
759  // offset: $secOffset+4; size: 4; property count
760  $data .= pack('V', $dataSection_NumProps);
761  // Section Summary
762  $data .= $dataSection_Summary;
763  // Section Content
764  $data .= $dataSection_Content;
765 
766  return $data;
767  }
$data
Definition: bench.php:6
+ Here is the caller graph for this function:

◆ writeSummaryInformation()

PhpOffice\PhpSpreadsheet\Writer\Xls::writeSummaryInformation ( )
private

Build the OLE Part for Summary Information.

Returns
string

Definition at line 803 of file Xls.php.

References $data, PhpOffice\PhpSpreadsheet\Writer\Xls\writeSummaryProp(), and PhpOffice\PhpSpreadsheet\Writer\Xls\writeSummaryPropOle().

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\save().

804  {
805  // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
806  $data = pack('v', 0xFFFE);
807  // offset: 2; size: 2;
808  $data .= pack('v', 0x0000);
809  // offset: 4; size: 2; OS version
810  $data .= pack('v', 0x0106);
811  // offset: 6; size: 2; OS indicator
812  $data .= pack('v', 0x0002);
813  // offset: 8; size: 16
814  $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
815  // offset: 24; size: 4; section count
816  $data .= pack('V', 0x0001);
817 
818  // 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
819  $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3);
820  // offset: 44; size: 4; offset of the start
821  $data .= pack('V', 0x30);
822 
823  // SECTION
824  $dataSection = [];
825  $dataSection_NumProps = 0;
826  $dataSection_Summary = '';
827  $dataSection_Content = '';
828 
829  // CodePage : CP-1252
830  $dataSection[] = [
831  'summary' => ['pack' => 'V', 'data' => 0x01],
832  'offset' => ['pack' => 'V'],
833  'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
834  'data' => ['data' => 1252],
835  ];
836  ++$dataSection_NumProps;
837 
838  $props = $this->spreadsheet->getProperties();
839  $this->writeSummaryProp($props->getTitle(), $dataSection_NumProps, $dataSection, 0x02, 0x1e);
840  $this->writeSummaryProp($props->getSubject(), $dataSection_NumProps, $dataSection, 0x03, 0x1e);
841  $this->writeSummaryProp($props->getCreator(), $dataSection_NumProps, $dataSection, 0x04, 0x1e);
842  $this->writeSummaryProp($props->getKeywords(), $dataSection_NumProps, $dataSection, 0x05, 0x1e);
843  $this->writeSummaryProp($props->getDescription(), $dataSection_NumProps, $dataSection, 0x06, 0x1e);
844  $this->writeSummaryProp($props->getLastModifiedBy(), $dataSection_NumProps, $dataSection, 0x08, 0x1e);
845  $this->writeSummaryPropOle($props->getCreated(), $dataSection_NumProps, $dataSection, 0x0c, 0x40);
846  $this->writeSummaryPropOle($props->getModified(), $dataSection_NumProps, $dataSection, 0x0d, 0x40);
847 
848  // Security
849  $dataSection[] = [
850  'summary' => ['pack' => 'V', 'data' => 0x13],
851  'offset' => ['pack' => 'V'],
852  'type' => ['pack' => 'V', 'data' => 0x03], // 4 byte signed integer
853  'data' => ['data' => 0x00],
854  ];
855  ++$dataSection_NumProps;
856 
857  // 4 Section Length
858  // 4 Property count
859  // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4))
860  $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
861  foreach ($dataSection as $dataProp) {
862  // Summary
863  $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
864  // Offset
865  $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
866  // DataType
867  $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
868  // Data
869  if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
870  $dataSection_Content .= pack('V', $dataProp['data']['data']);
871 
872  $dataSection_Content_Offset += 4 + 4;
873  } elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
874  $dataSection_Content .= pack('V', $dataProp['data']['data']);
875 
876  $dataSection_Content_Offset += 4 + 4;
877  } elseif ($dataProp['type']['data'] == 0x1E) { // null-terminated string prepended by dword string length
878  // Null-terminated string
879  $dataProp['data']['data'] .= chr(0);
880  ++$dataProp['data']['length'];
881  // Complete the string with null string for being a %4
882  $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
883  $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
884 
885  $dataSection_Content .= pack('V', $dataProp['data']['length']);
886  $dataSection_Content .= $dataProp['data']['data'];
887 
888  $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
889  } elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
890  $dataSection_Content .= $dataProp['data']['data'];
891 
892  $dataSection_Content_Offset += 4 + 8;
893  }
894  // Data Type Not Used at the moment
895  }
896  // Now $dataSection_Content_Offset contains the size of the content
897 
898  // section header
899  // offset: $secOffset; size: 4; section length
900  // + x Size of the content (summary + content)
901  $data .= pack('V', $dataSection_Content_Offset);
902  // offset: $secOffset+4; size: 4; property count
903  $data .= pack('V', $dataSection_NumProps);
904  // Section Summary
905  $data .= $dataSection_Summary;
906  // Section Content
907  $data .= $dataSection_Content;
908 
909  return $data;
910  }
writeSummaryProp(string $dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata)
Definition: Xls.php:785
writeSummaryPropOle($dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata)
Definition: Xls.php:772
$data
Definition: bench.php:6
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writeSummaryProp()

PhpOffice\PhpSpreadsheet\Writer\Xls::writeSummaryProp ( string  $dataProp,
int &  $dataSection_NumProps,
array &  $dataSection,
int  $sumdata,
int  $typdata 
)
private

Definition at line 785 of file Xls.php.

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\writeSummaryInformation().

785  : void
786  {
787  if ($dataProp) {
788  $dataSection[] = [
789  'summary' => ['pack' => 'V', 'data' => $sumdata],
790  'offset' => ['pack' => 'V'],
791  'type' => ['pack' => 'V', 'data' => $typdata], // null-terminated string prepended by dword string length
792  'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
793  ];
794  ++$dataSection_NumProps;
795  }
796  }
+ Here is the caller graph for this function:

◆ writeSummaryPropOle()

PhpOffice\PhpSpreadsheet\Writer\Xls::writeSummaryPropOle (   $dataProp,
int &  $dataSection_NumProps,
array &  $dataSection,
int  $sumdata,
int  $typdata 
)
private
Parameters
float | int$dataProp

Definition at line 772 of file Xls.php.

References PhpOffice\PhpSpreadsheet\Shared\OLE\localDateToOLE().

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\writeSummaryInformation().

772  : void
773  {
774  if ($dataProp) {
775  $dataSection[] = [
776  'summary' => ['pack' => 'V', 'data' => $sumdata],
777  'offset' => ['pack' => 'V'],
778  'type' => ['pack' => 'V', 'data' => $typdata], // null-terminated string prepended by dword string length
779  'data' => ['data' => OLE::localDateToOLE($dataProp)],
780  ];
781  ++$dataSection_NumProps;
782  }
783  }
static localDateToOLE($date)
Utility function Returns a string for the OLE container with the date given.
Definition: OLE.php:498
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $colors

PhpOffice\PhpSpreadsheet\Writer\Xls::$colors
private

Definition at line 65 of file Xls.php.

◆ $documentSummaryInformation

PhpOffice\PhpSpreadsheet\Writer\Xls::$documentSummaryInformation
private

Definition at line 93 of file Xls.php.

◆ $IDCLs

PhpOffice\PhpSpreadsheet\Writer\Xls::$IDCLs
private

Definition at line 79 of file Xls.php.

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\Escher\close().

◆ $parser

PhpOffice\PhpSpreadsheet\Writer\Xls::$parser
private

Definition at line 72 of file Xls.php.

◆ $spreadsheet

PhpOffice\PhpSpreadsheet\Writer\Xls::$spreadsheet
private

Definition at line 37 of file Xls.php.

Referenced by PhpOffice\PhpSpreadsheet\Writer\Xls\__construct().

◆ $strTable

PhpOffice\PhpSpreadsheet\Writer\Xls::$strTable = []
private

Definition at line 58 of file Xls.php.

◆ $strTotal

PhpOffice\PhpSpreadsheet\Writer\Xls::$strTotal = 0
private

Definition at line 44 of file Xls.php.

◆ $strUnique

PhpOffice\PhpSpreadsheet\Writer\Xls::$strUnique = 0
private

Definition at line 51 of file Xls.php.

◆ $summaryInformation

PhpOffice\PhpSpreadsheet\Writer\Xls::$summaryInformation
private

Definition at line 86 of file Xls.php.

◆ $writerWorkbook

PhpOffice\PhpSpreadsheet\Writer\Xls::$writerWorkbook
private

Definition at line 98 of file Xls.php.

◆ $writerWorksheets

PhpOffice\PhpSpreadsheet\Writer\Xls::$writerWorksheets
private

Definition at line 103 of file Xls.php.


The documentation for this class was generated from the following file: