Разбил файл exceltable на классы

This commit is contained in:
origami11 2017-02-17 17:08:18 +03:00
parent b26e521657
commit 7ce493414e
5 changed files with 135 additions and 132 deletions

View file

@ -1,439 +0,0 @@
<?php
class Excel_Number
{
public $value;
function __construct($value)
{
$this->value = intval($value);
}
function getString()
{
return $this->value;
}
}
class Excel_DateTime
{
public $value;
function __construct($value)
{
$this->value = intval($value);
}
function getString()
{
return date('Y-m-d\TH:i:s.u', $this->value);
}
}
/**
* Клетка таблицы
*/
class TableCell
{
public $style = false;
public $value;
public $merge = false;
function __construct ($value)
{
$this->value = $value;
}
}
/**
* Ряд таблицы
*/
class TableRow
{
public $style = false;
public $cells = array();
public $height = false;
function setCell($y, $value)
{
$this->cells[$y] = new TableCell($value);
}
function setCellStyle($y, $name)
{
$this->cells[$y]->style = $name;
}
}
/**
* Таблица
*/
class ExcelTable
{
static $index;
private $name;
private $style;
protected $rows = array();
protected $_splitVertical = false;
protected $_splitHorizontal = false;
function __construct()
{
$this->name = "Page " . intval(self::$index ++);
}
/**
* Записать значение в клетку с заданными координатами
*/
function setCell($x, $y, $value)
{
assert(is_numeric($x) && $x > 0);
assert(is_numeric($y) && $y > 0);
if(! isset($this->rows[$x])) {
$this->rows[$x] = new TableRow();
}
/*.TableRow.*/$row = $this->rows[$x];
$row->setCell($y, $value);
}
/**
* Заполняет ряд начиная с указанного столбца значениями из массива
*/
function setRow($row, $index, array $data)
{
assert(is_numeric($index) && $index > 0);
assert(is_numeric($row) && $row > 0);
reset($data);
for ($i = $index; $i < $index + count($data); $i++) {
$this->setCell($row, $i, current($data));
next($data);
}
}
/**
* Устанавливает высоту ряда
* @param $row integer Номер ряда
* @parma $value real Высота ряда
*/
function setRowHeight ($row, $value)
{
assert(is_numeric($row) && $row > 0);
$this->rows[$row]->height = $value;
}
/**
* Устанавливает стиль ряда
* @param $row integer Номер ряда
* @parma $name string Имя стиля
*/
function setRowStyle ($row, $name)
{
assert(is_numeric($row) && $row > 0);
$this->rows[$row]->style = $name;
}
/**
* Обьединяет клетки в строке
* @param $row Номер ряда
* @param $cell Номер столбца
* @param $merge Количество клеток для обьединения
*/
function setCellMerge($x, $cell, $merge)
{
assert(is_numeric($x) && $x > 0);
assert(is_numeric($cell) && $cell > 0);
/*.TableRow.*/$row = $this->rows[$x];
$row->cells[$cell]->merge = $merge;
}
/**
* Устанавливает стиль для клеток ряда
* @param $row integer Номер ряда
* @param $y integer Номер столбца
* @parma $name string Имя стиля
*/
function setCellStyle ($row, $y, $name)
{
if (isset($this->rows[$row]))
$this->rows[$row]->setCellStyle($y, $name);
}
/**
* Добавляет строку к таблице
*/
function addRow($index = 1, array $data = array(""))
{
assert(is_numeric($index) && $index > 0);
$offset = $this->getRows() + 1;
$this->setRow($offset, $index, $data);
return $offset;
}
/**
* Количество строк в таблице
*
* @return int
*/
function getRows()
{
/*.array.*/$keys = array_keys($this->rows);
return max($keys);
}
/**
* Количество столбцов в строке
*
* @return int
*/
function getRowCells(TableRow $row)
{
/*.array.*/$keys = array_keys($row->cells);
return max($keys);
}
/**
* Разделяет таблицу на две части по вертикали
* @param $n integer Количество столбцов слева
*/
function splitVertical($n) {
$this->_splitVertical = $n;
}
/**
* Разделяет таблицу на две части по горизонтали
* @param $n integer Количество столбцов сверху
*/
function splitHorizontal($n) {
$this->_splitHorizontal = $n;
}
/**
* Количество столбцов в таблице
*
* @return int
*/
function getColumns() {
return max(array_map(array($this, 'getRowCells'), $this->rows));
}
function encode($s)
{
return $s;
}
/**
* Генерация клетки таблицы (Переработать)
*/
function createCell (TableCell $ncell, XMLWriter $doc, $j, /*.any.*/$value, $setIndex) {
$doc->startElement("Cell");
if ($ncell->style) {
$doc->writeAttribute('ss:StyleID', $ncell->style);
}
if ($ncell->merge) {
$doc->writeAttribute('ss:MergeAcross', $ncell->merge);
}
if ($setIndex) {
$doc->writeAttribute('ss:Index', $j);
}
$doc->startElement("Data");
if ($value instanceof Excel_DateTime) {
$doc->writeAttribute('ss:Type', "DateTime");
$doc->text($value->getString());
} else if ($value instanceof Excel_Number) {
$doc->writeAttribute('ss:Type', "Number");
$doc->text($value->getString());
} else {
if (is_string($value)) {
$doc->writeAttribute('ss:Type', "String");
} else {
$doc->writeAttribute('ss:Type', "Number");
}
$doc->writeCData($this->encode($value));
}
$doc->endElement();
$doc->endElement();
}
/**
* Генерация таблицы
*/
public function createTable (XMLWriter $doc) {
$doc->startElement('Worksheet');
$doc->writeAttribute('ss:Name', $this->name);
$columns = $this->getColumns();
$rows = $this->getRows();
$doc->startElement('Table');
$doc->writeAttribute('ss:ExpandedColumnCount', $columns);
$doc->writeAttribute('ss:ExpandedRowCount', $rows);
// Переписать цыкл !!!!!!!
for ($i = 1; $i <= $rows; $i++) {
$doc->startElement('Row');
if (isset($this->rows[$i])) {
if ($this->rows[$i]->style) {
$doc->writeAttribute('ss:StyleID', $this->rows[$i]->style);
}
if ($this->rows[$i]->height) {
$doc->writeAttribute('ss:Height', $this->rows[$i]->height);
}
/*.TableRow.*/$nrow = $this->rows[$i];
// Флаг индикатор подстановки номера столбца
$setIndex = false;
for ($j = 1; $j <= $columns; $j++) {
$value = null;
if (isset($nrow->cells[$j])) {
$value = $nrow->cells[$j]->value;
}
if (!empty($value)) {
$this->createCell($nrow->cells[$j], $doc, $j, $value, $setIndex);
$setIndex = false;
} else {
$setIndex = true;
}
}
}
$doc->endElement();
}
$doc->endElement();
$this->splitPane ($doc);
$doc->endElement();
}
protected function splitPane (XMLWriter $doc) {
$doc->startElement('WorksheetOptions');
$doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel');
$doc->writeElement('FrozenNoSplit');
if ($this->_splitVertical) {
$doc->writeElement('SplitVertical', $this->_splitVertical);
$doc->writeElement('LeftColumnRightPane', $this->_splitVertical);
}
if ($this->_splitHorizontal) {
$doc->writeElement('SplitHorizontal', $this->_splitHorizontal);
$doc->writeElement('TopRowBottomPane', $this->_splitHorizontal);
}
if ($this->_splitHorizontal && $this->_splitVertical) {
$doc->writeElement('ActivePane', 0);
} else if($this->_splitHorizontal) {
$doc->writeElement('ActivePane', 2);
}
$doc->endElement();
}
}
/**
* Документ
*/
class ExcelDocument {
static $ns = "urn:schemas-microsoft-com:office:spreadsheet";
private $table = array ();
protected $styles = array();
function addTable($table) {
$this->table [] = $table;
}
/**
* Добавление стиля к документу
* @param $name string Имя стиля
* @param $values array Параметры стиля
* @param $type Тип стиля
*/
function setStyle ($name, array $values, $type = 'Interior')
{
if(!isset($this->styles[$name])) {
$this->styles[$name] = array();
}
$this->styles[$name][$type] = $values;
}
/**
* Генерация стилей
*/
private function createStyles (XMLWriter $doc) {
$doc->startElement('Styles');
foreach ($this->styles as $name => $sn) {
$doc->startElement('Style');
$doc->writeAttribute('ss:ID', $name);
foreach ($sn as $type => $s) {
// Стиль Borders - составной
if ($type == 'Borders') {
$doc->startElement('Borders');
foreach ($s as $border) {
/*.array.*/$border = $border;
$doc->startElement('Border');
foreach ($border as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
$doc->endElement();
} else {
$doc->startElement($type);
foreach ($s as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
}
$doc->endElement();
}
$doc->endElement();
}
/**
* Преобразует переводы строки в спец символы
*/
function clean ($s) {
assert(is_string($s));
return strtr($s, array ("\n" => "&#10;"));
}
/**
* Сохраняет таблицу в формате Office 2003 XML
* http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
*/
function save($filename)
{
$doc = new XMLWriter();
$doc->openURI($filename);
$doc->setIndent(false);
$doc->startDocument('1.0','utf-8');
$doc->startElement('Workbook');
$doc->writeAttribute('xmlns', self::$ns);
$doc->writeAttribute('xmlns:ss', self::$ns);
$this->createStyles($doc);
foreach ($this->table as $table) {
if ($table instanceof ExcelTable) {
$table->createTable($doc);
} else {
$table_data = call_user_func($table);
$table_data->createTable($doc);
unset($table_data);
}
}
$doc->endElement();
}
}