ExcelWriterXML
[ class tree: ExcelWriterXML ] [ index: ExcelWriterXML ] [ all elements ]

Source for file ExcelWriterXML.php

Documentation is available at ExcelWriterXML.php

  1. <?php
  2. /**
  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
  7.  */
  8.  
  9. /**
  10.  * Includes the other class file to create Sheets
  11.  */
  12. include('ExcelWriterXML_Sheet.php');
  13. /**
  14.  * Includes the other class file to create Styles
  15.  */
  16. include('ExcelWriterXML_Style.php');
  17.  
  18. /**
  19.  * Class for generating the initial Excel XML document
  20.  * <code>
  21.  * <?php
  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();
  29.  * $xml->writeData();
  30.  * ?>
  31.  * </code>
  32.  * @link http://msdn.microsoft.com/en-us/library/aa140066(office.10).aspx
  33.  * @author Robert F Greer
  34.  * @version 1.0
  35.  * @package ExcelWriterXML
  36.  */
  37.     // Private Variables //
  38.     private $styles array();
  39.     public  $formatErrors = array();
  40.     private $sheets array();
  41.     private $showErrorSheet false;
  42.     private $overwriteFile false;
  43.     private $docFileName;
  44.     private $docTitle;
  45.     private $docSubject;
  46.     private $docAuthor;
  47.     private $docCreated;
  48.     private $docManager;
  49.     private $docCompany;
  50.     private $docVersion 11.9999;
  51.     ///////////////////////
  52.  
  53.     /**
  54.      * Constructor for the ExcelWriterXML class.
  55.      * A default style is created, a filename is generated (if not supplied) and
  56.      * the create time of the document is stored.
  57.      * @param string $fileName This is the filename that will be passed to the
  58.      *  browser.  If not present it will default to "file.xml"
  59.      * @return ExcelWriterXML Instance of the class
  60.      */
  61.     function ExcelWriterXML($fileName 'file.xml'){
  62.         // Add default style
  63.         $style $this->addStyle('Default');
  64.         $style->name('Normal');
  65.         $style->alignVertical('Bottom');
  66.         
  67.         if ($fileName == ''){
  68.             $fileName 'file.xml';
  69.             $this->addError(__FUNCTION__,'File name was blank, default to "file.xml"');
  70.         }
  71.         
  72.         $this->docFileName $fileName;
  73.         $this->docCreated date('Y-m-d').'T'.date('H:i:s').'Z';
  74.         EWXcreateStylesDB($this);
  75.     }
  76.  
  77.     /**
  78.      * Whether or not to overwrite a file (when writing to disk)
  79.      * @param boolean $overwrite True or False
  80.      */
  81.     public function overwriteFile($overwrite true){
  82.         if (!is_bool($overwrite)){
  83.             $this->overwriteFile false;
  84.             return;
  85.         }
  86.         else{
  87.             $this->overwriteFile $overwrite;
  88.         }
  89.     }
  90.  
  91.     /**
  92.      * Whether or not to show the sheet containing the Formatting Errors
  93.      * @param boolean $show 
  94.      */
  95.     public function showErrorSheet($show true){
  96.         if (!is_bool($show)){
  97.             $this->showErrorSheet true;
  98.             return;
  99.         }
  100.         else{
  101.             $this->showErrorSheet $show;
  102.         }
  103.     }
  104.  
  105.     /**
  106.      * Adds a format error.  When the document is generated if there are any
  107.      * errors they will be listed on a seperate sheet.
  108. @param string $function The name of the function that was called
  109.      * @param string $message Details of the error
  110.      */
  111.     public function addError($function$message){
  112.         $tmp array(
  113.             'function'    => $function,
  114.             'message'    => $message,
  115.         );
  116.         $this->formatErrors[$tmp;
  117.     }
  118.     
  119.     /**
  120.      * Sends the HTML headers to the client.
  121.      * This is only necessary if the XML doc is to be delivered from the server
  122.      * to the browser.
  123.      */
  124.     public function sendHeaders(){
  125.         header('content-type: text/xml');
  126.         header('Content-Disposition: attachment; filename="'.$this->docFileName.'"');
  127.         header('Expires: 0');
  128.         header('Cache-Control: must-revalidate, post-check=0,pre-check=0');
  129.         header('Pragma: public');
  130.     }
  131.  
  132.     /**
  133.      * Gets the default style that was created by the contructor.
  134.      * This is used when modifications to the default style are required.
  135.      * @return ExcelWriterXML_Style Reference to a style class
  136.      */
  137.     public function getDefaultStyle(){
  138.         return($this->styles[0]);
  139.     }
  140.  
  141.     /**
  142.      * Creates a new style within the spreadsheet.
  143.      * Styles cannot have the same name as any other style. If a style has the
  144.      * same name as another style then it will follow the default naming
  145.      * convention as if $id was null
  146.      * @param string $id The name of the style.  If left blank then the style
  147.      *  will default to "CustomStyle" + n (e.g. "CustomStyle1")
  148.      * @return ExcelWriterXML_Style Reference to a new style class
  149.      */
  150.     public function addStyle($id null){
  151.         static $styleNum 1;
  152.         if (trim($id== ''$id null;
  153.  
  154.         if ($id == null){
  155.             $id 'CustomStyle'.$styleNum;
  156.             $styleNum++;
  157.             //$this->addError(__FUNCTION__,'Style name was blank, renamed to "'.$id.'"');
  158.         }
  159.  
  160.         while (!$this->checkStyleID($id)){
  161.             $old_id $id;
  162.             $id 'CustomStyle'.$styleNum;
  163.             $this->addError(__FUNCTION__,'Style name was duplicate ("'.$old_id.'"), renamed to "'.$id.'"');
  164.             $styleNum++;
  165.         }
  166.         
  167.         $style =new ExcelWriterXML_Style($id);
  168.         $this->styles[$style;
  169.         return ($style);
  170.     }
  171.     
  172.     /**
  173.      * Creates a new sheet within the spreadsheet
  174.      * At least one sheet is required.
  175.      * Additional sheets cannot have the same name as any other sheet.
  176.      * If a sheet has the same name as another sheet then it will follow the
  177.      * default naming convention as if $id was null
  178.      * @param string $id The name of the sheet.  If left blank then the sheet
  179.      *  will default to "Sheet" + n (e.g. "Sheet1")
  180.      * @return ExcelWriterXML_Sheet Reference to a new sheet class
  181.      */
  182.     public function addSheet($id null){
  183.         static $sheetNum 1;
  184.         if (trim($id== ''$id null;
  185.  
  186.         if ($id == null){
  187.             $id 'Sheet'.$sheetNum;
  188.             $sheetNum++;
  189.             $this->addError(__FUNCTION__,'Sheet name was blank, renamed to "'.$id.'"');
  190.         }
  191.  
  192.         while (!$this->checkSheetID($id)){
  193.             $old_id $id;
  194.             $id 'Sheet'.$sheetNum;
  195.             $this->addError(__FUNCTION__,'Sheet name was duplicate ("'.$old_id.'"), renamed to "'.$id.'"');
  196.             $sheetNum++;
  197.         }
  198.         
  199.         $sheet =new ExcelWriterXML_Sheet($id);
  200.         $this->sheets[$sheet;
  201.         return ($sheet);
  202.     }
  203.     
  204.     /**
  205.      * Checks whether a proposed Sheet ID has already been used
  206.      * @param string $id The sheet id to be checked
  207.      * @return boolean True if the id is unique, false otherwise
  208.      */
  209.     private function checkSheetID($id){
  210.         foreach($this->sheets as $sheet){
  211.             $sheetID $sheet->getID();
  212.             if ($id == $sheetID){
  213.                 return false;
  214.             }
  215.         }
  216.         return true;
  217.     }
  218.  
  219.     /**
  220.      * Checks whether a proposed Style ID has already been used
  221.      * @param string $id The style id to be checked
  222.      * @return boolean True if the id is unique, false otherwise
  223.      */
  224.     public function checkStyleID($id){
  225.         foreach($this->styles as $style){
  226.             $styleID $style->getID();
  227.             if ($id == $styleID){
  228.                 return false;
  229.             }
  230.         }
  231.         return true;
  232.     }
  233.  
  234.     /**
  235.      * Writes the XML data
  236.      * @param string $target If left null the function will output to STD OUT
  237.      *  (e. g. browser or console)
  238.      */
  239.     public function writeData($target null){
  240.         $docTitle '';
  241.         $docSubject '';
  242.         $docAuthor '';
  243.         $docCreated '';
  244.         $docManager '';
  245.         $docCompany '';
  246.         $docVersion 12;
  247.         
  248.         $errors false;
  249.         
  250.         if ($this->showErrorSheet == true){
  251.             $format $this->addStyle('formatErrorsHeader');
  252.             $format->fontBold();
  253.             $format->bgColor('red');
  254.         }
  255.         
  256.         if (!empty($this->docTitle)) $docTitle '<Title>'.htmlspecialchars($this->docTitle).'</Title>'."\r";
  257.         if (!empty($this->docSubject)) $docSubject '<Subject>'.htmlspecialchars($this->docSubject).'</Subject>'."\r";
  258.         if (!empty($this->docAuthor)) $docAuthor '<Author>'.htmlspecialchars($this->docAuthor).'</Author>'."\r";
  259.         if (!empty($this->docCreated)) $docCreated '<Created>'.htmlspecialchars($this->docCreated).'</Created>'."\r";
  260.         if (!empty($this->docManager)) $docManager '<Manager>'.htmlspecialchars($this->docManager).'</Manager>'."\r";
  261.         if (!empty($this->docCompany)) $docCompany '<Company>'.htmlspecialchars($this->docCompany).'</Company>'."\r";
  262.         
  263.         $xml '<?xml version="1.0"?>'."\r";
  264.         $xml .= '<?mso-application progid="Excel.Sheet"?>'."\r";
  265.         $xml .= '<Workbook
  266.             xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  267.             xmlns:o="urn:schemas-microsoft-com:office:office"
  268.             xmlns:x="urn:schemas-microsoft-com:office:excel"
  269.             xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
  270.             xmlns:html="http://www.w3.org/TR/REC-html40">'."\r";
  271.         $xml .= '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">'."\r";
  272.             if (!empty($this->docTitle))    $xml .= '    '.$docTitle;
  273.             if (!empty($this->docSubject))    $xml .= '    '.$docSubject;
  274.             if (!empty($this->docAuthor))    $xml .= '    '.$docAuthor;
  275.             if (!empty($this->docCreated))    $xml .= '    '.$docCreated;
  276.             if (!empty($this->docManager))    $xml .= '    '.$docManager;
  277.             if (!empty($this->docCompany))    $xml .= '    '.$docCompany;
  278.             $xml .= '    <Version>'.$this->docVersion.'</Version>'."\r";
  279.         $xml .= '</DocumentProperties>'."\r";
  280.         $xml .= '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel" />'."\r";
  281.         $xml .= '<Styles>'."\r";
  282.         foreach($this->styles as $style){
  283.             $xml .= $style->getStyleXML();
  284.             if (count($style->getErrors()) 0){
  285.                 $errors true;
  286.             }
  287.         }
  288.         $xml .= '</Styles>'."\r";
  289.         if (count($this->sheets== 0){
  290.             $this->addSheet();
  291.         }
  292.         foreach($this->sheets as $sheet){
  293.             $xml .= $sheet->getSheetXML();
  294.             if (count($sheet->getErrors()) 0){
  295.                 $errors true;
  296.             }
  297.         }
  298.         if (count($this->formatErrors0){
  299.             $errors true;
  300.         }
  301.         
  302.         if ($errors == true && $this->showErrorSheet == true){
  303.             $sheet $this->addSheet('formatErrors');
  304.             $sheet->cellMerge(1,1,3,0);    // Merge the first three cells across in row 1
  305.             $sheet->writeString(1,1,'Formatting Errors');
  306.             $sheet->writeString(2,1,'Type','formatErrorsHeader');
  307.             $sheet->writeString(2,2,'Function','formatErrorsHeader');
  308.             $sheet->cellWidth(2,1,200);
  309.             $sheet->cellWidth(2,2,200);
  310.             $sheet->cellWidth(2,3,400);
  311.             $sheet->writeString(2,3,'Error Message','formatErrorsHeader');
  312.             $row 3;
  313.             foreach($this->formatErrors as $error){
  314.                 $function $error['function'];
  315.                 $message $error['message'];
  316.                 $sheet->writeString($row,1,'Document');
  317.                 $sheet->writeString($row,2,$function);
  318.                 $sheet->writeString($row,3,$message);
  319.                 $row++;
  320.             }
  321.             foreach($this->styles as $styleObject){
  322.                 $formatErrors $styleObject->getErrors();
  323.                 $styleID 'Style='.$styleObject->getID();
  324.                 foreach($formatErrors as $error){
  325.                     $function $error['function'];
  326.                     $message $error['message'];
  327.                     $sheet->writeString($row,1,$styleID);
  328.                     $sheet->writeString($row,2,$function);
  329.                     $sheet->writeString($row,3,$message);
  330.                     $row++;
  331.                 }
  332.             }
  333.             foreach($this->sheets as $sheetObject){
  334.                 $formatErrors $sheetObject->getErrors();
  335.                 $sheetID 'Sheet='.$sheetObject->getID();
  336.                 foreach($formatErrors as $error){
  337.                     $function $error['function'];
  338.                     $message $error['message'];
  339.                     $sheet->writeString($row,1,$sheetID);
  340.                     $sheet->writeString($row,2,$function);
  341.                     $sheet->writeString($row,3,$message);
  342.                     $row++;
  343.                 }
  344.             }
  345.             $xml .= $sheet->getSheetXML();
  346.         }
  347.         
  348.         
  349.         $xml .= '</Workbook>';
  350.         
  351.         if ($target == null){
  352.             // We aren't writing this file to disk, so echo back to the client.
  353.             echo $xml;
  354.             return true;
  355.         }
  356.         else{
  357.             $fileExists file_exists($target);
  358.             if ($fileExists == true && $this->overwriteFile == false){
  359.                 die('"'.$target.'" exists and "overwriteFile" is set to "false"');
  360.             }
  361.             $handle fopen($target'w');
  362.             if ($handle){
  363.                 fwrite($handle,$xml);
  364.                 fclose($handle);
  365.                 return true;
  366.             }
  367.             else{
  368.                 echo('<br/>Not able to open "'.$target.'" for writing');
  369.                 return false;
  370.             }
  371.         }
  372.     }
  373.     
  374.     /**
  375.      * Sets the Title of the document
  376.      * @param string $title Part of the properties of the document.
  377.      */
  378.     public function docTitle($title ''){$this->docTitle = $title;}
  379.  
  380.     /**
  381.      * Sets the Subject of the document
  382.      * @param string $subject Part of the properties of the document.
  383.      */
  384.     public function docSubject($subject ''){$this->docSubject = $subject;}
  385.  
  386.     /**
  387.      * Sets the Author of the document
  388.      * @param string $author Part of the properties of the document.
  389.      */
  390.     public function docAuthor($author ''){$this->docAuthor = $author;}
  391.  
  392.     /**
  393.      * Sets the Manager of the document
  394.      * @param string $manager Part of the properties of the document.
  395.      */
  396.     public function docManager($manager ''){$this->docManager = $manager;}
  397.  
  398.     /**
  399.      * Sets the Company of the document
  400.      * @param string $company Part of the properties of the document.
  401.      */
  402.     public function docCompany($company ''){$this->docCompany = $company;}
  403.     
  404.     /**
  405.      * Outputs a MYSQL table or list of tables to an Excel doc
  406.      * @param string $host MySQL host to connect to
  407.      * @param string $username Username to connect with
  408.      * @param string $password Password to connect with
  409.      * @param string $db Database to use
  410.      * @param mixed $table If string, out specific table.  If array, each table will have it's own sheet
  411.      * @param mixed $alternateName For multiple tables this does nothing.  For table, overrides auto naming of the sheet (table name)
  412.      */
  413.     public function mysqlTableDump($host,$username,$password,$db,$table,$alternateName null){
  414.         EWXcheckDriverDB('mysql');
  415.         if (empty($host))        $this->addError('Database','HOSTNAME is empty');
  416.         if (empty($username))    $this->addError('Database','USERNAME is empty');
  417.         if (empty($db))            $this->addError('Database','DB is empty');
  418.         if (empty($table))        $this->addError('Database','TABLE(S) is empty');
  419.         if (count($this->formatErrors0){$this->showErrorSheet();return false;}
  420.         
  421.         $link mysql_connect($host,$username,$password);
  422.         if (!$link$this->addError('Database','UNABLE to connect to '.$host.'('.mysql_error().')');
  423.         if (count($this->formatErrors0)$this->showErrorSheet()return false}
  424.         
  425.         $db_selected mysql_select_db($db);
  426.         if (!$db_selected$this->addError('Database','DB "'.$db.'" does not exist');
  427.         if (count($this->formatErrors0)$this->showErrorSheet()return false}
  428.         
  429.         if (gettype($table== 'array'){
  430.             foreach($table as $table2){
  431.                 $sheet $this->addSheet($table2);
  432.                 $query 'SELECT * FROM `'.$db.'`.`'.$table2.'` ';
  433.                 EWXmysqlGenerateByQuery($sheet,$link,$query);
  434.             }
  435.         }
  436.         else{
  437.             if ($alternateName == null || empty($alternateName)) $sheet $this->addSheet($table);
  438.             else $sheet $this->addSheet($alternateName);
  439.             $query 'SELECT * FROM `'.$db.'`.`'.$table.'` ';
  440.             EWXmysqlGenerateByQuery($sheet,$link,$query);
  441.         }
  442.         if (count($this->formatErrors0)$this->showErrorSheet()return false}
  443.     }
  444. }
  445.  
  446. function EWXmysqlGenerateByQuery(&$sheet,$link,$query){
  447.     $res mysql_query($query,$link);
  448.     if (!$res$sheet->addError('Database','Unable to execute query ('.mysql_error().')');
  449.     if (count($sheet->formatErrors0){return false;}
  450.  
  451.     if (mysql_num_rows($res== 0){
  452.         $sheet->writeString(1,1,'No data');
  453.         return true;
  454.     }
  455.     $row 0;
  456.     $headersWritten false;
  457.     while($data mysql_fetch_row($res)){
  458.         $row++;$col=1;
  459.         if ($headersWritten == false){
  460.             $numFields mysql_num_fields($res);
  461.             for($x=0$x<$numFields;$x++){
  462.                 $name mysql_field_name($res,$x);
  463.                 $sheet->writeString($row,$col++,$name,'db_header');
  464.             }
  465.             $row++;$col=1;
  466.             $headersWritten true;
  467.         }
  468.         foreach($data as $offset => $value){
  469.             $field mysql_field_name($res,$offset);
  470.             $type mysql_field_type($res,$offset);
  471.             $value htmlentities(trim($value));
  472.             if (strstr($type,'int')){
  473.                 $sheet->writeNumber($row,$col++,$value);
  474.             }
  475.             else if ($type == 'datetime'){
  476.                 $value $sheet->convertMysqlDateTime($value);
  477.                 $sheet->writeDateTime($row,$col++,$value,'db_datetime');
  478.             }
  479.             else if ($type == 'date'){
  480.                 $value $sheet->convertMysqlDate($value);
  481.                 $sheet->writeDateTime($row,$col++,$value,'db_date');
  482.             }
  483.             else if ($type == 'time'){
  484.                 $value $sheet->convertMysqlTime($value);
  485.                 $sheet->writeDateTime($row,$col++,$value,'db_time');
  486.             }
  487.             else if (is_numeric($value)){
  488.                 $sheet->writeNumber($row,$col++,$value);
  489.             }
  490.             else{
  491.                 $sheet->writeString($row,$col++,$value);
  492.             }
  493.         }
  494.     }
  495.     return true;
  496. }
  497. function EWXcheckDriverDB($driver){
  498.     if (!extension_loaded($driver)){
  499.         $this->addError('Database','DB driver "'.$driver.'" could not be loaded');
  500.         return false;
  501.     }
  502.     return true;
  503. }
  504.  
  505. function EWXcreateStylesDB(&$xml){
  506.     if ($xml->checkStyleID('db_header')){
  507.         $sHeader $xml->addStyle('db_header');
  508.         $sHeader->fontBold();
  509.         $sHeader->fontFamily('Swiss');
  510.         $sHeader->fontColor('0000FF');
  511.     }
  512.     if ($xml->checkStyleID('db_datetime')){
  513.         $hDateTime $xml->addStyle('db_datetime');
  514.         $hDateTime->numberFormatDateTime();
  515.     }
  516.     if ($xml->checkStyleID('db_date')){
  517.         $hDate $xml->addStyle('db_date');
  518.         $hDate->numberFormatDate();
  519.     }
  520.     if ($xml->checkStyleID('db_time')){
  521.         $hTime $xml->addStyle('db_time');
  522.         $hTime->numberFormatTime();
  523.     }
  524. }
  525.  
  526. ?>

Documentation generated on Wed, 16 Feb 2011 20:04:35 -0600 by phpDocumentor 1.4.3