I haven't used spreadtab or xstring before but xstring repeatedly assigns \groupID using both local and global assignments which is the usual way of filling the save stack.
If I change a local copy so all assignments are global then your example works and I get

But I have no idea if that is the intended result>
The diff I applied is below.
Unrelated to your problem but a table argument of [h] just makes it highly likely that the table goes to the end of the document, always include p at least so something like [htp]
*** xstring.tex~ 2012-11-29 09:38:39.484507200 +0000
--- xstring.tex 2012-11-29 09:41:38.830854400 +0000
***************
*** 427,433 ****
% si l'occurrence n'existe pas ou qu'un des arguments est vide, toutes les chaines renvoy\'ees sont vides
\def\@xs@cutafteroccur#1#2#3{%
\def\@xs@reserved@D{#1}\let\@xs@reserved@C\@empty\def\@xs@reserved@E{#2}%
! \decimalpart\z@\integerpart\z@\def\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\expandafter{\@xs@reserved@C}}%
--- 427,433 ----
% si l'occurrence n'existe pas ou qu'un des arguments est vide, toutes les chaines renvoy\'ees sont vides
\def\@xs@cutafteroccur#1#2#3{%
\def\@xs@reserved@D{#1}\let\@xs@reserved@C\@empty\def\@xs@reserved@E{#2}%
! \decimalpart\z@\integerpart\z@\gdef\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\expandafter{\@xs@reserved@C}}%
***************
*** 449,455 ****
\let\@xs@reserved@E\@xs@reserved@D
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\@xs@reserved@D\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\@xs@argument@A}%
\else
! \let\@xs@reserved@C\@empty\let\@xs@reserved@E\@empty\let\groupID\@empty
\fi}
\@xs@newmacro*3\IfSubStr{1}{2}{0}{%
--- 449,455 ----
\let\@xs@reserved@E\@xs@reserved@D
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\@xs@reserved@D\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\@xs@argument@A}%
\else
! \let\@xs@reserved@C\@empty\let\@xs@reserved@E\@empty\global\let\groupID\@empty
\fi}
\@xs@newmacro*3\IfSubStr{1}{2}{0}{%
***************
*** 534,540 ****
\expandafter\expandafter\expandafter\@xs@cutafteroccur\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\expandafter}\expandafter{\@xs@reserved@A}{#2}%
\def\@xs@reserved@A{#4}%
\expandafter\expandafter\expandafter\@xs@cutafteroccur\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\expandafter}\expandafter{\@xs@reserved@A}{#1}%
! \let\groupID\@empty
\expandafter\@xs@testempty\expandafter{\@xs@reserved@C}%
\if@xs@empty
\expandafter\@secondoftwo
--- 534,540 ----
\expandafter\expandafter\expandafter\@xs@cutafteroccur\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\expandafter}\expandafter{\@xs@reserved@A}{#2}%
\def\@xs@reserved@A{#4}%
\expandafter\expandafter\expandafter\@xs@cutafteroccur\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\expandafter}\expandafter{\@xs@reserved@A}{#1}%
! \global\let\groupID\@empty
\expandafter\@xs@testempty\expandafter{\@xs@reserved@C}%
\if@xs@empty
\expandafter\@secondoftwo
***************
*** 682,688 ****
\expandafter
\endgroup
\expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@E}{#6}%
! \let\groupID\@empty}
\def\exploregroups{\let\@xs@exploregroups\relax}
\def\noexploregroups{\def\@xs@exploregroups{\let\@xs@toks0\relax}}
--- 682,688 ----
\expandafter
\endgroup
\expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@E}{#6}%
! \global\let\groupID\@empty}
\def\exploregroups{\let\@xs@exploregroups\relax}
\def\noexploregroups{\def\@xs@exploregroups{\let\@xs@toks0\relax}}
***************
*** 694,700 ****
\@xs@newmacro\StrSubstitute{0}{3}{1}{%
\def\@xs@reserved@D{#2}\let\@xs@reserved@C\@empty\def\@xs@reserved@E{#3}%
\def\@xs@argument@C{#3}\def\@xs@argument@D{#4}%
! \decimalpart\z@\integerpart\z@\def\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\expandafter{\@xs@reserved@C}}%
--- 694,700 ----
\@xs@newmacro\StrSubstitute{0}{3}{1}{%
\def\@xs@reserved@D{#2}\let\@xs@reserved@C\@empty\def\@xs@reserved@E{#3}%
\def\@xs@argument@C{#3}\def\@xs@argument@D{#4}%
! \decimalpart\z@\integerpart\z@\gdef\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\expandafter{\@xs@reserved@C}}%
***************
*** 729,735 ****
\def\@xs@reserved@C{#1}%
\decimalpart\z@
\let\@xs@nestlevel\z@
! \def\groupID{0}%
\let\@xs@atbegingroup\relax
\def\@xs@atendofgroup{\endgroup\@xs@read@reserved@C}%
\let\@xs@atnextsyntaxunit\relax
--- 729,735 ----
\def\@xs@reserved@C{#1}%
\decimalpart\z@
\let\@xs@nestlevel\z@
! \gdef\groupID{0}%
\let\@xs@atbegingroup\relax
\def\@xs@atendofgroup{\endgroup\@xs@read@reserved@C}%
\let\@xs@atnextsyntaxunit\relax
***************
*** 749,755 ****
\def\@xs@manage@groupID{%
\begingroup\def\@xs@reserved@A{0}%
\ifx\@xs@reserved@A\groupID% si on arrive du groupe de niveau 0
! \endgroup\edef\groupID{\number\integerpart}% on met simplement le niveau
\else
\endgroup\expandafter\@xs@addtomacro\expandafter\groupID\expandafter{\expandafter,\number\integerpart}%
\fi}
--- 749,755 ----
\def\@xs@manage@groupID{%
\begingroup\def\@xs@reserved@A{0}%
\ifx\@xs@reserved@A\groupID% si on arrive du groupe de niveau 0
! \endgroup\xdef\groupID{\number\integerpart}% on met simplement le niveau
\else
\endgroup\expandafter\@xs@addtomacro\expandafter\groupID\expandafter{\expandafter,\number\integerpart}%
\fi}
***************
*** 760,768 ****
% Cette macro interne coupe la chaine #2 apr\`es l'unit\'e syntaxique n°#1
% Le d\'ebut est assign\'e dans \@xs@reserved@B et la fin dans \@xs@reserved@C
\def\@xs@StrSplit@i#1#2{%
! \def\@xs@reserved@D{#1}\def\@xs@reserved@C{#2}\let\@xs@reserved@B\@empty\let\groupID\@empty
\ifnum#1>\z@
! \decimalpart\z@\integerpart\z@\def\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@B\expandafter{\expandafter{\@xs@reserved@B}}%
--- 760,768 ----
% Cette macro interne coupe la chaine #2 apr\`es l'unit\'e syntaxique n°#1
% Le d\'ebut est assign\'e dans \@xs@reserved@B et la fin dans \@xs@reserved@C
\def\@xs@StrSplit@i#1#2{%
! \def\@xs@reserved@D{#1}\def\@xs@reserved@C{#2}\let\@xs@reserved@B\@empty\global\let\groupID\@empty
\ifnum#1>\z@
! \decimalpart\z@\integerpart\z@\gdef\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@B\expandafter{\expandafter{\@xs@reserved@B}}%
***************
*** 794,800 ****
\expandafter\expandafter\expandafter\@xs@StrSplit@i\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\expandafter}\expandafter{\@xs@reserved@B}%
\expandafter\endgroup
\expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#4}%
! \let\groupID\@empty}
% supprime #2 unit\'es syntaxiques \`a gauche dans la chaine #1
\@xs@newmacro\StrGobbleLeft{}{2}{1}{%
--- 794,800 ----
\expandafter\expandafter\expandafter\@xs@StrSplit@i\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@C\expandafter}\expandafter{\@xs@reserved@B}%
\expandafter\endgroup
\expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#4}%
! \global\let\groupID\@empty}
% supprime #2 unit\'es syntaxiques \`a gauche dans la chaine #1
\@xs@newmacro\StrGobbleLeft{}{2}{1}{%
***************
*** 826,832 ****
\let\@xs@reserved@B\@empty
\def\@xs@reserved@C{#1}\def\@xs@reserved@D{#2}%
\ifnum#2>\z@
! \def\groupID{0}\let\@xs@nestlevel\z@\integerpart\z@\decimalpart\z@
\let\@xs@atbegingroup\relax
\def\@xs@atendofgroup{\endgroup\@xs@read@reserved@C}%
\def\@xs@atnextsyntaxunit{%
--- 826,832 ----
\let\@xs@reserved@B\@empty
\def\@xs@reserved@C{#1}\def\@xs@reserved@D{#2}%
\ifnum#2>\z@
! \gdef\groupID{0}\let\@xs@nestlevel\z@\integerpart\z@\decimalpart\z@
\let\@xs@atbegingroup\relax
\def\@xs@atendofgroup{\endgroup\@xs@read@reserved@C}%
\def\@xs@atnextsyntaxunit{%
***************
*** 839,845 ****
\@xs@read@reserved@C
\fi
\expandafter\@xs@testempty\expandafter{\@xs@reserved@B}%
! \if@xs@empty\let\groupID\@empty\fi
\expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@B}{#3}}
% Combien de fois compte t-on #2 dans #1 ?
--- 839,845 ----
\@xs@read@reserved@C
\fi
\expandafter\@xs@testempty\expandafter{\@xs@reserved@B}%
! \if@xs@empty\global\let\groupID\@empty\fi
\expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@B}{#3}}
% Combien de fois compte t-on #2 dans #1 ?
***************
*** 849,855 ****
\if@xs@empty
\@xs@ReturnResult{0}{#3}%
\else
! \decimalpart\z@\integerpart\z@\def\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\expandafter{\@xs@reserved@C}}%
--- 849,855 ----
\if@xs@empty
\@xs@ReturnResult{0}{#3}%
\else
! \decimalpart\z@\integerpart\z@\gdef\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\expandafter{\@xs@reserved@C}}%
***************
*** 870,876 ****
\expandafter\@xs@StrLen\expandafter{\@xs@reserved@C}[\@xs@reserved@C]%
\expandafter\@xs@ReturnResult\expandafter{\number\numexpr\@xs@reserved@C+1}{#4}%
\fi
! \let\groupID\@xs@reserved@E}
\def\comparestrict{\let\@xs@comparecoeff\@ne}
\def\comparenormal{\let\@xs@comparecoeff\z@}
--- 870,876 ----
\expandafter\@xs@StrLen\expandafter{\@xs@reserved@C}[\@xs@reserved@C]%
\expandafter\@xs@ReturnResult\expandafter{\number\numexpr\@xs@reserved@C+1}{#4}%
\fi
! \global\let\groupID\@xs@reserved@E}
\def\comparestrict{\let\@xs@comparecoeff\@ne}
\def\comparenormal{\let\@xs@comparecoeff\z@}
***************
*** 975,981 ****
\@xs@expandingroups
\ifnum#1>\z@
\integerpart#1\relax
! \decimalpart\z@\def\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@B\expandafter{\expandafter{\@xs@reserved@B}}%
--- 975,981 ----
\@xs@expandingroups
\ifnum#1>\z@
\integerpart#1\relax
! \decimalpart\z@\gdef\groupID{0}\let\@xs@nestlevel\z@
\def\@xs@atendofgroup{%
\expandafter\endgroup
\expandafter\@xs@addtomacro\expandafter\@xs@reserved@B\expandafter{\expandafter{\@xs@reserved@B}}%
***************
*** 993,999 ****
\global\let\@xs@reserved@B\@xs@reserved@B
\endgroup
\let#3\@xs@reserved@B
! \let\groupID\@empty}
\def\@xs@StrExpand@i#1{%
\ifnum#1>\z@
\let\@xs@reserved@B\@empty
--- 993,999 ----
\global\let\@xs@reserved@B\@xs@reserved@B
\endgroup
\let#3\@xs@reserved@B
! \global\let\groupID\@empty}
\def\@xs@StrExpand@i#1{%
\ifnum#1>\z@
\let\@xs@reserved@B\@empty
\textitor\it,\bfseriesor\bf, etc. and Will two-letter font style commands (\bf,\it, …) ever be resurrected in LaTeX? – Werner Nov 29 '12 at 5:39save stackerror, the spreadtab environment (espacially if is a big table) must not be in a group. If you remove the\begin{table}[h]and\end{table}, no save stack error occur anymore. – unbonpetit Nov 29 '12 at 6:53