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

/plugins/sfPhpExcelPlugin/lib/PHPExcel/PHPExcel/Reader/SYLK.php

https://github.com/bshaffer/Donate-Nashville
PHP | 509 lines | 268 code | 44 blank | 197 comment | 47 complexity | a32eff8e5c77b6dfae9b614541281fc6 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2010 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 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. /** PHPExcel root directory */
  28. if (!defined('PHPEXCEL_ROOT')) {
  29. /**
  30. * @ignore
  31. */
  32. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  33. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  34. PHPExcel_Autoloader::Register();
  35. PHPExcel_Shared_ZipStreamWrapper::register();
  36. // check mbstring.func_overload
  37. if (ini_get('mbstring.func_overload') & 2) {
  38. throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
  39. }
  40. }
  41. /**
  42. * PHPExcel_Reader_SYLK
  43. *
  44. * @category PHPExcel
  45. * @package PHPExcel_Reader
  46. * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
  47. */
  48. class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader
  49. {
  50. /**
  51. * Input encoding
  52. *
  53. * @var string
  54. */
  55. private $_inputEncoding;
  56. /**
  57. * Delimiter
  58. *
  59. * @var string
  60. */
  61. private $_delimiter;
  62. /**
  63. * Enclosure
  64. *
  65. * @var string
  66. */
  67. private $_enclosure;
  68. /**
  69. * Line ending
  70. *
  71. * @var string
  72. */
  73. private $_lineEnding;
  74. /**
  75. * Sheet index to read
  76. *
  77. * @var int
  78. */
  79. private $_sheetIndex;
  80. /**
  81. * Formats
  82. *
  83. * @var array
  84. */
  85. private $_formats = array();
  86. /**
  87. * Format Count
  88. *
  89. * @var int
  90. */
  91. private $_format = 0;
  92. /**
  93. * PHPExcel_Reader_IReadFilter instance
  94. *
  95. * @var PHPExcel_Reader_IReadFilter
  96. */
  97. private $_readFilter = null;
  98. /**
  99. * Create a new PHPExcel_Reader_SYLK
  100. */
  101. public function __construct() {
  102. $this->_inputEncoding = 'ANSI';
  103. $this->_delimiter = ';';
  104. $this->_enclosure = '"';
  105. $this->_lineEnding = PHP_EOL;
  106. $this->_sheetIndex = 0;
  107. $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
  108. }
  109. /**
  110. * Can the current PHPExcel_Reader_IReader read the file?
  111. *
  112. * @param string $pFileName
  113. * @return boolean
  114. */
  115. public function canRead($pFilename)
  116. {
  117. // Check if file exists
  118. if (!file_exists($pFilename)) {
  119. throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
  120. }
  121. // Read sample data (first 2 KB will do)
  122. $fh = fopen($pFilename, 'r');
  123. $data = fread($fh, 2048);
  124. fclose($fh);
  125. // Count delimiters in file
  126. $delimiterCount = substr_count($data, ';');
  127. if ($delimiterCount < 1) {
  128. return false;
  129. }
  130. // Analyze first line looking for ID; signature
  131. $lines = explode("\n", $data);
  132. if (substr($lines[0],0,4) != 'ID;P') {
  133. return false;
  134. }
  135. return true;
  136. }
  137. /**
  138. * Loads PHPExcel from file
  139. *
  140. * @param string $pFilename
  141. * @return PHPExcel
  142. * @throws Exception
  143. */
  144. public function load($pFilename)
  145. {
  146. // Create new PHPExcel
  147. $objPHPExcel = new PHPExcel();
  148. // Load into this instance
  149. return $this->loadIntoExisting($pFilename, $objPHPExcel);
  150. }
  151. /**
  152. * Read filter
  153. *
  154. * @return PHPExcel_Reader_IReadFilter
  155. */
  156. public function getReadFilter() {
  157. return $this->_readFilter;
  158. }
  159. /**
  160. * Set read filter
  161. *
  162. * @param PHPExcel_Reader_IReadFilter $pValue
  163. */
  164. public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
  165. $this->_readFilter = $pValue;
  166. return $this;
  167. }
  168. /**
  169. * Set input encoding
  170. *
  171. * @param string $pValue Input encoding
  172. */
  173. public function setInputEncoding($pValue = 'ANSI')
  174. {
  175. $this->_inputEncoding = $pValue;
  176. return $this;
  177. }
  178. /**
  179. * Get input encoding
  180. *
  181. * @return string
  182. */
  183. public function getInputEncoding()
  184. {
  185. return $this->_inputEncoding;
  186. }
  187. /**
  188. * Loads PHPExcel from file into PHPExcel instance
  189. *
  190. * @param string $pFilename
  191. * @param PHPExcel $objPHPExcel
  192. * @return PHPExcel
  193. * @throws Exception
  194. */
  195. public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
  196. {
  197. // Check if file exists
  198. if (!file_exists($pFilename)) {
  199. throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
  200. }
  201. // Create new PHPExcel
  202. while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) {
  203. $objPHPExcel->createSheet();
  204. }
  205. $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex );
  206. $fromFormats = array('\-', '\ ');
  207. $toFormats = array('-', ' ');
  208. // Open file
  209. $fileHandle = fopen($pFilename, 'r');
  210. if ($fileHandle === false) {
  211. throw new Exception("Could not open file $pFilename for reading.");
  212. }
  213. // Loop through file
  214. $rowData = array();
  215. $column = $row = '';
  216. // loop through one row (line) at a time in the file
  217. while (($rowData = fgets($fileHandle)) !== FALSE) {
  218. // convert SYLK encoded $rowData to UTF-8
  219. $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData);
  220. // explode each row at semicolons while taking into account that literal semicolon (;)
  221. // is escaped like this (;;)
  222. $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData)))));
  223. $dataType = array_shift($rowData);
  224. // Read shared styles
  225. if ($dataType == 'P') {
  226. $formatArray = array();
  227. foreach($rowData as $rowDatum) {
  228. switch($rowDatum{0}) {
  229. case 'P' : $formatArray['numberformat']['code'] = str_replace($fromFormats,$toFormats,substr($rowDatum,1));
  230. break;
  231. case 'E' :
  232. case 'F' : $formatArray['font']['name'] = substr($rowDatum,1);
  233. break;
  234. case 'L' : $formatArray['font']['size'] = substr($rowDatum,1);
  235. break;
  236. case 'S' : $styleSettings = substr($rowDatum,1);
  237. for ($i=0;$i<strlen($styleSettings);++$i) {
  238. switch ($styleSettings{$i}) {
  239. case 'I' : $formatArray['font']['italic'] = true;
  240. break;
  241. case 'D' : $formatArray['font']['bold'] = true;
  242. break;
  243. case 'T' : $formatArray['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  244. break;
  245. case 'B' : $formatArray['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  246. break;
  247. case 'L' : $formatArray['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  248. break;
  249. case 'R' : $formatArray['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  250. break;
  251. }
  252. }
  253. break;
  254. }
  255. }
  256. $this->_formats['P'.$this->_format++] = $formatArray;
  257. // Read cell value data
  258. } elseif ($dataType == 'C') {
  259. $hasCalculatedValue = false;
  260. $cellData = $cellDataFormula = '';
  261. foreach($rowData as $rowDatum) {
  262. switch($rowDatum{0}) {
  263. case 'C' :
  264. case 'X' : $column = substr($rowDatum,1);
  265. break;
  266. case 'R' :
  267. case 'Y' : $row = substr($rowDatum,1);
  268. break;
  269. case 'K' : $cellData = substr($rowDatum,1);
  270. break;
  271. case 'E' : $cellDataFormula = '='.substr($rowDatum,1);
  272. // Convert R1C1 style references to A1 style references (but only when not quoted)
  273. $temp = explode('"',$cellDataFormula);
  274. foreach($temp as $key => &$value) {
  275. // Only count/replace in alternate array entries
  276. if (($key % 2) == 0) {
  277. preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE);
  278. // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way
  279. // through the formula from left to right. Reversing means that we work right to left.through
  280. // the formula
  281. $cellReferences = array_reverse($cellReferences);
  282. // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
  283. // then modify the formula to use that new reference
  284. foreach($cellReferences as $cellReference) {
  285. $rowReference = $cellReference[2][0];
  286. // Empty R reference is the current row
  287. if ($rowReference == '') $rowReference = $row;
  288. // Bracketed R references are relative to the current row
  289. if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]');
  290. $columnReference = $cellReference[4][0];
  291. // Empty C reference is the current column
  292. if ($columnReference == '') $columnReference = $column;
  293. // Bracketed C references are relative to the current column
  294. if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]');
  295. $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference;
  296. $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0]));
  297. }
  298. }
  299. }
  300. unset($value);
  301. // Then rebuild the formula string
  302. $cellDataFormula = implode('"',$temp);
  303. $hasCalculatedValue = true;
  304. break;
  305. }
  306. }
  307. $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1);
  308. $cellData = PHPExcel_Calculation::_unwrapResult($cellData);
  309. // Set cell value
  310. $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData);
  311. if ($hasCalculatedValue) {
  312. $cellData = PHPExcel_Calculation::_unwrapResult($cellData);
  313. $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData);
  314. }
  315. // Read cell formatting
  316. } elseif ($dataType == 'F') {
  317. $formatStyle = $columnWidth = $styleSettings = '';
  318. $styleData = array();
  319. foreach($rowData as $rowDatum) {
  320. switch($rowDatum{0}) {
  321. case 'C' :
  322. case 'X' : $column = substr($rowDatum,1);
  323. break;
  324. case 'R' :
  325. case 'Y' : $row = substr($rowDatum,1);
  326. break;
  327. case 'P' : $formatStyle = $rowDatum;
  328. break;
  329. case 'W' : list($startCol,$endCol,$columnWidth) = explode(' ',substr($rowDatum,1));
  330. break;
  331. case 'S' : $styleSettings = substr($rowDatum,1);
  332. for ($i=0;$i<strlen($styleSettings);++$i) {
  333. switch ($styleSettings{$i}) {
  334. case 'I' : $styleData['font']['italic'] = true;
  335. break;
  336. case 'D' : $styleData['font']['bold'] = true;
  337. break;
  338. case 'T' : $styleData['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  339. break;
  340. case 'B' : $styleData['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  341. break;
  342. case 'L' : $styleData['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  343. break;
  344. case 'R' : $styleData['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN;
  345. break;
  346. }
  347. }
  348. break;
  349. }
  350. }
  351. if (($formatStyle > '') && ($column > '') && ($row > '')) {
  352. $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1);
  353. $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]);
  354. }
  355. if ((count($styleData) > 0) && ($column > '') && ($row > '')) {
  356. $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1);
  357. $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData);
  358. }
  359. if ($columnWidth > '') {
  360. if ($startCol == $endCol) {
  361. $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1);
  362. $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
  363. } else {
  364. $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1);
  365. $endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1);
  366. $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
  367. do {
  368. $objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth);
  369. } while ($startCol != $endCol);
  370. }
  371. }
  372. } else {
  373. foreach($rowData as $rowDatum) {
  374. switch($rowDatum{0}) {
  375. case 'C' :
  376. case 'X' : $column = substr($rowDatum,1);
  377. break;
  378. case 'R' :
  379. case 'Y' : $row = substr($rowDatum,1);
  380. break;
  381. }
  382. }
  383. }
  384. }
  385. // Close file
  386. fclose($fileHandle);
  387. // Return
  388. return $objPHPExcel;
  389. }
  390. /**
  391. * Get delimiter
  392. *
  393. * @return string
  394. */
  395. public function getDelimiter() {
  396. return $this->_delimiter;
  397. }
  398. /**
  399. * Set delimiter
  400. *
  401. * @param string $pValue Delimiter, defaults to ,
  402. * @return PHPExcel_Reader_SYLK
  403. */
  404. public function setDelimiter($pValue = ',') {
  405. $this->_delimiter = $pValue;
  406. return $this;
  407. }
  408. /**
  409. * Get enclosure
  410. *
  411. * @return string
  412. */
  413. public function getEnclosure() {
  414. return $this->_enclosure;
  415. }
  416. /**
  417. * Set enclosure
  418. *
  419. * @param string $pValue Enclosure, defaults to "
  420. * @return PHPExcel_Reader_SYLK
  421. */
  422. public function setEnclosure($pValue = '"') {
  423. if ($pValue == '') {
  424. $pValue = '"';
  425. }
  426. $this->_enclosure = $pValue;
  427. return $this;
  428. }
  429. /**
  430. * Get line ending
  431. *
  432. * @return string
  433. */
  434. public function getLineEnding() {
  435. return $this->_lineEnding;
  436. }
  437. /**
  438. * Set line ending
  439. *
  440. * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL)
  441. * @return PHPExcel_Reader_SYLK
  442. */
  443. public function setLineEnding($pValue = PHP_EOL) {
  444. $this->_lineEnding = $pValue;
  445. return $this;
  446. }
  447. /**
  448. * Get sheet index
  449. *
  450. * @return int
  451. */
  452. public function getSheetIndex() {
  453. return $this->_sheetIndex;
  454. }
  455. /**
  456. * Set sheet index
  457. *
  458. * @param int $pValue Sheet index
  459. * @return PHPExcel_Reader_SYLK
  460. */
  461. public function setSheetIndex($pValue = 0) {
  462. $this->_sheetIndex = $pValue;
  463. return $this;
  464. }
  465. }