[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** PHPExcel root directory */ 4 if (!defined('PHPEXCEL_ROOT')) { 5 /** 6 * @ignore 7 */ 8 define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); 9 require (PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); 10 } 11 12 /** 13 * PHPExcel_Reader_Excel2007 14 * 15 * Copyright (c) 2006 - 2015 PHPExcel 16 * 17 * This library is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU Lesser General Public 19 * License as published by the Free Software Foundation; either 20 * version 2.1 of the License, or (at your option) any later version. 21 * 22 * This library is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 * Lesser General Public License for more details. 26 * 27 * You should have received a copy of the GNU Lesser General Public 28 * License along with this library; if not, write to the Free Software 29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 30 * 31 * @category PHPExcel 32 * @package PHPExcel_Reader 33 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) 34 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL 35 * @version ##VERSION##, ##DATE## 36 */ 37 class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader 38 { 39 /** 40 * PHPExcel_ReferenceHelper instance 41 * 42 * @var PHPExcel_ReferenceHelper 43 */ 44 private $referenceHelper = null; 45 46 /** 47 * PHPExcel_Reader_Excel2007_Theme instance 48 * 49 * @var PHPExcel_Reader_Excel2007_Theme 50 */ 51 private static $theme = null; 52 53 /** 54 * Create a new PHPExcel_Reader_Excel2007 instance 55 */ 56 public function __construct() 57 { 58 $this->readFilter = new PHPExcel_Reader_DefaultReadFilter(); 59 $this->referenceHelper = PHPExcel_ReferenceHelper::getInstance(); 60 } 61 62 /** 63 * Can the current PHPExcel_Reader_IReader read the file? 64 * 65 * @param string $pFilename 66 * @return boolean 67 * @throws PHPExcel_Reader_Exception 68 */ 69 public function canRead($pFilename) 70 { 71 // Check if file exists 72 if (!file_exists($pFilename)) { 73 throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); 74 } 75 76 $zipClass = PHPExcel_Settings::getZipClass(); 77 78 // Check if zip class exists 79 // if (!class_exists($zipClass, false)) { 80 // throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); 81 // } 82 83 $xl = false; 84 // Load file 85 $zip = new $zipClass; 86 if ($zip->open($pFilename) === true) { 87 // check if it is an OOXML archive 88 $rels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 89 if ($rels !== false) { 90 foreach ($rels->Relationship as $rel) { 91 switch ($rel["Type"]) { 92 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": 93 if (basename($rel["Target"]) == 'workbook.xml') { 94 $xl = true; 95 } 96 break; 97 98 } 99 } 100 } 101 $zip->close(); 102 } 103 104 return $xl; 105 } 106 107 108 /** 109 * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object 110 * 111 * @param string $pFilename 112 * @throws PHPExcel_Reader_Exception 113 */ 114 public function listWorksheetNames($pFilename) 115 { 116 // Check if file exists 117 if (!file_exists($pFilename)) { 118 throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); 119 } 120 121 $worksheetNames = array(); 122 123 $zipClass = PHPExcel_Settings::getZipClass(); 124 125 $zip = new $zipClass; 126 $zip->open($pFilename); 127 128 // The files we're looking at here are small enough that simpleXML is more efficient than XMLReader 129 $rels = simplexml_load_string( 130 $this->securityScan($this->getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) 131 ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 132 foreach ($rels->Relationship as $rel) { 133 switch ($rel["Type"]) { 134 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": 135 $xmlWorkbook = simplexml_load_string( 136 $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) 137 ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 138 139 if ($xmlWorkbook->sheets) { 140 foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { 141 // Check if sheet should be skipped 142 $worksheetNames[] = (string) $eleSheet["name"]; 143 } 144 } 145 } 146 } 147 148 $zip->close(); 149 150 return $worksheetNames; 151 } 152 153 154 /** 155 * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) 156 * 157 * @param string $pFilename 158 * @throws PHPExcel_Reader_Exception 159 */ 160 public function listWorksheetInfo($pFilename) 161 { 162 // Check if file exists 163 if (!file_exists($pFilename)) { 164 throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); 165 } 166 167 $worksheetInfo = array(); 168 169 $zipClass = PHPExcel_Settings::getZipClass(); 170 171 $zip = new $zipClass; 172 $zip->open($pFilename); 173 174 $rels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 175 foreach ($rels->Relationship as $rel) { 176 if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") { 177 $dir = dirname($rel["Target"]); 178 $relsWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 179 $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); 180 181 $worksheets = array(); 182 foreach ($relsWorkbook->Relationship as $ele) { 183 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") { 184 $worksheets[(string) $ele["Id"]] = $ele["Target"]; 185 } 186 } 187 188 $xmlWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 189 if ($xmlWorkbook->sheets) { 190 $dir = dirname($rel["Target"]); 191 foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { 192 $tmpInfo = array( 193 'worksheetName' => (string) $eleSheet["name"], 194 'lastColumnLetter' => 'A', 195 'lastColumnIndex' => 0, 196 'totalRows' => 0, 197 'totalColumns' => 0, 198 ); 199 200 $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; 201 202 $xml = new XMLReader(); 203 $res = $xml->xml($this->securityScanFile('zip://'.PHPExcel_Shared_File::realpath($pFilename).'#'."$dir/$fileWorksheet"), null, PHPExcel_Settings::getLibXmlLoaderOptions()); 204 $xml->setParserProperty(2, true); 205 206 $currCells = 0; 207 while ($xml->read()) { 208 if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) { 209 $row = $xml->getAttribute('r'); 210 $tmpInfo['totalRows'] = $row; 211 $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells); 212 $currCells = 0; 213 } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) { 214 $currCells++; 215 } 216 } 217 $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells); 218 $xml->close(); 219 220 $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; 221 $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); 222 223 $worksheetInfo[] = $tmpInfo; 224 } 225 } 226 } 227 } 228 229 $zip->close(); 230 231 return $worksheetInfo; 232 } 233 234 private static function castToBoolean($c) 235 { 236 // echo 'Initial Cast to Boolean', PHP_EOL; 237 $value = isset($c->v) ? (string) $c->v : null; 238 if ($value == '0') { 239 return false; 240 } elseif ($value == '1') { 241 return true; 242 } else { 243 return (bool)$c->v; 244 } 245 return $value; 246 } 247 248 private static function castToError($c) 249 { 250 // echo 'Initial Cast to Error', PHP_EOL; 251 return isset($c->v) ? (string) $c->v : null; 252 } 253 254 private static function castToString($c) 255 { 256 // echo 'Initial Cast to String, PHP_EOL; 257 return isset($c->v) ? (string) $c->v : null; 258 } 259 260 private function castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType) 261 { 262 // echo 'Formula', PHP_EOL; 263 // echo '$c->f is ', $c->f, PHP_EOL; 264 $cellDataType = 'f'; 265 $value = "={$c->f}"; 266 $calculatedValue = self::$castBaseType($c); 267 268 // Shared formula? 269 if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') { 270 // echo 'SHARED FORMULA', PHP_EOL; 271 $instance = (string)$c->f['si']; 272 273 // echo 'Instance ID = ', $instance, PHP_EOL; 274 // 275 // echo 'Shared Formula Array:', PHP_EOL; 276 // print_r($sharedFormulas); 277 if (!isset($sharedFormulas[(string)$c->f['si']])) { 278 // echo 'SETTING NEW SHARED FORMULA', PHP_EOL; 279 // echo 'Master is ', $r, PHP_EOL; 280 // echo 'Formula is ', $value, PHP_EOL; 281 $sharedFormulas[$instance] = array('master' => $r, 'formula' => $value); 282 // echo 'New Shared Formula Array:', PHP_EOL; 283 // print_r($sharedFormulas); 284 } else { 285 // echo 'GETTING SHARED FORMULA', PHP_EOL; 286 // echo 'Master is ', $sharedFormulas[$instance]['master'], PHP_EOL; 287 // echo 'Formula is ', $sharedFormulas[$instance]['formula'], PHP_EOL; 288 $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']); 289 $current = PHPExcel_Cell::coordinateFromString($r); 290 291 $difference = array(0, 0); 292 $difference[0] = PHPExcel_Cell::columnIndexFromString($current[0]) - PHPExcel_Cell::columnIndexFromString($master[0]); 293 $difference[1] = $current[1] - $master[1]; 294 295 $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]); 296 // echo 'Adjusted Formula is ', $value, PHP_EOL; 297 } 298 } 299 } 300 301 302 private function getFromZipArchive($archive, $fileName = '') 303 { 304 // Root-relative paths 305 if (strpos($fileName, '//') !== false) { 306 $fileName = substr($fileName, strpos($fileName, '//') + 1); 307 } 308 $fileName = PHPExcel_Shared_File::realpath($fileName); 309 310 // Apache POI fixes 311 $contents = $archive->getFromName($fileName); 312 if ($contents === false) { 313 $contents = $archive->getFromName(substr($fileName, 1)); 314 } 315 316 return $contents; 317 } 318 319 320 /** 321 * Loads PHPExcel from file 322 * 323 * @param string $pFilename 324 * @return PHPExcel 325 * @throws PHPExcel_Reader_Exception 326 */ 327 public function load($pFilename) 328 { 329 // Check if file exists 330 if (!file_exists($pFilename)) { 331 throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); 332 } 333 334 // Initialisations 335 $excel = new PHPExcel; 336 $excel->removeSheetByIndex(0); 337 if (!$this->readDataOnly) { 338 $excel->removeCellStyleXfByIndex(0); // remove the default style 339 $excel->removeCellXfByIndex(0); // remove the default style 340 } 341 342 $zipClass = PHPExcel_Settings::getZipClass(); 343 344 $zip = new $zipClass; 345 $zip->open($pFilename); 346 347 // Read the theme first, because we need the colour scheme when reading the styles 348 $wbRels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 349 foreach ($wbRels->Relationship as $rel) { 350 switch ($rel["Type"]) { 351 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme": 352 $themeOrderArray = array('lt1', 'dk1', 'lt2', 'dk2'); 353 $themeOrderAdditional = count($themeOrderArray); 354 355 $xmlTheme = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "xl/{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 356 if (is_object($xmlTheme)) { 357 $xmlThemeName = $xmlTheme->attributes(); 358 $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); 359 $themeName = (string)$xmlThemeName['name']; 360 361 $colourScheme = $xmlTheme->themeElements->clrScheme->attributes(); 362 $colourSchemeName = (string)$colourScheme['name']; 363 $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); 364 365 $themeColours = array(); 366 foreach ($colourScheme as $k => $xmlColour) { 367 $themePos = array_search($k, $themeOrderArray); 368 if ($themePos === false) { 369 $themePos = $themeOrderAdditional++; 370 } 371 if (isset($xmlColour->sysClr)) { 372 $xmlColourData = $xmlColour->sysClr->attributes(); 373 $themeColours[$themePos] = $xmlColourData['lastClr']; 374 } elseif (isset($xmlColour->srgbClr)) { 375 $xmlColourData = $xmlColour->srgbClr->attributes(); 376 $themeColours[$themePos] = $xmlColourData['val']; 377 } 378 } 379 self::$theme = new PHPExcel_Reader_Excel2007_Theme($themeName, $colourSchemeName, $themeColours); 380 } 381 break; 382 } 383 } 384 385 $rels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 386 foreach ($rels->Relationship as $rel) { 387 switch ($rel["Type"]) { 388 case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": 389 $xmlCore = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 390 if (is_object($xmlCore)) { 391 $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); 392 $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); 393 $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); 394 $docProps = $excel->getProperties(); 395 $docProps->setCreator((string) self::getArrayItem($xmlCore->xpath("dc:creator"))); 396 $docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath("cp:lastModifiedBy"))); 397 $docProps->setCreated(strtotime(self::getArrayItem($xmlCore->xpath("dcterms:created")))); //! respect xsi:type 398 $docProps->setModified(strtotime(self::getArrayItem($xmlCore->xpath("dcterms:modified")))); //! respect xsi:type 399 $docProps->setTitle((string) self::getArrayItem($xmlCore->xpath("dc:title"))); 400 $docProps->setDescription((string) self::getArrayItem($xmlCore->xpath("dc:description"))); 401 $docProps->setSubject((string) self::getArrayItem($xmlCore->xpath("dc:subject"))); 402 $docProps->setKeywords((string) self::getArrayItem($xmlCore->xpath("cp:keywords"))); 403 $docProps->setCategory((string) self::getArrayItem($xmlCore->xpath("cp:category"))); 404 } 405 break; 406 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties": 407 $xmlCore = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 408 if (is_object($xmlCore)) { 409 $docProps = $excel->getProperties(); 410 if (isset($xmlCore->Company)) { 411 $docProps->setCompany((string) $xmlCore->Company); 412 } 413 if (isset($xmlCore->Manager)) { 414 $docProps->setManager((string) $xmlCore->Manager); 415 } 416 } 417 break; 418 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties": 419 $xmlCore = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 420 if (is_object($xmlCore)) { 421 $docProps = $excel->getProperties(); 422 foreach ($xmlCore as $xmlProperty) { 423 $cellDataOfficeAttributes = $xmlProperty->attributes(); 424 if (isset($cellDataOfficeAttributes['name'])) { 425 $propertyName = (string) $cellDataOfficeAttributes['name']; 426 $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); 427 $attributeType = $cellDataOfficeChildren->getName(); 428 $attributeValue = (string) $cellDataOfficeChildren->{$attributeType}; 429 $attributeValue = PHPExcel_DocumentProperties::convertProperty($attributeValue, $attributeType); 430 $attributeType = PHPExcel_DocumentProperties::convertPropertyType($attributeType); 431 $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType); 432 } 433 } 434 } 435 break; 436 //Ribbon 437 case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility": 438 $customUI = $rel['Target']; 439 if (!is_null($customUI)) { 440 $this->readRibbon($excel, $customUI, $zip); 441 } 442 break; 443 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": 444 $dir = dirname($rel["Target"]); 445 $relsWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 446 $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); 447 448 $sharedStrings = array(); 449 $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); 450 $xmlStrings = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 451 if (isset($xmlStrings) && isset($xmlStrings->si)) { 452 foreach ($xmlStrings->si as $val) { 453 if (isset($val->t)) { 454 $sharedStrings[] = PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $val->t); 455 } elseif (isset($val->r)) { 456 $sharedStrings[] = $this->parseRichText($val); 457 } 458 } 459 } 460 461 $worksheets = array(); 462 $macros = $customUI = null; 463 foreach ($relsWorkbook->Relationship as $ele) { 464 switch ($ele['Type']) { 465 case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet": 466 $worksheets[(string) $ele["Id"]] = $ele["Target"]; 467 break; 468 // a vbaProject ? (: some macros) 469 case "http://schemas.microsoft.com/office/2006/relationships/vbaProject": 470 $macros = $ele["Target"]; 471 break; 472 } 473 } 474 475 if (!is_null($macros)) { 476 $macrosCode = $this->getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin 477 if ($macrosCode !== false) { 478 $excel->setMacrosCode($macrosCode); 479 $excel->setHasMacros(true); 480 //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir 481 $Certificate = $this->getFromZipArchive($zip, 'xl/vbaProjectSignature.bin'); 482 if ($Certificate !== false) { 483 $excel->setMacrosCertificate($Certificate); 484 } 485 } 486 } 487 $styles = array(); 488 $cellStyles = array(); 489 $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); 490 $xmlStyles = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 491 //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 492 493 $numFmts = null; 494 if ($xmlStyles && $xmlStyles->numFmts[0]) { 495 $numFmts = $xmlStyles->numFmts[0]; 496 } 497 if (isset($numFmts) && ($numFmts !== null)) { 498 $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 499 } 500 if (!$this->readDataOnly && $xmlStyles) { 501 foreach ($xmlStyles->cellXfs->xf as $xf) { 502 $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; 503 504 if ($xf["numFmtId"]) { 505 if (isset($numFmts)) { 506 $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); 507 508 if (isset($tmpNumFmt["formatCode"])) { 509 $numFmt = (string) $tmpNumFmt["formatCode"]; 510 } 511 } 512 513 // We shouldn't override any of the built-in MS Excel values (values below id 164) 514 // But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used 515 // So we make allowance for them rather than lose formatting masks 516 if ((int)$xf["numFmtId"] < 164 && PHPExcel_Style_NumberFormat::builtInFormatCodeIndex((int)$xf["numFmtId"]) !== false) { 517 $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); 518 } 519 } 520 $quotePrefix = false; 521 if (isset($xf["quotePrefix"])) { 522 $quotePrefix = (boolean) $xf["quotePrefix"]; 523 } 524 525 $style = (object) array( 526 "numFmt" => $numFmt, 527 "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], 528 "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], 529 "border" => $xmlStyles->borders->border[intval($xf["borderId"])], 530 "alignment" => $xf->alignment, 531 "protection" => $xf->protection, 532 "quotePrefix" => $quotePrefix, 533 ); 534 $styles[] = $style; 535 536 // add style to cellXf collection 537 $objStyle = new PHPExcel_Style; 538 self::readStyle($objStyle, $style); 539 $excel->addCellXf($objStyle); 540 } 541 542 foreach ($xmlStyles->cellStyleXfs->xf as $xf) { 543 $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; 544 if ($numFmts && $xf["numFmtId"]) { 545 $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); 546 if (isset($tmpNumFmt["formatCode"])) { 547 $numFmt = (string) $tmpNumFmt["formatCode"]; 548 } elseif ((int)$xf["numFmtId"] < 165) { 549 $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); 550 } 551 } 552 553 $cellStyle = (object) array( 554 "numFmt" => $numFmt, 555 "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], 556 "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], 557 "border" => $xmlStyles->borders->border[intval($xf["borderId"])], 558 "alignment" => $xf->alignment, 559 "protection" => $xf->protection, 560 "quotePrefix" => $quotePrefix, 561 ); 562 $cellStyles[] = $cellStyle; 563 564 // add style to cellStyleXf collection 565 $objStyle = new PHPExcel_Style; 566 self::readStyle($objStyle, $cellStyle); 567 $excel->addCellStyleXf($objStyle); 568 } 569 } 570 571 $dxfs = array(); 572 if (!$this->readDataOnly && $xmlStyles) { 573 // Conditional Styles 574 if ($xmlStyles->dxfs) { 575 foreach ($xmlStyles->dxfs->dxf as $dxf) { 576 $style = new PHPExcel_Style(false, true); 577 self::readStyle($style, $dxf); 578 $dxfs[] = $style; 579 } 580 } 581 // Cell Styles 582 if ($xmlStyles->cellStyles) { 583 foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { 584 if (intval($cellStyle['builtinId']) == 0) { 585 if (isset($cellStyles[intval($cellStyle['xfId'])])) { 586 // Set default style 587 $style = new PHPExcel_Style; 588 self::readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); 589 590 // normal style, currently not using it for anything 591 } 592 } 593 } 594 } 595 } 596 597 $xmlWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 598 599 // Set base date 600 if ($xmlWorkbook->workbookPr) { 601 PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); 602 if (isset($xmlWorkbook->workbookPr['date1904'])) { 603 if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) { 604 PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); 605 } 606 } 607 } 608 609 $sheetId = 0; // keep track of new sheet id in final workbook 610 $oldSheetId = -1; // keep track of old sheet id in final workbook 611 $countSkippedSheets = 0; // keep track of number of skipped sheets 612 $mapSheetId = array(); // mapping of sheet ids from old to new 613 614 $charts = $chartDetails = array(); 615 616 if ($xmlWorkbook->sheets) { 617 foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { 618 ++$oldSheetId; 619 620 // Check if sheet should be skipped 621 if (isset($this->loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->loadSheetsOnly)) { 622 ++$countSkippedSheets; 623 $mapSheetId[$oldSheetId] = null; 624 continue; 625 } 626 627 // Map old sheet id in original workbook to new sheet id. 628 // They will differ if loadSheetsOnly() is being used 629 $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; 630 631 // Load sheet 632 $docSheet = $excel->createSheet(); 633 // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet 634 // references in formula cells... during the load, all formulae should be correct, 635 // and we're simply bringing the worksheet name in line with the formula, not the 636 // reverse 637 $docSheet->setTitle((string) $eleSheet["name"], false); 638 $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; 639 $xmlSheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/$fileWorksheet")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 640 641 $sharedFormulas = array(); 642 643 if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { 644 $docSheet->setSheetState((string) $eleSheet["state"]); 645 } 646 647 if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { 648 if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { 649 $docSheet->getSheetView()->setZoomScale(intval($xmlSheet->sheetViews->sheetView['zoomScale'])); 650 } 651 if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { 652 $docSheet->getSheetView()->setZoomScaleNormal(intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])); 653 } 654 if (isset($xmlSheet->sheetViews->sheetView['view'])) { 655 $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']); 656 } 657 if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { 658 $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines'])); 659 } 660 if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) { 661 $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'])); 662 } 663 if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { 664 $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft'])); 665 } 666 if (isset($xmlSheet->sheetViews->sheetView->pane)) { 667 if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { 668 $docSheet->freezePane((string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell']); 669 } else { 670 $xSplit = 0; 671 $ySplit = 0; 672 673 if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { 674 $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); 675 } 676 677 if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { 678 $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); 679 } 680 681 $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); 682 } 683 } 684 685 if (isset($xmlSheet->sheetViews->sheetView->selection)) { 686 if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { 687 $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; 688 $sqref = explode(' ', $sqref); 689 $sqref = $sqref[0]; 690 $docSheet->setSelectedCells($sqref); 691 } 692 } 693 } 694 695 if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { 696 if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { 697 $docSheet->getTabColor()->setARGB((string)$xmlSheet->sheetPr->tabColor['rgb']); 698 } 699 } 700 if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) { 701 $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']); 702 } 703 if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { 704 if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && 705 !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) { 706 $docSheet->setShowSummaryRight(false); 707 } else { 708 $docSheet->setShowSummaryRight(true); 709 } 710 711 if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && 712 !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) { 713 $docSheet->setShowSummaryBelow(false); 714 } else { 715 $docSheet->setShowSummaryBelow(true); 716 } 717 } 718 719 if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { 720 if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && 721 !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) { 722 $docSheet->getPageSetup()->setFitToPage(false); 723 } else { 724 $docSheet->getPageSetup()->setFitToPage(true); 725 } 726 } 727 728 if (isset($xmlSheet->sheetFormatPr)) { 729 if (isset($xmlSheet->sheetFormatPr['customHeight']) && 730 self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) && 731 isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { 732 $docSheet->getDefaultRowDimension()->setRowHeight((float)$xmlSheet->sheetFormatPr['defaultRowHeight']); 733 } 734 if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { 735 $docSheet->getDefaultColumnDimension()->setWidth((float)$xmlSheet->sheetFormatPr['defaultColWidth']); 736 } 737 if (isset($xmlSheet->sheetFormatPr['zeroHeight']) && 738 ((string)$xmlSheet->sheetFormatPr['zeroHeight'] == '1')) { 739 $docSheet->getDefaultRowDimension()->setZeroHeight(true); 740 } 741 } 742 743 if (isset($xmlSheet->cols) && !$this->readDataOnly) { 744 foreach ($xmlSheet->cols->col as $col) { 745 for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { 746 if ($col["style"] && !$this->readDataOnly) { 747 $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); 748 } 749 if (self::boolean($col["bestFit"])) { 750 //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); 751 } 752 if (self::boolean($col["hidden"])) { 753 // echo PHPExcel_Cell::stringFromColumnIndex($i), ': HIDDEN COLUMN',PHP_EOL; 754 $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); 755 } 756 if (self::boolean($col["collapsed"])) { 757 $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true); 758 } 759 if ($col["outlineLevel"] > 0) { 760 $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); 761 } 762 $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); 763 764 if (intval($col["max"]) == 16384) { 765 break; 766 } 767 } 768 } 769 } 770 771 if (isset($xmlSheet->printOptions) && !$this->readDataOnly) { 772 if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) { 773 $docSheet->setShowGridlines(true); 774 } 775 if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) { 776 $docSheet->setPrintGridlines(true); 777 } 778 if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) { 779 $docSheet->getPageSetup()->setHorizontalCentered(true); 780 } 781 if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) { 782 $docSheet->getPageSetup()->setVerticalCentered(true); 783 } 784 } 785 786 if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { 787 foreach ($xmlSheet->sheetData->row as $row) { 788 if ($row["ht"] && !$this->readDataOnly) { 789 $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); 790 } 791 if (self::boolean($row["hidden"]) && !$this->readDataOnly) { 792 $docSheet->getRowDimension(intval($row["r"]))->setVisible(false); 793 } 794 if (self::boolean($row["collapsed"])) { 795 $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true); 796 } 797 if ($row["outlineLevel"] > 0) { 798 $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); 799 } 800 if ($row["s"] && !$this->readDataOnly) { 801 $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); 802 } 803 804 foreach ($row->c as $c) { 805 $r = (string) $c["r"]; 806 $cellDataType = (string) $c["t"]; 807 $value = null; 808 $calculatedValue = null; 809 810 // Read cell? 811 if ($this->getReadFilter() !== null) { 812 $coordinates = PHPExcel_Cell::coordinateFromString($r); 813 814 if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { 815 continue; 816 } 817 } 818 819 // echo 'Reading cell ', $coordinates[0], $coordinates[1], PHP_EOL; 820 // print_r($c); 821 // echo PHP_EOL; 822 // echo 'Cell Data Type is ', $cellDataType, ': '; 823 // 824 // Read cell! 825 switch ($cellDataType) { 826 case "s": 827 // echo 'String', PHP_EOL; 828 if ((string)$c->v != '') { 829 $value = $sharedStrings[intval($c->v)]; 830 831 if ($value instanceof PHPExcel_RichText) { 832 $value = clone $value; 833 } 834 } else { 835 $value = ''; 836 } 837 break; 838 case "b": 839 // echo 'Boolean', PHP_EOL; 840 if (!isset($c->f)) { 841 $value = self::castToBoolean($c); 842 } else { 843 // Formula 844 $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean'); 845 if (isset($c->f['t'])) { 846 $att = array(); 847 $att = $c->f; 848 $docSheet->getCell($r)->setFormulaAttributes($att); 849 } 850 // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; 851 } 852 break; 853 case "inlineStr": 854 // echo 'Inline String', PHP_EOL; 855 if (isset($c->f)) { 856 $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); 857 } else { 858 $value = $this->parseRichText($c->is); 859 } 860 break; 861 case "e": 862 // echo 'Error', PHP_EOL; 863 if (!isset($c->f)) { 864 $value = self::castToError($c); 865 } else { 866 // Formula 867 $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); 868 // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; 869 } 870 break; 871 default: 872 // echo 'Default', PHP_EOL; 873 if (!isset($c->f)) { 874 // echo 'Not a Formula', PHP_EOL; 875 $value = self::castToString($c); 876 } else { 877 // echo 'Treat as Formula', PHP_EOL; 878 // Formula 879 $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString'); 880 // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; 881 } 882 break; 883 } 884 // echo 'Value is ', $value, PHP_EOL; 885 886 // Check for numeric values 887 if (is_numeric($value) && $cellDataType != 's') { 888 if ($value == (int)$value) { 889 $value = (int)$value; 890 } elseif ($value == (float)$value) { 891 $value = (float)$value; 892 } elseif ($value == (double)$value) { 893 $value = (double)$value; 894 } 895 } 896 897 // Rich text? 898 if ($value instanceof PHPExcel_RichText && $this->readDataOnly) { 899 $value = $value->getPlainText(); 900 } 901 902 $cell = $docSheet->getCell($r); 903 // Assign value 904 if ($cellDataType != '') { 905 $cell->setValueExplicit($value, $cellDataType); 906 } else { 907 $cell->setValue($value); 908 } 909 if ($calculatedValue !== null) { 910 $cell->setCalculatedValue($calculatedValue); 911 } 912 913 // Style information? 914 if ($c["s"] && !$this->readDataOnly) { 915 // no style index means 0, it seems 916 $cell->setXfIndex(isset($styles[intval($c["s"])]) ? 917 intval($c["s"]) : 0); 918 } 919 } 920 } 921 } 922 923 $conditionals = array(); 924 if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { 925 foreach ($xmlSheet->conditionalFormatting as $conditional) { 926 foreach ($conditional->cfRule as $cfRule) { 927 if (((string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) && isset($dxfs[intval($cfRule["dxfId"])])) { 928 $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; 929 } 930 } 931 } 932 933 foreach ($conditionals as $ref => $cfRules) { 934 ksort($cfRules); 935 $conditionalStyles = array(); 936 foreach ($cfRules as $cfRule) { 937 $objConditional = new PHPExcel_Style_Conditional(); 938 $objConditional->setConditionType((string)$cfRule["type"]); 939 $objConditional->setOperatorType((string)$cfRule["operator"]); 940 941 if ((string)$cfRule["text"] != '') { 942 $objConditional->setText((string)$cfRule["text"]); 943 } 944 945 if (count($cfRule->formula) > 1) { 946 foreach ($cfRule->formula as $formula) { 947 $objConditional->addCondition((string)$formula); 948 } 949 } else { 950 $objConditional->addCondition((string)$cfRule->formula); 951 } 952 $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); 953 $conditionalStyles[] = $objConditional; 954 } 955 956 // Extract all cell references in $ref 957 foreach (PHPExcel_Cell::extractAllCellReferencesInRange($ref) as $reference) { 958 $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); 959 } 960 } 961 } 962 963 $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); 964 if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { 965 foreach ($aKeys as $key) { 966 $method = "set" . ucfirst($key); 967 $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key])); 968 } 969 } 970 971 if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { 972 $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); 973 if ($xmlSheet->protectedRanges->protectedRange) { 974 foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { 975 $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); 976 } 977 } 978 } 979 980 if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) { 981 $autoFilterRange = (string) $xmlSheet->autoFilter["ref"]; 982 if (strpos($autoFilterRange, ':') !== false) { 983 $autoFilter = $docSheet->getAutoFilter(); 984 $autoFilter->setRange($autoFilterRange); 985 986 foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) { 987 $column = $autoFilter->getColumnByOffset((integer) $filterColumn["colId"]); 988 // Check for standard filters 989 if ($filterColumn->filters) { 990 $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER); 991 $filters = $filterColumn->filters; 992 if ((isset($filters["blank"])) && ($filters["blank"] == 1)) { 993 // Operator is undefined, but always treated as EQUAL 994 $column->createRule()->setRule(null, '')->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER); 995 } 996 // Standard filters are always an OR join, so no join rule needs to be set 997 // Entries can be either filter elements 998 foreach ($filters->filter as $filterRule) { 999 // Operator is undefined, but always treated as EQUAL 1000 $column->createRule()->setRule(null, (string) $filterRule["val"])->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER); 1001 } 1002 // Or Date Group elements 1003 foreach ($filters->dateGroupItem as $dateGroupItem) { 1004 $column->createRule()->setRule( 1005 // Operator is undefined, but always treated as EQUAL 1006 null, 1007 array( 1008 'year' => (string) $dateGroupItem["year"], 1009 'month' => (string) $dateGroupItem["month"], 1010 'day' => (string) $dateGroupItem["day"], 1011 'hour' => (string) $dateGroupItem["hour"], 1012 'minute' => (string) $dateGroupItem["minute"], 1013 'second' => (string) $dateGroupItem["second"], 1014 ), 1015 (string) $dateGroupItem["dateTimeGrouping"] 1016 ) 1017 ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP); 1018 } 1019 } 1020 // Check for custom filters 1021 if ($filterColumn->customFilters) { 1022 $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER); 1023 $customFilters = $filterColumn->customFilters; 1024 // Custom filters can an AND or an OR join; 1025 // and there should only ever be one or two entries 1026 if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) { 1027 $column->setJoin(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND); 1028 } 1029 foreach ($customFilters->customFilter as $filterRule) { 1030 $column->createRule()->setRule( 1031 (string) $filterRule["operator"], 1032 (string) $filterRule["val"] 1033 ) 1034 ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); 1035 } 1036 } 1037 // Check for dynamic filters 1038 if ($filterColumn->dynamicFilter) { 1039 $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); 1040 // We should only ever have one dynamic filter 1041 foreach ($filterColumn->dynamicFilter as $filterRule) { 1042 $column->createRule()->setRule( 1043 // Operator is undefined, but always treated as EQUAL 1044 null, 1045 (string) $filterRule["val"], 1046 (string) $filterRule["type"] 1047 ) 1048 ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER); 1049 if (isset($filterRule["val"])) { 1050 $column->setAttribute('val', (string) $filterRule["val"]); 1051 } 1052 if (isset($filterRule["maxVal"])) { 1053 $column->setAttribute('maxVal', (string) $filterRule["maxVal"]); 1054 } 1055 } 1056 } 1057 // Check for dynamic filters 1058 if ($filterColumn->top10) { 1059 $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER); 1060 // We should only ever have one top10 filter 1061 foreach ($filterColumn->top10 as $filterRule) { 1062 $column->createRule()->setRule( 1063 (((isset($filterRule["percent"])) && ($filterRule["percent"] == 1)) 1064 ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT 1065 : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE 1066 ), 1067 (string) $filterRule["val"], 1068 (((isset($filterRule["top"])) && ($filterRule["top"] == 1)) 1069 ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP 1070 : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM 1071 ) 1072 ) 1073 ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER); 1074 } 1075 } 1076 } 1077 } 1078 } 1079 1080 if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) { 1081 foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { 1082 $mergeRef = (string) $mergeCell["ref"]; 1083 if (strpos($mergeRef, ':') !== false) { 1084 $docSheet->mergeCells((string) $mergeCell["ref"]); 1085 } 1086 } 1087 } 1088 1089 if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) { 1090 $docPageMargins = $docSheet->getPageMargins(); 1091 $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); 1092 $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); 1093 $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); 1094 $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); 1095 $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); 1096 $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); 1097 } 1098 1099 if ($xmlSheet && $xmlSheet->pageSetup && !$this->readDataOnly) { 1100 $docPageSetup = $docSheet->getPageSetup(); 1101 1102 if (isset($xmlSheet->pageSetup["orientation"])) { 1103 $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); 1104 } 1105 if (isset($xmlSheet->pageSetup["paperSize"])) { 1106 $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); 1107 } 1108 if (isset($xmlSheet->pageSetup["scale"])) { 1109 $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), false); 1110 } 1111 if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { 1112 $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), false); 1113 } 1114 if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { 1115 $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), false); 1116 } 1117 if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && 1118 self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) { 1119 $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); 1120 } 1121 } 1122 1123 if ($xmlSheet && $xmlSheet->headerFooter && !$this->readDataOnly) { 1124 $docHeaderFooter = $docSheet->getHeaderFooter(); 1125 1126 if (isset($xmlSheet->headerFooter["differentOddEven"]) && 1127 self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) { 1128 $docHeaderFooter->setDifferentOddEven(true); 1129 } else { 1130 $docHeaderFooter->setDifferentOddEven(false); 1131 } 1132 if (isset($xmlSheet->headerFooter["differentFirst"]) && 1133 self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) { 1134 $docHeaderFooter->setDifferentFirst(true); 1135 } else { 1136 $docHeaderFooter->setDifferentFirst(false); 1137 } 1138 if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && 1139 !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) { 1140 $docHeaderFooter->setScaleWithDocument(false); 1141 } else { 1142 $docHeaderFooter->setScaleWithDocument(true); 1143 } 1144 if (isset($xmlSheet->headerFooter["alignWithMargins"]) && 1145 !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) { 1146 $docHeaderFooter->setAlignWithMargins(false); 1147 } else { 1148 $docHeaderFooter->setAlignWithMargins(true); 1149 } 1150 1151 $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); 1152 $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); 1153 $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); 1154 $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); 1155 $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); 1156 $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); 1157 } 1158 1159 if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->readDataOnly) { 1160 foreach ($xmlSheet->rowBreaks->brk as $brk) { 1161 if ($brk["man"]) { 1162 $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); 1163 } 1164 } 1165 } 1166 if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->readDataOnly) { 1167 foreach ($xmlSheet->colBreaks->brk as $brk) { 1168 if ($brk["man"]) { 1169 $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex((string) $brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); 1170 } 1171 } 1172 } 1173 1174 if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) { 1175 foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { 1176 // Uppercase coordinate 1177 $range = strtoupper($dataValidation["sqref"]); 1178 $rangeSet = explode(' ', $range); 1179 foreach ($rangeSet as $range) { 1180 $stRange = $docSheet->shrinkRangeToFit($range); 1181 1182 // Extract all cell references in $range 1183 foreach (PHPExcel_Cell::extractAllCellReferencesInRange($stRange) as $reference) { 1184 // Create validation 1185 $docValidation = $docSheet->getCell($reference)->getDataValidation(); 1186 $docValidation->setType((string) $dataValidation["type"]); 1187 $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); 1188 $docValidation->setOperator((string) $dataValidation["operator"]); 1189 $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); 1190 $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); 1191 $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); 1192 $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); 1193 $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); 1194 $docValidation->setError((string) $dataValidation["error"]); 1195 $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); 1196 $docValidation->setPrompt((string) $dataValidation["prompt"]); 1197 $docValidation->setFormula1((string) $dataValidation->formula1); 1198 $docValidation->setFormula2((string) $dataValidation->formula2); 1199 } 1200 } 1201 } 1202 } 1203 1204 // Add hyperlinks 1205 $hyperlinks = array(); 1206 if (!$this->readDataOnly) { 1207 // Locate hyperlink relations 1208 if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { 1209 $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 1210 foreach ($relsWorksheet->Relationship as $ele) { 1211 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { 1212 $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; 1213 } 1214 } 1215 } 1216 1217 // Loop through hyperlinks 1218 if ($xmlSheet && $xmlSheet->hyperlinks) { 1219 foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { 1220 // Link url 1221 $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); 1222 1223 foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { 1224 $cell = $docSheet->getCell($cellReference); 1225 if (isset($linkRel['id'])) { 1226 $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ]; 1227 if (isset($hyperlink['location'])) { 1228 $hyperlinkUrl .= '#' . (string) $hyperlink['location']; 1229 } 1230 $cell->getHyperlink()->setUrl($hyperlinkUrl); 1231 } elseif (isset($hyperlink['location'])) { 1232 $cell->getHyperlink()->setUrl('sheet://' . (string)$hyperlink['location']); 1233 } 1234 1235 // Tooltip 1236 if (isset($hyperlink['tooltip'])) { 1237 $cell->getHyperlink()->setTooltip((string)$hyperlink['tooltip']); 1238 } 1239 } 1240 } 1241 } 1242 } 1243 1244 // Add comments 1245 $comments = array(); 1246 $vmlComments = array(); 1247 if (!$this->readDataOnly) { 1248 // Locate comment relations 1249 if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { 1250 $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 1251 foreach ($relsWorksheet->Relationship as $ele) { 1252 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { 1253 $comments[(string)$ele["Id"]] = (string)$ele["Target"]; 1254 } 1255 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { 1256 $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; 1257 } 1258 } 1259 } 1260 1261 // Loop through comments 1262 foreach ($comments as $relName => $relPath) { 1263 // Load comments file 1264 $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); 1265 $commentsFile = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 1266 1267 // Utility variables 1268 $authors = array(); 1269 1270 // Loop through authors 1271 foreach ($commentsFile->authors->author as $author) { 1272 $authors[] = (string)$author; 1273 } 1274 1275 // Loop through contents 1276 foreach ($commentsFile->commentList->comment as $comment) { 1277 if (!empty($comment['authorId'])) { 1278 $docSheet->getComment((string)$comment['ref'])->setAuthor($authors[(string)$comment['authorId']]); 1279 } 1280 $docSheet->getComment((string)$comment['ref'])->setText($this->parseRichText($comment->text)); 1281 } 1282 } 1283 1284 // Loop through VML comments 1285 foreach ($vmlComments as $relName => $relPath) { 1286 // Load VML comments file 1287 $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); 1288 $vmlCommentsFile = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 1289 $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); 1290 1291 $shapes = $vmlCommentsFile->xpath('//v:shape'); 1292 foreach ($shapes as $shape) { 1293 $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); 1294 1295 if (isset($shape['style'])) { 1296 $style = (string)$shape['style']; 1297 $fillColor = strtoupper(substr((string)$shape['fillcolor'], 1)); 1298 $column = null; 1299 $row = null; 1300 1301 $clientData = $shape->xpath('.//x:ClientData'); 1302 if (is_array($clientData) && !empty($clientData)) { 1303 $clientData = $clientData[0]; 1304 1305 if (isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note') { 1306 $temp = $clientData->xpath('.//x:Row'); 1307 if (is_array($temp)) { 1308 $row = $temp[0]; 1309 } 1310 1311 $temp = $clientData->xpath('.//x:Column'); 1312 if (is_array($temp)) { 1313 $column = $temp[0]; 1314 } 1315 } 1316 } 1317 1318 if (($column !== null) && ($row !== null)) { 1319 // Set comment properties 1320 $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1); 1321 $comment->getFillColor()->setRGB($fillColor); 1322 1323 // Parse style 1324 $styleArray = explode(';', str_replace(' ', '', $style)); 1325 foreach ($styleArray as $stylePair) { 1326 $stylePair = explode(':', $stylePair); 1327 1328 if ($stylePair[0] == 'margin-left') { 1329 $comment->setMarginLeft($stylePair[1]); 1330 } 1331 if ($stylePair[0] == 'margin-top') { 1332 $comment->setMarginTop($stylePair[1]); 1333 } 1334 if ($stylePair[0] == 'width') { 1335 $comment->setWidth($stylePair[1]); 1336 } 1337 if ($stylePair[0] == 'height') { 1338 $comment->setHeight($stylePair[1]); 1339 } 1340 if ($stylePair[0] == 'visibility') { 1341 $comment->setVisible($stylePair[1] == 'visible'); 1342 } 1343 } 1344 } 1345 } 1346 } 1347 } 1348 1349 // Header/footer images 1350 if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->readDataOnly) { 1351 if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { 1352 $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 1353 $vmlRelationship = ''; 1354 1355 foreach ($relsWorksheet->Relationship as $ele) { 1356 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { 1357 $vmlRelationship = self::dirAdd("$dir/$fileWorksheet", $ele["Target"]); 1358 } 1359 } 1360 1361 if ($vmlRelationship != '') { 1362 // Fetch linked images 1363 $relsVML = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 1364 $drawings = array(); 1365 foreach ($relsVML->Relationship as $ele) { 1366 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { 1367 $drawings[(string) $ele["Id"]] = self::dirAdd($vmlRelationship, $ele["Target"]); 1368 } 1369 } 1370 1371 // Fetch VML document 1372 $vmlDrawing = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $vmlRelationship)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 1373 $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); 1374 1375 $hfImages = array(); 1376 1377 $shapes = $vmlDrawing->xpath('//v:shape'); 1378 foreach ($shapes as $idx => $shape) { 1379 $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); 1380 $imageData = $shape->xpath('//v:imagedata'); 1381 $imageData = $imageData[$idx]; 1382 1383 $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); 1384 $style = self::toCSSArray((string)$shape['style']); 1385 1386 $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); 1387 if (isset($imageData['title'])) { 1388 $hfImages[ (string)$shape['id'] ]->setName((string)$imageData['title']); 1389 } 1390 1391 $hfImages[ (string)$shape['id'] ]->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false); 1392 $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); 1393 $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); 1394 $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); 1395 if (isset($style['margin-left'])) { 1396 $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); 1397 } 1398 $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); 1399 $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); 1400 } 1401 1402 $docSheet->getHeaderFooter()->setImages($hfImages); 1403 } 1404 } 1405 } 1406 1407 } 1408 1409 // TODO: Autoshapes from twoCellAnchors! 1410 if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { 1411 $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 1412 $drawings = array(); 1413 foreach ($relsWorksheet->Relationship as $ele) { 1414 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { 1415 $drawings[(string) $ele["Id"]] = self::dirAdd("$dir/$fileWorksheet", $ele["Target"]); 1416 } 1417 } 1418 if ($xmlSheet->drawing && !$this->readDataOnly) { 1419 foreach ($xmlSheet->drawing as $drawing) { 1420 $fileDrawing = $drawings[(string) self::getArrayItem($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; 1421 $relsDrawing = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); 1422 $images = array(); 1423 1424 if ($relsDrawing && $relsDrawing->Relationship) { 1425 foreach ($relsDrawing->Relationship as $ele) { 1426 if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { 1427 $images[(string) $ele["Id"]] = self::dirAdd($fileDrawing, $ele["Target"]); 1428 } elseif ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart") { 1429 if ($this->includeCharts) { 1430 $charts[self::dirAdd($fileDrawing, $ele["Target"])] = array( 1431 'id' => (string) $ele["Id"], 1432 'sheet' => $docSheet->getTitle() 1433 ); 1434 } 1435 } 1436 } 1437 } 1438 $xmlDrawing = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $fileDrawing)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); 1439 1440 if ($xmlDrawing->oneCellAnchor) { 1441 foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { 1442 if ($oneCellAnchor->pic->blipFill) { 1443 $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; 1444 $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; 1445 $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; 1446 $objDrawing = new PHPExcel_Worksheet_Drawing; 1447 $objDrawing->setName((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); 1448 $objDrawing->setDescription((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); 1449 $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::getArrayItem($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); 1450 $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); 1451 $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); 1452 $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); 1453 $objDrawing->setResizeProportional(false); 1454 $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cx"))); 1455 $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cy"))); 1456 if ($xfrm) { 1457 $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), "rot"))); 1458 } 1459 if ($outerShdw) { 1460 $shadow = $objDrawing->getShadow(); 1461 $shadow->setVisible(true); 1462 $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "blurRad"))); 1463 $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "dist"))); 1464 $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), "dir"))); 1465 $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), "algn")); 1466 $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), "val")); 1467 $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); 1468 } 1469 $objDrawing->setWorksheet($docSheet); 1470 } else { 1471 // ? Can charts be positioned with a oneCellAnchor ? 1472 $coordinates = PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1); 1473 $offsetX = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff); 1474 $offsetY = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff); 1475 $width = PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cx")); 1476 $height = PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cy")); 1477 } 1478 } 1479 } 1480 if ($xmlDrawing->twoCellAnchor) { 1481 foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { 1482 if ($twoCellAnchor->pic->blipFill) { 1483 $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; 1484 $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; 1485 $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; 1486 $objDrawing = new PHPExcel_Worksheet_Drawing; 1487 $objDrawing->setName((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); 1488 $objDrawing->setDescription((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); 1489 $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::getArrayItem($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); 1490 $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); 1491 $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); 1492 $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); 1493 $objDrawing->setResizeProportional(false); 1494 1495 if ($xfrm) { 1496 $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), "cx"))); 1497 $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), "cy"))); 1498 $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), "rot"))); 1499 } 1500 if ($outerShdw) { 1501 $shadow = $objDrawing->getShadow(); 1502 $shadow->setVisible(true); 1503 $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "blurRad"))); 1504 $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "dist"))); 1505 $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), "dir"))); 1506 $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), "algn")); 1507 $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), "val")); 1508 $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); 1509 } 1510 $objDrawing->setWorksheet($docSheet); 1511 } elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) { 1512 $fromCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1); 1513 $fromOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff); 1514 $fromOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff); 1515 $toCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1); 1516 $toOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->colOff); 1517 $toOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->rowOff); 1518 $graphic = $twoCellAnchor->graphicFrame->children("http://schemas.openxmlformats.org/drawingml/2006/main")->graphic; 1519 $chartRef = $graphic->graphicData->children("http://schemas.openxmlformats.org/drawingml/2006/chart")->chart; 1520 $thisChart = (string) $chartRef->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"); 1521 1522 $chartDetails[$docSheet->getTitle().'!'.$thisChart] = array( 1523 'fromCoordinate' => $fromCoordinate, 1524 'fromOffsetX' => $fromOffsetX, 1525 'fromOffsetY' => $fromOffsetY, 1526 'toCoordinate' => $toCoordinate, 1527 'toOffsetX' => $toOffsetX, 1528 'toOffsetY' => $toOffsetY, 1529 'worksheetTitle' => $docSheet->getTitle() 1530 ); 1531 } 1532 } 1533 } 1534 } 1535 } 1536 } 1537 1538 // Loop through definedNames 1539 if ($xmlWorkbook->definedNames) { 1540 foreach ($xmlWorkbook->definedNames->definedName as $definedName) { 1541 // Extract range 1542 $extractedRange = (string)$definedName; 1543 $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); 1544 if (($spos = strpos($extractedRange, '!')) !== false) { 1545 $extractedRange = substr($extractedRange, 0, $spos).str_replace('$', '', substr($extractedRange, $spos)); 1546 } else { 1547 $extractedRange = str_replace('$', '', $extractedRange); 1548 } 1549 1550 // Valid range? 1551 if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { 1552 continue; 1553 } 1554 1555 // Some definedNames are only applicable if we are on the same sheet... 1556 if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { 1557 // Switch on type 1558 switch ((string)$definedName['name']) { 1559 case '_xlnm._FilterDatabase': 1560 if ((string)$definedName['hidden'] !== '1') { 1561 $extractedRange = explode(',', $extractedRange); 1562 foreach ($extractedRange as $range) { 1563 $autoFilterRange = $range; 1564 if (strpos($autoFilterRange, ':') !== false) { 1565 $docSheet->getAutoFilter()->setRange($autoFilterRange); 1566 } 1567 } 1568 } 1569 break; 1570 case '_xlnm.Print_Titles': 1571 // Split $extractedRange 1572 $extractedRange = explode(',', $extractedRange); 1573 1574 // Set print titles 1575 foreach ($extractedRange as $range) { 1576 $matches = array(); 1577 $range = str_replace('$', '', $range); 1578 1579 // check for repeating columns, e g. 'A:A' or 'A:D' 1580 if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { 1581 $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2])); 1582 } elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) { 1583 // check for repeating rows, e.g. '1:1' or '1:5' 1584 $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2])); 1585 } 1586 } 1587 break; 1588 case '_xlnm.Print_Area': 1589 $rangeSets = explode(',', $extractedRange); // FIXME: what if sheetname contains comma? 1590 $newRangeSets = array(); 1591 foreach ($rangeSets as $rangeSet) { 1592 $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark? 1593 $rangeSet = isset($range[1]) ? $range[1] : $range[0]; 1594 if (strpos($rangeSet, ':') === false) { 1595 $rangeSet = $rangeSet . ':' . $rangeSet; 1596 } 1597 $newRangeSets[] = str_replace('$', '', $rangeSet); 1598 } 1599 $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets)); 1600 break; 1601 1602 default: 1603 break; 1604 } 1605 } 1606 } 1607 } 1608 1609 // Next sheet id 1610 ++$sheetId; 1611 } 1612 1613 // Loop through definedNames 1614 if ($xmlWorkbook->definedNames) { 1615 foreach ($xmlWorkbook->definedNames->definedName as $definedName) { 1616 // Extract range 1617 $extractedRange = (string)$definedName; 1618 $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); 1619 if (($spos = strpos($extractedRange, '!')) !== false) { 1620 $extractedRange = substr($extractedRange, 0, $spos).str_replace('$', '', substr($extractedRange, $spos)); 1621 } else { 1622 $extractedRange = str_replace('$', '', $extractedRange); 1623 } 1624 1625 // Valid range? 1626 if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { 1627 continue; 1628 } 1629 1630 // Some definedNames are only applicable if we are on the same sheet... 1631 if ((string)$definedName['localSheetId'] != '') { 1632 // Local defined name 1633 // Switch on type 1634 switch ((string)$definedName['name']) { 1635 case '_xlnm._FilterDatabase': 1636 case '_xlnm.Print_Titles': 1637 case '_xlnm.Print_Area': 1638 break; 1639 default: 1640 if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) { 1641 $range = explode('!', (string)$definedName); 1642 if (count($range) == 2) { 1643 $range[0] = str_replace("''", "'", $range[0]); 1644 $range[0] = str_replace("'", "", $range[0]); 1645 if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { 1646 $extractedRange = str_replace('$', '', $range[1]); 1647 $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]); 1648 $excel->addNamedRange(new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope)); 1649 } 1650 } 1651 } 1652 break; 1653 } 1654 } elseif (!isset($definedName['localSheetId'])) { 1655 // "Global" definedNames 1656 $locatedSheet = null; 1657 $extractedSheetName = ''; 1658 if (strpos((string)$definedName, '!') !== false) { 1659 // Extract sheet name 1660 $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle((string)$definedName, true); 1661 $extractedSheetName = $extractedSheetName[0]; 1662 1663 // Locate sheet 1664 $locatedSheet = $excel->getSheetByName($extractedSheetName); 1665 1666 // Modify range 1667 $range = explode('!', $extractedRange); 1668 $extractedRange = isset($range[1]) ? $range[1] : $range[0]; 1669 } 1670 1671 if ($locatedSheet !== null) { 1672 $excel->addNamedRange(new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false)); 1673 } 1674 } 1675 } 1676 } 1677 } 1678 1679 if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) { 1680 // active sheet index 1681 $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index 1682 1683 // keep active sheet index if sheet is still loaded, else first sheet is set as the active 1684 if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) { 1685 $excel->setActiveSheetIndex($mapSheetId[$activeTab]); 1686 } else { 1687 if ($excel->getSheetCount() == 0) { 1688 $excel->createSheet(); 1689 } 1690 $excel->setActiveSheetIndex(0); 1691 } 1692 } 1693 break; 1694 } 1695 } 1696 1697 if (!$this->readDataOnly) { 1698 $contentTypes = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "[Content_Types].xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 1699 foreach ($contentTypes->Override as $contentType) { 1700 switch ($contentType["ContentType"]) { 1701 case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": 1702 if ($this->includeCharts) { 1703 $chartEntryRef = ltrim($contentType['PartName'], '/'); 1704 $chartElements = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $chartEntryRef)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 1705 $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements, basename($chartEntryRef, '.xml')); 1706 1707 // echo 'Chart ', $chartEntryRef, '<br />'; 1708 // var_dump($charts[$chartEntryRef]); 1709 // 1710 if (isset($charts[$chartEntryRef])) { 1711 $chartPositionRef = $charts[$chartEntryRef]['sheet'].'!'.$charts[$chartEntryRef]['id']; 1712 // echo 'Position Ref ', $chartPositionRef, '<br />'; 1713 if (isset($chartDetails[$chartPositionRef])) { 1714 // var_dump($chartDetails[$chartPositionRef]); 1715 1716 $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart); 1717 $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet'])); 1718 $objChart->setTopLeftPosition($chartDetails[$chartPositionRef]['fromCoordinate'], $chartDetails[$chartPositionRef]['fromOffsetX'], $chartDetails[$chartPositionRef]['fromOffsetY']); 1719 $objChart->setBottomRightPosition($chartDetails[$chartPositionRef]['toCoordinate'], $chartDetails[$chartPositionRef]['toOffsetX'], $chartDetails[$chartPositionRef]['toOffsetY']); 1720 } 1721 } 1722 } 1723 } 1724 } 1725 } 1726 1727 $zip->close(); 1728 1729 return $excel; 1730 } 1731 1732 private static function readColor($color, $background = false) 1733 { 1734 if (isset($color["rgb"])) { 1735 return (string)$color["rgb"]; 1736 } elseif (isset($color["indexed"])) { 1737 return PHPExcel_Style_Color::indexedColor($color["indexed"]-7, $background)->getARGB(); 1738 } elseif (isset($color["theme"])) { 1739 if (self::$theme !== null) { 1740 $returnColour = self::$theme->getColourByIndex((int)$color["theme"]); 1741 if (isset($color["tint"])) { 1742 $tintAdjust = (float) $color["tint"]; 1743 $returnColour = PHPExcel_Style_Color::changeBrightness($returnColour, $tintAdjust); 1744 } 1745 return 'FF'.$returnColour; 1746 } 1747 } 1748 1749 if ($background) { 1750 return 'FFFFFFFF'; 1751 } 1752 return 'FF000000'; 1753 } 1754 1755 private static function readStyle($docStyle, $style) 1756 { 1757 // format code 1758 // if (isset($style->numFmt)) { 1759 // if (isset($style->numFmt['formatCode'])) { 1760 // $docStyle->getNumberFormat()->setFormatCode((string) $style->numFmt['formatCode']); 1761 // } else { 1762 $docStyle->getNumberFormat()->setFormatCode($style->numFmt); 1763 // } 1764 // } 1765 1766 // font 1767 if (isset($style->font)) { 1768 $docStyle->getFont()->setName((string) $style->font->name["val"]); 1769 $docStyle->getFont()->setSize((string) $style->font->sz["val"]); 1770 if (isset($style->font->b)) { 1771 $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"])); 1772 } 1773 if (isset($style->font->i)) { 1774 $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"])); 1775 } 1776 if (isset($style->font->strike)) { 1777 $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"])); 1778 } 1779 $docStyle->getFont()->getColor()->setARGB(self::readColor($style->font->color)); 1780 1781 if (isset($style->font->u) && !isset($style->font->u["val"])) { 1782 $docStyle->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); 1783 } elseif (isset($style->font->u) && isset($style->font->u["val"])) { 1784 $docStyle->getFont()->setUnderline((string)$style->font->u["val"]); 1785 } 1786 1787 if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) { 1788 $vertAlign = strtolower((string)$style->font->vertAlign["val"]); 1789 if ($vertAlign == 'superscript') { 1790 $docStyle->getFont()->setSuperScript(true); 1791 } 1792 if ($vertAlign == 'subscript') { 1793 $docStyle->getFont()->setSubScript(true); 1794 } 1795 } 1796 } 1797 1798 // fill 1799 if (isset($style->fill)) { 1800 if ($style->fill->gradientFill) { 1801 $gradientFill = $style->fill->gradientFill[0]; 1802 if (!empty($gradientFill["type"])) { 1803 $docStyle->getFill()->setFillType((string) $gradientFill["type"]); 1804 } 1805 $docStyle->getFill()->setRotation(floatval($gradientFill["degree"])); 1806 $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); 1807 $docStyle->getFill()->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath("sml:stop[@position=0]"))->color)); 1808 $docStyle->getFill()->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath("sml:stop[@position=1]"))->color)); 1809 } elseif ($style->fill->patternFill) { 1810 $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid'; 1811 $docStyle->getFill()->setFillType($patternType); 1812 if ($style->fill->patternFill->fgColor) { 1813 $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true)); 1814 } else { 1815 $docStyle->getFill()->getStartColor()->setARGB('FF000000'); 1816 } 1817 if ($style->fill->patternFill->bgColor) { 1818 $docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true)); 1819 } 1820 } 1821 } 1822 1823 // border 1824 if (isset($style->border)) { 1825 $diagonalUp = self::boolean((string) $style->border["diagonalUp"]); 1826 $diagonalDown = self::boolean((string) $style->border["diagonalDown"]); 1827 if (!$diagonalUp && !$diagonalDown) { 1828 $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); 1829 } elseif ($diagonalUp && !$diagonalDown) { 1830 $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); 1831 } elseif (!$diagonalUp && $diagonalDown) { 1832 $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); 1833 } else { 1834 $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); 1835 } 1836 self::readBorder($docStyle->getBorders()->getLeft(), $style->border->left); 1837 self::readBorder($docStyle->getBorders()->getRight(), $style->border->right); 1838 self::readBorder($docStyle->getBorders()->getTop(), $style->border->top); 1839 self::readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom); 1840 self::readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal); 1841 } 1842 1843 // alignment 1844 if (isset($style->alignment)) { 1845 $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]); 1846 $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]); 1847 1848 $textRotation = 0; 1849 if ((int)$style->alignment["textRotation"] <= 90) { 1850 $textRotation = (int)$style->alignment["textRotation"]; 1851 } elseif ((int)$style->alignment["textRotation"] > 90) { 1852 $textRotation = 90 - (int)$style->alignment["textRotation"]; 1853 } 1854 1855 $docStyle->getAlignment()->setTextRotation(intval($textRotation)); 1856 $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"])); 1857 $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"])); 1858 $docStyle->getAlignment()->setIndent(intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0); 1859 $docStyle->getAlignment()->setReadorder(intval((string)$style->alignment["readingOrder"]) > 0 ? intval((string)$style->alignment["readingOrder"]) : 0); 1860 } 1861 1862 // protection 1863 if (isset($style->protection)) { 1864 if (isset($style->protection['locked'])) { 1865 if (self::boolean((string) $style->protection['locked'])) { 1866 $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); 1867 } else { 1868 $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); 1869 } 1870 } 1871 1872 if (isset($style->protection['hidden'])) { 1873 if (self::boolean((string) $style->protection['hidden'])) { 1874 $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED); 1875 } else { 1876 $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); 1877 } 1878 } 1879 } 1880 1881 // top-level style settings 1882 if (isset($style->quotePrefix)) { 1883 $docStyle->setQuotePrefix($style->quotePrefix); 1884 } 1885 } 1886 1887 private static function readBorder($docBorder, $eleBorder) 1888 { 1889 if (isset($eleBorder["style"])) { 1890 $docBorder->setBorderStyle((string) $eleBorder["style"]); 1891 } 1892 if (isset($eleBorder->color)) { 1893 $docBorder->getColor()->setARGB(self::readColor($eleBorder->color)); 1894 } 1895 } 1896 1897 private function parseRichText($is = null) 1898 { 1899 $value = new PHPExcel_RichText(); 1900 1901 if (isset($is->t)) { 1902 $value->createText(PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $is->t)); 1903 } else { 1904 if (is_object($is->r)) { 1905 foreach ($is->r as $run) { 1906 if (!isset($run->rPr)) { 1907 $objText = $value->createText(PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $run->t)); 1908 1909 } else { 1910 $objText = $value->createTextRun(PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $run->t)); 1911 1912 if (isset($run->rPr->rFont["val"])) { 1913 $objText->getFont()->setName((string) $run->rPr->rFont["val"]); 1914 } 1915 if (isset($run->rPr->sz["val"])) { 1916 $objText->getFont()->setSize((string) $run->rPr->sz["val"]); 1917 } 1918 if (isset($run->rPr->color)) { 1919 $objText->getFont()->setColor(new PHPExcel_Style_Color(self::readColor($run->rPr->color))); 1920 } 1921 if ((isset($run->rPr->b["val"]) && self::boolean((string) $run->rPr->b["val"])) || 1922 (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) { 1923 $objText->getFont()->setBold(true); 1924 } 1925 if ((isset($run->rPr->i["val"]) && self::boolean((string) $run->rPr->i["val"])) || 1926 (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) { 1927 $objText->getFont()->setItalic(true); 1928 } 1929 if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) { 1930 $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]); 1931 if ($vertAlign == 'superscript') { 1932 $objText->getFont()->setSuperScript(true); 1933 } 1934 if ($vertAlign == 'subscript') { 1935 $objText->getFont()->setSubScript(true); 1936 } 1937 } 1938 if (isset($run->rPr->u) && !isset($run->rPr->u["val"])) { 1939 $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); 1940 } elseif (isset($run->rPr->u) && isset($run->rPr->u["val"])) { 1941 $objText->getFont()->setUnderline((string)$run->rPr->u["val"]); 1942 } 1943 if ((isset($run->rPr->strike["val"]) && self::boolean((string) $run->rPr->strike["val"])) || 1944 (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) { 1945 $objText->getFont()->setStrikethrough(true); 1946 } 1947 } 1948 } 1949 } 1950 } 1951 1952 return $value; 1953 } 1954 1955 private function readRibbon($excel, $customUITarget, $zip) 1956 { 1957 $baseDir = dirname($customUITarget); 1958 $nameCustomUI = basename($customUITarget); 1959 // get the xml file (ribbon) 1960 $localRibbon = $this->getFromZipArchive($zip, $customUITarget); 1961 $customUIImagesNames = array(); 1962 $customUIImagesBinaries = array(); 1963 // something like customUI/_rels/customUI.xml.rels 1964 $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels'; 1965 $dataRels = $this->getFromZipArchive($zip, $pathRels); 1966 if ($dataRels) { 1967 // exists and not empty if the ribbon have some pictures (other than internal MSO) 1968 $UIRels = simplexml_load_string($this->securityScan($dataRels), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); 1969 if ($UIRels) { 1970 // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image 1971 foreach ($UIRels->Relationship as $ele) { 1972 if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') { 1973 // an image ? 1974 $customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target']; 1975 $customUIImagesBinaries[(string)$ele['Target']] = $this->getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']); 1976 } 1977 } 1978 } 1979 } 1980 if ($localRibbon) { 1981 $excel->setRibbonXMLData($customUITarget, $localRibbon); 1982 if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) { 1983 $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries); 1984 } else { 1985 $excel->setRibbonBinObjects(null); 1986 } 1987 } else { 1988 $excel->setRibbonXMLData(null); 1989 $excel->setRibbonBinObjects(null); 1990 } 1991 } 1992 1993 private static function getArrayItem($array, $key = 0) 1994 { 1995 return (isset($array[$key]) ? $array[$key] : null); 1996 } 1997 1998 private static function dirAdd($base, $add) 1999 { 2000 return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add"); 2001 } 2002 2003 private static function toCSSArray($style) 2004 { 2005 $style = str_replace(array("\r","\n"), "", $style); 2006 2007 $temp = explode(';', $style); 2008 $style = array(); 2009 foreach ($temp as $item) { 2010 $item = explode(':', $item); 2011 2012 if (strpos($item[1], 'px') !== false) { 2013 $item[1] = str_replace('px', '', $item[1]); 2014 } 2015 if (strpos($item[1], 'pt') !== false) { 2016 $item[1] = str_replace('pt', '', $item[1]); 2017 $item[1] = PHPExcel_Shared_Font::fontSizeToPixels($item[1]); 2018 } 2019 if (strpos($item[1], 'in') !== false) { 2020 $item[1] = str_replace('in', '', $item[1]); 2021 $item[1] = PHPExcel_Shared_Font::inchSizeToPixels($item[1]); 2022 } 2023 if (strpos($item[1], 'cm') !== false) { 2024 $item[1] = str_replace('cm', '', $item[1]); 2025 $item[1] = PHPExcel_Shared_Font::centimeterSizeToPixels($item[1]); 2026 } 2027 2028 $style[$item[0]] = $item[1]; 2029 } 2030 2031 return $style; 2032 } 2033 2034 private static function boolean($value = null) 2035 { 2036 if (is_object($value)) { 2037 $value = (string) $value; 2038 } 2039 if (is_numeric($value)) { 2040 return (bool) $value; 2041 } 2042 return ($value === 'true' || $value === 'TRUE'); 2043 } 2044 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |