<?php
/**
 * Created by Ido Graiman
 * Design by Ido Graiman & Andi Gutmans
 *
 * Copyright (c) 2004 - 2005 Zend Technologies Inc. All rights reserved.
 * This software is freely available under the BSD License:
 * http://www.opensource.org/licenses/bsd-license.php
 *
 * This class provide PHP / Excel connectivity through COM
 * It is meant to create a simple and easy interface for communicating between PHP and Excel.
 *
 * The following is what you can do with this class:
 * 1. Open Excel with an active workbook and one sheet
 * 2. Create a new sheet
 * 3. Set / chage the active sheet
 * 4. Set data into a sheet
 * 5. Create an Excel chart out of the data in the sheet
 * 6. Set chart type
 * 7. Set main, X axis and Y axis titles for a chart
 * 8. Set chart background color
 * 9. Remove grid between cells (done by default)
 *
 * PLEASE NOTE: This class uses PHP 5 features, and will not run on PHP4!
 *
 */
class COM_excel {
    
// The following constants set the chart types
    
const xlArea 1;
    const 
xlLine 4;
    const 
xlPie 5;
    const 
xlBubbleChart 15;
    const 
xlColumnClustered 51;
    const 
xlColumnStacked 52;
    const 
xlColumnStacked100 53;
    const 
xlColumnClustered3D54;
    const 
xlColumnStacked3D 55;
    const 
xlColumnStacked1003D 56;
    const 
xlBarClustered 57;
    const 
xlBarStacked 58;
    const 
xlBarStacked100 59;
    const 
xlBarClustered3D 60;
    const 
xlBarStacked3D 61;
    const 
xlBarStacked1003D 62;
    const 
xlLineStacked 63;
    const 
xlLineStacked100 64;
    const 
xlLineMarkers 65;
    const 
xlLineMarkersStacked 66;
    const 
xlLineMarkersStacked100 67;
    const 
xlPieOfPie 68;
    const 
xlPieExploded 69;
    const 
xlPieExploded3D 70;
    const 
xlBarOfPie 71;
    const 
xlXYScatter 72;
    const 
xlXYScatterSmooth 73;
    const 
xlXYScatterSmoothNoMarkers 74;
    const 
xlXYScatterLines 75;
    const 
xlAreaStacked 76;
    const 
xlAreaStacked100 77;
    const 
xlAreaStacked3D 78;
    const 
xlAreaStacked1003D 79;
    const 
xlDoughnutExploded 80;
    const 
xlRadarMarkers 81;
    const 
xlRadarFilled 82;
    
    
// The following constants set the value for the default sheet direction
    
const xlLTR = -5003;    // Sheet direction from left to right
    
const xlRTL = -5004;    // Sheet direction from right to left
    
    
private $excel_app;        // Holds the COM object for Excel
    
private $workbook;        // Holds the Excel workbook
    
private $sheet = array();    // Holds the collection of sheets in a workbook
    
private $active_sheet;    // Holds the active sheet
    
private $chartObj;        // Holds the chart object
    
private $chart;            // Holds the chart itself
    
private $row_start;        // Holds the first row index where the excel data starts
    
private $column_start;    // Holds the first column index where the excel data starts
    
private $row_index;        // Index for filling data into row
    
private $column_index;    // Index for filling data into columns
    
private $chartFillFormat;    // Holds the object that control's the chart's background color
    
private $chartTitle;    // Holds the object controling the chart's title
    
private $chartAxisX;    // Holds the object controling the chart's X axis title
    
private $chartAxisY;    // Holds the object controling the chart's Y axis title
    
    
    /**
     * Class constructor - Create the COM object with a working sheet, and giving this sheet a name
     *
     * @param int $direction Default value is left to right, but user can set it using either xlLTR or xlRTL constants
     * @return void
     */
    
public function COM_excel($direction = -5003) {
        try {
            
$this->excel_app = new COM("Excel.application");
            
$this->excel_app->SheetsInNewWorkbook 1;    // Setting the default number of open sheets to 1. It seems that it's not possible to set it to 0.
            
$this->excel_app->DefaultSheetDirection $direction;    // Setting the direction of sheets
            
$this->workbook $this->excel_app->Workbooks->add();    // Opening a new workbook
        
} catch (com_exception $e) {
            throw new 
com_exception("[".__CLASS__."::".__FUNCTION__."] ".$e->getMessage()."<BR>");
        }
    }
    
    
/**
     * Class destructor - closing the Excel COM object and unsetting the variable holding the COM object
     *
     */
    
function __destruct() {
        
$this->excel_app->Quit();
        unset(
$this->excel_app);
    }
    
    
/**
     * Adding a new sheet to the Excel Workbook and setting it as the active sheet
     *
     * @param string $sheet_name Name of the new sheet
     */
    
public function newSheet($sheet_name) {
        try {
            
$this->sheet[$sheet_name] = $this->workbook->Worksheets->add();    // Creating a new sheet
            
$this->sheet[$sheet_name]->activate;    // Setting new sheet as the active sheet
            
$this->setActiveSheet($sheet_name);    // Keeping a 'pointer' to the active sheet
            
$this->sheet[$sheet_name]->name $sheet_name;    // Setting sheet's name
        
} catch (com_exception $e) {
            throw new 
com_exception("[".__CLASS__."::".__FUNCTION__."] ".$e->getMessage()."<BR>");
        }
    }
        
    
/**
     * Setting data into the current active sheet
     *
     * @param array $data_array An array holding the data to be set
     * @param int $start_in_row Set the starting row from which data will be inserted.
     * @param int $start_in_column Set the starting column from which data will be inserted.
     * @param string $chart_title The chart title
     * @param string $chart_description    The description of the chart
     */
    
public function setChartData($data_array$start_in_row 1$start_in_column 1$chart_title ""$chart_description "") {
        
// Setting starting point 
        
$this->row_start $start_in_row;
        
$this->column_start $start_in_column;
        
$this->row_index $this->row_start;

        if (
$chart_title) {    // If chart title is available - use it
            
$this->setCellData($chart_title11);
        }
        if (
$chart_description) { // If chart description is available - use it
            
$this->setCellData($chart_description21);
        }
        
        
// Inserting data into the Excel sheet
        
foreach ($data_array as $row) {
            
$this->column_index $this->column_start;
            foreach (
$row as $column) {
                
$this->setCellData($column$this->row_index$this->column_index);
                
$this->column_index++;
            }
            
$this->row_index++;
        }
        
$this->removeCellBoundries();    // Removes the cell boundries from the excel sheet.
    
}
    
    
/**
     * Set data into a specific cell
     *
     * @param int $row_index The row index where the data will be set
     * @param int $column_index The column index where the data will be set
     */
    
private function setCellData($data$row_index$column_index) {
        try {
            
$cell $this->sheet[$this->active_sheet]->Cells($row_index$column_index);    // Select the cell to work on (Row#, Column#)
        
} catch (com_exception $e) {
            throw new 
com_exception("[".__CLASS__."::".__FUNCTION__."] ".$e->getMessage()."<BR>");
        }                    
        
$cell->value $data;    
    }

    
/**
     * Removes the grid seperating the cells in Excel
     *
     */
    
private function removeCellBoundries() {
        
$cellRange $this->sheet[$this->active_sheet]->Cells;    // Getting the range of cells
        
$cellInterior $cellRange->Interior;    
        
$cellInterior->ColorIndex 2;

    }
    
    
/**
     * Setting chart type for the Excel graph
     *
     * @param int $chart_type A value for the chart type (use one of the classes constants: "xl..."
     * @param int $location_X The X location where the graph should be painted
     * @param int $location_Y The Y location where the graph should be painted
     * @param int $width  Graph's width
     * @param int $height Graph's height
     */
    
public function setChartType($chart_type$location_X 10$location_Y 40$width 400$height 300) {
        try {
            
$this->chartObj $this->sheet[$this->active_sheet]->chartobjects->add($location_X$location_Y$width$height);        
        } catch (
com_exception $e) {
            throw new 
com_exception("[".__CLASS__."::".__FUNCTION__."] ".$e->getMessage()."<BR>");
        }
        
$this->chartObj->Activate// place a chart in the chart object
        
$this->chart $this->chartObj->chart;
        
$this->chart->ChartType $chart_type;    // Setting the chart type
    
}
    
    
/**
     * Generates the Excel graph, saves the Excel worksheet into a file
     *
     * @param string $chart_title The title for the chart
     * @param string $X_title The title for the X axis of the chart
     * @param string $Y_title The title for the Y axis of the chart
     * @param int $chart_bgcolor The background color for the chart
     */
    
public function generateGraph($chart_title ""$X_title ""$Y_title ""$chart_bgcolor 19) {
        
// Calculating the first and last data cells in the sheet
        
$firstCell chr(64 $this->column_start). ($this->row_start);
        
$lastCell chr(64 $this->column_index 1). ($this->row_index 1);

        
// Setting the data area the chart uses
        
$selectedArea $this->sheet[$this->active_sheet]->range("$firstCell:$lastCell");
        
$this->chart->setsourcedata($selectedArea2); // set the data the chart uses
        
        
$this->setTitles($chart_title$X_title$Y_title);    // Setting chart titles
        
        // Setting the background color of the chart / graph
        
$this->chartFillFormat $this->chart->chartArea->Fill;
        
$this->chartFillFormat->Visible true;
        
$this->chartFillFormat->ForeColor->SchemeColor $chart_bgcolor;
    }

    
/**
     * Setting the main, X axis and Y axis titles of the chart
     *
     * @param string $graph_title
     * @param string $X_axis_title
     * @param string $Y_axis_title
     */
    
private function setTitles($graph_title$X_axis_title$Y_axis_title) {
        if (
$graph_title) {        // Setting the chart's title
            
$this->chart->HasTitle true;
            
$this->chartTitle $this->chart->ChartTitle;
            
$this->chartTitle->Text $graph_title;
        }        
        if (
$X_axis_title) {    //Setting the chart's X axis title
            
$this->chartAxisX $this->chart->Axes(11);
            
$this->chartAxisX->HasTitle True;
            
$this->chartAxisX->AxisTitle->Characters->Text $X_axis_title;
        }
        if (
$Y_axis_title) {    //Setting the chart's Y axis title
            
$this->chartAxisY $this->chart->Axes(21);
            
$this->chartAxisY->HasTitle True;
            
$this->chartAxisY->AxisTitle->Characters->Text $Y_axis_title;
        }
    }
    
    
    
/**
     * Saving Excel file
     *
     * @param string $filename The name used to save the file under
     */
    
public function saveFile($filename "COM_excel_auto_generated_file") {
        if (
file_exists($filename)) {
            
unlink($filename);
        }
        if (!
$this->workbook->SaveAs($filename)) { // saves sheet
            
throw new com_exception("Could not save excel file [".__CLASS__."::".__FUNCTION__."(".__LINE__.")]<BR>");
        }
    }
    
    
/**
     * Set the active sheet to a different one
     *
     * @param string $activeSheet 
     */
    
public function setActiveSheet($activeSheet) {
        
$this->active_sheet $activeSheet;
        
$this->sheet[$this->active_sheet]->activate;
    }
}
?>