ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
Excel5.php
Go to the documentation of this file.
1 <?php
37 {
43  private $_preCalculateFormulas = true;
44 
50  private $_phpExcel;
51 
57  private $_BIFF_version = 0x0600;
58 
64  private $_str_total = 0;
65 
71  private $_str_unique = 0;
72 
78  private $_str_table = array();
79 
85  private $_colors;
86 
92  private $_parser;
93 
99  private $_IDCLs;
100 
101 
107  public function __construct(PHPExcel $phpExcel) {
108  $this->_phpExcel = $phpExcel;
109 
110  $this->_parser = new PHPExcel_Writer_Excel5_Parser($this->_BIFF_version);
111  }
112 
119  public function save($pFilename = null) {
120 
121  // garbage collect
122  $this->_phpExcel->garbageCollect();
123 
124  $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
125  PHPExcel_Calculation::getInstance()->writeDebugLog = false;
128 
129  // initialize colors array
130  $this->_colors = array();
131 
132  // Initialise workbook writer
133  $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, $this->_BIFF_version,
134  $this->_str_total, $this->_str_unique, $this->_str_table, $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->_BIFF_version,
140  $this->_str_total, $this->_str_unique,
141  $this->_str_table, $this->_colors,
142  $this->_parser,
143  $this->_preCalculateFormulas,
144  $this->_phpExcel->getSheet($i));
145  }
146 
147  // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
148  $this->_buildWorksheetEschers();
149  $this->_buildWorkbookEscher();
150 
151  // add 15 identical cell style Xfs
152  // for now, we use the first cellXf instead of cellStyleXf
153  $cellXfCollection = $this->_phpExcel->getCellXfCollection();
154  for ($i = 0; $i < 15; ++$i) {
155  $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true);
156  }
157 
158  // add all the cell Xfs
159  foreach ($this->_phpExcel->getCellXfCollection() as $style) {
160  $this->_writerWorkbook->addXfWriter($style, false);
161  }
162 
163  // initialize OLE file
164  $workbookStreamName = ($this->_BIFF_version == 0x0600) ? 'Workbook' : 'Book';
165  $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName));
166 
167  // Write the worksheet streams before the global workbook stream,
168  // because the byte sizes of these are needed in the global workbook stream
169  $worksheetSizes = array();
170  for ($i = 0; $i < $countSheets; ++$i) {
171  $this->_writerWorksheets[$i]->close();
172  $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize;
173  }
174 
175  // add binary data for global workbook stream
176  $OLE->append( $this->_writerWorkbook->writeWorkbook($worksheetSizes) );
177 
178  // add binary data for sheet streams
179  for ($i = 0; $i < $countSheets; ++$i) {
180  $OLE->append($this->_writerWorksheets[$i]->getData());
181  }
182 
183  $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), array($OLE));
184  // save the OLE file
185  $res = $root->save($pFilename);
186 
188  PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
189  }
190 
199  public function setTempDir($pValue = '') {
200  return $this;
201  }
202 
208  public function getPreCalculateFormulas() {
210  }
211 
217  public function setPreCalculateFormulas($pValue = true) {
218  $this->_preCalculateFormulas = $pValue;
219  }
220 
221  private function _buildWorksheetEschers()
222  {
223  // 1-based index to BstoreContainer
224  $blipIndex = 0;
225 
226  foreach ($this->_phpExcel->getAllsheets() as $sheet) {
227  // sheet index
228  $sheetIndex = $sheet->getParent()->getIndex($sheet);
229 
230  $escher = null;
231 
232  // check if there are any shapes for this sheet
233  if (count($sheet->getDrawingCollection()) == 0) {
234  continue;
235  }
236 
237  // create intermediate Escher object
238  $escher = new PHPExcel_Shared_Escher();
239 
240  // dgContainer
241  $dgContainer = new PHPExcel_Shared_Escher_DgContainer();
242 
243  // set the drawing index (we use sheet index + 1)
244  $dgId = $sheet->getParent()->getIndex($sheet) + 1;
245  $dgContainer->setDgId($dgId);
246  $escher->setDgContainer($dgContainer);
247 
248  // spgrContainer
250  $dgContainer->setSpgrContainer($spgrContainer);
251 
252  // add one shape which is the group shape
254  $spContainer->setSpgr(true);
255  $spContainer->setSpType(0);
256  $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
257  $spgrContainer->addChild($spContainer);
258 
259  // add the shapes
260 
261  $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet
262 
263  foreach ($sheet->getDrawingCollection() as $drawing) {
264  ++$blipIndex;
265 
266  ++$countShapes[$sheetIndex];
267 
268  // add the shape
270 
271  // set the shape type
272  $spContainer->setSpType(0x004B);
273 
274  // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
275  $reducedSpId = $countShapes[$sheetIndex];
276  $spId = $reducedSpId
277  | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
278  $spContainer->setSpId($spId);
279 
280  // keep track of last reducedSpId
281  $lastReducedSpId = $reducedSpId;
282 
283  // keep track of last spId
284  $lastSpId = $spId;
285 
286  // set the BLIP index
287  $spContainer->setOPT(0x4104, $blipIndex);
288 
289  // set coordinates and offsets, client anchor
290  $coordinates = $drawing->getCoordinates();
291  $offsetX = $drawing->getOffsetX();
292  $offsetY = $drawing->getOffsetY();
293  $width = $drawing->getWidth();
294  $height = $drawing->getHeight();
295 
296  $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
297 
298  $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
299  $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
300  $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
301  $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
302  $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
303  $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
304 
305  $spgrContainer->addChild($spContainer);
306  }
307 
308  // identifier clusters, used for workbook Escher object
309  $this->_IDCLs[$dgId] = $lastReducedSpId;
310 
311  // set last shape index
312  $dgContainer->setLastSpId($lastSpId);
313 
314  // set the Escher object
315  $this->_writerWorksheets[$sheetIndex]->setEscher($escher);
316  }
317  }
318 
322  private function _buildWorkbookEscher()
323  {
324  $escher = null;
325 
326  // any drawings in this workbook?
327  $found = false;
328  foreach ($this->_phpExcel->getAllSheets() as $sheet) {
329  if (count($sheet->getDrawingCollection()) > 0) {
330  $found = true;
331  }
332  }
333 
334  // nothing to do if there are no drawings
335  if (!$found) {
336  return;
337  }
338 
339  // if we reach here, then there are drawings in the workbook
340  $escher = new PHPExcel_Shared_Escher();
341 
342  // dggContainer
343  $dggContainer = new PHPExcel_Shared_Escher_DggContainer();
344  $escher->setDggContainer($dggContainer);
345 
346  // set IDCLs (identifier clusters)
347  $dggContainer->setIDCLs($this->_IDCLs);
348 
349  // this loop is for determining maximum shape identifier of all drawing
350  $spIdMax = 0;
351  $totalCountShapes = 0;
352  $countDrawings = 0;
353 
354  foreach ($this->_phpExcel->getAllsheets() as $sheet) {
355  $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
356 
357  if (count($sheet->getDrawingCollection()) > 0) {
358  ++$countDrawings;
359 
360  foreach ($sheet->getDrawingCollection() as $drawing) {
361  ++$sheetCountShapes;
362  ++$totalCountShapes;
363 
364  $spId = $sheetCountShapes
365  | ($this->_phpExcel->getIndex($sheet) + 1) << 10;
366  $spIdMax = max($spId, $spIdMax);
367  }
368  }
369  }
370 
371  $dggContainer->setSpIdMax($spIdMax + 1);
372  $dggContainer->setCDgSaved($countDrawings);
373  $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
374 
375  // bstoreContainer
377  $dggContainer->setBstoreContainer($bstoreContainer);
378 
379  // the BSE's (all the images)
380  foreach ($this->_phpExcel->getAllsheets() as $sheet) {
381  foreach ($sheet->getDrawingCollection() as $drawing) {
382  if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
383 
384  $filename = $drawing->getPath();
385 
386  list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);
387 
388  switch ($imageFormat) {
389 
390  case 1: // GIF, not supported by BIFF8, we convert to PNG
392  ob_start();
393  imagepng(imagecreatefromgif($filename));
394  $blipData = ob_get_contents();
395  ob_end_clean();
396  break;
397 
398  case 2: // JPEG
400  $blipData = file_get_contents($filename);
401  break;
402 
403  case 3: // PNG
405  $blipData = file_get_contents($filename);
406  break;
407 
408  case 6: // Windows DIB (BMP), we convert to PNG
410  ob_start();
412  $blipData = ob_get_contents();
413  ob_end_clean();
414  break;
415 
416  default: continue 2;
417 
418  }
419 
421  $blip->setData($blipData);
422 
424  $BSE->setBlipType($blipType);
425  $BSE->setBlip($blip);
426 
427  $bstoreContainer->addBSE($BSE);
428 
429  } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {
430 
431  switch ($drawing->getRenderingFunction()) {
432 
435  $renderingFunction = 'imagejpeg';
436  break;
437 
442  $renderingFunction = 'imagepng';
443  break;
444 
445  }
446 
447  ob_start();
448  call_user_func($renderingFunction, $drawing->getImageResource());
449  $blipData = ob_get_contents();
450  ob_end_clean();
451 
453  $blip->setData($blipData);
454 
456  $BSE->setBlipType($blipType);
457  $BSE->setBlip($blip);
458 
459  $bstoreContainer->addBSE($BSE);
460  }
461  }
462  }
463 
464  // Set the Escher object
465  $this->_writerWorkbook->setEscher($escher);
466  }
467 
468 }