Commit bf4cbf25 authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

Meilleure gestion des récursivités

parent d175f821
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ switch ($action) {
                    if (str_starts_with($msg, 'ORA-24344')) {
                        $msg = 'ERREUR : Le package ne compile pas';
                    }
                    echo $msg ?>
                    echo nl2br($msg) ?>
                </div>
                <?php
            }
+7 −2
Original line number Diff line number Diff line
@@ -36,9 +36,13 @@ CREATE OR REPLACE PACKAGE BODY FORMULE_<--NAME--> AS
    dbgi( '[calc|' || fncName || '|' || c || '|' || res );
  END;

  FUNCTION cell( c VARCHAR2, l NUMERIC DEFAULT 0 ) RETURN FLOAT IS
  FUNCTION cell( c VARCHAR2, l NUMERIC DEFAULT 9999 ) RETURN FLOAT IS
    val FLOAT;
  BEGIN
    IF l = 0 THEN
      RETURN 0;
    END IF;

    IF feuille.exists(c) THEN
      IF feuille(c).cells.exists(l) THEN
        IF feuille(c).cells(l).enCalcul THEN
@@ -115,7 +119,7 @@ CREATE OR REPLACE PACKAGE BODY FORMULE_<--NAME--> AS
    val FLOAT;
  BEGIN
    i := ose_formule.intervenant;
    IF l > 0 THEN
    IF l > 0 AND l <> 9999 THEN
      vh := ose_formule.volumes_horaires.items(l);
    END IF;
    CASE c
@@ -124,6 +128,7 @@ CREATE OR REPLACE PACKAGE BODY FORMULE_<--NAME--> AS

<--CELLS-->
    ELSE
      dbms_output.put_line('La colonne c=' || c || ', l=' || l || ' n''existe pas!');
      raise_application_error( -20001, 'La colonne c=' || c || ', l=' || l || ' n''existe pas!');
  END CASE;
  raise_application_error( -20001, 'La colonne c=' || c || ', l=' || l || ' n''existe pas!');
+91 −40
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ class FormuleCalcul

    private array   $cellsPos = [];

    private string  $currentCellName;



    public function __construct(?string $filename = null, ?string $name = null)
