3 * ExcelWriterXML Package
4 * Used the schema documentation from Microsoft
5 * @link http://msdn.microsoft.com/en-us/library/aa140066(office.10).aspx
6 * @package ExcelWriterXML
10 * Includes the other class file to create Sheets
12 include('ExcelWriterXML_Sheet.php');
14 * Includes the other class file to create Styles
16 include('ExcelWriterXML_Style.php');
19 * Class for generating the initial Excel XML document
22 * $xml = new ExcelWriterXML;
23 * $format = $xml->addStyle('StyleHeader');
24 * $format->fontBold();
25 * $sheet = $xml->addSheet('Test Sheet');
26 * $sheet->writeString (1,1,'Header1','StyleHeader');
27 * $sheet->writeString(2,1,'My String');
28 * $xml->sendHeaders();
32 * @link http://msdn.microsoft.com/en-us/library/aa140066(office.10).aspx
33 * @author Robert F Greer
35 * @package ExcelWriterXML
39 // Private Variables //
40 var $styles = array();
41 var $formatErrors = array();
42 var $sheets = array();
43 var $showErrorSheet = false;
44 var $overwriteFile = false;
52 var $docVersion = 11.9999;
53 var $charSet = "utf-8"; // 2009-02-28 Added by Joe Hunt, FA
54 ///////////////////////
57 * Constructor for the ExcelWriterXML class.
58 * A default style is created, a filename is generated (if not supplied) and
59 * the create time of the document is stored.
60 * @param string $fileName This is the filename that will be passed to the
61 * browser. If not present it will default to "file.xml"
62 * @return ExcelWriterXML Instance of the class
64 function ExcelWriterXML($fileName = 'file.xml')
67 $style = $this->addStyle('Default');
68 $style->name('Normal');
69 $style->alignVertical('Bottom');
73 $fileName = 'file.xml';
74 $this->_addError(__FUNCTION__,'File name was blank, default to "file.xml"');
77 $this->docFileName = $fileName;
78 $this->docCreated = date('Y-m-d').'T'.date('H:i:s').'Z';
82 * Whether or not to overwrite a file (when writing to disk)
83 * @param boolean $overwrite True or False
85 function overwriteFile($overwrite = true)
87 if (!is_bool($overwrite))
89 $this->overwriteFile = false;
94 $this->overwriteFile = $overwrite;
99 * Whether or not to show the sheet containing the Formatting Errors
100 * @param boolean $show
102 function showErrorSheet($show = true)
106 $this->showErrorSheet = true;
110 $this->showErrorSheet = $show;
115 * Adds a format error. When the document is generated if there are any
116 * errors they will be listed on a seperate sheet.
117 * @param string $function The name of the function that was called
118 * @param string $message Details of the error
120 function _addError($function, $message)
123 'function' => $function,
124 'message' => $message,
126 $this->formatErrors[] = $tmp;
130 * Sends the HTML headers to the client.
131 * This is only necessary if the XML doc is to be delivered from the server
134 function sendHeaders()
136 header('content-type: text/xml');
137 header('Content-Disposition: attachment; filename="'.$this->docFileName.'"');
138 header('Expires: 0');
139 header('Cache-Control: must-revalidate, post-check=0,pre-check=0');
140 header('Pragma: public');
144 * Gets the default style that was created by the contructor.
145 * This is used when modifications to the default style are required.
146 * @return ExcelWriterXML_Style Reference to a style class
148 function getDefaultStyle()
150 return($this->styles[0]);
154 * Creates a new style for the spreadsheet
155 * @param string $id The name of the style to be referenced within the
157 * @return ExcelWriterXML_Style Reference to a new style class
158 * @todo Parameter validation for styles, can't have duplicates
161 function addStyle($id)
163 $style =& new ExcelWriterXML_Style($id);
164 $this->styles[] = $style;
169 * Creates a new style within the spreadsheet.
170 * Styles cannot have the same name as any other style. If a style has the
171 * same name as another style then it will follow the default naming
172 * convention as if $id was null
173 * @param string $id The name of the style. If left blank then the style
174 * will default to "CustomStyle" + n (e.g. "CustomStyle1")
175 * @return ExcelWriterXML_Style Reference to a new style class
177 function addStyle($id = null)
179 static $styleNum = 1;
185 $id = 'CustomStyle'.$styleNum;
187 //$this->_addError(__FUNCTION__,'Style name was blank, renamed to "'.$id.'"');
190 while (!$this->_checkStyleID($id))
193 $id = 'CustomStyle'.$styleNum;
194 $this->_addError(__FUNCTION__,'Style name was duplicate ("'.$old_id.'"), renamed to "'.$id.'"');
198 $style =& new ExcelWriterXML_Style($id);
199 $this->styles[] = $style;
204 * Creates a new sheet within the spreadsheet
205 * At least one sheet is required.
206 * Additional sheets cannot have the same name as any other sheet.
207 * If a sheet has the same name as another sheet then it will follow the
208 * default naming convention as if $id was null
209 * @param string $id The name of the sheet. If left blank then the sheet
210 * will default to "Sheet" + n (e.g. "Sheet1")
211 * @return ExcelWriterXML_Sheet Reference to a new sheet class
213 function addSheet($id = null)
215 static $sheetNum = 1;
221 $id = 'Sheet'.$sheetNum;
223 $this->_addError(__FUNCTION__,'Sheet name was blank, renamed to "'.$id.'"');
226 while (!$this->_checkSheetID($id))
229 $id = 'Sheet'.$sheetNum;
230 $this->_addError(__FUNCTION__,'Sheet name was duplicate ("'.$old_id.'"), renamed to "'.$id.'"');
234 $sheet =& new ExcelWriterXML_Sheet($id);
235 $this->sheets[] = $sheet;
240 * Checks whether a proposed Sheet ID has already been used
241 * @param string $id The sheet id to be checked
242 * @return boolean True if the id is unique, false otherwise
244 function _checkSheetID($id){
245 foreach($this->sheets as $sheet)
247 $sheetID = $sheet->getID();
257 * Checks whether a proposed Style ID has already been used
258 * @param string $id The style id to be checked
259 * @return boolean True if the id is unique, false otherwise
261 function _checkStyleID($id)
263 foreach($this->styles as $style)
265 $styleID = $style->getID();
274 // 2009-02-28 Added by Joe Hunt, FA
275 function setCharSet($charset)
277 $this->charSet = $charset;
280 * Writes the XML data
281 * @param string $target If left null the function will output to STD OUT
282 * (e. g. browser or console)
284 function writeData($target = null)
296 if ($this->showErrorSheet == true)
298 $format = $this->addStyle('formatErrorsHeader');
300 $format->bgColor('red');
303 if (!empty($this->docTitle))
304 $docTitle = '<Title>'.htmlspecialchars($this->docTitle).'</Title>'."\r";
305 if (!empty($this->docSubject))
306 $docSubject = '<Subject>'.htmlspecialchars($this->docSubject).'</Subject>'."\r";
307 if (!empty($this->docAuthor))
308 $docAuthor = '<Author>'.htmlspecialchars($this->docAuthor).'</Author>'."\r";
309 if (!empty($this->docCreated))
310 $docCreated = '<Created>'.htmlspecialchars($this->docCreated).'</Created>'."\r";
311 if (!empty($this->docManager))
312 $docManager = '<Manager>'.htmlspecialchars($this->docManager).'</Manager>'."\r";
313 if (!empty($this->docCompany))
314 $docCompany = '<Company>'.htmlspecialchars($this->docCompany).'</Company>'."\r";
315 //$docCompany = '<Company>'.$this->docCompany.'</Company>'."\r";
317 $xml = '<?xml version="1.0" encoding="'.$this->charSet.'"?>'."\r"; // 2009-02-28 Added by Joe Hunt, FA
318 $xml .= '<?mso-application progid="Excel.Sheet"?>'."\r";
320 xmlns="urn:schemas-microsoft-com:office:spreadsheet"
321 xmlns:o="urn:schemas-microsoft-com:office:office"
322 xmlns:x="urn:schemas-microsoft-com:office:excel"
323 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
324 xmlns:html="http://www.w3.org/TR/REC-html40">'."\r";
325 $xml .= '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">'."\r";
326 if (!empty($this->docTitle))
327 $xml .= ' '.$docTitle;
328 if (!empty($this->docSubject))
329 $xml .= ' '.$docSubject;
330 if (!empty($this->docAuthor))
331 $xml .= ' '.$docAuthor;
332 if (!empty($this->docCreated))
333 $xml .= ' '.$docCreated;
334 if (!empty($this->docManager))
335 $xml .= ' '.$docManager;
336 if (!empty($this->docCompany))
337 $xml .= ' '.$docCompany;
338 $xml .= ' <Version>'.$this->docVersion.'</Version>'."\r";
339 $xml .= '</DocumentProperties>'."\r";
340 $xml .= '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel" />'."\r";
341 $xml .= '<Styles>'."\r";
342 foreach($this->styles as $style)
344 $xml .= $style->getStyleXML();
345 if (count($style->getErrors()) > 0)
350 $xml .= '</Styles>'."\r";
351 if (count($this->sheets) == 0)
355 foreach($this->sheets as $sheet)
357 $xml .= $sheet->getSheetXML();
358 if (count($sheet->getErrors()) > 0)
363 if (count($this->formatErrors) > 0)
368 if ($errors == true && $this->showErrorSheet == true)
370 $sheet = $this->addSheet('formatErrors');
371 $sheet->cellMerge(1,1,3,0); // Merge the first three cells across in row 1
372 $sheet->writeString(1,1,'Formatting Errors');
373 $sheet->writeString(2,1,'Type','formatErrorsHeader');
374 $sheet->writeString(2,2,'Function','formatErrorsHeader');
375 $sheet->cellWidth(2,1,200);
376 $sheet->cellWidth(2,2,200);
377 $sheet->cellWidth(2,3,400);
378 $sheet->writeString(2,3,'Error Message','formatErrorsHeader');
380 foreach($this->formatErrors as $error)
382 $function = $error['function'];
383 $message = $error['message'];
384 $sheet->writeString($row,1,'Document');
385 $sheet->writeString($row,2,$function);
386 $sheet->writeString($row,3,$message);
389 foreach($this->styles as $styleObject)
391 $formatErrors = $styleObject->getErrors();
392 $styleID = 'Style='.$styleObject->getID();
393 foreach($formatErrors as $error)
395 $function = $error['function'];
396 $message = $error['message'];
397 $sheet->writeString($row,1,$styleID);
398 $sheet->writeString($row,2,$function);
399 $sheet->writeString($row,3,$message);
403 foreach($this->sheets as $sheetObject)
405 $formatErrors = $sheetObject->getErrors();
406 $sheetID = 'Sheet='.$sheetObject->getID();
407 foreach($formatErrors as $error)
409 $function = $error['function'];
410 $message = $error['message'];
411 $sheet->writeString($row,1,$sheetID);
412 $sheet->writeString($row,2,$function);
413 $sheet->writeString($row,3,$message);
417 $xml .= $sheet->getSheetXML();
421 $xml .= '</Workbook>';
425 // We aren't writing this file to disk, so echo back to the client.
431 $fileExists = file_exists($target);
432 if ($fileExists == true && $this->overwriteFile == false)
434 die('"'.$target.'" exists and "overwriteFile" is set to "false"');
436 $handle = fopen($target, 'w');
439 fwrite($handle,$xml);
445 echo('<br/>Not able to open "'.$target.'" for writing');
452 * Sets the Title of the document
453 * @param string $title Part of the properties of the document.
455 function docTitle($title = '') { $this->docTitle = $title; }
458 * Sets the Subject of the document
459 * @param string $subject Part of the properties of the document.
461 function docSubject($subject = '') { $this->docSubject = $subject; }
464 * Sets the Author of the document
465 * @param string $author Part of the properties of the document.
467 function docAuthor($author = '') { $this->docAuthor = $author; }
470 * Sets the Manager of the document
471 * @param string $manager Part of the properties of the document.
473 function docManager($manager = '') { $this->docManager = $manager; }
476 * Sets the Company of the document
477 * @param string $company Part of the properties of the document.
479 function docCompany($company = '') { $this->docCompany = $company; }