How to fill a Vigenère square?

Fill the table one row at a time.

\documentclass{article}
\usepackage[table]{xcolor}

\definecolor{headers}{RGB}{234,232,218}

\ExplSyntaxOn

\tl_new:N \l_vigenere_body_tl

\NewDocumentCommand{\vigenere}{}
 {
  % make the first row
  \tl_set:Nn \l_vigenere_body_tl { \hline \rowcolor{headers} }
  \tl_put_right:Nx \l_vigenere_body_tl
   {
    \int_step_function:nN {26} \vigenere_first:n
   }
  \tl_put_right:Nn \l_vigenere_body_tl { \\ \hline }
  \int_step_inline:nn { 26 }
   {
    \tl_put_right:Nn \l_vigenere_body_tl { \bfseries \int_to_Alph:n { ##1 } }
    \tl_put_right:Nx \l_vigenere_body_tl
     {
      \int_step_function:nnN { ##1 } { ##1+25 } \vigenere_further:n
     }
    \tl_put_right:Nn \l_vigenere_body_tl { \\ \hline }
   }
  \group_begin:
  \setlength{\tabcolsep}{0.5pt}\sffamily
  \begin{tabular}{ | >{\columncolor{headers}}c | *{26}{c|} }
  \l_vigenere_body_tl
  \end{tabular}
  \group_end:
 }

\cs_new:Nn \vigenere_first:n { & \exp_not:N \bfseries \int_to_Alph:n { #1 } }
\cs_new:Nn \vigenere_further:n
 {
  & \int_to_Alph:n { \int_mod:nn { #1-1 } { 26 } + 1 }
 }
\ExplSyntaxOff

\begin{document}

\vigenere

\end{document}

enter image description here


Here's a LuaLaTeX-based solution.

enter image description here

\documentclass{article}
\usepackage[letterpaper,margin=1in]{geometry} % set page parameters suitably
\usepackage{array} % for '\extrarowheight' macro
\usepackage[table]{xcolor}

\usepackage{luacode} 
\begin{luacode}
s="ABCDEFGHIJKLMNOPQRSTUVWXYZ"

-- an auxiliary function
function rowprint ( t )
    for i = 1,26 do
       tex.sprint ( "&" .. t:sub(i,i) )
    end
    tex.sprint ("\\\\ \\hline")
end

-- the main function
function vigenere ()
    tex.sprint ( "\\hline" )
    -- header row
    tex.sprint ( "\\rowcolor{lightgray}" )
    for i = 1,26 do
       tex.sprint ( "&\\textbf{\\textsf{" .. s:sub(i,i) .. "}}" )
    end
    tex.sprint ("\\\\ \\hline")
    
    -- data rows (from A to Z )
    t = s
    for j=1,26 do
       t = s:sub(j) .. s:sub(1,j-1)
       tex.sprint (  "\\cellcolor{lightgray}\\textbf{\\textsf{" .. t:sub(1,1) .. "}}" )
       rowprint ( t )
    end
end
\end{luacode}

\begin{document}
\begin{center}
\setlength\tabcolsep{3pt}
\setlength\extrarowheight{3pt}
\begin{tabular}{|*{27}{c|}}
   \directlua{vigenere()} 
\end{tabular}
\end{center} 
\end{document}

Another way of cycling through the alphabet using pgffor:

enter image description here

\documentclass{article}

\usepackage[margin=1in]{geometry}
\usepackage{pgffor,xcolor,eqparbox}

\makeatletter
\newcommand{\ALPH}[1]{%
  \ifnum #1>26
    \@Alph{\numexpr#1-26}%
  \else
    \@Alph{#1}%
  \fi
}
\makeatother

\begin{document}

\begingroup
  \makeatletter
  \sffamily\footnotesize
  \centering
  \fcolorbox{black}{brown!50!white}{\eqmakebox[vignere]{\vphantom{Q}}}% Top-left box
  \foreach \Char in {1, ..., 26} {%
    \fcolorbox{black}{brown!50!white}{\eqmakebox[vignere]{\vphantom{Q}\bfseries\@Alph{\Char}}}% header
  }\\[-1pt]
  \foreach \CharA in {0, ..., 25} {%
    \fcolorbox{black}{brown!50!white}{\eqmakebox[vignere]{\vphantom{Q}\bfseries\@Alph{\numexpr\CharA + 1}}}% Left column
    \foreach \CharB in {0, ..., 25} {%
      \fbox{\eqmakebox[vignere]{\vphantom{Q}\ALPH{\numexpr\CharA + \CharB + 1}}}%
    }%
    \\[-1pt]
  }
  \par
\endgroup

\end{document}