Voici une solution (un peu) générale, dont la syntaxe est assez commode.
La macro `\movetab` attend des mouvements de colonnes sous la forme `a->b` (`a` est le numéro de la colonne à déplacer et `b` est celui de la colonne cible. cible). S'il y a plusieurs mouvements à exécuter, il faut les séparer de par des virgules, mais attention, il faut tenir compte des mouvements déjà faits pour les mouvements qui suivent.
Juste à la suite de ces mouvements doit se trouver le tableau dans lequel les colonnes seront déplacées. Normalement et si aucun bug n'est présent, tous les environnements de tableau du type `\begin{<nom>}{préambule}<corps du tableau\end{<nom>}` tableau>\end{<nom>}` sont possibles, mais pour simplifier, l'argument optionnel de l'environnement n'est pas admis.
La macro `\movextab` est identique sauf qu'elle soit être utilisée avec l'environnement `tabularx`.
Au niveau des limitations :
- les caractères de changement de colonnes *doivent* être `&` `&`, de catcode 4 evidemment ;
- les fins de lignes *doivent* être `\\`, avec éventuellement un argument optionnel du type `[<dimension>]`. Pour changer cette macro en une autre telle que `\tabularnewline`, utiliser `\STeol{<nouvelle macro}` ;
- après le changement de ligne par `\\`, les commandes suivantes sont admises, quel que soit leur nombre : `\hline`, `\cline`, `\hhline`, `\noalign`, `toprule`, `\midrule`, `\bottomrule`, `addlinespace`, `\morecmidrule` et `\specialrule`, ainsi que leur éventuels arguments optionnels ou obligatoires.
obligatoires
- pour simplifier par rapport à `spreadtab`, la macro `\multicolumn` *n'est pas gérée* : elle est bêtement déplacée dans la colonne cible, avec toutes les fâcheuses conséquences que cela peut avoir.
Pour la sauvegarde de colonnes, je n'ai absolument pas compris dans quel but et je ne vois pas avec quelle syntaxe on pourrait faire en sorte qu'elle qu'elles soient réutilisées dans un autre tableau. la La demande est bien trop imprécise.
\documentclass{article}
\usepackage{spreadtab,array,booktabs,tabularx}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\makeatletter
\long\def\MT@get@body@env#1\end{\ST@add@tomacro\ST@tab{#1}\MT@find@end}
\newcommand*\MT@find@end[1]{%
\def\ST@temp@a{#1}%
\ifx\ST@temp@a\MT@envname
\expandafter\movetab@i
\else
\ST@add@tomacro\ST@tab{\end{#1}}%
\expandafter\MT@get@body@env
\fi
}
\def\movetab#1\begin#2#3{%
\begingroup
\def\MT@envname{#2}%
\expandarg\noexploregroups
\def\MT@tab@preamble{\begin{#2}{#3}}%
\def\MT@tab@end{\end{#2}}%
\def\MT@optcode{#1}%
\let\ST@tab\@empty
\MT@get@body@env
}
\def\movextab#1\begin#2#3#4{%
\begingroup
\def\MT@envname{#2}%
\expandarg\noexploregroups
\def\MT@tab@preamble{\begin{#2}{#3}{#4}}%
\def\MT@tab@end{\end{#2}}%
\def\MT@optcode{#1}%
\let\ST@tab\@empty
\MT@get@body@env
}
\newcommand*\movetab@i{%
\MT@read@tab
\MT@genlistcol
\unless\ifx\MT@optcode\@empty\expandafter\MT@movecol\MT@optcode,\relax->\relax,\fi
\let\ST@tab\MT@tab@preamble
\MT@build@tab
\ST@expadd@tomacro\ST@tab\MT@tab@end
\ST@tab
\restoreexpandmode\restoreexploremode
\endgroup
}
\newcommand*\MT@read@tab{%
\def\ST@total@colnumber{0}%
\ST@rowcount\z@
\ST@search@hline
\MT@read@tab@i
}
\newcommand*\MT@read@tab@i{%
\advance\ST@rowcount\@ne
\ST@Ifinstr\ST@tab{\ST@eol}%
{\expandafter\ST@split\expandafter\ST@tab\expandafter{\ST@eol}\ST@current@row\ST@tab
\@namedef{endrow@\number\ST@rowcount\expandafter}\expandafter{\ST@eol}%
\ST@Iffirstis\ST@tab[%
{\ST@between\ST@tab[]\ST@temp@a
\ST@Ifinstr\ST@temp@a,%
\relax
{\ST@split\ST@tab]\ST@temp@a\ST@tab
\expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname{\ST@temp@a]}%
}%
}%
\relax
\ST@search@hline
\ifx\ST@tab\@empty
\let\ST@next@readrows\relax
\edef\ST@total@rownumber{\number\ST@rowcount}%
\else
\let\ST@next@readrows\MT@read@tab@i
\fi
}%
{\let\ST@current@row\ST@tab
\let\ST@next@readrows\relax
\edef\ST@total@rownumber{\number\ST@rowcount}%
}%
\ST@colcount\z@
\MT@read@cells
\ST@next@readrows
}
\newcommand*\MT@read@cells{%
\advance\ST@colcount\@ne
\ST@Ifinstr\ST@current@row&%
{\ST@split\ST@current@row&\ST@current@cell\ST@current@row
\let\ST@next@readcells\MT@read@cells
}%
{\let\ST@current@cell\ST@current@row
\let\ST@next@readcells\relax
\ifnum\ST@colcount>\ST@total@colnumber\edef\ST@total@colnumber{\number\ST@colcount}\fi
}%
\ST@letname{text@\number\ST@colcount @\number\ST@rowcount}\ST@current@cell
\ST@next@readcells
}
\newcommand*\MT@genlistcol{%
\ST@colcount\z@
\def\MT@listcol{,}%
\loop
\advance\ST@colcount\@ne
\unless\ifnum\ST@colcount>\ST@total@colnumber\space
\edef\MT@listcol{\MT@listcol\number\ST@colcount,}%
\repeat
}
\def\sanitize@listcol,#1,\@nil{\def\MT@listcol{#1}}
\def\MT@movecol#1->#2,{%
\unless\ifx\relax#1%
\StrBetween[\numexpr#1,\numexpr#1+1]\MT@listcol,,[\ST@temp@a]%
\StrSubstitute\MT@listcol{\expandafter,\ST@temp@a,},[\MT@listcol]%
\StrCut[\numexpr#2]\MT@listcol,\MT@listcol\ST@temp@b
\edef\MT@listcol{\MT@listcol,\ST@temp@a,\ST@temp@b}%
\expandafter\MT@movecol
\fi
}
\newcommand\MT@build@tab{%
\expandafter\sanitize@listcol\MT@listcol\@nil
\ST@rowcount\@ne
\expandafter\ST@expadd@tomacro\expandafter\ST@tab\csname endrow@0\endcsname
\MT@build@tab@i
}
\newcommand\MT@build@tab@i{%
\ST@colcount\@ne
\@for\MT@colnum:=\MT@listcol\do{%
\ifcsname text@\MT@colnum @\number\ST@rowcount\endcsname
\expandafter\ST@expadd@tomacro\expandafter\ST@tab\csname text@\MT@colnum @\number\ST@rowcount\endcsname
\fi
\advance\ST@colcount\@ne
\unless\ifnum\ST@colcount>\ST@total@colnumber\relax\ST@add@tomacro\ST@tab&\fi
}%
\ifcsname endrow@\number\ST@rowcount\endcsname
\expandafter\ST@expadd@tomacro\expandafter\ST@tab\csname endrow@\number\ST@rowcount\endcsname
\fi
\advance\ST@rowcount\@ne
\unless\ifnum\ST@rowcount>\ST@total@rownumber
\expandafter\MT@build@tab@i
\fi
}
\makeatother
\begin{document}
\parindent=0pt
Essai 1 : colonne 1->3
\movetab 1->3
\begin{tabular}{ccc}\hline
foo & bar & BAZ \\[2ex]
123 & 456 & 789 \\
a & \textbf{b} & c \\\hline
\end{tabular}
\vskip2cm
Essai 2 : échange des colonnes 1 et 5
\movetab 1->5,4->1% échange les colonnes 1 et 5
\begin{tabular}{|*6{>{\centering\arraybackslash}m{1cm}|}}\hline\hline
1 & 2 & 3 & 4 & 5 & 6\\
a & b & c & d & e & f\\\cline{1-4}
11& 22& 33& 44& 55&66\\\noalign{\vskip1ex}
A & B & C & D & E & F\\\hline\hline
\end{tabular}
\vskip2cm
Essai 3 : colonne 2->3, 4->5 et 6->1
\movetab 2->3,4->5,6->1
\begin{tabular}{*6{c}}\toprule[1.5pt]
1 & 2 & 3 & 4 & 5 & 6\\\midrule[0.5pt]
a & b & c & d & e & f\\
11& 22& 33& 44& 55&66\\
A & B & C & D & E & F\\\bottomrule
\end{tabular}
\vskip2cm
Essai 4, tabularx : colonne 1->4
\hfill
\movextab 1->4
\begin{tabularx}{0.75\linewidth}{|c|c|c|X|}\hline
1 & 2 & 3 & 4\\
11111111111111111 & 222222 & 3333 & 44\\\hline
\end{tabularx}
\hfill\null
\end{document}