@@ -308,34 +310,8 @@ END FORMULE_" . $this->getName() . ";";



    public function makePackageBody(?string $intervenantQuery = null, ?string $volumeHoraireQuery = null): string
    public function getFormuleCells(): array
    {
        if (!$intervenantQuery) {
            $intervenantQuery = 'SELECT
      fi.*,
      NULL param_1,
      NULL param_2,
      NULL param_3,
      NULL param_4,
      NULL param_5
    FROM
      V_FORMULE_INTERVENANT fi';
        }

        if (!$volumeHoraireQuery) {
            $volumeHoraireQuery = 'SELECT
      fvh.*,
      NULL param_1,
      NULL param_2,
      NULL param_3,
      NULL param_4,
      NULL param_5
    FROM
      V_FORMULE_VOLUME_HORAIRE fvh
    ORDER BY
      ordre';
        }

        $s        = $this->getSheet();
        $formules = [];

@@ -351,7 +327,7 @@ END FORMULE_" . $this->getName() . ";";
                }
            }
        }
        $cells = '';


        /** @var Calc\Cell[] $formules */
        foreach ($formules as $name => $cell) {
@@ -384,19 +360,55 @@ END FORMULE_" . $this->getName() . ";";
            }
        }

        return $formules;
    }



    public function makePackageBody(?string $intervenantQuery = null, ?string $volumeHoraireQuery = null): string
    {
        if (!$intervenantQuery) {
            $intervenantQuery = 'SELECT
      fi.*,
      NULL param_1,
      NULL param_2,
      NULL param_3,
      NULL param_4,
      NULL param_5
    FROM
      V_FORMULE_INTERVENANT fi';
        }

        if (!$volumeHoraireQuery) {
            $volumeHoraireQuery = 'SELECT
      fvh.*,
      NULL param_1,
      NULL param_2,
      NULL param_3,
      NULL param_4,
      NULL param_5
    FROM
      V_FORMULE_VOLUME_HORAIRE fvh
    ORDER BY
      ordre';
        }

        $s        = $this->getSheet();
        $formules = $this->getFormuleCells();

        $cells = '';
        foreach ($formules as $name => $cell) {
            $this->currentCellName = $name;

            $expr = $cell->getFormuleExpr();
            if ($this->exprIsTest($expr)) {
                $expr = $this->exprTestToIf($expr);
            }
            $this->exprInit($expr);

            $mls = (string)$this->mainLine;
            if (str_ends_with($name, $mls)) {
                $name = substr($name, 0, -strlen($mls));
            }

            $cellPlsql = "-- $name" . substr($cell->getFormule(), 3) . "\n";
            $cellPlsql = "-- $name" . (substr($cell->getFormule(), 3) ?? $cell->getValue()) . "\n";
            $cellPlsql .= "WHEN '$name' THEN\n";
            $cellPlsql .= $this->indent($this->exprToPlSql($expr)) . "\n\n";

@@ -409,6 +421,7 @@ END FORMULE_" . $this->getName() . ";";
        $body     = str_replace('<--NAME-->', $this->getName(), $body);
        $body     = str_replace('<--INTERVENANT_QUERY-->', $intervenantQuery, $body);
        $body     = str_replace('<--VOLUME_HORAIRE_QUERY-->', $volumeHoraireQuery, $body);
        $cellsPos = $this->getCellsPos();
        foreach ($cellsPos as $param => $cell) {
            $body = str_replace("<--$param-->", "'" . $cell . "'", $body);
        }
@@ -418,17 +431,17 @@ END FORMULE_" . $this->getName() . ";";



    public function testFormule(string $formule)
    public function testFormule(string $cellName, string $formule)
    {
        $this->currentCellName = $cellName;

        $tableur = $formule;
        $formule = new Formule($tableur);

        $struct = $formule->analyse();
        if ($this->exprIsTest($struct)) {
            $struct = $this->exprTestToIf($struct);
        }
        $expr = $formule->analyse();
        $this->exprInit($expr);

        $plsql = $this->exprToPlSql($struct);
        $plsql = $this->exprToPlSql($expr);
        \UnicaenCode\Util::highlight($plsql, 'plsql', true, ['show-line-numbers' => true]);

        $formule->displayTerms();
@@ -437,6 +450,15 @@ END FORMULE_" . $this->getName() . ";";



    private function exprInit(array &$expr)
    {
        if ($this->exprIsTest($expr)) {
            $expr = $this->exprTestToIf($expr);
        }
    }



    private function exprIsTest(array &$expr): bool
    {
        if (count($expr) === 1 && $expr[0]['type'] === 'function') {
@@ -673,7 +695,19 @@ END FORMULE_" . $this->getName() . ";";
    private function preTraitementCell(array &$expr, int $i)
    {
        // On retire les $ qui sont inutiles pour la conversion en Pl/SQL
        $an               = $expr[$i]['name'];
        $expr[$i]['name'] = str_replace('$', '', $expr[$i]['name']);

        // On voit comme absolue toute référence fixe, CAD si ligne < 20, pour éviter des soucis par la suite
        ['col' => $col, 'row' => $row] = Calc::cellNameToCoords($this->currentCellName);
        if ($row < 20) {
            $an = str_replace('19', '$19', $an);
            $an = str_replace('$$', '$', $an);
        }

        if (!isset($expr[$i]['absName'])) {
            $expr[$i]['absName'] = $an;
        }
    }


@@ -833,13 +867,20 @@ END FORMULE_" . $this->getName() . ";";



    private function traductionCell(array &$expr, int $i): string
    public function traductionCell(array &$expr, int $i): string
    {
        $term = $expr[$i];
        ['col' => $col, 'row' => $row] = Calc::cellNameToCoords($term['name']);

        $col = Calc::numberToLetter($col);

        $absName = $term['absName'];
        if (str_starts_with($absName, '$')) {
            $absName = substr($absName, 1); // on élimine le premier $ lié à la colonne
        }

        $absolute = str_contains($absName, '$'); // si on en trouve un autre => ligne relative!!

        if ($row === $this->mainLine) {
            $cellsPos = $this->getCellsPos();
            foreach ($cellsPos as $variable => $column) {
@@ -847,10 +888,20 @@ END FORMULE_" . $this->getName() . ";";
                    return $variable;
                }
            }
        }

        if ($row < $this->mainLine - 1 || $absolute) {
            return "cell('" . $term['name'] . "')";
        } else {
            $rowDiff = $row - $this->mainLine;

            if ($rowDiff < 0) {
                return "cell('$col',l$rowDiff)";
            } elseif ($rowDiff == 0) {
                return "cell('$col',l)";
            } else {
            return "cell('" . $term['name'] . "')";
                return "cell('$col',l+$rowDiff)";
            }
        }
    }