Commit 037fc7d1 authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

refactorin & gestion des nommages de cellules (alias)

parent 74c51faf
Loading
Loading
Loading
Loading
Loading
+117 −33
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Unicaen\OpenDocument;

use Unicaen\OpenDocument\Calc\Formule;
use Unicaen\OpenDocument\Calc\Sheet;

class Calc
@@ -10,23 +11,28 @@ class Calc
    const PARAGRAPH = 'text:p';
    const TABLE_ROW = 'table:table-row';

    /**
     * Lecteur de fichier OpenDocument
     *
     * @var Document
     */
    private $document;
    private \DOMNode $node;

    private Document $document;

    /**
     * @var Sheet[]
     */
    private array $sheets = [];

    private bool $parsedAliases = false;
    private array $aliases = [];



    public function __construct(Document $document)
    {
        $this->document = $document;
        $this->node = $this->document->find($this->document->getContent(), 'office:spreadsheet')[0];
    }



    /**
     * @return Document
     */
    public function getDocument(): Document
    {
        return $this->document;
@@ -34,36 +40,114 @@ class Calc



    /**
     * @param Document $document
     *
     * @return Calc
     */
    public function setDocument(Document $document): Calc
    public function getNode(): \DOMNode
    {
        $this->document = $document;

        return $this;
        return $this->node;
    }



    public function getSheet(int $index): Sheet
    public function getSheet(int|string $index): Sheet
    {
        if (empty($this->sheets)) {
            $nodes = $this->document->find($this->node, 'table:table');
            foreach ($nodes as $ind => $node) {
                $sheet = new Sheet($this, $ind, $node);
                $this->sheets[$ind] = $sheet;
                $this->sheets[$sheet->getName()] = $sheet;
            }
        }

        if (!isset($this->sheets[$index])) {
            $content = $this->document->getContent();
            throw new \Exception('La feuille ' . $index . ' n\'existe pas');
        }

        return $this->sheets[$index];
    }



    public function getAliases(): array
    {
        if (!$this->parsedAliases) {
            $this->parsedAliases = true;
            $namedExpressions = $this->document->find($this->node, 'table:named-expressions')[0];
            if ($namedExpressions) {
                $nrs = $this->document->find($namedExpressions, 'table:named-range');
                foreach ($nrs as $nr) {
                    $alias = $nr->getAttribute('table:name');
                    $target = $nr->getAttribute('table:cell-range-address');
                    $this->aliases[$alias] = $this->analyseAliasTarget($target);
                }
            }

        }

        return $this->aliases;
    }


            $spreadsheet = $this->document->find($content, 'office:spreadsheet')[0];
            $node        = $this->document->find($spreadsheet, 'table:table')[$index];

            if ($node) {
                $this->sheets[$index] = new Sheet($this, $index, $node);
    public function getAliasTarget(string $alias): array
    {
        $aliases = $this->getAliases();
        if (array_key_exists($alias, $aliases)){
            return $aliases[$alias];
        }else{
                throw new \Exception('La feuille '.$index.' n\'existe pas');
            throw new \Exception('L\'alias '.$alias.' n\'a pas été trouvé');
        }
    }

        return $this->sheets[$index];


    private function analyseAliasTarget(string $target): array
    {
        $target = str_replace('$', '', $target);
        $dot = strpos($target, '.');
        $sheetName = substr($target, 0, $dot);
        $target = str_replace('.', '', substr($target, $dot));

        if (str_contains($target, ':')) {
            $target = $this->analyseAliasRange($target);
        } else {
            $target = $this->analyseAliasCell($target);
        }

        $target['sheet'] = $sheetName;

        return $target;
    }



    private function analyseAliasCell(string $cell): array
    {
        return [
            'type' => 'cell',
            'name' => $cell,
        ];
    }



    private function analyseAliasRange(string $range): array
    {
        [$begin, $end] = explode(':', $range);

        $cBegin = Calc::cellNameToCoords($begin);
        $cEnd = Calc::cellNameToCoords($end);

        return [
            'type'          => 'range',
            'begin'         => $begin,
            'end'           => $end,
            'rowBegin'      => $cBegin['row'],
            'rowEnd'        => $cEnd['row'],
            'colBegin'      => $cBegin['col'],
            'colNamedBegin' => Calc::numberToLetter($cBegin['col']),
            'colEnd'        => $cEnd['col'],
            'colNamedEnd'   => Calc::numberToLetter($cEnd['col']),
        ];
    }


+28 −23
Original line number Diff line number Diff line
@@ -84,11 +84,16 @@ class Formule
        $this->analyse();

        foreach ($this->terms as $term) {
            if ($term['type'] === 'cell') {
            switch($term['type']){
                case 'cell':
                    $deps[] = $term['name'];
            }
            if ($term['type'] === 'range') {
                    break;
                case 'variable':
                    $deps[] = $term;
                    break;
                case 'range':
                    $deps[] = $term;
                    break;
            }
        }

+14 −0
Original line number Diff line number Diff line
@@ -51,6 +51,20 @@ class Sheet



    public function getIndex(): int
    {
        return $this->index;
    }



    public function getName(): string
    {
        return $this->node->getAttribute('table:name');
    }



    public function read()
    {
        $this->cells       = [];
+1 −2
Original line number Diff line number Diff line
@@ -543,8 +543,7 @@ class Document
    public function getCalc(): Calc
    {
        if (!$this->calc) {
            $this->calc = new Calc();
            $this->calc->setDocument($this);
            $this->calc = new Calc($this);
        }

        return $this->calc;