texlive[74630] Master/texmf-dist: spreadtab (15mar25)

commits+karl at tug.org commits+karl at tug.org
Sat Mar 15 20:39:38 CET 2025


Revision: 74630
          https://tug.org/svn/texlive?view=revision&revision=74630
Author:   karl
Date:     2025-03-15 20:39:38 +0100 (Sat, 15 Mar 2025)
Log Message:
-----------
spreadtab (15mar25)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/spreadtab/README
    trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-en.pdf
    trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-en.tex
    trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-fr.pdf
    trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-fr.tex
    trunk/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty

Modified: trunk/Master/texmf-dist/doc/latex/spreadtab/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spreadtab/README	2025-03-15 19:39:28 UTC (rev 74629)
+++ trunk/Master/texmf-dist/doc/latex/spreadtab/README	2025-03-15 19:39:38 UTC (rev 74630)
@@ -1,9 +1,9 @@
                              L'extension
                               spreadtab
 
-                                v0.6
+                                v0.61
 
-                          27 février 2025
+                            14 mars 2025
 
 Author    : Christian Tellechea
 Email     : unbonpetit at netc.fr     (CT)

Modified: trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-en.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-en.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-en.tex	2025-03-15 19:39:28 UTC (rev 74629)
+++ trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-en.tex	2025-03-15 19:39:38 UTC (rev 74630)
@@ -55,12 +55,13 @@
 		\begingroup
 			\let\do\@makeother\dospecials
 			\make at car@active\ {\space}%
-			\make at car@active\^^M{\par\leavevmode}%
+			\make at car@active\^^M{\par\noexpand\color{black}\leavevmode\noexpand\normalshape}%
 			\make at car@active\^^I{\space\space\space\space}%
 			\make at car@active\,{\leavevmode\kern\z@\string,}%
 			\make at car@active\-{\leavevmode\kern\z@\string-}%
 			\make at car@active\>{\leavevmode\kern\z@\string>}%
 			\make at car@active\<{\leavevmode\kern\z@\string<}%
+			\make at car@active\%{\noexpand\itshape\noexpand\color{gray}\char37 }
 			\exemple@@{#1}%
 }
 
@@ -261,7 +262,7 @@
 
 Therefore, \ST proceeds in 3 steps:
 \begin{itemize}
-	\item First, \ST reads the body of the array. If the macro \texttt{\bfseries\color{red}\string\STxp}\NEW{} is present one or more times, its argument is expanded to the maximum. The body of the table is then divided into rows and cells;
+	\item First, \ST reads the body of the array. If the macro \verb|\STxp| is present one or more times, its argument is expanded to the maximum. The body of the table is then divided into rows and cells;
 	\item the formulas contained in the cells are then calculated, having first calculated the dependent cells;
 	\item the body of the table is finally reconstructed, having replaced each formula with the numerical value previously calculated, and the whole is given to the table environment specified by the user.
 \end{itemize}
@@ -273,35 +274,25 @@
 
 where \Verb-<tabname>- represents the name of any array environment available with \LaTeX{} or with a package. You can replace \verb|\begin{spreadtab}...\end{spreadtab}| with \verb|\spreadtab...\endspreadtab|.
 
-The \Verb|<options>| must be in the form \STkv{key}{value}\NEW{} to apply only to the current array. To specify \Verb|<options>| valid for all future arrays, use
+The \Verb|<options>| must be in the form \STkv{key}{value} to apply only to the current array. To specify \Verb|<options>| valid for all future arrays, use
 \centerverb|\STset{<key>=<value>}|
 The list of \STkey{keys} and associated \STval{values} is available on page~\pageref{key/val}.
 
 Although the spreadsheet-like functionality of \LaTeX{} is appreciable, you should not lose sight of the fact that the 3 steps described above are time-consuming. As a result, compilation times are much longer than with a conventional table.
 
-\section{New in version 0.6}
-This version is likely to break usage compared to previous versions\NEW{} due to the removal of certain macros and a change in the optional argument. Therefore, it is important to pay attention to the following points, especially if compilation errors occur:
+\section{New in v0.61}
+\subsection{Deletion}
+The macro functions \STmacro{ifeq}, \STmacro{iflt} and \STmacro{ilgt} have been removed, since \xfp provides the ternary operator
+\centerverb|<test>?<true>:<false>|
 
