ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
Excel2007.php
Go to the documentation of this file.
1 <?php
30 if (!defined('PHPEXCEL_ROOT')) {
34  define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
35 }
36 
38 require_once PHPEXCEL_ROOT . 'PHPExcel.php';
39 
41 require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php';
42 
44 require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php';
45 
47 require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php';
48 
50 require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php';
51 
53 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php';
54 
56 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Conditional.php';
57 
59 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php';
60 
62 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php';
63 
65 require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php';
66 
68 require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php';
69 
71 require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php';
72 
74 require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php';
75 
77 require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php';
78 
80 require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php';
81 
83 require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php';
84 
86 require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReadFilter.php';
87 
89 require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php';
90 
91 
100 {
106  private $_readDataOnly = false;
107 
113  private $_loadSheetsOnly = null;
114 
120  private $_readFilter = null;
121 
127  public function getReadDataOnly() {
128  return $this->_readDataOnly;
129  }
130 
137  public function setReadDataOnly($pValue = false) {
138  $this->_readDataOnly = $pValue;
139  return $this;
140  }
141 
147  public function getLoadSheetsOnly()
148  {
149  return $this->_loadSheetsOnly;
150  }
151 
158  public function setLoadSheetsOnly($value = null)
159  {
160  $this->_loadSheetsOnly = is_array($value) ?
161  $value : array($value);
162  return $this;
163  }
164 
170  public function setLoadAllSheets()
171  {
172  $this->_loadSheetsOnly = null;
173  return $this;
174  }
175 
181  public function getReadFilter() {
182  return $this->_readFilter;
183  }
184 
191  public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
192  $this->_readFilter = $pValue;
193  return $this;
194  }
195 
199  public function __construct() {
200  $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
201  }
202 
209  public function canRead($pFilename)
210  {
211  // Check if file exists
212  if (!file_exists($pFilename)) {
213  throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
214  }
215 
216  // Load file
217  $zip = new ZipArchive;
218  if ($zip->open($pFilename) === true) {
219  // check if it is an OOXML archive
220  $rels = simplexml_load_string($zip->getFromName("_rels/.rels"));
221 
222  $zip->close();
223 
224  return ($rels !== false);
225  }
226 
227  return false;
228  }
229 
230 
231  private function _castToBool($c) {
232 // echo 'Initial Cast to Boolean<br />';
233  $value = isset($c->v) ? (string) $c->v : null;
234  if ($value == '0') {
235  $value = false;
236  } elseif ($value == '1') {
237  $value = true;
238  } else {
239  $value = (bool)$c->v;
240  }
241  return $value;
242  } // function _castToBool()
243 
244  private function _castToError($c) {
245 // echo 'Initial Cast to Error<br />';
246  return isset($c->v) ? (string) $c->v : null;;
247  } // function _castToError()
248 
249  private function _castToString($c) {
250 // echo 'Initial Cast to String<br />';
251  return isset($c->v) ? (string) $c->v : null;;
252  } // function _castToString()
253 
254  private function _castToFormula($c,$r,&$cellDataType,&$value,&$calculatedValue,&$sharedFormulas,$castBaseType) {
255 // echo '<font color="darkgreen">Formula</font><br />';
256 // echo '$c->f is '.$c->f.'<br />';
257  $cellDataType = 'f';
258  $value = "={$c->f}";
259  $calculatedValue = $this->$castBaseType($c);
260 
261  // Shared formula?
262  if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') {
263 // echo '<font color="darkgreen">SHARED FORMULA</font><br />';
264  $instance = (string)$c->f['si'];
265 
266 // echo 'Instance ID = '.$instance.'<br />';
267 //
268 // echo 'Shared Formula Array:<pre>';
269 // print_r($sharedFormulas);
270 // echo '</pre>';
271  if (!isset($sharedFormulas[(string)$c->f['si']])) {
272 // echo '<font color="darkgreen">SETTING NEW SHARED FORMULA</font><br />';
273 // echo 'Master is '.$r.'<br />';
274 // echo 'Formula is '.$value.'<br />';
275  $sharedFormulas[$instance] = array( 'master' => $r,
276  'formula' => $value
277  );
278 // echo 'New Shared Formula Array:<pre>';
279 // print_r($sharedFormulas);
280 // echo '</pre>';
281  } else {
282 // echo '<font color="darkgreen">GETTING SHARED FORMULA</font><br />';
283 // echo 'Master is '.$sharedFormulas[$instance]['master'].'<br />';
284 // echo 'Formula is '.$sharedFormulas[$instance]['formula'].'<br />';
285  $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']);
287 
288  $difference = array(0, 0);
289  $difference[0] = PHPExcel_Cell::columnIndexFromString($current[0]) - PHPExcel_Cell::columnIndexFromString($master[0]);
290  $difference[1] = $current[1] - $master[1];
291 
293  $value = $helper->updateFormulaReferences( $sharedFormulas[$instance]['formula'],
294  'A1',
295  $difference[0],
296  $difference[1]
297  );
298 // echo 'Adjusted Formula is '.$value.'<br />';
299  }
300  }
301  }
302 
303 
310  public function load($pFilename)
311  {
312  // Check if file exists
313  if (!file_exists($pFilename)) {
314  throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
315  }
316 
317  // Initialisations
318  $excel = new PHPExcel;
319  $excel->removeSheetByIndex(0);
320  if (!$this->_readDataOnly) {
321  $excel->removeCellStyleXfByIndex(0); // remove the default style
322  $excel->removeCellXfByIndex(0); // remove the default style
323  }
324  $zip = new ZipArchive;
325  $zip->open($pFilename);
326 
327  $rels = simplexml_load_string($zip->getFromName("_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships");
328  foreach ($rels->Relationship as $rel) {
329  switch ($rel["Type"]) {
330  case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties":
331  $xmlCore = simplexml_load_string($zip->getFromName("{$rel['Target']}"));
332  if ($xmlCore === false) { // Apache POI hack
333  $xmlCore = simplexml_load_string($zip->getFromName(substr("{$rel['Target']}", 1)));
334  }
335  if ($xmlCore) {
336  $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
337  $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/");
338  $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
339  $docProps = $excel->getProperties();
340  $docProps->setCreator((string) self::array_item($xmlCore->xpath("dc:creator")));
341  $docProps->setLastModifiedBy((string) self::array_item($xmlCore->xpath("cp:lastModifiedBy")));
342  $docProps->setCreated(strtotime(self::array_item($xmlCore->xpath("dcterms:created"))));
343  $docProps->setModified(strtotime(self::array_item($xmlCore->xpath("dcterms:modified"))));
344  $docProps->setTitle((string) self::array_item($xmlCore->xpath("dc:title")));
345  $docProps->setDescription((string) self::array_item($xmlCore->xpath("dc:description")));
346  $docProps->setSubject((string) self::array_item($xmlCore->xpath("dc:subject")));
347  $docProps->setKeywords((string) self::array_item($xmlCore->xpath("cp:keywords")));
348  $docProps->setCategory((string) self::array_item($xmlCore->xpath("cp:category")));
349  }
350  break;
351 
352  case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
353  $dir = dirname($rel["Target"]);
354  $relsWorkbook = simplexml_load_string($zip->getFromName("$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships");
355  if ($relsWorkbook === false) { // Apache POI hack
356  $relsWorkbook = simplexml_load_string($zip->getFromName(substr("$dir/_rels/" . basename($rel["Target"]) . ".rels", 1))); //~ http://schemas.openxmlformats.org/package/2006/relationships");
357  }
358  $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships");
359 
360  $sharedStrings = array();
361  $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
362  $xmlStrings = simplexml_load_string($zip->getFromName("$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
363  if (isset($xmlStrings) && isset($xmlStrings->si)) {
364  foreach ($xmlStrings->si as $val) {
365  if (isset($val->t)) {
366  $sharedStrings[] = PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $val->t );
367  } elseif (isset($val->r)) {
368  $sharedStrings[] = $this->_parseRichText($val);
369  }
370  }
371  }
372 
373  $worksheets = array();
374  foreach ($relsWorkbook->Relationship as $ele) {
375  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") {
376  $worksheets[(string) $ele["Id"]] = $ele["Target"];
377  }
378  }
379 
380  $styles = array();
381  $cellStyles = array();
382  $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
383  $xmlStyles = simplexml_load_string($zip->getFromName("$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
384  $numFmts = null;
385  if ($xmlStyles && $xmlStyles->numFmts[0]) {
386  $numFmts = $xmlStyles->numFmts[0];
387  }
388  if (isset($numFmts) && !is_null($numFmts)) {
389  $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
390  }
391  if (!$this->_readDataOnly && $xmlStyles) {
392  foreach ($xmlStyles->cellXfs->xf as $xf) {
394 
395  if ($xf["numFmtId"]) {
396  if (isset($numFmts)) {
397  $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
398 
399  if (isset($tmpNumFmt["formatCode"])) {
400  $numFmt = (string) $tmpNumFmt["formatCode"];
401  }
402  }
403 
404  if ((int)$xf["numFmtId"] < 164) {
405  $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]);
406  }
407  }
408  //$numFmt = str_replace('mm', 'i', $numFmt);
409  //$numFmt = str_replace('h', 'H', $numFmt);
410 
411  $style = (object) array(
412  "numFmt" => $numFmt,
413  "font" => $xmlStyles->fonts->font[intval($xf["fontId"])],
414  "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])],
415  "border" => $xmlStyles->borders->border[intval($xf["borderId"])],
416  "alignment" => $xf->alignment,
417  "protection" => $xf->protection,
418  "applyAlignment" => (isset($xf["applyAlignment"]) && ((string)$xf["applyAlignment"] == 'true' || (string)$xf["applyAlignment"] == '1')),
419  "applyBorder" => (isset($xf["applyBorder"]) && ((string)$xf["applyBorder"] == 'true' || (string)$xf["applyBorder"] == '1')),
420  "applyFill" => (isset($xf["applyFill"]) && ((string)$xf["applyFill"] == 'true' || (string)$xf["applyFill"] == '1')),
421  "applyFont" => (isset($xf["applyFont"]) && ((string)$xf["applyFont"] == 'true' || (string)$xf["applyFont"] == '1')),
422  "applyNumberFormat" => (isset($xf["applyNumberFormat"]) && ((string)$xf["applyNumberFormat"] == 'true' || (string)$xf["applyNumberFormat"] == '1')),
423  "applyProtection" => (isset($xf["applyProtection"]) && ((string)$xf["applyProtection"] == 'true' || (string)$xf["applyProtection"] == '1'))
424  );
425  $styles[] = $style;
426 
427  // add style to cellXf collection
428  $objStyle = new PHPExcel_Style;
429  $this->_readStyle($objStyle, $style);
430  $excel->addCellXf($objStyle);
431  }
432 
433  foreach ($xmlStyles->cellStyleXfs->xf as $xf) {
435  if ($numFmts && $xf["numFmtId"]) {
436  $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
437  if (isset($tmpNumFmt["formatCode"])) {
438  $numFmt = (string) $tmpNumFmt["formatCode"];
439  } else if ((int)$xf["numFmtId"] < 165) {
440  $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]);
441  }
442  }
443 
444  $cellStyle = (object) array(
445  "numFmt" => $numFmt,
446  "font" => $xmlStyles->fonts->font[intval($xf["fontId"])],
447  "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])],
448  "border" => $xmlStyles->borders->border[intval($xf["borderId"])],
449  "alignment" => $xf->alignment,
450  "protection" => $xf->protection,
451  "applyAlignment" => true,
452  "applyBorder" => true,
453  "applyFill" => true,
454  "applyFont" => true,
455  "applyNumberFormat" => true,
456  "applyProtection" => true
457  );
458  $cellStyles[] = $cellStyle;
459 
460  // add style to cellStyleXf collection
461  $objStyle = new PHPExcel_Style;
462  $this->_readStyle($objStyle, $cellStyle);
463  $excel->addCellStyleXf($objStyle);
464  }
465  }
466 
467  $dxfs = array();
468  if (!$this->_readDataOnly && $xmlStyles) {
469  foreach ($xmlStyles->dxfs->dxf as $dxf) {
470  $style = new PHPExcel_Style;
471  $this->_readStyle($style, $dxf);
472  $dxfs[] = $style;
473  }
474 
475  foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) {
476  if (intval($cellStyle['builtinId']) == 0) {
477  if (isset($cellStyles[intval($cellStyle['xfId'])])) {
478  // Set default style
479  $style = new PHPExcel_Style;
480  $this->_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]);
481 
482  // normal style, currently not using it for anything
483  }
484  }
485  }
486  }
487 
488  $xmlWorkbook = simplexml_load_string($zip->getFromName("{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
489  if ($xmlWorkbook === false) { // Apache POI hack
490  $xmlWorkbook = simplexml_load_string($zip->getFromName(substr("{$rel['Target']}", 1))); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
491  }
492  // Set base date
493  if ($xmlWorkbook->workbookPr) {
495  if (isset($xmlWorkbook->workbookPr['date1904'])) {
496  $date1904 = (string)$xmlWorkbook->workbookPr['date1904'];
497  if ($date1904 == "true" || $date1904 == "1") {
499  }
500  }
501  }
502 
503  $sheetId = 0; // keep track of new sheet id in final workbook
504  $oldSheetId = -1; // keep track of old sheet id in final workbook
505  $countSkippedSheets = 0; // keep track of number of skipped sheets
506  $mapSheetId = array(); // mapping of sheet ids from old to new
507 
508  foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
509  ++$oldSheetId;
510 
511  // Check if sheet should be skipped
512  if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) {
513  ++$countSkippedSheets;
514  $mapSheetId[$oldSheetId] = null;
515  continue;
516  }
517 
518  // Map old sheet id in original workbook to new sheet id.
519  // They will differ if loadSheetsOnly() is being used
520  $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets;
521 
522  // Load sheet
523  $docSheet = $excel->createSheet();
524  $docSheet->setTitle((string) $eleSheet["name"]);
525  $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
526  $xmlSheet = simplexml_load_string($zip->getFromName("$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
527 
528  $sharedFormulas = array();
529 
530  if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) {
531  if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) {
532  $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) );
533  }
534 
535  if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) {
536  $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) );
537  }
538 
539  if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) {
540  $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false);
541  }
542 
543  if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) {
544  $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false);
545  }
546 
547  if (isset($xmlSheet->sheetViews->sheetView->pane)) {
548  if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
549  $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] );
550  } else {
551  $xSplit = 0;
552  $ySplit = 0;
553 
554  if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) {
555  $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']);
556  }
557 
558  if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) {
559  $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']);
560  }
561 
562  $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit);
563  }
564  }
565  }
566 
567  if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) {
568  if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) {
569  $docSheet->setShowSummaryRight(false);
570  } else {
571  $docSheet->setShowSummaryRight(true);
572  }
573 
574  if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) {
575  $docSheet->setShowSummaryBelow(false);
576  } else {
577  $docSheet->setShowSummaryBelow(true);
578  }
579  }
580 
581  if (isset($xmlSheet->sheetFormatPr)) {
582  if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) {
583  $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] );
584  }
585  if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) {
586  $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] );
587  }
588  }
589 
590  if (isset($xmlSheet->cols) && !$this->_readDataOnly) {
591  foreach ($xmlSheet->cols->col as $col) {
592  for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) {
593  if ($col["bestFit"]) {
594  $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true);
595  }
596  if ($col["hidden"]) {
597  $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false);
598  }
599  if ($col["collapsed"]) {
600  $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true);
601  }
602  if ($col["outlineLevel"] > 0) {
603  $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"]));
604  }
605  $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"]));
606 
607  if (intval($col["max"]) == 16384) {
608  break;
609  }
610  }
611  }
612  }
613 
614  if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) {
615  if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') {
616  $docSheet->setShowGridlines(true);
617  }
618 
619  if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') {
620  $docSheet->setPrintGridlines(true);
621  }
622 
623  if ($xmlSheet->printOptions['horizontalCentered']) {
624  $docSheet->getPageSetup()->setHorizontalCentered(true);
625  }
626  if ($xmlSheet->printOptions['verticalCentered']) {
627  $docSheet->getPageSetup()->setVerticalCentered(true);
628  }
629  }
630 
631  if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
632  foreach ($xmlSheet->sheetData->row as $row) {
633  if ($row["ht"] && !$this->_readDataOnly) {
634  $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"]));
635  }
636  if ($row["hidden"] && !$this->_readDataOnly) {
637  $docSheet->getRowDimension(intval($row["r"]))->setVisible(false);
638  }
639  if ($row["collapsed"]) {
640  $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true);
641  }
642  if ($row["outlineLevel"] > 0) {
643  $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"]));
644  }
645 
646  foreach ($row->c as $c) {
647  $r = (string) $c["r"];
648  $cellDataType = (string) $c["t"];
649  $value = null;
650  $calculatedValue = null;
651 
652  // Read cell?
653  if (!is_null($this->getReadFilter())) {
654  $coordinates = PHPExcel_Cell::coordinateFromString($r);
655 
656  if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) {
657  break;
658  }
659  }
660 
661 // echo '<b>Reading cell '.$coordinates[0].$coordinates[1].'</b><br />';
662 // print_r($c);
663 // echo '<br />';
664 // echo 'Cell Data Type is '.$cellDataType.': ';
665 //
666  // Read cell!
667  switch ($cellDataType) {
668  case "s":
669 // echo 'String<br />';
670  if ((string)$c->v != '') {
671  $value = $sharedStrings[intval($c->v)];
672 
673  if ($value instanceof PHPExcel_RichText) {
674  $value = clone $value;
675  }
676  } else {
677  $value = '';
678  }
679 
680  break;
681  case "b":
682 // echo 'Boolean<br />';
683  if (!isset($c->f)) {
684  $value = $this->_castToBool($c);
685  } else {
686  // Formula
687  $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool');
688 // echo '$calculatedValue = '.$calculatedValue.'<br />';
689  }
690  break;
691  case "inlineStr":
692 // echo 'Inline String<br />';
693  $value = $this->_parseRichText($c->is);
694 
695  break;
696  case "e":
697 // echo 'Error<br />';
698  if (!isset($c->f)) {
699  $value = $this->_castToError($c);
700  } else {
701  // Formula
702  $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError');
703 // echo '$calculatedValue = '.$calculatedValue.'<br />';
704  }
705 
706  break;
707 
708  default:
709 // echo 'Default<br />';
710  if (!isset($c->f)) {
711 // echo 'Not a Formula<br />';
712  $value = $this->_castToString($c);
713  } else {
714 // echo 'Treat as Formula<br />';
715  // Formula
716  $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString');
717 // echo '$calculatedValue = '.$calculatedValue.'<br />';
718  }
719 
720  break;
721  }
722 // echo 'Value is '.$value.'<br />';
723 
724  // Check for numeric values
725  if (is_numeric($value) && $cellDataType != 's') {
726  if ($value == (int)$value) $value = (int)$value;
727  elseif ($value == (float)$value) $value = (float)$value;
728  elseif ($value == (double)$value) $value = (double)$value;
729  }
730 
731  // Rich text?
732  if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) {
733  $value = $value->getPlainText();
734  }
735 
736  // Assign value
737  if ($cellDataType != '') {
738  $docSheet->setCellValueExplicit($r, $value, $cellDataType);
739  } else {
740  $docSheet->setCellValue($r, $value);
741  }
742  if (!is_null($calculatedValue)) {
743  $docSheet->getCell($r)->setCalculatedValue($calculatedValue);
744  }
745 
746  // Style information?
747  if ($c["s"] && !$this->_readDataOnly) {
748  // no style index means 0, it seems
749  $docSheet->getCell($r)->setXfIndex(isset($styles[intval($c["s"])]) ?
750  intval($c["s"]) : 0);
751  }
752 
753  // Set rich text parent
754  if ($value instanceof PHPExcel_RichText && !$this->_readDataOnly) {
755  $value->setParent($docSheet->getCell($r));
756  }
757  }
758  }
759  }
760 
761  $conditionals = array();
762  if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
763  foreach ($xmlSheet->conditionalFormatting as $conditional) {
764  foreach ($conditional->cfRule as $cfRule) {
765  if (
766  (
767  (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE ||
768  (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS ||
769  (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT
770  ) && isset($dxfs[intval($cfRule["dxfId"])])
771  ) {
772  $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule;
773  }
774  }
775  }
776 
777  foreach ($conditionals as $ref => $cfRules) {
778  ksort($cfRules);
779  $conditionalStyles = array();
780  foreach ($cfRules as $cfRule) {
781  $objConditional = new PHPExcel_Style_Conditional();
782  $objConditional->setConditionType((string)$cfRule["type"]);
783  $objConditional->setOperatorType((string)$cfRule["operator"]);
784 
785  if ((string)$cfRule["text"] != '') {
786  $objConditional->setText((string)$cfRule["text"]);
787  }
788 
789  if (count($cfRule->formula) > 1) {
790  foreach ($cfRule->formula as $formula) {
791  $objConditional->addCondition((string)$formula);
792  }
793  } else {
794  $objConditional->addCondition((string)$cfRule->formula);
795  }
796  $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]);
797  $conditionalStyles[] = $objConditional;
798  }
799 
800  // Extract all cell references in $ref
802  foreach ($aReferences as $reference) {
803  $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles);
804  }
805  }
806  }
807 
808  $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells");
809  if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
810  foreach ($aKeys as $key) {
811  $method = "set" . ucfirst($key);
812  $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true");
813  }
814  }
815 
816  if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
817  $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true);
818  if ($xmlSheet->protectedRanges->protectedRange) {
819  foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
820  $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true);
821  }
822  }
823  }
824 
825  if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) {
826  $docSheet->setAutoFilter((string) $xmlSheet->autoFilter["ref"]);
827  }
828 
829  if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) {
830  foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
831  $docSheet->mergeCells((string) $mergeCell["ref"]);
832  }
833  }
834 
835  if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) {
836  $docPageMargins = $docSheet->getPageMargins();
837  $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"]));
838  $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"]));
839  $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"]));
840  $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"]));
841  $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"]));
842  $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"]));
843  }
844 
845  if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) {
846  $docPageSetup = $docSheet->getPageSetup();
847 
848  if (isset($xmlSheet->pageSetup["orientation"])) {
849  $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]);
850  }
851  if (isset($xmlSheet->pageSetup["paperSize"])) {
852  $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"]));
853  }
854  if (isset($xmlSheet->pageSetup["scale"])) {
855  $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]));
856  }
857  if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) > 0) {
858  $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]));
859  }
860  if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) > 0) {
861  $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]));
862  }
863  }
864 
865  if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) {
866  $docHeaderFooter = $docSheet->getHeaderFooter();
867 
868  if (isset($xmlSheet->headerFooter["differentOddEven"]) &&
869  ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) {
870  $docHeaderFooter->setDifferentOddEven(true);
871  } else {
872  $docHeaderFooter->setDifferentOddEven(false);
873  }
874  if (isset($xmlSheet->headerFooter["differentFirst"]) &&
875  ((string)$xmlSheet->headerFooter["differentFirst"] == 'true' || (string)$xmlSheet->headerFooter["differentFirst"] == '1')) {
876  $docHeaderFooter->setDifferentFirst(true);
877  } else {
878  $docHeaderFooter->setDifferentFirst(false);
879  }
880  if (isset($xmlSheet->headerFooter["scaleWithDoc"]) &&
881  ((string)$xmlSheet->headerFooter["scaleWithDoc"] == 'false' || (string)$xmlSheet->headerFooter["scaleWithDoc"] == '0')) {
882  $docHeaderFooter->setScaleWithDocument(false);
883  } else {
884  $docHeaderFooter->setScaleWithDocument(true);
885  }
886  if (isset($xmlSheet->headerFooter["alignWithMargins"]) &&
887  ((string)$xmlSheet->headerFooter["alignWithMargins"] == 'false' || (string)$xmlSheet->headerFooter["alignWithMargins"] == '0')) {
888  $docHeaderFooter->setAlignWithMargins(false);
889  } else {
890  $docHeaderFooter->setAlignWithMargins(true);
891  }
892 
893  $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
894  $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
895  $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
896  $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
897  $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
898  $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
899  }
900 
901  if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) {
902  foreach ($xmlSheet->rowBreaks->brk as $brk) {
903  if ($brk["man"]) {
904  $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW);
905  }
906  }
907  }
908  if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) {
909  foreach ($xmlSheet->colBreaks->brk as $brk) {
910  if ($brk["man"]) {
911  $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex($brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN);
912  }
913  }
914  }
915 
916  if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) {
917  foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
918  // Uppercase coordinate
919  $range = strtoupper($dataValidation["sqref"]);
920 
921  // Extract all cell references in $range
922  $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($range);
923  foreach ($aReferences as $reference) {
924  // Create validation
925  $docValidation = $docSheet->getCell($reference)->getDataValidation();
926  $docValidation->setType((string) $dataValidation["type"]);
927  $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]);
928  $docValidation->setOperator((string) $dataValidation["operator"]);
929  $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0);
930  $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0);
931  $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0);
932  $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0);
933  $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]);
934  $docValidation->setError((string) $dataValidation["error"]);
935  $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]);
936  $docValidation->setPrompt((string) $dataValidation["prompt"]);
937  $docValidation->setFormula1((string) $dataValidation->formula1);
938  $docValidation->setFormula2((string) $dataValidation->formula2);
939  }
940  }
941  }
942 
943  // Add hyperlinks
944  $hyperlinks = array();
945  if (!$this->_readDataOnly) {
946  // Locate hyperlink relations
947  if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
948  $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
949  foreach ($relsWorksheet->Relationship as $ele) {
950  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") {
951  $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"];
952  }
953  }
954  }
955 
956  // Loop trough hyperlinks
957  if ($xmlSheet && $xmlSheet->hyperlinks) {
958  foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) {
959  // Link url
960  $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
961 
962  foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
963  if (isset($linkRel['id'])) {
964  $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] );
965  }
966  if (isset($hyperlink['location'])) {
967  $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] );
968  }
969 
970  // Tooltip
971  if (isset($hyperlink['tooltip'])) {
972  $docSheet->getCell( $cellReference )->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] );
973  }
974  }
975  }
976  }
977  }
978 
979  // Add comments
980  $comments = array();
981  $vmlComments = array();
982  if (!$this->_readDataOnly) {
983  // Locate comment relations
984  if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
985  $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
986  foreach ($relsWorksheet->Relationship as $ele) {
987  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") {
988  $comments[(string)$ele["Id"]] = (string)$ele["Target"];
989  }
990  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
991  $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"];
992  }
993  }
994  }
995 
996  // Loop trough comments
997  foreach ($comments as $relName => $relPath) {
998  // Load comments file
999  $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath);
1000  $commentsFile = simplexml_load_string($zip->getFromName($relPath) );
1001 
1002  // Utility variables
1003  $authors = array();
1004 
1005  // Loop trough authors
1006  foreach ($commentsFile->authors->author as $author) {
1007  $authors[] = (string)$author;
1008  }
1009 
1010  // Loop trough contents
1011  foreach ($commentsFile->commentList->comment as $comment) {
1012  $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] );
1013  $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) );
1014  }
1015  }
1016 
1017  // Loop trough VML comments
1018  foreach ($vmlComments as $relName => $relPath) {
1019  // Load VML comments file
1020  $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath);
1021  $vmlCommentsFile = simplexml_load_string( $zip->getFromName($relPath) );
1022  $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1023 
1024  $shapes = $vmlCommentsFile->xpath('//v:shape');
1025  foreach ($shapes as $shape) {
1026  $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1027 
1028  if (isset($shape['style'])) {
1029  $style = (string)$shape['style'];
1030  $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) );
1031  $column = null;
1032  $row = null;
1033 
1034  $clientData = $shape->xpath('.//x:ClientData');
1035  if (is_array($clientData)) {
1036  $clientData = $clientData[0];
1037 
1038  if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) {
1039  $temp = $clientData->xpath('.//x:Row');
1040  if (is_array($temp)) $row = $temp[0];
1041 
1042  $temp = $clientData->xpath('.//x:Column');
1043  if (is_array($temp)) $column = $temp[0];
1044  }
1045  }
1046 
1047  if (!is_null($column) && !is_null($row)) {
1048  // Set comment properties
1049  $comment = $docSheet->getCommentByColumnAndRow($column, $row + 1);
1050  $comment->getFillColor()->setRGB( $fillColor );
1051 
1052  // Parse style
1053  $styleArray = explode(';', str_replace(' ', '', $style));
1054  foreach ($styleArray as $stylePair) {
1055  $stylePair = explode(':', $stylePair);
1056 
1057  if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]);
1058  if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]);
1059  if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]);
1060  if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]);
1061  if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' );
1062 
1063  }
1064  }
1065  }
1066  }
1067  }
1068 
1069  // Header/footer images
1070  if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) {
1071  if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1072  $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1073  $vmlRelationship = '';
1074 
1075  foreach ($relsWorksheet->Relationship as $ele) {
1076  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
1077  $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]);
1078  }
1079  }
1080 
1081  if ($vmlRelationship != '') {
1082  // Fetch linked images
1083  $relsVML = simplexml_load_string($zip->getFromName( dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1084  $drawings = array();
1085  foreach ($relsVML->Relationship as $ele) {
1086  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") {
1087  $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]);
1088  }
1089  }
1090 
1091  // Fetch VML document
1092  $vmlDrawing = simplexml_load_string($zip->getFromName($vmlRelationship));
1093  $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1094 
1095  $hfImages = array();
1096 
1097  $shapes = $vmlDrawing->xpath('//v:shape');
1098  foreach ($shapes as $shape) {
1099  $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1100  $imageData = $shape->xpath('//v:imagedata');
1101  $imageData = $imageData[0];
1102 
1103  $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office');
1104  $style = self::toCSSArray( (string)$shape['style'] );
1105 
1106  $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing();
1107  if (isset($imageData['title'])) {
1108  $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] );
1109  }
1110 
1111  $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false);
1112  $hfImages[ (string)$shape['id'] ]->setResizeProportional(false);
1113  $hfImages[ (string)$shape['id'] ]->setWidth($style['width']);
1114  $hfImages[ (string)$shape['id'] ]->setHeight($style['height']);
1115  $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']);
1116  $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']);
1117  $hfImages[ (string)$shape['id'] ]->setResizeProportional(true);
1118  }
1119 
1120  $docSheet->getHeaderFooter()->setImages($hfImages);
1121  }
1122  }
1123  }
1124 
1125  }
1126 
1127 // TODO: Make sure drawings and graph are loaded differently!
1128  if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1129  $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1130  $drawings = array();
1131  foreach ($relsWorksheet->Relationship as $ele) {
1132  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") {
1133  $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]);
1134  }
1135  }
1136  if ($xmlSheet->drawing && !$this->_readDataOnly) {
1137  foreach ($xmlSheet->drawing as $drawing) {
1138  $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
1139  $relsDrawing = simplexml_load_string($zip->getFromName( dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1140  $images = array();
1141 
1142  if ($relsDrawing && $relsDrawing->Relationship) {
1143  foreach ($relsDrawing->Relationship as $ele) {
1144  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") {
1145  $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]);
1146  }
1147  }
1148  }
1149  $xmlDrawing = simplexml_load_string($zip->getFromName($fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing");
1150 
1151  if ($xmlDrawing->oneCellAnchor) {
1152  foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) {
1153  if ($oneCellAnchor->pic->blipFill) {
1154  $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip;
1155  $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm;
1156  $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw;
1157  $objDrawing = new PHPExcel_Worksheet_Drawing;
1158  $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name"));
1159  $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr"));
1160  $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false);
1161  $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1));
1162  $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff));
1163  $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff));
1164  $objDrawing->setResizeProportional(false);
1165  $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx")));
1166  $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy")));
1167  if ($xfrm) {
1168  $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot")));
1169  }
1170  if ($outerShdw) {
1171  $shadow = $objDrawing->getShadow();
1172  $shadow->setVisible(true);
1173  $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad")));
1174  $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist")));
1175  $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir")));
1176  $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn"));
1177  $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val"));
1178  $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000);
1179  }
1180  $objDrawing->setWorksheet($docSheet);
1181  }
1182  }
1183  }
1184  if ($xmlDrawing->twoCellAnchor) {
1185  foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) {
1186  if ($twoCellAnchor->pic->blipFill) {
1187  $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip;
1188  $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm;
1189  $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw;
1190  $objDrawing = new PHPExcel_Worksheet_Drawing;
1191  $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name"));
1192  $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr"));
1193  $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false);
1194  $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1));
1195  $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff));
1196  $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff));
1197  $objDrawing->setResizeProportional(false);
1198 
1199  $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx")));
1200  $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy")));
1201 
1202  if ($xfrm) {
1203  $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot")));
1204  }
1205  if ($outerShdw) {
1206  $shadow = $objDrawing->getShadow();
1207  $shadow->setVisible(true);
1208  $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad")));
1209  $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist")));
1210  $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir")));
1211  $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn"));
1212  $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val"));
1213  $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000);
1214  }
1215  $objDrawing->setWorksheet($docSheet);
1216  }
1217  }
1218  }
1219 
1220  }
1221  }
1222  }
1223 
1224  // Loop trough definedNames
1225  if ($xmlWorkbook->definedNames) {
1226  foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1227  // Extract range
1228  $extractedRange = (string)$definedName;
1229  $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange);
1230  $extractedRange = str_replace('$', '', $extractedRange);
1231 
1232  // Valid range?
1233  if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') {
1234  continue;
1235  }
1236 
1237  // Some definedNames are only applicable if we are on the same sheet...
1238  if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) {
1239  // Switch on type
1240  switch ((string)$definedName['name']) {
1241 
1242  case '_xlnm._FilterDatabase':
1243  $docSheet->setAutoFilter($extractedRange);
1244  break;
1245 
1246  case '_xlnm.Print_Titles':
1247  // Split $extractedRange
1248  $extractedRange = explode(',', $extractedRange);
1249 
1250  // Set print titles
1251  if (isset($extractedRange[0])) {
1252  $range = explode(':', $extractedRange[0]);
1253 
1254  if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '')
1255  $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]);
1256  $range[0] = str_replace('$', '', $range[0]);
1257  if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '')
1258  $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]);
1259  $range[1] = str_replace('$', '', $range[1]);
1260 
1261  $docSheet->getPageSetup()->setColumnsToRepeatAtLeft( $range );
1262  }
1263  if (isset($extractedRange[1])) {
1264  $range = explode(':', $extractedRange[1]);
1265 
1266  if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '')
1267  $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]);
1268  $range[0] = str_replace('$', '', $range[0]);
1269  if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '')
1270  $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]);
1271  $range[1] = str_replace('$', '', $range[1]);
1272 
1273  $docSheet->getPageSetup()->setRowsToRepeatAtTop( $range );
1274  }
1275 
1276  break;
1277 
1278  case '_xlnm.Print_Area':
1279  $range = explode('!', $extractedRange);
1280  $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1281 
1282  $docSheet->getPageSetup()->setPrintArea($extractedRange);
1283  break;
1284 
1285  default:
1286  $range = explode('!', $extractedRange);
1287  $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1288 
1289  $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, true) );
1290  break;
1291  }
1292  } else {
1293  // "Global" definedNames
1294  $locatedSheet = null;
1295  $extractedSheetName = '';
1296  if (strpos( (string)$definedName, '!' ) !== false) {
1297  // Extract sheet name
1298  $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true );
1299  $extractedSheetName = $extractedSheetName[0];
1300 
1301  // Locate sheet
1302  $locatedSheet = $excel->getSheetByName($extractedSheetName);
1303 
1304  // Modify range
1305  $range = explode('!', $extractedRange);
1306  $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1307  }
1308 
1309  if (!is_null($locatedSheet)) {
1310  $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) );
1311  }
1312  }
1313  }
1314  }
1315 
1316  // Next sheet id
1317  ++$sheetId;
1318  }
1319 
1320  if (!$this->_readDataOnly) {
1321  // active sheet index
1322  $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index
1323 
1324  // keep active sheet index if sheet is still loaded, else first sheet is set as the active
1325  if ($mapSheetId[$activeTab] !== null) {
1326  $excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1327  } else {
1328  $excel->setActiveSheetIndex(0);
1329  }
1330  }
1331  break;
1332  }
1333 
1334  }
1335 
1336  return $excel;
1337  }
1338 
1339  private function _readColor($color) {
1340  if (isset($color["rgb"])) {
1341  return (string)$color["rgb"];
1342  } else if (isset($color["indexed"])) {
1343  return PHPExcel_Style_Color::indexedColor($color["indexed"])->getARGB();
1344  }
1345  }
1346 
1347  private function _readStyle($docStyle, $style) {
1348  // format code
1349  if ($style->applyNumberFormat) $docStyle->getNumberFormat()->setFormatCode($style->numFmt);
1350 
1351  // font
1352  if (isset($style->font)) {
1353  $docStyle->getFont()->setName((string) $style->font->name["val"]);
1354  $docStyle->getFont()->setSize((string) $style->font->sz["val"]);
1355  if (isset($style->font->b)) {
1356  $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || $style->font->b["val"] == 'true');
1357  }
1358  if (isset($style->font->i)) {
1359  $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || $style->font->i["val"] == 'true');
1360  }
1361  if (isset($style->font->strike)) {
1362  $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || $style->font->strike["val"] == 'true');
1363  }
1364  $docStyle->getFont()->getColor()->setARGB($this->_readColor($style->font->color));
1365 
1366  if (isset($style->font->u) && !isset($style->font->u["val"])) {
1367  $docStyle->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
1368  } else if (isset($style->font->u) && isset($style->font->u["val"])) {
1369  $docStyle->getFont()->setUnderline((string)$style->font->u["val"]);
1370  }
1371 
1372  if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) {
1373  $vertAlign = strtolower((string)$style->font->vertAlign["val"]);
1374  if ($vertAlign == 'superscript') {
1375  $docStyle->getFont()->setSuperScript(true);
1376  }
1377  if ($vertAlign == 'subscript') {
1378  $docStyle->getFont()->setSubScript(true);
1379  }
1380  }
1381  }
1382 
1383  // fill
1384  if (isset($style->fill) && ($style->applyFill || $style instanceof SimpleXMLElement)) {
1385  if ($style->fill->gradientFill) {
1386  $gradientFill = $style->fill->gradientFill[0];
1387  $docStyle->getFill()->setFillType((string) $gradientFill["type"]);
1388  $docStyle->getFill()->setRotation(floatval($gradientFill["degree"]));
1389  $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
1390  $docStyle->getFill()->getStartColor()->setARGB($this->_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=0]"))->color) );
1391  $docStyle->getFill()->getEndColor()->setARGB($this->_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=1]"))->color) );
1392  } elseif ($style->fill->patternFill) {
1393  $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid';
1394  $docStyle->getFill()->setFillType($patternType);
1395  if ($style->fill->patternFill->fgColor) {
1396  $docStyle->getFill()->getStartColor()->setARGB($this->_readColor($style->fill->patternFill->fgColor));
1397  } else {
1398  $docStyle->getFill()->getStartColor()->setARGB('FF000000');
1399  }
1400  if ($style->fill->patternFill->bgColor) {
1401  $docStyle->getFill()->getEndColor()->setARGB($this->_readColor($style->fill->patternFill->bgColor));
1402  }
1403  }
1404  }
1405 
1406  // border
1407  if (isset($style->border) && ($style->applyBorder || $style instanceof SimpleXMLElement)) {
1408  if ($style->border["diagonalUp"] == 'true') {
1409  $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP);
1410  } elseif ($style->border["diagonalDown"] == 'true') {
1411  $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN);
1412  }
1413  $this->_readBorder($docStyle->getBorders()->getLeft(), $style->border->left);
1414  $this->_readBorder($docStyle->getBorders()->getRight(), $style->border->right);
1415  $this->_readBorder($docStyle->getBorders()->getTop(), $style->border->top);
1416  $this->_readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom);
1417  $this->_readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal);
1418  }
1419 
1420  // alignment
1421  if (isset($style->alignment) && ($style->applyAlignment || $style instanceof SimpleXMLElement)) {
1422  $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]);
1423  $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]);
1424 
1425  $textRotation = 0;
1426  if ((int)$style->alignment["textRotation"] <= 90) {
1427  $textRotation = (int)$style->alignment["textRotation"];
1428  } else if ((int)$style->alignment["textRotation"] > 90) {
1429  $textRotation = 90 - (int)$style->alignment["textRotation"];
1430  }
1431 
1432  $docStyle->getAlignment()->setTextRotation(intval($textRotation));
1433  $docStyle->getAlignment()->setWrapText( (string)$style->alignment["wrapText"] == "true" || (string)$style->alignment["wrapText"] == "1" );
1434  $docStyle->getAlignment()->setShrinkToFit( (string)$style->alignment["shrinkToFit"] == "true" || (string)$style->alignment["shrinkToFit"] == "1" );
1435  $docStyle->getAlignment()->setIndent( intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0 );
1436  }
1437 
1438  // protection
1439  if (isset($style->protection) && $style->applyProtection) {
1440  if (isset($style->protection['locked'])) {
1441  if ((string)$style->protection['locked'] == 'true') {
1442  $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED);
1443  } else {
1444  $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED);
1445  }
1446  }
1447 
1448  if (isset($style->protection['hidden'])) {
1449  if ((string)$style->protection['hidden'] == 'true') {
1450  $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED);
1451  } else {
1452  $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED);
1453  }
1454  }
1455  }
1456  }
1457 
1458  private function _readBorder($docBorder, $eleBorder) {
1459  if (isset($eleBorder["style"])) {
1460  $docBorder->setBorderStyle((string) $eleBorder["style"]);
1461  }
1462  if (isset($eleBorder->color)) {
1463  $docBorder->getColor()->setARGB($this->_readColor($eleBorder->color));
1464  }
1465  }
1466 
1467  private function _parseRichText($is = null) {
1468  $value = new PHPExcel_RichText();
1469 
1470  if (isset($is->t)) {
1471  $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $is->t ) );
1472  } else {
1473  foreach ($is->r as $run) {
1474  $objText = $value->createTextRun( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) );
1475 
1476  if (isset($run->rPr)) {
1477  if (isset($run->rPr->rFont["val"])) {
1478  $objText->getFont()->setName((string) $run->rPr->rFont["val"]);
1479  }
1480 
1481  if (isset($run->rPr->sz["val"])) {
1482  $objText->getFont()->setSize((string) $run->rPr->sz["val"]);
1483  }
1484 
1485  if (isset($run->rPr->color)) {
1486  $objText->getFont()->setColor( new PHPExcel_Style_Color( $this->_readColor($run->rPr->color) ) );
1487  }
1488 
1489  if ( (isset($run->rPr->b["val"]) && ((string) $run->rPr->b["val"] == 'true' || (string) $run->rPr->b["val"] == '1'))
1490  || (isset($run->rPr->b) && !isset($run->rPr->b["val"])) ) {
1491  $objText->getFont()->setBold(true);
1492  }
1493 
1494  if ( (isset($run->rPr->i["val"]) && ((string) $run->rPr->i["val"] == 'true' || (string) $run->rPr->i["val"] == '1'))
1495  || (isset($run->rPr->i) && !isset($run->rPr->i["val"])) ) {
1496  $objText->getFont()->setItalic(true);
1497  }
1498 
1499  if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) {
1500  $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]);
1501  if ($vertAlign == 'superscript') {
1502  $objText->getFont()->setSuperScript(true);
1503  }
1504  if ($vertAlign == 'subscript') {
1505  $objText->getFont()->setSubScript(true);
1506  }
1507  }
1508 
1509  if (isset($run->rPr->u) && !isset($run->rPr->u["val"])) {
1510  $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
1511  } else if (isset($run->rPr->u) && isset($run->rPr->u["val"])) {
1512  $objText->getFont()->setUnderline((string)$run->rPr->u["val"]);
1513  }
1514 
1515  if ( (isset($run->rPr->strike["val"]) && ((string) $run->rPr->strike["val"] == 'true' || (string) $run->rPr->strike["val"] == '1'))
1516  || (isset($run->rPr->strike) && !isset($run->rPr->strike["val"])) ) {
1517  $objText->getFont()->setStrikethrough(true);
1518  }
1519  }
1520  }
1521  }
1522 
1523  return $value;
1524  }
1525 
1526  private static function array_item($array, $key = 0) {
1527  return (isset($array[$key]) ? $array[$key] : null);
1528  }
1529 
1530  private static function dir_add($base, $add) {
1531  return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
1532  }
1533 
1534  private static function toCSSArray($style) {
1535  $style = str_replace("\r", "", $style);
1536  $style = str_replace("\n", "", $style);
1537 
1538  $temp = explode(';', $style);
1539 
1540  $style = array();
1541  foreach ($temp as $item) {
1542  $item = explode(':', $item);
1543 
1544  if (strpos($item[1], 'px') !== false) {
1545  $item[1] = str_replace('px', '', $item[1]);
1546  }
1547  if (strpos($item[1], 'pt') !== false) {
1548  $item[1] = str_replace('pt', '', $item[1]);
1549  $item[1] = PHPExcel_Shared_Font::fontSizeToPixels($item[1]);
1550  }
1551  if (strpos($item[1], 'in') !== false) {
1552  $item[1] = str_replace('in', '', $item[1]);
1553  $item[1] = PHPExcel_Shared_Font::inchSizeToPixels($item[1]);
1554  }
1555  if (strpos($item[1], 'cm') !== false) {
1556  $item[1] = str_replace('cm', '', $item[1]);
1557  $item[1] = PHPExcel_Shared_Font::centimeterSizeToPixels($item[1]);
1558  }
1559 
1560  $style[$item[0]] = $item[1];
1561  }
1562 
1563  return $style;
1564  }
1565 }