exportTo = $exportTo; $this->filename = $filename; } public function initialize() { switch($this->exportTo) { case 'browser': $this->sendHttpHeaders(); break; case 'string': $this->stringData = ''; break; case 'file': $this->tempFilename = tempnam(sys_get_temp_dir(), 'exportdata'); $this->tempFile = fopen($this->tempFilename, "w"); break; } $this->write($this->generateHeader()); } public function addRow($row) { $this->write($this->generateRow($row)); } public function finalize() { $this->write($this->generateFooter()); switch($this->exportTo) { case 'browser': flush(); break; case 'string': // do nothing break; case 'file': // close temp file and move it to correct location fclose($this->tempFile); rename($this->tempFilename, $this->filename); break; } } public function getString() { return $this->stringData; } abstract public function sendHttpHeaders(); protected function write($data) { switch($this->exportTo) { case 'browser': echo $data; break; case 'string': $this->stringData .= $data; break; case 'file': fwrite($this->tempFile, $data); break; } } protected function generateHeader() { // can be overridden by subclass to return any data that goes at the top of the exported file } protected function generateFooter() { // can be overridden by subclass to return any data that goes at the bottom of the exported file } // In subclasses generateRow will take $row array and return string of it formatted for export type abstract protected function generateRow($row); } /** * ExportDataTSV - Exports to TSV (tab separated value) format. */ class ExportDataTSV extends ExportData { function generateRow($row) { foreach ($row as $key => $value) { // Escape inner quotes and wrap all contents in new quotes. // Note that we are using \" to escape double quote not "" $row[$key] = '"'. str_replace('"', '\"', $value) .'"'; } return implode("\t", $row) . "\n"; } function sendHttpHeaders() { header("Content-type: text/tab-separated-values"); header("Content-Disposition: attachment; filename=".basename($this->filename)); } } /** * ExportDataCSV - Exports to CSV (comma separated value) format. */ class ExportDataCSV extends ExportData { function generateRow($row) { foreach ($row as $key => $value) { // Escape inner quotes and wrap all contents in new quotes. // Note that we are using \" to escape double quote not "" $row[$key] = '"'. str_replace('"', '\"', $value) .'"'; } return implode(",", $row) . "\n"; } function sendHttpHeaders() { header("Content-type: text/csv"); header("Content-Disposition: attachment; filename=".basename($this->filename)); } } /** * ExportDataExcel exports data into an XML format (spreadsheetML) that can be * read by MS Excel 2003 and newer as well as OpenOffice * * Creates a workbook with a single worksheet (title specified by * $title). * * Note that using .XML is the "correct" file extension for these files, but it * generally isn't associated with Excel. Using .XLS is tempting, but Excel 2007 will * throw a scary warning that the extension doesn't match the file type. * * Based on Excel XML code from Excel_XML (http://github.com/oliverschwarz/php-excel) * by Oliver Schwarz */ class ExportDataExcel extends ExportData { const XmlHeader = "\n"; const XmlFooter = ""; public $encoding = 'UTF-8'; // encoding type to specify in file. // Note that you're on your own for making sure your data is actually encoded to this encoding public $title = 'Sheet1'; // title for Worksheet function generateHeader() { // workbook header $output = stripslashes(sprintf(self::XmlHeader, $this->encoding)) . "\n"; // Set up styles $output .= "\n"; $output .= "\n"; $output .= "\n"; // worksheet header $output .= sprintf("\n \n", htmlentities($this->title)); return $output; } function generateFooter() { $output = ''; // worksheet footer $output .= "
\n
\n"; // workbook footer $output .= self::XmlFooter; return $output; } function generateRow($row) { $output = ''; $output .= " \n"; foreach ($row as $k => $v) { $output .= $this->generateCell($v); } $output .= " \n"; return $output; } private function generateCell($item) { $output = ''; $style = ''; // Tell Excel to treat as a number. Note that Excel only stores roughly 15 digits, so keep // as text if number is longer than that. if(preg_match("/^-?\d+(?:[.,]\d+)?$/",$item) && (strlen($item) < 15)) { $type = 'Number'; } // Sniff for valid dates; should look something like 2010-07-14 or 7/14/2010 etc. Can // also have an optional time after the date. // // Note we want to be very strict in what we consider a date. There is the possibility // of really screwing up the data if we try to reformat a string that was not actually // intended to represent a date. elseif(preg_match("/^(\d{1,2}|\d{4})[\/\-]\d{1,2}[\/\-](\d{1,2}|\d{4})([^\d].+)?$/",$item) && ($timestamp = strtotime($item)) && ($timestamp > 0) && ($timestamp < strtotime('+500 years'))) { $type = 'DateTime'; $item = strftime("%Y-%m-%dT%H:%M:%S",$timestamp); $style = 'sDT'; // defined in header; tells excel to format date for display } else { $type = 'String'; } $item = str_replace(''', ''', htmlspecialchars($item, ENT_QUOTES)); $output .= " "; $output .= $style ? "" : ""; $output .= sprintf("%s", $type, $item); $output .= "\n"; return $output; } function sendHttpHeaders() { header("Content-Type: application/vnd.ms-excel; charset=" . $this->encoding); header("Content-Disposition: inline; filename=\"" . basename($this->filename) . "\""); } }