-\begin{enumerate}
-	\item \xfp is now the only possible calculation engine, and therefore, it is mandatory to use a version of \LaTeX{} released after the integration of \texttt{xfp} into the kernel on 2022/06/01;
-	\item support for the old calculation engine \href{http://mirrors.ctan.org/macros/latex/contrib/fp/documentation.pdf}{\texttt{fp}} is permanently discontinued;
-	\item when calling the package with \verb|\usepackage{spreadtab}|, no optional argument is now possible since there is only one calculation engine;
-	\item the environment now operates within a semi-simple group;
-	\item The \href{https://ctan.org/pkg/simplekv}{\texttt{simplekv}} package is loaded to use the \STkv{key}{value} system. All \ST settings are now done using the macro \verb|\STset{|\STkv{key}{value}\verb|}|;
-	\item the optional argument that follows \Verb|\begin{spreadtab}[<options>]| now contains \textbf{\color{red} exclusively} the keys/values to set the current table, and therefore:
-		\begin{itemize}
-			\item the macro \verb|\STsavecell| is removed and replaced by the key \STkey{save list} (see page~\pageref{save list})
-			\item the macros \verb|\STdebug| and \verb|\STdisplaytab| are removed and replaced by the key \STkey{debug} (see page~\pageref{debug})
-		\end{itemize}
-		This point will cause compilation errors if the optional argument contains the above macros as it did in previous versions.
-	\item if \verb|\STxp| appears one or more times within the table body, the maximum expansion of its argument is performed during the table reading;
-	\item the macro \verb|\STmakegtag| is removed; assignments through the macro-function \STmacro{tag} are always global due to point 4;
-	\item the macro-function \STmacro{tag} allows, if the key \STkv{tag to aux}{true}, to write assignments to the auxiliary file;
-	\item the key \STkey{aux save list} allows saving the content of user-selected cells into macros and writing assignments to the auxiliary file; 
-	\item belonging to older versions, the macros \verb|\STautoround|, \verb|\STsetdecimalsep|, \verb|\STeol|, \verb|\STsetdisplaymarks|, \verb|\STmessage|, \verb|\STnumericfieldmarker|, \verb|\STtranposechar|, and \verb|\STtextcell|, while still functioning (but no longer documented), will be removed in the next version;
-	\item the macro functions \STmacro{ifeq}, \STmacro{ifgt} and \STmacro{iflt} will be removed in the next version.
-\end{enumerate}
+The following macros, available in previous versions, have been removed: \verb|\STautoround|, \verb|\STsetdecimalsep|, \verb|\STeol|, \verb|\STsetdisplaymarks|, \verb|\STmessage|, \verb|\STnumericfieldmarker|, \verb|\STtextcell| and \verb|\STtranposechar|. All settings are now made via \Verb|\STset{<keys>=<values>}|.
 
+\subsection{Macro \texttt{\textbackslash STrep}}
+See page~\pageref{STrep}.
+
+\subsection{Macro-function \STmacro{test}}
+See page~\pageref{test}.
+
 \section{Common Features}
 \subsection{Calculation}
 A cell can now contain any calculation understood by \xfp: basic operations, trigonometry and inverses, exponentials and logarithms, comparisons, logical connectors\footnote{If you wish to use the logical connector "and" in \xfp, denoted by "\texttt{\string&\string&}", it is \emph{mandatory} to enclose this operator in braces within a table to prevent the \texttt{\string&} tokens from being interpreted as column separators. In a table cell, for example, to check if the content of the cell \texttt{a1} belongs to an interval, you would write: "\texttt{a1>1 \string{\string&\string&\string} a1<10}".}, factorials, random numbers, etc. See the documentation for \href{http://mirrors.ctan.org/macros/latex/required/l3kernel/interface3.pdf}{\texttt{interface3}}.
@@ -434,9 +425,33 @@
 
 When copying a formula, if the target cell already contains a non-empty numeric field, this is not overwritten and the copy is not made.
 
+\subsection{Macros provided by \ST}
+\subsubsection{Macro \texttt{\textbackslash STset}}
+The \verb|\STset| macro includes in its mandatory argument a csv of \STkv{keys}{values} to specify settings that operate for the rest of the document.
+
+The list of \STkey{keys} and associated \STval{values} is available on the~\pageref{key/val} page.
+
+\subsubsection{The macros \texttt{\textbackslash STxp} and \texttt{\textbackslash STrep}}
+The presence\footnote{\ST tests its \emph{presence} and then acts on its argument: \texttt{\textbackslash STxp} takes the place of a marker and is not executed when the array is read.} of \verb|\STxp{<argument>}| in the body of the table has the effect of fulle xpansion of the \Verb|<argument>|. If one or more parts of the \verb|<argument>| are not expandable (e.g. non-robust macros), it's up to the user to block full expansion using, for example, the \verb|\noexpand| or \verb|\unexpanded| primitives. The \verb|\STxp| macro must not be enclosed in braces: it will be ignored and executed much later, causing a compilation error.
+\bigbreak
+
+The expandable macro \verb|\STrep|\label{STrep} replicates \Verb| | times an arbitrary \Verb|<code>|:
+\centerverb!\STrep{<n>}{<code>}!
+
+Used in the argument of \verb|\STxp|, it allows you to generate empty cells or identical lines in a concise way.
+\exemple*/\begin{spreadtab}{{tabular}{|c|*{10}{c}|}}
+	\hline
+	@$\times$        & 1                     & \STcopy{>}{b1+1}  \STxp{\STrep8&}\\\hline
+	1                & \STcopy{>,v}{!a2*b!1} \STxp{\STrep9&}\\
+	\STcopy{v}{a2+1} \STxp{\STrep9{\STrep{10}&\\}}
+	\hline
+\end{spreadtab}/
+
+If one or more parts of the \verb|<code>| cannot be expanded (non-robust macros in particular), it is up to the user to stop the full expansion initiated by \verb|\STxp| with, for example, the \verb|\noexpand| or \verb|\unexpanded| primitives.
+
 \section{Table formatting}
 \subsection{Codes executed before or after the table}
-The \STkv{pretab code}{code}\label{pretab code} and \STkv{posttab code}{code}\label{posttab code}\NEW{} keys define arbitrary codes executed just before and just after table display.
+The \STkv{pretab code}{code}\label{pretab code} and \STkv{posttab code}{code}\label{posttab code} keys define arbitrary codes executed just before and just after table display.
 \exemple!A simple
 \begin{spreadtab}[pretab code=\begingroup\color{red},
                   posttab code=\endgroup]{{tabular}[t]{r}}
@@ -661,50 +676,31 @@
 \end{spreadtab}!
 
 \subsection{Comparison macro-functions}
-Three test macro-functions are available and will soon be removed since \xfp has the operator «\verb|?:|», see below.
-\centerverb|ifeq(<number1>,<number2>,<number3>,<number4>)
-ifgt(<number1>,<number2>,<number3>,<number4>)
-iflt(<number1>,<number2>,<number3>,<number4>)|
+There are no more comparison macros since the \xfp engine has a ternary operator \Verb|<a>?<b>:<c>|. If the test \Verb|<a>| is true, \Verb|<b>| is returned; otherwise, \Verb|<c>| is returned.
 
-The comparison is between \Verb|<number1>| and \Verb|<number2>|:
-\begin{itemize}
-	\item \STmacro{ifeq}: \Verb|<number1>| = \Verb|<number2>| ?
-	\item \STmacro{ifgt}: \Verb|<number1>| > \Verb|<number2>| ?
-	\item \STmacro{iflt}: \Verb|<number1>| < \Verb|<number2>| ?
-\end{itemize}
-If the test is true, \Verb|<number3>| is returned, otherwise it's \Verb|<number4>|.
+On the other hand, \ST offers the macro function \STmacro{test}\label{test} which has a special syntax with 2 arguments:
+\centerverb|test(csv of <tests>)<optional spaces>(csv of <texts>)|
 
-As an example, here are a few values of the function
-$f(x)=\begin{cases}
-10  &\text{si }x<1\\
-0   &\text{si }x=1\\
--10 &\text{si }x>1
-\end{cases}
-$\smallskip
+The \Verb|<tests>| are performed from left to right and the first one that is \verb|true|, the corresponding \Verb|<text>| is returned. If there are $n$ \Verb|<test>|, the \Verb|<text>| of index $n+1$ will be returned if all the tests are false.
 
-\exemple!\begin{spreadtab}{{tabular}{|*2c|}}\hline
-	@$x$       & @$f(x)$               \\\hline
-	-0.5       & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\\hline
-\end{spreadtab}!
-The \xfp engine and its ternary operator \Verb|<a>?<b>:<c>| make tests easier in evaluated expressions; if the test \Verb|<a>| is true, \Verb|<b>| is selected, otherwise \Verb|<c>| is used. Thus, the nesting of tests above is programmed as follows:
+If the number of \Verb|<texts>| is insufficient compared to the number of \Verb|<tests>|, the missing \Verb|<texts>| are considered empty.
 
-\exemple!\begin{spreadtab}{{tabular}{|*2c|}}\hline
-	@$x$       & @$f(x)$               \\\hline
-	-0.5       & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\\hline
+\exemple!\begin{spreadtab}{{tabular}{c|c}}
+	\hline
+	@Month & @Season \\\hline
+	1     & \STcopy v{test("a2=1||a2>10 , a2<5 , a2<8")
+	                      (Winter,Spring,Summer,Fall)} \\
+	\STcopy v{a2+1} \STxp{\STrep{11}{& \\}}% 11 empty lines
+	\hline
 \end{spreadtab}!
 
+The part of the formula to be copied between the characters ''\verb|"|'' indicates which part should be taken into account for the offset when copying. It can be modified with the key \STkey{copy char}\label{copy char}.
+
+If you wish to use the logical connector \verb|&&|, it is \emph{necessary} to enclose it in braces. In this way, the cell to be copied could contain the following equivalent tests\chevronsfalse
+\centerverb|\STcopy v{test("a2>2{&&}a2<6,a2>5{&&}a2<9,a2>8{&&}a2<12")
+              (Spring,Summer,Fall,Winter)}|
+\chevronstrue
+
 \subsection{Macro-functions manipulating dates}
 \subsubsection{Date to number with \ttfamily engshortdatetonum}\label{datetonum}
 The macro \verb-engshortdatetonum- converts a short date like 1789/7/14 to an integer which is the number of days passed since the 1st March of the year 0. It is important to note that this macro-function requires a \emph{textual} argument and not a number or the result of a mathematical calculation. Therefore, if the argument of this macro-function refers to a cell, that cell \emph{must} be a text cell, i.e. a cell containing `\verb- at -' or `\verb-:={}-'.
@@ -720,7 +716,7 @@
 \end{spreadtab}!
 
 \subsubsection{From a number to a date}
-Several macro-functions translate a number into a date. All these macro-functions have in common that their result is \emph{text}. Therefore, the cells containing such results \emph{become cells containing text} and if the cell is composed of two fields, the numeric field becomes empty and `\verb-:={<formula>}-' is replaced by its result in the text field.
+Several macro functions can be used to translate a number into a date. All these macro-functions have in common that their result is \emph{text}. As a result, immediately after a number-to-text macro function has been evaluated, any other evaluation in the cell is stopped and the cell becomes a text cell. If there was text in the cell with the formula, the result of the formula will be inserted instead of \Verb-:={<formula>}-. As the cell is made up of text only, it can no longer be processed mathematically.
 
 These macro-functions are:
 \begin{itemize}
@@ -934,6 +930,7 @@
 	\STkey{save list} & \STval[]{} & \pageref{save list} & csv list of the form \chevrons{macro}$=$\chevrons{absolute reference}: each number contained in the referenced cells is stored (globally) in a macro. This key is reset to empty after each table. \\
 	\STkey{aux save list} &\STval[]{} & \pageref{aux save list} & same syntax and behavior as above, but assignments are also written to the auxiliary file. This key is reset to empty after each table.  \\
 	\STkey{display marks} & \STval[]{<\kern0pt<;>\kern0pt>} & \pageref{display marks} & markers around an absolute reference in a text field to display the number contained in the referenced cell \\
+	\STkey{copy char} & \STval{"} & \pageref{copy char} & in the argument to \verb|\STcopy|, sets the beginning and end of the part of the formula which must be taken into account for the offsets when copying \\
 	\STkey{tag to aux} & \STval{false} & \pageref{tag to aux} & when \STval{true}, assignments made by the macro function \STmacro{tag} are also written to the auxiliary file. \\
 	\STkey{messages} & \STval{false} & \pageref{messages} & allows \ST to send messages to the log file about what it's doing \\
 	\STkey{debug} & \STval[]{} & \pageref{debug} & must contain words from \STval{text}, \STval{formula} or \STval{cellcode} in csv format to display the corresponding debugging table. If the word \STval{show tab} is added, the table is also displayed. This key is reset to empty after each table.\\

Modified: trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-fr.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-fr.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-fr.tex	2025-03-15 19:39:28 UTC (rev 74629)
+++ trunk/Master/texmf-dist/doc/latex/spreadtab/spreadtab-fr.tex	2025-03-15 19:39:38 UTC (rev 74630)
@@ -55,12 +55,13 @@
 		\begingroup
 			\let\do\@makeother\dospecials
 			\make at car@active\ {\space}%
-			\make at car@active\^^M{\par\leavevmode}%
+			\make at car@active\^^M{\par\noexpand\color{black}\leavevmode\noexpand\normalshape}%
 			\make at car@active\^^I{\space\space\space\space}%
 			\make at car@active\,{\leavevmode\kern\z@\string,}%
 			\make at car@active\-{\leavevmode\kern\z@\string-}%
 			\make at car@active\>{\leavevmode\kern\z@\string>}%
 			\make at car@active\<{\leavevmode\kern\z@\string<}%
+			\make at car@active\%{\noexpand\itshape\noexpand\color{gray}\char37 }
 			\exemple@@{#1}%
 }
 
@@ -261,7 +262,7 @@
 
 Par conséquent, \ST procède en 3 étapes :
 \begin{itemize}
-	\item en premier lieu, \ST lit le corps du tableau. Si la macro \texttt{\bfseries\color{red}\string\STxp}\NEW{} est présente une ou plusieurs fois, son argument est développé au maximum. Le corps du tableau est ensuite divisé en lignes puis en cellules;
+	\item en premier lieu, \ST lit le corps du tableau. Si la macro \verb|\STxp| est présente une ou plusieurs fois, son argument est développé au maximum. Le corps du tableau est ensuite divisé en lignes puis en cellules;
 	\item le calcul des formules contenues dans les cellules est ensuite effectué, en ayant pris soin pour chacune de calculer auparavant les cellules dépendantes;
 	\item le corps du tableau est enfin reconstruit en ayant remplacé chaque formule par la valeur numérique préalablement calculée et le tout est donné à l'environnement tableau spécifié par l'utilisateur.
 \end{itemize}
@@ -273,38 +274,28 @@
 
 où \Verb-<tabname>- représente le nom de n'importe quel environnement de type tableau disponible avec \LaTeX{} ou avec un package. Il est possible de remplacer \verb|\begin{spreadtab}...\end{spreadtab}| par \verb|\spreadtab...\endspreadtab|.
 
-Les \Verb|<options>| doivent se présenter sous la forme \STkv{clé}{valeur}\NEW{} pour ne s'appliquer qu'au tableau en cours. Pour spécifier des \Verb|<options>| valables pour tous les tableaux à venir, on utilise
+Les \Verb|<options>| doivent se présenter sous la forme \STkv{clé}{valeur} pour ne s'appliquer qu'au tableau en cours. Pour spécifier des \Verb|<options>| valables pour tous les tableaux à venir, on utilise
 \centerverb|\STset{<clé>=<valeur>}|
 La liste des \STkey{clés} et des \STval{valeurs} associées est disponible à la page~\pageref{key/val}.
 
 Même si disposer de fonctionnalités ressemblant à celles d'un tableur avec \LaTeX{} est appréciable, il ne faut pas perdre de vue que les 3 étapes décrites ci-dessus prennent du temps. L'ensemble conduit donc à des temps de compilation \emph{beaucoup plus importants} qu'avec un tableau classique.
 
-\section{Nouveau dans la version 0.6}
-Cette version\NEW{} est susceptible de casser l'utilisation selon les versions précédentes en raison de la suppression de certaines macros et d'un changement dans l'argument optionnel. Il est donc important de prêter attention aux points qui suivent, surtout si des erreurs de compilation se produisent :
+\section{Nouveau dans la version 0.61}
+\subsection{Suppressions}
+Les macro-fonctions \STmacro{ifeq}, \STmacro{iflt} et \STmacro{ilgt} sont supprimées puisque \xfp met à disposition l'opérateur ternaire
+\centerverb|<test>?<vrai>:<faux>|
 
-\begin{enumerate}
-	\item \xfp est désormais le seul moteur de calcul possible et donc, il est obligatoire d'utiliser une version de \LaTeX{} postérieure à l'intégration de \texttt{xfp} dans le noyau le 2022/06/01;
-	\item le support du vieux moteur de calcul \href{http://mirrors.ctan.org/macros/latex/contrib/fp/documentation.pdf}{\texttt{fp}} est définitivement abandonné;
-	\item lors de l'appel du package par \verb|\usepackage{spreadtab}|, aucun argument optionnel n'est désormais possible puisqu'il n'y a qu'un moteur de calcul;
-	\item l'environnement agit désormais dans un groupe semi simple;
-	\item Le package \href{https://ctan.org/pkg/simplekv}{\texttt{simplekv}} est chargé pour utiliser le système de \STkv{clé}{valeur}. Tous les réglages de \ST se font désormais avec la macro \verb|\STset{|\STkv{clé}{valeur}\verb|}|;
-	\item l'argument optionnel qui suit \Verb|\begin{spreadtab}[<options>]| contient désormais \textbf{\color{red}exclusivement} les clés/valeurs que l'on souhaite appliaquer au tableau en cours et donc :
-		\begin{itemize}
-			\item la macro \verb|\STsavecell| est supprimée et remplacée par la clé \STkey{save list} (voir page~\pageref{save list})
-			\item les macros \verb|\STdebug| et \verb|\STdisplaytab| sont supprimées et remplacés par la clé \STkey{debug} (voir page~\pageref{debug})
-		\end{itemize}
-	Ce point va provoquer des erreurs de compilation si l'argument optionnel contient les macros ci-dessus comme c'était le cas dans les versions précédentes.
-	\item si \verb|\STxp| est présent dans le corps du tableau une ou plusieurs fois, le développement maximal de son argument est effectué pendant la lecture du tableau;
-	\item suppression de la macro \verb|\STmakegtag|, les assignations par la macro-fonction \STmacro{tag} sont toujours globales à cause du point 4;
-	\item la macro-fonction \STmacro{tag} permet, si la clé \STkv{tag to aux}{true}, d'écrire les assignations dans le fichier auxiliaire;
-	\item la clé \STkey{aux save list} permet de sauvegarder le contenu de cellules choisies par l'utilisateur dans des macros et écrire les assignations dans le fichier auxiliaire;
-	\item appartenant aux anciennes versions, les macros suivantes \verb|\STautoround|, \verb|\STsetdecimalsep|, \verb|\STeol|, \verb|\STsetdisplaymarks|, \verb|\STmessage|, \verb|\STnumericfieldmarker|, \verb|\STtranposechar| et \verb|\STtextcell|, bien que fonctionnant encore (mais plus documentées), seront supprimées à la prochaine version;
-	\item les macro-fonctions \STmacro{ifeq}, \STmacro{ifgt} et \STmacro{iflt} seront supprimées à la prochaine version.
-\end{enumerate}
+Les macros des versions précédentes \verb|\STautoround|, \verb|\STsetdecimalsep|, \verb|\STeol|, \verb|\STsetdisplaymarks|, \verb|\STmessage|, \verb|\STnumericfieldmarker|, \verb|\STtextcell| et \verb|\STtranposechar| sont supprimées : tous les réglages se font désormais par l'intermédiaire de \Verb|\STset{<clés>=<valeurs>}|.
 
+\subsection{La macro \texttt{\textbackslash STrep}}
+Voir page~\pageref{STrep}.
+
+\subsection{La macro fonction \STmacro{test}}
+Voir page~\pageref{test}.
+
 \section{Fonctionnalités courantes}
 \subsection{Calcul}
-Une cellule peut désormais contenir tout calcul compris par \xfp : opérations courantes, trigonométrie et inverses, exponentielles et logarithmes, comparaisons, connecteurs logiques\footnote{Si l'on souhaite utiliser le connecteur logique «et» de \xfp noté «\texttt{\string&\string&}», il est \emph{obligatoire} de mettre cet opérateur entre accolades dans un tableau afin que les tokens \texttt{\string&} ne soient pas compris comme des séparateurs de colonnes. Dans une cellule d'un tableau, pour tester si le contenu de la cellule \texttt{a1} appartient à un intervalle, on écrira donc par exemple «\texttt{a1>1 \string{\string&\string&\string} a1<10}».}, factorielle, nombres aléatoires, etc. Voir la documentation de \href{http://mirrors.ctan.org/macros/latex/required/l3kernel/interface3.pdf}{\texttt{interface3}}.
+Une cellule peut contenir tout calcul compris par \xfp : opérations courantes, trigonométrie et inverses, exponentielles et logarithmes, comparaisons, connecteurs logiques\footnote{Si l'on souhaite utiliser le connecteur logique «et» de \xfp noté «\texttt{\string&\string&}», il est \emph{obligatoire} de mettre cet opérateur entre accolades dans un tableau afin que les tokens \texttt{\string&} ne soient pas compris comme des séparateurs de colonnes. Dans une cellule d'un tableau, pour tester si le contenu de la cellule \texttt{a1} appartient à un intervalle, on écrira donc par exemple «\texttt{a1>1 \string{\string&\string&\string} a1<10}».}, factorielle, nombres aléatoires, etc. Voir la documentation de \href{http://mirrors.ctan.org/macros/latex/required/l3kernel/interface3.pdf}{\texttt{interface3}}.
 
 Par conséquent, les macro-fonctions \STmacro{rand}, \STmacro{rnd} et \STmacro{fact} sont toujours utilisables, mais ne sont \emph{plus} des macro-fonctions de \ST : elles sont directement comprises par \xfp.
 
@@ -434,9 +425,33 @@
 
 Lors d'une copie de formule, si la cellule cible contient déjà un champ numérique non vide, celui-ci n'est pas écrasé et la copie ne se fait pas.
 
+\subsection{Macros mises à disposition par \ST}
+\subsubsection{Macro \texttt{\textbackslash STset}}
+La macro \verb|\STset| admet dans son argument obligatoire une série de \STkv{clés}{valeurs} pour spécifier des réglages opérant pour le reste du document.
+
+La liste des \STkey{clés} et des \STval{valeurs} associées est disponible à la page~\pageref{key/val}
+
+\subsubsection{Les macros \texttt{\textbackslash STxp} et \texttt{\textbackslash STrep}}
+La présence\footnote{\ST teste sa \emph{présence} et agit ensuite sur son argument : \texttt{\textbackslash STxp} tient lieu de marqueur et n'est pas exécutée lors de la lecture du tableau.} de \verb|\STxp{<argument>}| dans le corps du tableau a pour effet de développer au maximum l'\Verb|<argument>|. Si une ou plusieurs parties de l'\Verb|<argument>| ne sont pas développables (macros non robustes notamment), il appartient à l'utilisateur de bloquer le développement maximal avec, par exemple, les primitives \verb|\noexpand| ou \verb|\unexpanded|. La macro \verb|\STxp| ne doit pas se trouver dans des accolades : elle y serait ignorée  et exécutée bien plus tard en provoquant une erreur de compilation.
+\bigbreak
+
+La macro développable \verb|\STrep|\label{STrep} réplique \Verb|<n>| fois un \Verb|<code>| arbitraire :
+\centerverb!\STrep{<n>}{<code>}!
+
+Utilisée dans l'argument de \verb|\STxp|, elle permet de générer des cellules vide ou des lignes identiques de façon concise.
+\exemple*/\begin{spreadtab}{{tabular}{|c|*{10}{c}|}}
+	\hline
+	@$\times$        & 1                     & \STcopy{>}{b1+1}  \STxp{\STrep8&}\\\hline
+	1                & \STcopy{>,v}{!a2*b!1} \STxp{\STrep9&}\\
+	\STcopy{v}{a2+1} \STxp{\STrep9{\STrep{10}&\\}}
+	\hline
+\end{spreadtab}/
+
+Si une ou plusieurs parties du \Verb|<code>| ne sont pas développables (macros non robustes notamment), il appartient à l'utilisateur de bloquer le développement maximal initié par \verb|\STxp| avec, par exemple, les primitives \verb|\noexpand| ou \verb|\unexpanded|.
+
 \section{Mise en forme du tableau}
 \subsection{Codes exécutés avant ou après le tableau}
-Les clés \STkv{pretab code}{code}\label{pretab code} et \STkv{posttab code}{code}\label{posttab code}\NEW{} définissent des codes arbitraires exécutés juste avant et juste après l'affichage du tableau.
+Les clés \STkv{pretab code}{code}\label{pretab code} et \STkv{posttab code}{code}\label{posttab code} définissent des codes arbitraires exécutés juste avant et juste après l'affichage du tableau.
 \exemple!Une addition
 \begin{spreadtab}[pretab code=\begingroup\color{red},
                   posttab code=\endgroup]{{tabular}[t]{r}}
@@ -661,50 +676,31 @@
 \end{spreadtab}!
 
 \subsection{Macro-fonctions de test}
-3 macro-fonctions de test sont disponibles et seront prochainement supprimées puisque \xfp qui dispose de l'opérateur «\verb|?:|», voir plus bas) :
-\centerverb|ifeq(<nombre1>,<nombre2>,<nombre3>,<nombre4>)
-ifgt(<nombre1>,<nombre2>,<nombre3>,<nombre4>)
-iflt(<nombre1>,<nombre2>,<nombre3>,<nombre4>)|
+Il n'y a plus de macro-fonctions de comparaison qui renvoient un nombre puisque le moteur \xfp dispose d'un opérateur ternaire \Verb|<a>?<b>:<c>|. Si le test \Verb|<a>| est vrai, le nombre \Verb|<b>| est renvoyé sinon, c'est le nombre \Verb|<c>|.
 
-La comparaison se fait entre \Verb|<nombre1>| et \Verb|<nombre2>| :
-\begin{itemize}
-	\item test d'égalité pour \STmacro{ifeq} : \Verb|<nombre1>| = \Verb|<nombre2>| ?
-	\item test  de supériorité stricte pour \STmacro{ifgt} : \Verb|<nombre1>| > \Verb|<nombre2>| ?
-	\item test d'infériorité stricte pour \STmacro{iflt} : \Verb|<nombre1>| < \Verb|<nombre2>| ?
-\end{itemize}
-Si le test est vrai, \Verb|<nombre3>| est retourné, sinon c'est \Verb|<nombre4>|.
+\ST offre en revanche la macro fonction \STmacro{test}\label{test} qui a une syntaxe particulière ayant 2 arguments :
+\centerverb|test(csv de <tests>)<espaces optionnels>(csv de <textes>)|
 
-À titre d'exemple, voici quelques valeurs de la fonction
-$f(x)=\begin{cases}
-10  &\text{si }x<1\\
-0   &\text{si }x=1\\
--10 &\text{si }x>1
-\end{cases}
-$\smallskip
+Les \Verb|<tests>| sont effectués de gauche à droite et au premier qui est \verb|vrai|, le \Verb|<texte>| correspondant est renvoyé. S'il y a $n$ \Verb|<test>|, le \Verb|<texte>| d'index $n+1$ sera renvoyé si tous les tests sont faux.
 
-\exemple!\begin{spreadtab}{{tabular}{|*2c|}}\hline
-	@$x$       & @$f(x)$               \\\hline
-	-0.5       & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\
-	[0,-1]+0.5 & iflt([-1,0],1,10,ifeq([-1,0],1,0,-10))\\\hline
-\end{spreadtab}!
-Le moteur \xfp et son opérateur ternaire \Verb|<a>?<b>:<c>| rend les tests plus faciles dans les expressions évaluées ; si le test \Verb|<a>| est vrai, \Verb|<b>| est retenu sinon, c'est \Verb|<c>|. Ainsi, l'imbrication de tests ci-dessus se programme :
+Si le nombre de \Verb|<textes>| est insuffisant par rapport au nombre de \Verb|<tests>|, les \Verb|<textes>| manquants sont considérés vides.
 
-\exemple!\begin{spreadtab}{{tabular}{|*2c|}}\hline
-	@$x$       & @$f(x)$               \\\hline
-	-0.5       & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\
-	[0,-1]+0.5 & [-1,0]<1 ? 10 : [-1,0]=1 ? 0 : -10\\\hline
+\exemple!\begin{spreadtab}{{tabular}{c|c}}
+	\hline
+	@Mois & @Saison \\\hline
+	1     & \STcopy v{test("a2=1||a2>10 , a2<5 , a2<8")
+	                      (Hiver,Printemps,Été,Automne)} \\
+	\STcopy v{a2+1} \STxp{\STrep{11}{& \\}}% 11 lignes vides
+	\hline
 \end{spreadtab}!
 
+La partie de la formule à copier se trouvant entre les caractères «\verb|"|» indique quelle partie doit être prise en compte pour le décalage lors de la copie. Il est modifiable avec la clé \STkey{copy char}\label{copy char}.
+
+Si l'on souhaite utiliser le connecteur logique \verb|&&|, il est \emph{nécessaire} de le mettre entre accolades. Ainsi, la cellule à copier aurait pu contenir les tests équivalents suivants\chevronsfalse
+\centerverb|\STcopy v{test("a2>2{&&}a2<6,a2>5{&&}a2<9,a2>8{&&}a2<12")
+              (Printemps,Été,Automne,Hiver)}|
+\chevronstrue
+
 \subsection{Macro-fonctions de date}
 \subsubsection{Convertir une date en nombre avec \ttfamily frshortdatetonum}\label{datetonum}
 La macro \STmacro{frshortdatetonum} permet de convertir une date de la forme 14/7/1789 en un nombre qui est en fait le nombre de jours écoulés depuis le 1\ier{} mars de l'an 0\footnote{Cet «an 0» n'existe d'ailleurs pas, mais cela ne devrait pas être gênant pour les dates contemporaines}. Il est important de noter que cette macro-fonction requiert un argument \emph{textuel} et non pas un nombre ou le résultat d'un calcul mathématique. Par conséquent, si l'argument de cette macro-fonction fait référence à une cellule, cette cellule \emph{doit} être une cellule textuelle, c'est à dire contenant «\verb- at -» ou «\verb-:={}-»
@@ -720,7 +716,7 @@
 \end{spreadtab}!
 
 \subsubsection{Passer d'un nombre à une date}
-Plusieurs macro-fonctions permettent de traduire un nombre en une donnée de date. Toutes ces macro-fonctions ont en commun que leur résultat est du \emph{texte}. Par conséquent, \emph{la cellule les contenant deviendra une cellule textuelle} dont le texte sera le résultat de cette fonction. Si un texte cohabitait avec la formule dans cette cellule, le résultat de la formule sera inséré à la place de \Verb-:={<formule>}-. Il en résulte que la cellule ne peut plus faire l'objet d'aucun traitement mathématique ensuite.
+Plusieurs macro-fonctions permettent de traduire un nombre en une donnée de date. Toutes ces macro-fonctions ont en commun que leur résultat est du \emph{texte}. Par conséquent, immédiatement après l'évaluation d'une macro-fonction nombre vers texte, tout autre évaluation dans la cellule est stoppée et \emph{la cellule devient une cellule textuelle}. Si un texte cohabitait avec la formule dans cette cellule, le résultat de la formule sera inséré à la place de \Verb-:={<formule>}-. La cellule étant composée de texte seulement, ell ne peut plus faire l'objet d'aucun traitement mathématique ensuite.
 
 Voici ces fonctions :
 \begin{itemize}
@@ -915,7 +911,7 @@
 Dans les tableaux de débogage, les cellules contenant les coordonnées ne sont grisées que si le package \href{https://ctan.org/pkg/colortbl}{\texttt{colortbl}} a été chargé.
 
 \section{Liste des clés}\label{key/val}
-Tous les réglages concernant \ST se font à partir de la version 0.6\NEW{} par un système de \chevrons{clés}$=$\chevrons{valeur} qui peuvent se trouver :
+Tous les réglages concernant \ST se font à partir de la version 0.6 par un système de \chevrons{clés}$=$\chevrons{valeur} qui peuvent se trouver :
 \begin{enumerate}
 	\item dans l'argument de \verb|\STset| auquel cas les réglages spécifiés concernent tous les tableaux à venir ;
 	\item dans l'argument optionnel de \verb|\begin{spreadtab}| ou \verb|spreadtab| et dans ce cas, les réglages spécifiés ne concernent que le tableau en cours.
@@ -934,6 +930,7 @@
 	\STkey{save list} & \STval[]{} & \pageref{save list} & liste csv de la forme \chevrons{macro}$=$\chevrons{référence absolue} : chaque nombre contenu dans les cellules référencées est stockée (globalement) dans une macro. Cette clé est réinitialisée à vide après chaque tableau \\
 	\STkey{aux save list} &\STval[]{} & \pageref{aux save list} & même syntaxe et comportement que ci-dessus, mais les assignations sont également écrites dans le fichier auxiliaire. Cette clé est réinitialisée à vide après chaque tableau  \\
 	\STkey{display marks} & \STval[]{<\kern0pt<;>\kern0pt>} & \pageref{display marks} & marqueurs autour d'une référence absolue dans un champ textuel pour afficher le nombre contenu dans la cellule référencée \\
+	\STkey{copy char} & \STval{"} & \pageref{copy char} & dans l'argument de \verb|\STcopy|, indique le début et la fin de la partie de la formule qui doit être prise en compte pour les décalages lors de la copie \\
 	\STkey{tag to aux} & \STval{false} & \pageref{tag to aux} & lorsque \STval{true}, les assignations faites par la macro-fonction \STmacro{tag} sont également écrites dans le fichier auxiliaire \\
 	\STkey{messages} & \STval{false} & \pageref{messages} & permet à \ST d'émettre des messages dans le fichier log sur ce qu'il est en train de faire \\
 	\STkey{debug} & \STval[]{} & \pageref{debug} & doit contenir sous forme csv des mots parmi \STval{text}, \STval{formula} ou \STval{cellcode} pour afficher le tableau de débogage correspondant. Si le mot \STval{show tab} est ajouté, le tableau est également affiché. Cette clé est réinitialisée à vide après chaque tableau.\\

Modified: trunk/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty	2025-03-15 19:39:28 UTC (rev 74629)
+++ trunk/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty	2025-03-15 19:39:38 UTC (rev 74630)
@@ -3,9 +3,9 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                    %
 \def\STname                   {spreadtab}                            %
-\def\STver                       {0.6}                               %
+\def\STver                       {0.61}                              %
 %                                                                    %
-\def\STdate                   {2025/02/27}                           %
+\def\STdate                   {2025/03/14}                           %
 %                                                                    %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                    %
@@ -28,11 +28,16 @@
 \NeedsTeXFormat{LaTeX2e}[2022/06/01]
 \RequirePackage{xstring,simplekv}
 
-\expandafter\edef\csname ST_restorecatcode\endcsname{\catcode\number`\_=\the\catcode`\_\relax}
-\catcode`\_11
+\expandafter\edef\csname ST_restorecatcode\endcsname{%
+	\catcode\number`\_=\the\catcode`\_\relax
+	\catcode0=\the\catcode0 \relax
+}
+\catcode`\_ 11
+\catcode0 12
 %-------------------------------
 %----- Macros généralistes -----
 %-------------------------------
+\chardef\ST_stop0
 \def\ST_letcs#1#2{\expandafter\let\expandafter#1\csname#2\endcsname}
 \def\ST_antefi#1\fi{\fi#1}
 \def\ST_id#1{#1}
@@ -46,6 +51,8 @@
 \long\def\ST_exec_second#1#2{#2}
 \def\ST_remove_to_nnil#1\_nnil{}
 \def\ST_cslet#1{\expandafter\let\csname#1\endcsname}
+\def\ST_swaptwo#1#2{#2#1}
+\def\ST_e_after#1#2{\expandafter\ST_swaptwo\expandafter{#2}{#1}}% #1#2 -> #1*#2
 \long\def\ST_swaparg#1#2{#2{#1}}
 \long\def\ST_e_second#1#2{\expandafter\ST_swaparg\expandafter{#2}{#1}}
 \long\def\ST_ee_second#1#2{\expandafter\expandafter\expandafter\ST_swaparg\expandafter\expandafter\expandafter{#2}{#1}}
@@ -61,6 +68,10 @@
 \ST_letcs\ST_ifnextchar{@ifnextchar}
 \ST_letcs\ST_ifstar{@ifstar}
 \def\ST_quark{\ST_quark}% quark de spreadtab
+\def\ST_take_first_char#1#2{% #1= argument #2=macro qui reçoit le 1er car détokénisé de #1
+	\expandafter\ST_take_first_char_a\detokenize{#1}\_nil#2%
+}
+\def\ST_take_first_char_a#1#2\_nil#3{\def#3{#1}}
 \def\ST_grab_int#1{% partage #1 en une partie entière et une aprtie restante
 	\ST_e_second\ST_grab_int_a{\expanded{#1}}%
 }
@@ -104,8 +115,8 @@
 %----- liste des différentes macro-fonctions -----
 %-------------------------------------------------
 \def\ST_functions_with_num_arg{% liste des fonctions dont l'argument est numérique
-	id,ifeq,ifgt,iflt,numtofrshortdate,numtoengshortdate,numtofrlongdate,gcd,lcm,%
-	numtoenglongdate,numtofrmonth,numtoengmonth,numtofrday,numtoengday%
+	id,numtofrshortdate,numtoengshortdate,numtofrlongdate,gcd,lcm,%
+	numtoenglongdate,numtofrmonth,numtoengmonth,numtofrday,numtoengday,test%
 }
 
 \def\ST_functions_with_text_arg{% liste des fonctions dont l'argument est un texte
@@ -113,7 +124,7 @@
 }
 
 \def\ST_functions_no_calc_arg{% liste des fonctions dont l'argument ne doit pas être calculé
-	ifeq,ifgt,iflt,gcd,lcm,value%
+	gcd,lcm,value,test%
 }
 
 \def\ST_functions_with_assign_argument{% liste des fonctions dont l'argument est une variable -> il ne faut donc pas aller chercher des références dans l'argument
@@ -122,7 +133,7 @@
 
 \def\ST_functions_with_textresult{% liste des fonctions dont le résultat est un texte
 	numtofrshortdate,numtoengshortdate,numtofrlongdate,numtoenglongdate,%
-	numtofrmonth,numtoengmonth,numtofrday,numtoengday%
+	numtofrmonth,numtoengmonth,numtofrday,numtoengday,test%
 }
 
 \def\ST_functions_with_range_arg{% liste des fonctions admettant des plages de cellules
@@ -136,10 +147,6 @@
 %----- interface avec l3fp -----
 %-------------------------------
 \def\ST_fpeval#1#2{\edef#1{\fpeval{#2}}}
-\ST_letcs\ST_fp_compare{fp_compare:nNnTF}% TODO à supprimer
-\def\ST_ifgt#1#2{\ST_fp_compare{#1}>{#2}}% TODO à supprimer
-\def\ST_iflt#1#2{\ST_fp_compare{#1}<{#2}}% TODO à supprimer
-\def\ST_ifeq#1#2{\ST_fp_compare{#1}={#2}}% TODO à supprimer
 
 %-----------------------
 %----- allocations -----
@@ -263,6 +270,13 @@
 	}\STseedoc_a
 }
 
+\def\STxp{%
+	\PackageError\STname{%
+		\string\STxp\space remains after tab scan^^J
+		probably because inside braces.%
+	}\STseedoc_a
+}
+
 %---------------------------------
 %----- macros de coordonnées -----
 %---------------------------------
@@ -394,15 +408,30 @@
 	\expandafter\ST_mid_a#1\_nil
 }
 
-\def\ST_subst_once#1#2#3{% Dans la sc #1, substitue la première occurrence du pattern #2 par le pattern #3
-	\def\ST_subst_once_a##1#2##2\_nil{\def#1{##1#3##2}}%
+\def\ST_subst_once_unsafe#1#2#3{% Dans la sc #1, substitue la première occurrence du pattern #2 par le pattern #3
+	\def\ST_subst_once_unsafe_a##1#2##2\_nil{\def#1{##1#3##2}}%
 	\ST_if_instr#1{\empty#2}
-		{\expandafter\ST_subst_once_a#1\_nil}
+		{\expandafter\ST_subst_once_unsafe_a#1\_nil}
 		{}%
 }
 
-\def\ST_subst#1#2#3{% Dans la sc #1, substitue le pattern #2 par le pattern #3
-	\def\ST_subst_a##1#2##2\_nnil{%
+\def\ST_esubst_once_unsafe#1#2#3{% Dans la sc #1, substitue la première occurrence du pattern #2 par le pattern \romannumeral#3
+	\def\ST_esubst_once_unsafe_a##1#2##2\_nil{\ST_e_after{\ST_esubst_once_unsafe_b##1}{\romannumeral#3##2}\_nil#1}%
+	\ST_if_instr#1{\empty#2}
+		{\expandafter\ST_esubst_once_unsafe_a#1\_nil}
+		{}%
+}
+\def\ST_esubst_once_unsafe_b#1\_nil#2{%
+	\def#2{#1}%
+}
+
+\def\ST_esubst_once#1#2#3{% Dans la sc #1, substitue la première occurrence du pattern #2 par le pattern \romannumeral#3
+	\StrSubstitute[1]{#1}{\empty#2}{\empty\romannumeral#3}[#1]%
+}
+
+
+\def\ST_subst_unsafe#1#2#3{% Dans la sc #1, substitue le pattern #2 par le pattern #3
+	\def\ST_subst_unsafe_a##1#2##2\_nnil{%
 		\ST_ifempty{##2}
 			{%
 			\def#1{##1}%
@@ -409,19 +438,26 @@
 			\ST_remove_to_nnil
 			}
 			{%
-			\ST_subst_a
+			\ST_subst_unsafe_a
 			}%
 		##1#3##2\_nnil
 	}%
-	\expandafter\ST_subst_a#1#2\_nnil
+	\expandafter\ST_subst_unsafe_a#1#2\_nnil
 }
 
+\def\ST_eargs_subst_unsafe#1#2#3{%
+	\ST_exp_two_args{\ST_subst_unsafe#1}{#2}{#3}%
+}
+
+\def\ST_subst#1#2#3{% Dans la sc #1, substitue le pattern #2 par le pattern #3
+	\StrSubstitute{#1}{\empty#2}{\empty#3}[#1]%
+}
 \def\ST_eargs_subst#1#2#3{%
-	\ST_exp_two_args{\ST_subst#1}{#2}{#3}%
+	\StrSubstitute{#1}{#2}{#3}[#1]%
 }
 
 \def\ST_remove_sp#1{%
-	\ST_subst#1{ }{}%
+	\ST_subst_unsafe#1{ }{}%
 }
 
 \def\ST_ifvalid_csname#1#2#3{%
@@ -587,13 +623,11 @@
 					{%
 					\ST_find_copy_args\ST_current_cell\ST_copyrange\ST_copyformula% on chope les arguments de \STcopy
 					\ST_scan_copy_offset\ST_copyrange% cherche les décalages
-					\edef\ST_copyrange{\ST_hoffest,\ST_voffest}% et affecte sous forme a,b où a et b sont des nombres ou sont vides
-					\ST_e_second{\def\STtocopylist}{\expandafter|\ST_copyformula|}% \STtocopylist est le nouvel élément à ajouter à la copylist
-					\ST_xadd_tomacro\STtocopylist{[\number\ST_col_cnt,\number\ST_row_cnt]}%
-					\ST_eadd_tomacro\STtocopylist{\expandafter(\ST_copyrange)}%
-					\ST_eadd_tomacro\STtocopylist\ST_copy_list% ajoute la copylist à la fin
-					\let\ST_copy_list\STtocopylist% et l'assigne à copylist
-					\ST_transpose_formula00\ST_copyformula\ST_copyformula% on transpose éventuellement pour gérer les "!"
+					\ST_e_second{\def\ST_add_to_copylist}{\ST_copyformula^^00}% \ST_add_to_copylist est le nouvel élément à ajouter à la copylist
+					\ST_xadd_tomacro\ST_add_to_copylist{[\number\ST_col_cnt,\number\ST_row_cnt](\ST_hoffest,\ST_voffest)}%
+					\ST_eadd_tomacro\ST_add_to_copylist\ST_copy_list% ajoute la copylist à la fin
+					\let\ST_copy_list\ST_add_to_copylist% et l'assigne à copylist
+					\ST_shift_formula00\ST_copyformula\ST_copyformula% on transpose éventuellement pour gérer les "!"
 					\ST_cslet{formula_\number\ST_col_cnt _\number\ST_row_cnt}\ST_copyformula% affecte la formule inchangée au champ numérique courant
 					}%
 					{%
@@ -741,17 +775,45 @@
 % Cette macro transpose toutes les références (absolues et relatives) de la sc #3.
 % Le décalage est de #1 (nombre signé) pour les colonnes et de #2 (nombre signé) pour les lignes.
 % La sc #4 recoit la formule transposée.
-\def\ST_transpose_formula#1#2#3#4{%
+\def\ST_shift_formula#1#2#3#4{%
 	\def\ST_addcol{#1}%
 	\def\ST_addrow{#2}%
 	\let\ST_temp_formula#3%
-	\let\ST_initial_formula#3%
-	\let\ST_transposed_formula\empty
-	\ST_transpose_formula_a
-	\let#4\ST_transposed_formula
+	\StrCount{\ST_temp_formula}{\ST_copy_char}[\ST_occurs_copy_char]%
+	\ST_ifnum{\ST_occurs_copy_char>1 }
+		{%
+		\let#4\empty
+		\ST_shift_formula_a#4%
+		}
+		{%
+		\let\ST_shifted_formula\empty
+		\ST_shift_formula_b
+		\let#4\ST_shifted_formula
+		}%
 }
 
-\def\ST_transpose_formula_a{%
+\def\ST_shift_formula_a#1{%
+	\StrBefore\ST_temp_formula\ST_copy_char[\ST_temp_formula_before]%
+	\StrBehind[2]\ST_temp_formula\ST_copy_char[\ST_temp_formula_after]%
+	\StrBetween[1,2]\ST_temp_formula\ST_copy_char\ST_copy_char[\ST_temp_formula]%
+	\let\ST_shifted_formula\empty
+	\ST_shift_formula_b
+	\ST_xadd_tomacro#1{%
+		\unexpanded\expandafter{\ST_temp_formula_before}%
+		\unexpanded\expandafter{\ST_shifted_formula}%
+		}%
+	\StrCount{\ST_temp_formula}{\ST_copy_char}[\ST_occurs_copy_char]%
+	\ST_ifnum{\ST_occurs_copy_char>1 }
+		{%
+		\let\ST_temp_formula\ST_temp_formula_after
+		\ST_shift_formula_a#1%
+		}
+		{%
+		\ST_eadd_tomacro#1\ST_temp_formula_after
+		}%
+}
+
+\def\ST_shift_formula_b{%
 	\ST_ifx{\empty\ST_temp_formula}
 		{}
 		{% tant que l'on n'a pas parcouru \ST_temp_formula
@@ -782,7 +844,7 @@
 				\ifnum\ST_firstcar<1 % erreur de copie ?
 					\ST_illegal_copy
 				\fi% erreur de copie ?
-				\ST_xadd_tomacro\ST_transposed_formula{%
+				\ST_xadd_tomacro\ST_shifted_formula{%
 					\ifcase\ST_firstcar \or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or
 						n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z
 					\fi
@@ -792,7 +854,7 @@
 				\fi
 				}
 				{%
-				\ST_eadd_tomacro\ST_transposed_formula\ST_firstcar
+				\ST_eadd_tomacro\ST_shifted_formula\ST_firstcar
 				}%
 			}%
 			{%
@@ -822,16 +884,16 @@
 						\def\ST_addrow_{0}% sinon, on n'ajoute rien
 						}%
 					\ST_if_integer\ST_rel_num
-						{\ST_xadd_tomacro\ST_transposed_formula{[\ST_addcol_,\number\numexpr\ST_rel_num-\ST_addrow_]}}%
+						{\ST_xadd_tomacro\ST_shifted_formula{[\ST_addcol_,\number\numexpr\ST_rel_num-\ST_addrow_]}}%
 						{\ST_illegal_relativeref}%
 					}%
 					\ST_illegal_relativeref
 				}
 				{%
-				\ST_eadd_tomacro\ST_transposed_formula\ST_firstcar
+				\ST_eadd_tomacro\ST_shifted_formula\ST_firstcar
 				}%
 			}%
-		\ST_transpose_formula_a
+		\ST_shift_formula_b
 	}%
 }
 
@@ -903,12 +965,12 @@
 		}%
 }
 
-\def\ST_test_first_in_copy_list|#1|[#2,#3](#4,#5)#6\_nil{% Teste si un élément de la copylist contient une plage qui inclus la cellule en cours.
+\def\ST_test_first_in_copy_list#1^^00[#2,#3](#4,#5)#6\_nil{% Teste si un élément de la copylist contient une plage qui inclus la cellule en cours.
 	\def\ST_alias_copylist{#6}% on enlève le premier élément de la copylist
 	\ST_if_intereval\ST_copycol\ST_copyrow[#2,#3](#4,#5)% si ça correspond
 		{%
 		\def\ST_returned_formula{#1}%
-		\ST_transpose_formula{\numexpr\ST_copycol-#2}{\numexpr\ST_copyrow-#3}\ST_returned_formula\ST_returned_formula
+		\ST_shift_formula{\numexpr\ST_copycol-#2}{\numexpr\ST_copyrow-#3}\ST_returned_formula\ST_returned_formula
 		}%
 		{%
 		\ST_ifempty{#5}
@@ -915,7 +977,7 @@
 			{}
 			{%
 			\ifnum\ST_copyrow>\numexpr#3+#5\relax
-				\ST_subst\ST_copy_list{|#1|[#2,#3](#4,#5)}{}% si on a dépassé la ligne, on retire ce premier élément de la copylist
+				\ST_subst_unsafe\ST_copy_list{#1^^00[#2,#3](#4,#5)}{}% si on a dépassé la ligne, on retire ce premier élément de la copylist
 			\fi
 			}%
 		}%
@@ -960,9 +1022,9 @@
 	\ST_return_ref_in_formula_a
 	\let#2\ST_temp_formula
 	\unless\ifx\empty\ST_ref_found
-		\ST_if_first_is\ST_after_ref_found|
+		\ST_if_first_is\ST_after_ref_found^^00
 			{}
-			{\ST_exp_two_args{\ST_subst_once#1}\ST_ref_found{\ST_ref_found|}}%
+			{\ST_exp_two_args{\ST_subst_once_unsafe#1}\ST_ref_found{\ST_ref_found^^00}}%
 	\fi
 }
 
@@ -977,7 +1039,7 @@
 		\ST_e_second\ST_if_car_is_letter\ST_firstcar% est-ce que le 1er car est une lettre ?
 			{%
 			\ST_grab_int\ST_temp_formula\ST_target_rownumber\ST_after_ref_found
-			\ifnum\ST_target_rownumber>0 % si ce nombre est plus grand que 0 -> référence valide
+			\ifnum\ST_target_rownumber0>0 % si ce nombre est non vide et plus grand que 0 -> référence valide BUGFIX 0.61
 				\edef\ST_ref_found{\ST_firstcar\ST_target_rownumber}% est la référence trouvée
 				\edef\ST_target_colnumber{\number\numexpr\expandafter`\ST_firstcar-`a+1}% traduction lettre->chiffre
 				\ifnum\ST_target_colnumber<0
@@ -1172,17 +1234,17 @@
 							{\ST_e_second{\def\ST_target_formula}{\expandafter(\ST_target_formula)}}%
 							{}%
 						% on remplace toutes les références par la valeur cible
-						\expandafter\ST_eargs_subst\csname formula_#1_#2\endcsname{\ST_ref_found|}\ST_target_formula
+						\expandafter\ST_eargs_subst_unsafe\csname formula_#1_#2\endcsname{\ST_ref_found^^00}\ST_target_formula
 						\edef\ST_stack_call{(#1,#2)\ST_stack_call}% puis, on évalue à nouveau cette cellule
 					\else% code cible n'est pas {0,1,2} donc est -1, pas bon du tout !
 						\edef\ST_temp_callcell{#1,#2}% coordonnées de la cellule appelante
-						\ST_subst\ST_coord _,% coordonnées appelées
+						\ST_subst_unsafe\ST_coord _,% coordonnées appelées
 						\ST_multicol_cell
 					\fi
 					}%
 					{%
 					\edef\ST_temp_callcell{#1,#2}% coordonnées de la cellule appelante
-					\ST_subst\ST_coord _,% coordonnées appelées
+					\ST_subst_unsafe\ST_coord _,% coordonnées appelées
 					\ST_undefined_cell% code cible inexistant -> cellule hors limite du tableau
 					}%
 				}%
@@ -1199,18 +1261,27 @@
 					\ST_letcs\ST_current_formula{formula_#1_#2}% alias pour la formule
 					\let\ST_to_subst\ST_function_namefound
 					\ST_eadd_tomacro\ST_to_subst{\expandafter(\ST_function_argfound)}% ce qui va être replacé : fonction(argument)
-					\ST_if_instr{\ST_functions_no_calc_arg,}{\ST_function_namefound,}% doit-on calculer l'argument de cette fonction ?
+					\ST_if_instr{\ST_functions_no_calc_arg,}{\ST_function_namefound,}%
 						{}%
-						{\ST_fpeval\ST_function_argfound\ST_function_argfound}%
+						{\ST_fpeval\ST_function_argfound\ST_function_argfound}% doit-on calculer l'argument de cette fonction ?
 					\csname ST_func_\ST_function_namefound\endcsname\ST_function_argfound\ST_result_func% puis on évalue la fonctionfound
-					\ST_if_first_is\ST_result_func-%
-						{\ST_e_second{\def\ST_result_func}{\expandafter(\ST_result_func)}}
-						{}%
-					\ST_eargs_subst\ST_current_formula\ST_to_subst\ST_result_func% on replace dans l'alias
-					\ST_cslet{formula_#1_#2}\ST_current_formula% on l'assigne dans la formule
-					\ST_ifx{\empty\ST_current_formula}% pour cause de macro fonction "tag" qui est seule et qui a disparue après substitution
-						{\ST_csdef{code_#1_#2}{0}}%
-						{\edef\ST_stack_call{(#1,#2)\ST_stack_call}}% puis, on évalue à nouveau cette cellule
+					\IfSubStr{\ST_functions_with_textresult,}{\ST_function_namefound,}% si macro-fonction renvoie un texte
+						{%
+						\ST_exp_two_args{\ST_esubst_once\ST_current_formula}\ST_to_subst\ST_result_func% on replace dans l'alias en développant <resultat><reste formule>
+						\ST_csdef{code_#1_#2}{0}% neutralise tout le restant de la cellule
+						\ST_cslet{text_#1_#2}\ST_current_formula% on met tout dans le champ texte
+						\ST_cslet{formula_#1_#2}\empty
+						}
+						{%
+						\ST_if_first_is\ST_result_func-%
+							{\ST_e_second{\def\ST_result_func}{\expandafter(\ST_result_func)}}
+							{}%
+						\ST_eargs_subst\ST_current_formula\ST_to_subst\ST_result_func% on replace dans l'alias
+						\ST_cslet{formula_#1_#2}\ST_current_formula% on l'assigne dans la formule
+						\ST_ifx{\empty\ST_current_formula}% pour cause de macro fonction "tag" qui est seule et qui a disparue après substitution
+							{\ST_csdef{code_#1_#2}{0}}
+							{\edef\ST_stack_call{(#1,#2)\ST_stack_call}}%
+						}%
 					}
 					{%
 					\ST_ifnum{\csname code_\ST_temp_formula\endcsname=2 }% si la référence est calculée, on la replace par sa valeur
@@ -1222,8 +1293,8 @@
 						\let\ST_to_subst\ST_function_namefound
 						\ST_eadd_tomacro\ST_to_subst{\expandafter(\ST_function_argfound)}%
 						\let\ST_replaced\ST_to_subst
-						\ST_eargs_subst\ST_replaced{\ST_ref_found|}\ST_current_formula
-						\ST_subst\ST_to_subst|{}%
+						\ST_eargs_subst\ST_replaced{\ST_ref_found^^00}\ST_current_formula
+						\ST_subst\ST_to_subst^^00{}%
 						\expandafter\ST_eargs_subst\csname formula_#1_#2\endcsname\ST_to_subst\ST_replaced
 						\edef\ST_stack_call{(#1,#2)\ST_stack_call}%
 						}
@@ -1240,7 +1311,7 @@
 					\ST_if_first_is\ST_result_func-%
 						{\ST_e_second{\def\ST_result_func}{\expandafter(\ST_result_func)}}
 						{}%
-					\expandafter\ST_eargs_subst\csname formula_#1_#2\endcsname\ST_to_subst\ST_result_func% on replace dans la formule
+					\expandafter\ST_eargs_subst_unsafe\csname formula_#1_#2\endcsname\ST_to_subst\ST_result_func% on replace dans la formule
 					\edef\ST_stack_call{(#1,#2)\ST_stack_call}% puis, on évalue à nouveau cette cellule
 				\fi
 			\or% le code vaut 3, c'est un fonction dont l'argument est textuel
@@ -1254,7 +1325,7 @@
 					\let\ST_to_subst\ST_function_namefound
 					\ST_eadd_tomacro\ST_to_subst{\expandafter(\ST_function_argfound)}% ce qui va être remplacé : fonction(argument)
 					\csname ST_func_\ST_function_namefound\endcsname\ST_function_argfound_edefed\ST_result_func% puis on évalue la fonction
-					\ST_eargs_subst\ST_current_formula\ST_to_subst\ST_result_func% on replace dans l'alias
+					\ST_eargs_subst_unsafe\ST_current_formula\ST_to_subst\ST_result_func% on replace dans l'alias
 					\ST_cslet{formula_#1_#2}\ST_current_formula% on l'assigne dans la formule
 					\edef\ST_stack_call{(#1,#2)\ST_stack_call}% puis, on évalue à nouveau cette cellule
 					}
@@ -1268,9 +1339,9 @@
 							{}%
 						\let\ST_to_subst\ST_function_namefound
 						\ST_eadd_tomacro\ST_to_subst{\expandafter(\ST_function_argfound)}%
-						\ST_subst\ST_to_subst|{}%
+						\ST_subst_unsafe\ST_to_subst^^00{}%
 						\csname ST_func_\ST_function_namefound\endcsname\ST_current_formula\ST_result_func% puis on évalue la fonction
-						\expandafter\ST_eargs_subst\csname formula_#1_#2\endcsname\ST_to_subst\ST_result_func
+						\expandafter\ST_eargs_subst_unsafe\csname formula_#1_#2\endcsname\ST_to_subst\ST_result_func
 						\edef\ST_stack_call{(#1,#2)\ST_stack_call}% puis, on évalue à nouveau cette cellule
 						}
 						{%
@@ -1301,7 +1372,7 @@
 \def\ST_sanitize_stack{% enlève de \ST_stack_call toutes les occurrences de \ST_temp_a
 	\ST_if_instr\ST_stack_call\ST_temp_a
 		{%
-		\ST_e_second{\ST_subst\ST_stack_call}{\ST_temp_a}{}%
+		\ST_e_second{\ST_subst_unsafe\ST_stack_call}{\ST_temp_a}{}%
 		\ST_sanitize_stack
 		}%
 		{}%
@@ -1476,8 +1547,8 @@
 			\ST_if_ref\ST_temp_a{}\ST_invalid_range
 			\let\ST_currentmatcol\ST_target_colnumber
 			\let\ST_currentmatrow\ST_target_rownumber
-			\expandafter\edef\csname ST_vectorcol_\romannumeral\ST_cnt\endcsname{\number\numexpr\ST_target_colnumber-\ST_mat_firstcol}%
-			\expandafter\edef\csname ST_vectorrow_\romannumeral\ST_cnt\endcsname{\number\numexpr\ST_target_rownumber-\ST_mat_firstrow}%
+			\expandafter\edef\csname ST_vectorcol_\number\ST_cnt\endcsname{\number\numexpr\ST_target_colnumber-\ST_mat_firstcol}%
+			\expandafter\edef\csname ST_vectorrow_\number\ST_cnt\endcsname{\number\numexpr\ST_target_rownumber-\ST_mat_firstrow}%
 			\ST_right\ST_currentmat{\empty:}\ST_temp_a
 			\ST_if_ref\ST_temp_a{}\ST_invalid_range
 			\edef\ST_currentmatcol{\number\numexpr\ST_target_colnumber-\ST_currentmatcol}%
@@ -1505,11 +1576,11 @@
 		\fi
 		\ST_cnt1
 		\loop% on multiplie tous les nombres qui se correspondent dans les matrices
-			\edef\ST_tempcoord{\number\numexpr\ST_col_cnt_a+\csname ST_vectorcol_\romannumeral\ST_cnt\endcsname _\number\numexpr\ST_row_cnt_a+\csname ST_vectorrow_\romannumeral\ST_cnt\endcsname}%
+			\edef\ST_tempcoord{\number\numexpr\ST_col_cnt_a+\csname ST_vectorcol_\number\ST_cnt\endcsname _\number\numexpr\ST_row_cnt_a+\csname ST_vectorrow_\number\ST_cnt\endcsname}%
 			\ifcase\csname code_\ST_tempcoord\endcsname
 				\def\ST_inter_result{0}% code =0 -> on met le résultat partiel à 0
 			\or% code =1
-				\ST_subst\ST_tempcoord _,%
+				\ST_subst_unsafe\ST_tempcoord _,%
 				\edef\ST_temp_stack{\ST_temp_stack(\ST_tempcoord)}%
 				\edef\ST_dependance_tree{\ST_dependance_tree(\ST_tempcoord)}% mise à jour de l'arbre des dépendances
 			\or% code=2
@@ -1591,21 +1662,6 @@
 		\let#2#1%
 		}%
 }
-% les fonctions de test------------------------|
-% TODO à supprimer                             |
-\def\ST_def_funcif#1{%                         |
-	\expandafter\ST_def_funcif_a#1\_nil%       |
-}%                                             |
-%                                              |
-\def\ST_def_funcif_a#1,#2,#3,#4\_nil#5#6{%     |
-	\csname ST_if#6\endcsname{#1}{#2}%         |
-		{\def#5{#3}}%                          |
-		{\def#5{#4}}%                          |
-}%                                             |
-%                                              |
-\def\ST_func_ifeq#1#2{\ST_def_funcif#1#2{eq}}% |
-\def\ST_func_ifgt#1#2{\ST_def_funcif#1#2{gt}}% |
-\def\ST_func_iflt#1#2{\ST_def_funcif#1#2{lt}}%_|
 
 % Transforme une date en nombre
 \def\STdatetonum#1#2#3#4{% #1=sc recevant le résultat  #2=jj  #3=mm  #4=aa
@@ -1651,7 +1707,7 @@
 % Transforme un nombre en une date française de type jj/mm/aaaa
 \def\ST_func_numtofrshortdate#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_numtodate#1\ST___day\ST___month\ST___year
-	\edef#2{\ST___day/\ST___month/\ST___year}%
+	\edef#2{\noexpand\ST_stop\ST___day/\ST___month/\ST___year}%
 }
 
 % Transforme un nombre en une date longue française du type «14 juillet 1789»
@@ -1663,19 +1719,19 @@
 }
 \def\ST_func_numtofrlongdate#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_numtodate#1\ST___day\ST___month\ST___year
-	\edef#2{\ST___day\space\ST_num_to_frmonth\ST___month\space\ST___year}%
+	\edef#2{\noexpand\ST_stop\ST___day\space\ST_num_to_frmonth\ST___month\space\ST___year}%
 }
 
 % Extrait d'un nombre représentant une date le mois en toutes lettres en français
 \def\ST_func_numtofrmonth#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_numtodate#1\ST___day\ST___month\ST___year
-	\edef#2{\ST_num_to_frmonth\ST___month}%
+	\edef#2{\noexpand\ST_stop\ST_num_to_frmonth\ST___month}%
 }
 
 % Extrait d'un nombre repésentant une date le nom du jour en français
 \def\ST_func_numtofrday#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_fpeval\ST___day{#1-7*trunc(#1/7,0)}%
-	\edef#2{\ifcase\ST___day mercredi\or jeudi\or vendredi\or samedi\or dimanche\or lundi\or mardi\fi}
+	\edef#2{\noexpand\ST_stop\ifcase\ST___day mercredi\or jeudi\or vendredi\or samedi\or dimanche\or lundi\or mardi\fi}
 }
 
 % transforme une date anglaise courte du type aaaa/mm/jj en nombre
@@ -1687,7 +1743,7 @@
 % Transforme un nombre en une date anglaise de type aaaa/mm/jj
 \def\ST_func_numtoengshortdate#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_numtodate#1\ST___day\ST___month\ST___year
-	\edef#2{\ST___year/\ST___month/\ST___day}
+	\edef#2{\noexpand\ST_stop\ST___year/\ST___month/\ST___day}
 }
 
 % Transforme un nombre en une date longue anglaise du type «July 14, 1789»
@@ -1699,19 +1755,19 @@
 }
 \def\ST_func_numtoenglongdate#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_numtodate#1\ST___day\ST___month\ST___year
-	\edef#2{\ST_num_to_enmonth\ST___month\space\ST___day,\space\ST___year}%
+	\edef#2{\noexpand\ST_stop\ST_num_to_enmonth\ST___month\space\ST___day,\space\ST___year}%
 }
 
 % Extrait d'un nombre représentant une date le mois en toutes lettres en anglais
 \def\ST_func_numtoengmonth#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_numtodate#1\ST___day\ST___month\ST___year
-	\edef#2{\ST_num_to_enmonth\ST___month}%
+	\edef#2{\noexpand\ST_stop\ST_num_to_enmonth\ST___month}%
 }
 
 % Extrait d'un nombre repésentant une date le nom du jour en anglais
 \def\ST_func_numtoengday#1#2{% % #1=nombre représentant la date #2=sc recevant le résultat
 	\ST_fpeval\ST___day{#1-7*trunc(#1/7,0)}%
-	\edef#2{\ifcase\ST___day wednesday\or thursday\or friday\or saturday\or sunday\or monday\or tuesday\fi}
+	\edef#2{\noexpand\ST_stop\ifcase\ST___day wednesday\or thursday\or friday\or saturday\or sunday\or monday\or tuesday\fi}
 }
 
 % Teste si la date contenue dans les 3 sc #1 (jour) #2(mois) #3(année) est valide. Sinon, envoie un message d'erreur
@@ -1793,11 +1849,14 @@
 		\ST_remove_sp#3%
 		\def\ST_e{^^e9}\def\ST_u{^^fb}% é et û en latin1
 		\ifdefined\inputencodingname\ifx\ST_utfencoding\inputencodingname
-			\def\ST_e{^^c3^^a9}\def\ST_u{^^c3^^bb}% é et û en utf8
+			\def\ST_e{^^c3^^a9}%
+			\def\ST_u{^^c3^^bb}% é et û en utf8
 		\fi\fi
-		\expandafter\ST_subst\expandafter#3\expandafter{\ST_e}e\ST_subst#3\'{}%
-		\expandafter\ST_subst\expandafter#3\expandafter{\ST_u}u\ST_subst#3\^{}%
-		\lowercase\expandafter{\expandafter\def\expandafter\ST_temp_a\expandafter{#3}}%
+		\ST_e_second{\ST_subst_unsafe#3}{\ST_e}e%
+		\ST_subst_unsafe#3\'{}%
+		\ST_e_second{\ST_subst_unsafe#3}{\ST_u}u%
+		\ST_subst_unsafe#3\^{}%
+		\lowercase\expandafter{\expandafter\def\expandafter#3\expandafter{#3}}% BUGFIX 0.61
 		\IfStrEqCase#3{%
 			{janvier}{\def#3{1}}%
 			{fevrier}{\def#3{2}}%
@@ -1871,6 +1930,31 @@
 		}%
 }
 
+\def\ST_func_test#1#2{% #1=csv de tests #2=sc recevant le résultat
+	\expandafter\ST_func_test_a\expandafter#2\expandafter1#1,1,\_nil
+}
+\def\ST_func_test_a#1#2#3,{% #1=macro recevant le résultat #2=compteur de test, #3=test en cours
+	\ST_ifnum{\fpeval{#3}=1 }
+		{\ST_first_tonil{\def#1{\ST_func_test_b#2}}}
+		{\ST_e_second{\ST_func_test_a#1}{\number\numexpr#2+1\relax}}%
+}
+
+\def\ST_func_test_b#1(#2){% #1=index voulu  #2=csv textes
+	\ST_e_second{\ST_func_test_c1}{\number\numexpr#1}#2,\ST_quark,%
+}
+\def\ST_func_test_c#1#2#3,{% #1=index courant #2=index voulu #3=texte courant
+	\ST_ifx{\ST_quark#3}
+		{%
+		\ST_stop
+		}
+		{%
+		\ST_ifnum{#1=#2 }
+			{\ST_func_test_d{#3}}
+			{\ST_e_second\ST_func_test_c{\number\numexpr#1+1}{#2}}%
+		}%
+}
+\def\ST_func_test_d#1#2\ST_quark,{\ST_stop#1}
+
 %----------------------------------------------
 %----- Construction du tableau à afficher -----
 %----------------------------------------------
@@ -2053,7 +2137,7 @@
 		\ST_ifcsname{\ST_debuginfo _\number\ST_col_cnt _\number\ST_row_cnt}% si l'info existe pour la cellule concernée
 			{%
 			\ifx\ST_temp_a\ST_debuginfo
-				\expandafter\ST_subst\csname\ST_debuginfo _\number\ST_col_cnt _\number\ST_row_cnt\endcsname|{}%
+				\expandafter\ST_subst_unsafe\csname\ST_debuginfo _\number\ST_col_cnt _\number\ST_row_cnt\endcsname|{}%
 			\fi
 			\ST_xadd_tomacro\ST_debugtab{\detokenize\expandafter\expandafter\expandafter{\csname\ST_debuginfo _\number\ST_col_cnt _\number\ST_row_cnt\endcsname}}% on ajoute la cellule au tableau que l'on a detokenisée au préalable
 			}
@@ -2174,9 +2258,18 @@
 	\ST_tag_list
 	\ST_sanitize_cs
 	\endgroup
-	\restoreKV[STdebug]%
+	\STset{debug={}}% BUGFIX 0.61
 }
 
+\def\STrep{%
+	\STrep_a1\_nil%
+}
+\def\STrep_a#1\_nil#2#3{%
+	\ST_ifnum{#1>#2 }
+		{}
+		{\expandafter\STrep_a\the\numexpr#1+1\relax\_nil{#2}{#3}#3}%
+}
+
 %----------------------------------
 %----- Réglages et paramètres -----
 %----------------------------------
@@ -2195,13 +2288,6 @@
 		{}
 }
 
-\def\ST_set_freeze_char#1{%
-	\expandafter\ST_set_freeze_char_a\detokenize{#1!}\_nil
-}
-\def\ST_set_freeze_char_a#1#2\_nil{%
-	\def\ST_tranpose_char{#1}%
-}
-
 \setKVdefault[STdebug]{
 	text     = false,
 	formula  = false,
@@ -2223,7 +2309,8 @@
 	autoround     = \def\ST_round_digit{#1},
 	text mark     = \ST_exp_two_args{\ST_defifempty\ST_text_mark}{\detokenize{#1}}{\string @},
 	numeric mark  = \ST_defifempty\ST_numeric_mark{#1}{:=},
-	freeze char   = \ST_set_freeze_char{#1},
+	freeze char   = \ST_take_first_char{#1!}\ST_tranpose_char,
+	copy char     = \ST_take_first_char{#1"}\ST_copy_char,
 }
 \def\ST_default_dec_sep{.}% le séparateur décimal par défaut
 
@@ -2242,6 +2329,7 @@
 	freeze char   = !,
 	pretab code   = {},
 	posttab code  = {},
+	copy char     = ",
 }
 
 %------------------------------
@@ -2330,20 +2418,7 @@
 		}%
 }
 \ST_restorecatcode
-
-%------------------------------------------
-%----- Macros utilisateur à supprimer -----
-%------------------------------------------
-\def\STautoround#1{\STset{autoround={#1}}}
-\def\STsetdisplaymarks#1#2{\STset{display marks={#1;#2}}}
-\def\STsetdecimalsep#1{\STset{dec sep={#1}}}
-\def\STeol#1{\STset{tabline sep={#1}}}
-\def\STtextcell#1{\STset{text mark={#1}}}
-\def\STmessage#1{\STset{messages={#1}}}
-\def\STnumericfieldmarker#1{\STset{numeric mark={#1}}}
-\def\STtranposechar#1{\STset{freeze char={#1}}}
 \endinput
-
 %----------------------
 %----- Historique -----
 %----------------------
@@ -2553,4 +2628,35 @@
         *supprimées* à la prochaine version au profit de \STset{clé=valeur}
    12   les macros-fonctions de test ifeq, ifgt et iflt seront supprimées à la
         prochaine version puisque l3fp dispose de l'opérateur '?'
-   13   Mise en forme, nettoyage et améliorations du code
\ No newline at end of file
+   13   Mise en forme, nettoyage et améliorations du code
+-------------------------------------------------------------------------------
+v0.61       2025/03/14
+   1   Correction d'un bug dans \ST_return_ref_in_formula_a : si après une
+       lettre, rien n'est trouvé (\ST_target_rownumber est vide), on met 0 et
+       donc la formule "a1+pi" ne provoque plus de bug
+   2   Correction d'un bug qui fait que le débogage est persistent : rajout de
+       \STset{debug={}} après sortie du groupe et suppression de
+       \restoreKV[STdebug]
+   3   Correction d'un bug : si un macro-fonction donnant du texte est évaluée,
+       le travail sur la cellule cesse et elle passe comme cellule textuelle.
+       Le bug "numtofrmonth(0)2025" est évité (mars2025 -> ST ne cherche plus
+       la  cellule de coordonnées 's2025')
+   4   Correction d'un bug : il ne faut pas appeler \ST_subst lorsque le
+       pattern a des accolades, par exemple "{&&}", puisque \ST_subst_a plante
+       avec un # qui se retrouve dans la nature. Pareil avec \ST_esubst_once_a.
+       On revient donc aux macros de xstring, + lentes mais + sûres et ajout de
+       "_unsafe" aux macros non sûres (utilisées à bon escient ailleurs)
+   5   Correction d'un bug dans \ST_analyse_text_frdate
+   6   suppression des macros-fonctions de comparaison iflt, ifgt et ifeq
+   7   suppression des macros \STautoround, \STsetdecimalsep, \STeol,
+       \STsetdisplaymarks, \STmessage, \STnumericfieldmarker, \STtranposechar
+       et \STtextcell. Tout se passe désormais par \STset{clé=valeur}
+   8   Nouvelle macro-fonction 'test' qui retourne des textes selon l'issue de
+       tests en cascade
+   9   Caractère d'échappement «"» pour délimiter la partie qui doit être
+       décalée lors d'une copie. Si absence de 2 «"», toute la cellule est
+       prise en compte. À utiliser avec les macros qui retournent du texte
+   10  Clé "copy char" pour choisir le délimiteur du point précédent
+   11  Création d'une macro \STrep{<n>}{<arg>}, purement développable,
+       qui reproduit <n> fois l'<arg> et qui a vocation à se trouver dans 
+       l'argument de \STxp
\ No newline at end of file



More information about the tex-live-commits mailing list.