. ======================================================================*/ /*** Usage example: require_once('/var/www/default/libs/kjwlib/KjwLib.php'); require_once('/var/www/default/libs/kjwlib/KjwSimpleXmlWorkbook.php'); $sql = kjwsql_from_url('mssql://sql.server.tlb/some_data'); $excel = new KjwSimpleXmlWorkbook(); $res = $sql->execute("SELECT TOP 10 * FROM data_tbl ORDER BY data_id"); $excel->newWorksheetFromResultSet($res, 'my data'); $excel->offerAsDownload(); ***/ require_once(dirname(__FILE__) . '/KjwObject.php'); class KjwSimpleXmlWorkbook extends KjwObject { var $_null = null; function KjwSimpleXmlWorkbook() { $this->_initEmpty(); } function _initEmpty() { $this->_encoding = 'UTF-8'; $this->_author = 'KjwSimpleXmlWorkbook.php'; $this->_company = 'All4students / KjwLib'; $this->_data = array(); $this->_createDate = strftime('%Y-%m%dT%H:%M:%SZ'); $this->_currentWorksheet = null; } function &newWorkbook() { $this->_initEmpty(); return $this; } /** * creates new sheet and selects it as current sheet */ function &newWorksheet($sheetName) { if (($sheet = $this->_getWorksheet($sheetName)) !== null) return false; array_push($this->_data, array('_TAG' => 'Worksheet', 'Name' => $sheetName, '_DATA' => array())); $this->_currentWorksheet = &$this->_getWorksheet($sheetName); return $this; } function &newWorksheetFromResultSet(&$result, $sheetName) { $this->newWorksheet($sheetName); $at = $result->at(); $result->seekAbs(0); while (($row = $result->getNext())) { if ($result->at() == 1) $this->addHeaderRow(array_keys($row)); $this->addRow($row); } $result->seekAbs($at); return $this; } /** * Gets worksheet if it exists. */ function &_getWorksheet($sheetName) { foreach ($this->_data as $key => $value) { if ($value['Name'] == $sheetName) return $this->_data[$key]; } return $this->_null; } function setAuthor($author) { $this->_author = $author; } function setCompany($company) { $this->_company = $company; } function _toCellData($value, $styleId = null) { assert(!is_object($value) && !is_array($value)); $valueType = 'String'; if (is_double($value) || is_float($value) || is_integer($value)) { $valueType = 'Number'; } elseif (is_bool($value)) { $valueType = 'Boolean'; $value = (int)$value; } elseif (preg_match('/^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})$/', $value, $m)) { if ($styleId === null) $styleId = 'Date'; $valueType = 'DateTime'; $value = sprintf("%04d-%02d-%02dT00:00:00.000", $m[1], $m[2], $m[3]); } elseif (preg_match('/^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{2})/', $value, $m)) { if ($styleId === null) $styleId = 'DateTime'; $valueType = 'DateTime'; $value = sprintf("%04d-%02d-%02dT%02d:%02d:00.000", $m[1], $m[2], $m[3], $m[4], $m[5]); } elseif (preg_match('/^([0-9]{1,2}):([0-9]{2})/', $value, $m)) { if ($styleId === null) $styleId = 'Time'; $valueType = 'DateTime'; $value = sprintf("1899-12-31T%02d:%02d:00.000", $m[1], $m[2]); } $cell = array('_TAG' => 'Cell', '_DATA' => array( '_TAG' => 'Data', 'ss:Type' => $valueType, '_DATA' => $value)); if ($styleId !== null) $cell['ss:StyleID'] = $styleId; return $cell; } function addRow($row) { $newCells = array(); foreach ($row as $value) array_push($newCells, $this->_toCellData($value)); array_push($this->_currentWorksheet['_DATA'], array('_TAG' => 'Row', '_DATA' => $newCells)); } function addHeaderRow($row) { $newCells = array(); foreach ($row as $value) array_push($newCells, $this->_toCellData($value, 'Head')); array_push($this->_currentWorksheet['_DATA'], array('_TAG' => 'Row', '_DATA' => $newCells)); } function _countRowColumnStats($worksheet) { $rowCount = 0; $columnCount = 0; $columnSizes = array(); foreach ($worksheet['_DATA'] as $row) { ++$rowCount; $columnCount = max($columnCount, sizeof($row['_DATA'])); for ($i = 0; $i < sizeof($row['_DATA']); ++$i) { $columnSizes[$i] = max((int)@$columnSizes[$i], 2); if (@$row['_DATA'][$i]['ss:StyleID'] != 'Head') { if (isset($row['_DATA'][$i]['_DATA']) && is_array($row['_DATA'][$i]['_DATA']) && $row['_DATA'][$i]['_DATA']['_TAG'] == 'Data') { $columnSizes[$i] = max($columnSizes[$i], strlen(@$row['_DATA'][$i]['_DATA']['_DATA'])); } } } } return array($rowCount, $columnCount, $columnSizes); } function _xmlToString($data, $indent, $noIndent = false) { assert(!is_string($data)); $output = ''; if (is_array($data) && isset($data['_TAG'])) { $output = ($noIndent ? '' : str_repeat(' ', $indent)) . '<' . $data['_TAG']; foreach ($data as $key => $value) { if ($key[0] != '_') $output .= " $key=\"" . htmlentities($value, ENT_COMPAT, $this->_encoding) . '"';; } if (!isset($data['_DATA'])) { $output .= "/>" . ($noIndent ? '' : "\n"); return $output; } // This takes care of the is_string-case. if (!is_array($data['_DATA'])) { $output .= '>' . htmlentities($data['_DATA'], ENT_COMPAT, $this->_encoding) . "" . ($noIndent ? '' : "\n"); return $output; } if ($data['_TAG'] == 'Cell') { $output .= ">" . $this->_xmlToString($data['_DATA'], $indent + 1, true) . "\n"; } else { $output .= ">\n" . $this->_xmlToString($data['_DATA'], $indent + 1) . str_repeat(' ', $indent) . "" . ($noIndent ? '' : "\n"); } } elseif (is_array($data)) { foreach ($data as $value) { $output .= $this->_xmlToString($value, $indent); } } else { assert(0); } return $output; } function toString() { $author = htmlentities($this->_author, ENT_COMPAT, 'UTF-8'); $company = htmlentities($this->_company, ENT_COMPAT, 'UTF-8'); $createDate = htmlentities($this->_createDate); $output = <<<__EOF__ $author $author $createDate $company 11.5606 12465 13020 600 240 False False __EOF__; foreach ($this->_data as $worksheet) { $worksheetName = htmlentities($worksheet['Name'], ENT_COMPAT, $this->_encoding); list($rowCount, $columnCount, $columnSizes) = $this->_countRowColumnStats($worksheet); $output .= <<<__EOF__ __EOF__; for ($i = 0; $i < sizeof($columnSizes); ++$i) { $output .= " \n"; } foreach ($worksheet['_DATA'] as $row) { $output .= $this->_xmlToString($row, 3); } $output .= <<<__EOF__
False False
__EOF__; } $output .= <<<__EOF__
__EOF__; return $output; } function offerAsDownload($filename = 'data.xls') { header("Content-Disposition: attachment; filename=\"" . urlencode($filename) . "\""); header('Content-Type: application/vnd.ms-excel; charset=UTF-8'); echo $this->toString(); } } ?>