phplibrary/src/Excel/Table.php
2021-02-22 14:07:51 +03:00

311 lines
8.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Клетка таблицы
*/
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 Excel_Table
{
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();
}
$row/*: TableRow*/ = $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);
$row/*: TableRow*/ = $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()
{
$keys/*: array*/ = array_keys($this->rows);
return max($keys);
}
/**
* Количество столбцов в строке
*
* @return int
*/
function getRowCells(TableRow $row)
{
$keys/*: array*/ = 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, $value/*: any*/, $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);
}
$nrow/*: TableRow*/ = $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();
}
}