PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/common/libraries/plugin/phpexcel/PHPExcel/Reader/OOCalc.php

https://bitbucket.org/gugli/chamilo-dev
PHP | 641 lines | 401 code | 55 blank | 185 comment | 52 complexity | 8fc2461e04f52e7cb22e912244f521af MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT, GPL-2.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2011 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Reader
  23. * @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version 1.7.6, 2011-02-27
  26. */
  27. /** PHPExcel root directory */
  28. if (! defined('PHPEXCEL_ROOT'))
  29. {
  30. /**
  31. * @ignore
  32. */
  33. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  34. require (PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  35. }
  36. /**
  37. * PHPExcel_Reader_OOCalc
  38. *
  39. * @category PHPExcel
  40. * @package PHPExcel_Reader
  41. * @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  42. */
  43. class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader
  44. {
  45. /**
  46. * Read data only?
  47. * Identifies whether the Reader should only read data values for cells, and ignore any formatting information;
  48. * or whether it should read both data and formatting
  49. *
  50. * @var boolean
  51. */
  52. private $_readDataOnly = false;
  53. /**
  54. * Restrict which sheets should be loaded?
  55. * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded.
  56. *
  57. * @var array of string
  58. */
  59. private $_loadSheetsOnly = null;
  60. /**
  61. * Formats
  62. *
  63. * @var array
  64. */
  65. private $_styles = array();
  66. /**
  67. * PHPExcel_Reader_IReadFilter instance
  68. *
  69. * @var PHPExcel_Reader_IReadFilter
  70. */
  71. private $_readFilter = null;
  72. /**
  73. * Read data only?
  74. * If this is true, then the Reader will only read data values for cells, it will not read any formatting information.
  75. * If false (the default) it will read data and formatting.
  76. *
  77. * @return boolean
  78. */
  79. public function getReadDataOnly()
  80. {
  81. return $this->_readDataOnly;
  82. }
  83. /**
  84. * Set read data only
  85. * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information.
  86. * Set to false (the default) to advise the Reader to read both data and formatting for cells.
  87. *
  88. * @param boolean $pValue
  89. *
  90. * @return PHPExcel_Reader_OOCalc
  91. */
  92. public function setReadDataOnly($pValue = false)
  93. {
  94. $this->_readDataOnly = $pValue;
  95. return $this;
  96. }
  97. /**
  98. * Get which sheets to load
  99. * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null
  100. * indicating that all worksheets in the workbook should be loaded.
  101. *
  102. * @return mixed
  103. */
  104. public function getLoadSheetsOnly()
  105. {
  106. return $this->_loadSheetsOnly;
  107. }
  108. /**
  109. * Set which sheets to load
  110. *
  111. * @param mixed $value
  112. * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name.
  113. * If NULL, then it tells the Reader to read all worksheets in the workbook
  114. *
  115. * @return PHPExcel_Reader_OOCalc
  116. */
  117. public function setLoadSheetsOnly($value = null)
  118. {
  119. $this->_loadSheetsOnly = is_array($value) ? $value : array($value);
  120. return $this;
  121. }
  122. /**
  123. * Set all sheets to load
  124. * Tells the Reader to load all worksheets from the workbook.
  125. *
  126. * @return PHPExcel_Reader_OOCalc
  127. */
  128. public function setLoadAllSheets()
  129. {
  130. $this->_loadSheetsOnly = null;
  131. return $this;
  132. }
  133. /**
  134. * Read filter
  135. *
  136. * @return PHPExcel_Reader_IReadFilter
  137. */
  138. public function getReadFilter()
  139. {
  140. return $this->_readFilter;
  141. }
  142. /**
  143. * Set read filter
  144. *
  145. * @param PHPExcel_Reader_IReadFilter $pValue
  146. * @return PHPExcel_Reader_OOCalc
  147. */
  148. public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue)
  149. {
  150. $this->_readFilter = $pValue;
  151. return $this;
  152. }
  153. /**
  154. * Create a new PHPExcel_Reader_OOCalc
  155. */
  156. public function __construct()
  157. {
  158. $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
  159. }
  160. /**
  161. * Can the current PHPExcel_Reader_IReader read the file?
  162. *
  163. * @param string $pFileName
  164. * @return boolean
  165. */
  166. public function canRead($pFilename)
  167. {
  168. // Check if zip class exists
  169. if (! class_exists('ZipArchive'))
  170. {
  171. return false;
  172. }
  173. // Check if file exists
  174. if (! file_exists($pFilename))
  175. {
  176. throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
  177. }
  178. // Load file
  179. $zip = new ZipArchive();
  180. if ($zip->open($pFilename) === true)
  181. {
  182. // check if it is an OOXML archive
  183. $mimeType = $zip->getFromName("mimetype");
  184. $zip->close();
  185. return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet');
  186. }
  187. return false;
  188. }
  189. /**
  190. * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
  191. *
  192. * @param string $pFilename
  193. * @throws Exception
  194. */
  195. public function listWorksheetNames($pFilename)
  196. {
  197. // Check if file exists
  198. if (! file_exists($pFilename))
  199. {
  200. throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
  201. }
  202. $worksheetNames = array();
  203. $zip = new ZipArchive();
  204. if ($zip->open($pFilename) === true)
  205. {
  206. $xml = simplexml_load_string($zip->getFromName("content.xml"));
  207. $namespacesContent = $xml->getNamespaces(true);
  208. $workbook = $xml->children($namespacesContent['office']);
  209. foreach ($workbook->body->spreadsheet as $workbookData)
  210. {
  211. $workbookData = $workbookData->children($namespacesContent['table']);
  212. foreach ($workbookData->table as $worksheetDataSet)
  213. {
  214. $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
  215. $worksheetNames[] = $worksheetDataAttributes['name'];
  216. }
  217. }
  218. }
  219. return $worksheetNames;
  220. }
  221. /**
  222. * Loads PHPExcel from file
  223. *
  224. * @param string $pFilename
  225. * @return PHPExcel
  226. * @throws Exception
  227. */
  228. public function load($pFilename)
  229. {
  230. // Create new PHPExcel
  231. $objPHPExcel = new PHPExcel();
  232. // Load into this instance
  233. return $this->loadIntoExisting($pFilename, $objPHPExcel);
  234. }
  235. private static function identifyFixedStyleValue($styleList, &$styleAttributeValue)
  236. {
  237. $styleAttributeValue = strtolower($styleAttributeValue);
  238. foreach ($styleList as $style)
  239. {
  240. if ($styleAttributeValue == strtolower($style))
  241. {
  242. $styleAttributeValue = $style;
  243. return true;
  244. }
  245. }
  246. return false;
  247. }
  248. /**
  249. * Loads PHPExcel from file into PHPExcel instance
  250. *
  251. * @param string $pFilename
  252. * @param PHPExcel $objPHPExcel
  253. * @return PHPExcel
  254. * @throws Exception
  255. */
  256. public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
  257. {
  258. // Check if file exists
  259. if (! file_exists($pFilename))
  260. {
  261. throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
  262. }
  263. $timezoneObj = new DateTimeZone('Europe/London');
  264. $GMT = new DateTimeZone('UTC');
  265. $zip = new ZipArchive();
  266. if ($zip->open($pFilename) === true)
  267. {
  268. // echo '<h1>Meta Information</h1>';
  269. $xml = simplexml_load_string($zip->getFromName("meta.xml"));
  270. $namespacesMeta = $xml->getNamespaces(true);
  271. // echo '<pre>';
  272. // print_r($namespacesMeta);
  273. // echo '</pre><hr />';
  274. $docProps = $objPHPExcel->getProperties();
  275. $officeProperty = $xml->children($namespacesMeta['office']);
  276. foreach ($officeProperty as $officePropertyData)
  277. {
  278. $officePropertyDC = array();
  279. if (isset($namespacesMeta['dc']))
  280. {
  281. $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']);
  282. }
  283. foreach ($officePropertyDC as $propertyName => $propertyValue)
  284. {
  285. switch ($propertyName)
  286. {
  287. case 'title' :
  288. $docProps->setTitle($propertyValue);
  289. break;
  290. case 'subject' :
  291. $docProps->setSubject($propertyValue);
  292. break;
  293. case 'creator' :
  294. $docProps->setCreator($propertyValue);
  295. $docProps->setLastModifiedBy($propertyValue);
  296. break;
  297. case 'date' :
  298. $creationDate = strtotime($propertyValue);
  299. $docProps->setCreated($creationDate);
  300. $docProps->setModified($creationDate);
  301. break;
  302. case 'description' :
  303. $docProps->setDescription($propertyValue);
  304. break;
  305. }
  306. }
  307. $officePropertyMeta = array();
  308. if (isset($namespacesMeta['dc']))
  309. {
  310. $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
  311. }
  312. foreach ($officePropertyMeta as $propertyName => $propertyValue)
  313. {
  314. $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
  315. switch ($propertyName)
  316. {
  317. case 'initial-creator' :
  318. $docProps->setCreator($propertyValue);
  319. break;
  320. case 'keyword' :
  321. $docProps->setKeywords($propertyValue);
  322. break;
  323. case 'creation-date' :
  324. $creationDate = strtotime($propertyValue);
  325. $docProps->setCreated($creationDate);
  326. break;
  327. case 'user-defined' :
  328. $propertyValueType = PHPExcel_DocumentProperties :: PROPERTY_TYPE_STRING;
  329. foreach ($propertyValueAttributes as $key => $value)
  330. {
  331. if ($key == 'name')
  332. {
  333. $propertyValueName = (string) $value;
  334. }
  335. elseif ($key == 'value-type')
  336. {
  337. switch ($value)
  338. {
  339. case 'date' :
  340. $propertyValue = PHPExcel_DocumentProperties :: convertProperty($propertyValue, 'date');
  341. $propertyValueType = PHPExcel_DocumentProperties :: PROPERTY_TYPE_DATE;
  342. break;
  343. case 'boolean' :
  344. $propertyValue = PHPExcel_DocumentProperties :: convertProperty($propertyValue, 'bool');
  345. $propertyValueType = PHPExcel_DocumentProperties :: PROPERTY_TYPE_BOOLEAN;
  346. break;
  347. case 'float' :
  348. $propertyValue = PHPExcel_DocumentProperties :: convertProperty($propertyValue, 'r4');
  349. $propertyValueType = PHPExcel_DocumentProperties :: PROPERTY_TYPE_FLOAT;
  350. break;
  351. default :
  352. $propertyValueType = PHPExcel_DocumentProperties :: PROPERTY_TYPE_STRING;
  353. }
  354. }
  355. }
  356. $docProps->setCustomProperty($propertyValueName, $propertyValue, $propertyValueType);
  357. break;
  358. }
  359. }
  360. }
  361. // echo '<h1>Workbook Content</h1>';
  362. $xml = simplexml_load_string($zip->getFromName("content.xml"));
  363. $namespacesContent = $xml->getNamespaces(true);
  364. // echo '<pre>';
  365. // print_r($namespacesContent);
  366. // echo '</pre><hr />';
  367. $workbook = $xml->children($namespacesContent['office']);
  368. foreach ($workbook->body->spreadsheet as $workbookData)
  369. {
  370. $workbookData = $workbookData->children($namespacesContent['table']);
  371. $worksheetID = 0;
  372. foreach ($workbookData->table as $worksheetDataSet)
  373. {
  374. $worksheetData = $worksheetDataSet->children($namespacesContent['table']);
  375. // print_r($worksheetData);
  376. // echo '<br />';
  377. $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
  378. // print_r($worksheetDataAttributes);
  379. // echo '<br />';
  380. if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && (! in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly)))
  381. {
  382. continue;
  383. }
  384. // echo '<h2>Worksheet '.$worksheetDataAttributes['name'].'</h2>';
  385. // Create new Worksheet
  386. $objPHPExcel->createSheet();
  387. $objPHPExcel->setActiveSheetIndex($worksheetID);
  388. if (isset($worksheetDataAttributes['name']))
  389. {
  390. $worksheetName = (string) $worksheetDataAttributes['name'];
  391. $objPHPExcel->getActiveSheet()->setTitle($worksheetName);
  392. }
  393. $rowID = 1;
  394. foreach ($worksheetData as $key => $rowData)
  395. {
  396. // echo '<b>'.$key.'</b><br />';
  397. switch ($key)
  398. {
  399. case 'table-header-rows' :
  400. foreach ($rowData as $key => $cellData)
  401. {
  402. $rowData = $cellData;
  403. break;
  404. }
  405. case 'table-row' :
  406. $columnID = 'A';
  407. foreach ($rowData as $key => $cellData)
  408. {
  409. if (! is_null($this->getReadFilter()))
  410. {
  411. if (! $this->getReadFilter()->readCell($columnID, $rowID, $worksheetName))
  412. {
  413. continue;
  414. }
  415. }
  416. // echo '<b>'.$columnID.$rowID.'</b><br />';
  417. $cellDataText = $cellData->children($namespacesContent['text']);
  418. $cellDataOffice = $cellData->children($namespacesContent['office']);
  419. $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']);
  420. $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']);
  421. // echo 'Office Attributes: ';
  422. // print_r($cellDataOfficeAttributes);
  423. // echo '<br />Table Attributes: ';
  424. // print_r($cellDataTableAttributes);
  425. // echo '<br />Cell Data Text';
  426. // print_r($cellDataText);
  427. // echo '<br />';
  428. //
  429. $type = $formatting = $hyperlink = null;
  430. $hasCalculatedValue = false;
  431. $cellDataFormula = '';
  432. if (isset($cellDataTableAttributes['formula']))
  433. {
  434. $cellDataFormula = $cellDataTableAttributes['formula'];
  435. $hasCalculatedValue = true;
  436. }
  437. if (isset($cellDataOffice->annotation))
  438. {
  439. // echo 'Cell has comment<br />';
  440. $annotationText = $cellDataOffice->annotation->children($namespacesContent['text']);
  441. $textArray = array();
  442. foreach ($annotationText as $t)
  443. {
  444. foreach ($t->span as $text)
  445. {
  446. $textArray[] = (string) $text;
  447. }
  448. }
  449. $text = implode("\n", $textArray);
  450. // echo $text,'<br />';
  451. $objPHPExcel->getActiveSheet()->getComment($columnID . $rowID)->// ->setAuthor( $author )
  452. setText($this->_parseRichText($text));
  453. }
  454. if (isset($cellDataText->p))
  455. {
  456. // echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />';
  457. switch ($cellDataOfficeAttributes['value-type'])
  458. {
  459. case 'string' :
  460. $type = PHPExcel_Cell_DataType :: TYPE_STRING;
  461. $dataValue = $cellDataText->p;
  462. if (isset($dataValue->a))
  463. {
  464. $dataValue = $dataValue->a;
  465. $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']);
  466. $hyperlink = $cellXLinkAttributes['href'];
  467. }
  468. break;
  469. case 'boolean' :
  470. $type = PHPExcel_Cell_DataType :: TYPE_BOOL;
  471. $dataValue = ($cellDataText->p == 'TRUE') ? True : False;
  472. break;
  473. case 'float' :
  474. $type = PHPExcel_Cell_DataType :: TYPE_NUMERIC;
  475. $dataValue = (float) $cellDataOfficeAttributes['value'];
  476. if (floor($dataValue) == $dataValue)
  477. {
  478. $dataValue = (integer) $dataValue;
  479. }
  480. break;
  481. case 'date' :
  482. $type = PHPExcel_Cell_DataType :: TYPE_NUMERIC;
  483. $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT);
  484. $dateObj->setTimeZone($timezoneObj);
  485. list($year, $month, $day, $hour, $minute, $second) = explode(' ', $dateObj->format('Y m d H i s'));
  486. $dataValue = PHPExcel_Shared_Date :: FormattedPHPToExcel($year, $month, $day, $hour, $minute, $second);
  487. if ($dataValue != floor($dataValue))
  488. {
  489. $formatting = PHPExcel_Style_NumberFormat :: FORMAT_DATE_XLSX15 . ' ' . PHPExcel_Style_NumberFormat :: FORMAT_DATE_TIME4;
  490. }
  491. else
  492. {
  493. $formatting = PHPExcel_Style_NumberFormat :: FORMAT_DATE_XLSX15;
  494. }
  495. break;
  496. case 'time' :
  497. $type = PHPExcel_Cell_DataType :: TYPE_NUMERIC;
  498. $dataValue = PHPExcel_Shared_Date :: PHPToExcel(strtotime('01-01-1970 ' . implode(':', sscanf($cellDataOfficeAttributes['time-value'], 'PT%dH%dM%dS'))));
  499. $formatting = PHPExcel_Style_NumberFormat :: FORMAT_DATE_TIME4;
  500. break;
  501. }
  502. // echo 'Data value is '.$dataValue.'<br />';
  503. // if (!is_null($hyperlink)) {
  504. // echo 'Hyperlink is '.$hyperlink.'<br />';
  505. // }
  506. }
  507. if ($hasCalculatedValue)
  508. {
  509. $type = PHPExcel_Cell_DataType :: TYPE_FORMULA;
  510. // echo 'Formula: '.$cellDataFormula.'<br />';
  511. $cellDataFormula = substr($cellDataFormula, strpos($cellDataFormula, ':=') + 1);
  512. $temp = explode('"', $cellDataFormula);
  513. $tKey = false;
  514. foreach ($temp as &$value)
  515. {
  516. // Only replace in alternate array entries (i.e. non-quoted blocks)
  517. if ($tKey = ! $tKey)
  518. {
  519. $value = preg_replace('/\[\.(.*):\.(.*)\]/Ui', '$1:$2', $value);
  520. $value = preg_replace('/\[\.(.*)\]/Ui', '$1', $value);
  521. $value = PHPExcel_Calculation :: _translateSeparator(';', ',', $value, $inBraces);
  522. }
  523. }
  524. unset($value);
  525. // Then rebuild the formula string
  526. $cellDataFormula = implode('"', $temp);
  527. // echo 'Adjusted Formula: '.$cellDataFormula.'<br />';
  528. }
  529. if (! is_null($type))
  530. {
  531. $objPHPExcel->getActiveSheet()->getCell($columnID . $rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue), $type);
  532. if ($hasCalculatedValue)
  533. {
  534. // echo 'Forumla result is '.$dataValue.'<br />';
  535. $objPHPExcel->getActiveSheet()->getCell($columnID . $rowID)->setCalculatedValue($dataValue);
  536. }
  537. if (($cellDataOfficeAttributes['value-type'] == 'date') || ($cellDataOfficeAttributes['value-type'] == 'time'))
  538. {
  539. $objPHPExcel->getActiveSheet()->getStyle($columnID . $rowID)->getNumberFormat()->setFormatCode($formatting);
  540. }
  541. if (! is_null($hyperlink))
  542. {
  543. $objPHPExcel->getActiveSheet()->getCell($columnID . $rowID)->getHyperlink()->setUrl($hyperlink);
  544. }
  545. }
  546. // Merged cells
  547. if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned'])))
  548. {
  549. $columnTo = $columnID;
  550. if (isset($cellDataTableAttributes['number-columns-spanned']))
  551. {
  552. $columnTo = PHPExcel_Cell :: stringFromColumnIndex(PHPExcel_Cell :: columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] - 2);
  553. }
  554. $rowTo = $rowID;
  555. if (isset($cellDataTableAttributes['number-rows-spanned']))
  556. {
  557. $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1;
  558. }
  559. $cellRange = $columnID . $rowID . ':' . $columnTo . $rowTo;
  560. $objPHPExcel->getActiveSheet()->mergeCells($cellRange);
  561. }
  562. if (isset($cellDataTableAttributes['number-columns-repeated']))
  563. {
  564. // echo 'Repeated '.$cellDataTableAttributes['number-columns-repeated'].' times<br />';
  565. $columnID = PHPExcel_Cell :: stringFromColumnIndex(PHPExcel_Cell :: columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-repeated'] - 2);
  566. }
  567. ++ $columnID;
  568. }
  569. ++ $rowID;
  570. break;
  571. }
  572. }
  573. ++ $worksheetID;
  574. }
  575. }
  576. }
  577. // Return
  578. return $objPHPExcel;
  579. }
  580. private function _parseRichText($is = '')
  581. {
  582. $value = new PHPExcel_RichText();
  583. $value->createText($is);
  584. return $value;
  585. }
  586. }