PageRenderTime 54ms CodeModel.GetById 10ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/PHPExcel/Writer/Excel2007.php

https://bitbucket.org/nfredricks/wp-employee-time
PHP | 583 lines | 249 code | 75 blank | 259 comment | 42 complexity | 6bd65aa59a63a1daceb11d166b3bacb9 MD5 | raw file
  1<?php
  2/**
  3 * PHPExcel
  4 *
  5 * Copyright (c) 2006 - 2012 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_Writer_Excel2007
 23 * @copyright  Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
 24 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
 25 * @version    1.7.8, 2012-10-12
 26 */
 27
 28
 29/**
 30 * PHPExcel_Writer_Excel2007
 31 *
 32 * @category   PHPExcel
 33 * @package    PHPExcel_Writer_Excel2007
 34 * @copyright  Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
 35 */
 36class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter
 37{
 38	/**
 39	 * Write charts that are defined in the workbook?
 40	 * Identifies whether the Writer should write definitions for any charts that exist in the PHPExcel object;
 41	 *
 42	 * @var	boolean
 43	 */
 44	private $_includeCharts = false;
 45
 46	/**
 47	 * Pre-calculate formulas
 48	 *
 49	 * @var boolean
 50	 */
 51	private $_preCalculateFormulas = true;
 52
 53	/**
 54	 * Office2003 compatibility
 55	 *
 56	 * @var boolean
 57	 */
 58	private $_office2003compatibility = false;
 59
 60	/**
 61	 * Private writer parts
 62	 *
 63	 * @var PHPExcel_Writer_Excel2007_WriterPart[]
 64	 */
 65	private $_writerParts	= array();
 66
 67	/**
 68	 * Private PHPExcel
 69	 *
 70	 * @var PHPExcel
 71	 */
 72	private $_spreadSheet;
 73
 74	/**
 75	 * Private string table
 76	 *
 77	 * @var string[]
 78	 */
 79	private $_stringTable	= array();
 80
 81	/**
 82	 * Private unique PHPExcel_Style_Conditional HashTable
 83	 *
 84	 * @var PHPExcel_HashTable
 85	 */
 86	private $_stylesConditionalHashTable;
 87
 88	/**
 89	 * Private unique PHPExcel_Style_Fill HashTable
 90	 *
 91	 * @var PHPExcel_HashTable
 92	 */
 93	private $_fillHashTable;
 94
 95	/**
 96	 * Private unique PHPExcel_Style_Font HashTable
 97	 *
 98	 * @var PHPExcel_HashTable
 99	 */
100	private $_fontHashTable;
101
102	/**
103	 * Private unique PHPExcel_Style_Borders HashTable
104	 *
105	 * @var PHPExcel_HashTable
106	 */
107	private $_bordersHashTable ;
108
109	/**
110	 * Private unique PHPExcel_Style_NumberFormat HashTable
111	 *
112	 * @var PHPExcel_HashTable
113	 */
114	private $_numFmtHashTable;
115
116	/**
117	 * Private unique PHPExcel_Worksheet_BaseDrawing HashTable
118	 *
119	 * @var PHPExcel_HashTable
120	 */
121	private $_drawingHashTable;
122
123	/**
124	 * Use disk caching where possible?
125	 *
126	 * @var boolean
127	 */
128	private $_useDiskCaching = false;
129
130	/**
131	 * Disk caching directory
132	 *
133	 * @var string
134	 */
135	private $_diskCachingDirectory	= './';
136
137    /**
138     * Create a new PHPExcel_Writer_Excel2007
139     *
140	 * @param 	PHPExcel	$pPHPExcel
141     */
142    public function __construct(PHPExcel $pPHPExcel = null)
143    {
144    	// Assign PHPExcel
145		$this->setPHPExcel($pPHPExcel);
146
147    	$writerPartsArray = array(	'stringtable'	=> 'PHPExcel_Writer_Excel2007_StringTable',
148									'contenttypes'	=> 'PHPExcel_Writer_Excel2007_ContentTypes',
149									'docprops' 		=> 'PHPExcel_Writer_Excel2007_DocProps',
150									'rels'			=> 'PHPExcel_Writer_Excel2007_Rels',
151									'theme' 		=> 'PHPExcel_Writer_Excel2007_Theme',
152									'style' 		=> 'PHPExcel_Writer_Excel2007_Style',
153									'workbook' 		=> 'PHPExcel_Writer_Excel2007_Workbook',
154									'worksheet' 	=> 'PHPExcel_Writer_Excel2007_Worksheet',
155									'drawing' 		=> 'PHPExcel_Writer_Excel2007_Drawing',
156									'comments' 		=> 'PHPExcel_Writer_Excel2007_Comments',
157									'chart'			=> 'PHPExcel_Writer_Excel2007_Chart',
158								 );
159
160    	//	Initialise writer parts
161		//		and Assign their parent IWriters
162		foreach ($writerPartsArray as $writer => $class) {
163			$this->_writerParts[$writer] = new $class($this);
164		}
165
166    	$hashTablesArray = array( '_stylesConditionalHashTable',	'_fillHashTable',		'_fontHashTable',
167								  '_bordersHashTable',				'_numFmtHashTable',		'_drawingHashTable'
168							    );
169
170		// Set HashTable variables
171		foreach ($hashTablesArray as $tableName) {
172			$this->$tableName 	= new PHPExcel_HashTable();
173		}
174    }
175
176	/**
177	 * Get writer part
178	 *
179	 * @param 	string 	$pPartName		Writer part name
180	 * @return 	PHPExcel_Writer_Excel2007_WriterPart
181	 */
182	public function getWriterPart($pPartName = '') {
183		if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) {
184			return $this->_writerParts[strtolower($pPartName)];
185		} else {
186			return null;
187		}
188	}
189
190	/**
191	 * Save PHPExcel to file
192	 *
193	 * @param 	string 		$pFilename
194	 * @throws 	Exception
195	 */
196	public function save($pFilename = null)
197	{
198		if ($this->_spreadSheet !== NULL) {
199			// garbage collect
200			$this->_spreadSheet->garbageCollect();
201
202			// If $pFilename is php://output or php://stdout, make it a temporary file...
203			$originalFilename = $pFilename;
204			if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
205				$pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp');
206				if ($pFilename == '') {
207					$pFilename = $originalFilename;
208				}
209			}
210
211			$saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
212			PHPExcel_Calculation::getInstance()->writeDebugLog = false;
213			$saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType();
214			PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL);
215
216			// Create string lookup table
217			$this->_stringTable = array();
218			for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) {
219				$this->_stringTable = $this->getWriterPart('StringTable')->createStringTable($this->_spreadSheet->getSheet($i), $this->_stringTable);
220			}
221
222			// Create styles dictionaries
223			$this->_stylesConditionalHashTable->addFromSource( 	$this->getWriterPart('Style')->allConditionalStyles($this->_spreadSheet) 			);
224			$this->_fillHashTable->addFromSource( 				$this->getWriterPart('Style')->allFills($this->_spreadSheet) 			);
225			$this->_fontHashTable->addFromSource( 				$this->getWriterPart('Style')->allFonts($this->_spreadSheet) 			);
226			$this->_bordersHashTable->addFromSource( 			$this->getWriterPart('Style')->allBorders($this->_spreadSheet) 			);
227			$this->_numFmtHashTable->addFromSource( 			$this->getWriterPart('Style')->allNumberFormats($this->_spreadSheet) 	);
228
229			// Create drawing dictionary
230			$this->_drawingHashTable->addFromSource( 			$this->getWriterPart('Drawing')->allDrawings($this->_spreadSheet) 		);
231
232			// Create new ZIP file and open it for writing
233			$zipClass = PHPExcel_Settings::getZipClass();
234			$objZip = new $zipClass();
235
236			//	Retrieve OVERWRITE and CREATE constants from the instantiated zip class
237			//	This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP
238			$ro = new ReflectionObject($objZip);
239			$zipOverWrite = $ro->getConstant('OVERWRITE');
240			$zipCreate = $ro->getConstant('CREATE');
241
242			if (file_exists($pFilename)) {
243				unlink($pFilename);
244			}
245			// Try opening the ZIP file
246			if ($objZip->open($pFilename, $zipOverWrite) !== true) {
247				if ($objZip->open($pFilename, $zipCreate) !== true) {
248					throw new Exception("Could not open " . $pFilename . " for writing.");
249				}
250			}
251
252			// Add [Content_Types].xml to ZIP file
253			$objZip->addFromString('[Content_Types].xml', 			$this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts));
254
255			// Add relationships to ZIP file
256			$objZip->addFromString('_rels/.rels', 					$this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet));
257			$objZip->addFromString('xl/_rels/workbook.xml.rels', 	$this->getWriterPart('Rels')->writeWorkbookRelationships($this->_spreadSheet));
258
259			// Add document properties to ZIP file
260			$objZip->addFromString('docProps/app.xml', 				$this->getWriterPart('DocProps')->writeDocPropsApp($this->_spreadSheet));
261			$objZip->addFromString('docProps/core.xml', 			$this->getWriterPart('DocProps')->writeDocPropsCore($this->_spreadSheet));
262			$customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->_spreadSheet);
263			if ($customPropertiesPart !== NULL) {
264				$objZip->addFromString('docProps/custom.xml', 		$customPropertiesPart);
265			}
266
267			// Add theme to ZIP file
268			$objZip->addFromString('xl/theme/theme1.xml', 			$this->getWriterPart('Theme')->writeTheme($this->_spreadSheet));
269
270			// Add string table to ZIP file
271			$objZip->addFromString('xl/sharedStrings.xml', 			$this->getWriterPart('StringTable')->writeStringTable($this->_stringTable));
272
273			// Add styles to ZIP file
274			$objZip->addFromString('xl/styles.xml', 				$this->getWriterPart('Style')->writeStyles($this->_spreadSheet));
275
276			// Add workbook to ZIP file
277			$objZip->addFromString('xl/workbook.xml', 				$this->getWriterPart('Workbook')->writeWorkbook($this->_spreadSheet, $this->_preCalculateFormulas));
278
279			$chartCount = 0;
280			// Add worksheets
281			for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) {
282				$objZip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->_spreadSheet->getSheet($i), $this->_stringTable, $this->_includeCharts));
283				if ($this->_includeCharts) {
284					$charts = $this->_spreadSheet->getSheet($i)->getChartCollection();
285					if (count($charts) > 0) {
286						foreach($charts as $chart) {
287							$objZip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart));
288							$chartCount++;
289						}
290					}
291				}
292			}
293
294			$chartRef1 = $chartRef2 = 0;
295			// Add worksheet relationships (drawings, ...)
296			for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) {
297
298				// Add relationships
299				$objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', 	$this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1), $this->_includeCharts));
300
301				$drawings = $this->_spreadSheet->getSheet($i)->getDrawingCollection();
302				$drawingCount = count($drawings);
303				if ($this->_includeCharts) {
304					$chartCount = $this->_spreadSheet->getSheet($i)->getChartCount();
305				}
306
307				// Add drawing and image relationship parts
308				if (($drawingCount > 0) || ($chartCount > 0)) {
309					// Drawing relationships
310					$objZip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->_spreadSheet->getSheet($i),$chartRef1, $this->_includeCharts));
311
312					// Drawings
313					$objZip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->_spreadSheet->getSheet($i),$chartRef2,$this->_includeCharts));
314				}
315
316				// Add comment relationship parts
317				if (count($this->_spreadSheet->getSheet($i)->getComments()) > 0) {
318					// VML Comments
319					$objZip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->_spreadSheet->getSheet($i)));
320
321					// Comments
322					$objZip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->_spreadSheet->getSheet($i)));
323				}
324
325				// Add header/footer relationship parts
326				if (count($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
327					// VML Drawings
328					$objZip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->_spreadSheet->getSheet($i)));
329
330					// VML Drawing relationships
331					$objZip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->_spreadSheet->getSheet($i)));
332
333					// Media
334					foreach ($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) {
335						$objZip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath()));
336					}
337				}
338			}
339
340			// Add media
341			for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) {
342				if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) {
343					$imageContents = null;
344					$imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath();
345
346					if (strpos($imagePath, 'zip://') !== false) {
347						$imagePath = substr($imagePath, 6);
348						$imagePathSplitted = explode('#', $imagePath);
349
350						$imageZip = new ZipArchive();
351						$imageZip->open($imagePathSplitted[0]);
352						$imageContents = $imageZip->getFromName($imagePathSplitted[1]);
353						$imageZip->close();
354						unset($imageZip);
355					} else {
356						$imageContents = file_get_contents($imagePath);
357					}
358
359					$objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
360				} else if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) {
361					ob_start();
362					call_user_func(
363						$this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(),
364						$this->getDrawingHashTable()->getByIndex($i)->getImageResource()
365					);
366					$imageContents = ob_get_contents();
367					ob_end_clean();
368
369					$objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
370				}
371			}
372
373			PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType);
374			PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
375
376			// Close file
377			if ($objZip->close() === false) {
378				throw new Exception("Could not close zip file $pFilename.");
379			}
380
381			// If a temporary file was used, copy it to the correct file stream
382			if ($originalFilename != $pFilename) {
383				if (copy($pFilename, $originalFilename) === false) {
384					throw new Exception("Could not copy temporary zip file $pFilename to $originalFilename.");
385				}
386				@unlink($pFilename);
387			}
388		} else {
389			throw new Exception("PHPExcel object unassigned.");
390		}
391	}
392
393	/**
394	 * Get PHPExcel object
395	 *
396	 * @return PHPExcel
397	 * @throws Exception
398	 */
399	public function getPHPExcel() {
400		if ($this->_spreadSheet !== null) {
401			return $this->_spreadSheet;
402		} else {
403			throw new Exception("No PHPExcel assigned.");
404		}
405	}
406
407	/**
408	 * Set PHPExcel object
409	 *
410	 * @param 	PHPExcel 	$pPHPExcel	PHPExcel object
411	 * @throws	Exception
412	 * @return PHPExcel_Writer_Excel2007
413	 */
414	public function setPHPExcel(PHPExcel $pPHPExcel = null) {
415		$this->_spreadSheet = $pPHPExcel;
416		return $this;
417	}
418
419    /**
420     * Get string table
421     *
422     * @return string[]
423     */
424    public function getStringTable() {
425    	return $this->_stringTable;
426    }
427
428    /**
429     * Get PHPExcel_Style_Conditional HashTable
430     *
431     * @return PHPExcel_HashTable
432     */
433    public function getStylesConditionalHashTable() {
434    	return $this->_stylesConditionalHashTable;
435    }
436
437    /**
438     * Get PHPExcel_Style_Fill HashTable
439     *
440     * @return PHPExcel_HashTable
441     */
442    public function getFillHashTable() {
443    	return $this->_fillHashTable;
444    }
445
446    /**
447     * Get PHPExcel_Style_Font HashTable
448     *
449     * @return PHPExcel_HashTable
450     */
451    public function getFontHashTable() {
452    	return $this->_fontHashTable;
453    }
454
455    /**
456     * Get PHPExcel_Style_Borders HashTable
457     *
458     * @return PHPExcel_HashTable
459     */
460    public function getBordersHashTable() {
461    	return $this->_bordersHashTable;
462    }
463
464    /**
465     * Get PHPExcel_Style_NumberFormat HashTable
466     *
467     * @return PHPExcel_HashTable
468     */
469    public function getNumFmtHashTable() {
470    	return $this->_numFmtHashTable;
471    }
472
473    /**
474     * Get PHPExcel_Worksheet_BaseDrawing HashTable
475     *
476     * @return PHPExcel_HashTable
477     */
478    public function getDrawingHashTable() {
479    	return $this->_drawingHashTable;
480    }
481
482	/**
483	 * Write charts in workbook?
484	 *		If this is true, then the Writer will write definitions for any charts that exist in the PHPExcel object.
485	 *		If false (the default) it will ignore any charts defined in the PHPExcel object.
486	 *
487	 * @return	boolean
488	 */
489	public function getIncludeCharts() {
490		return $this->_includeCharts;
491	}
492
493	/**
494	 * Set write charts in workbook
495	 *		Set to true, to advise the Writer to include any charts that exist in the PHPExcel object.
496	 *		Set to false (the default) to ignore charts.
497	 *
498	 * @param	boolean	$pValue
499	 *
500	 * @return	PHPExcel_Writer_Excel2007
501	 */
502	public function setIncludeCharts($pValue = false) {
503		$this->_includeCharts = (boolean) $pValue;
504		return $this;
505	}
506
507    /**
508     * Get Pre-Calculate Formulas
509     *
510     * @return boolean
511     */
512    public function getPreCalculateFormulas() {
513    	return $this->_preCalculateFormulas;
514    }
515
516    /**
517     * Set Pre-Calculate Formulas
518     *
519     * @param boolean $pValue	Pre-Calculate Formulas?
520     */
521    public function setPreCalculateFormulas($pValue = true) {
522    	$this->_preCalculateFormulas = $pValue;
523    }
524
525    /**
526     * Get Office2003 compatibility
527     *
528     * @return boolean
529     */
530    public function getOffice2003Compatibility() {
531    	return $this->_office2003compatibility;
532    }
533
534    /**
535     * Set Pre-Calculate Formulas
536     *
537     * @param boolean $pValue	Office2003 compatibility?
538     * @return PHPExcel_Writer_Excel2007
539     */
540    public function setOffice2003Compatibility($pValue = false) {
541    	$this->_office2003compatibility = $pValue;
542    	return $this;
543    }
544
545	/**
546	 * Get use disk caching where possible?
547	 *
548	 * @return boolean
549	 */
550	public function getUseDiskCaching() {
551		return $this->_useDiskCaching;
552	}
553
554	/**
555	 * Set use disk caching where possible?
556	 *
557	 * @param 	boolean 	$pValue
558	 * @param	string		$pDirectory		Disk caching directory
559	 * @throws	Exception	Exception when directory does not exist
560	 * @return PHPExcel_Writer_Excel2007
561	 */
562	public function setUseDiskCaching($pValue = false, $pDirectory = null) {
563		$this->_useDiskCaching = $pValue;
564
565		if ($pDirectory !== NULL) {
566    		if (is_dir($pDirectory)) {
567    			$this->_diskCachingDirectory = $pDirectory;
568    		} else {
569    			throw new Exception("Directory does not exist: $pDirectory");
570    		}
571		}
572		return $this;
573	}
574
575	/**
576	 * Get disk caching directory
577	 *
578	 * @return string
579	 */
580	public function getDiskCachingDirectory() {
581		return $this->_diskCachingDirectory;
582	}
583}