7

I'm trying to typeset a table whose cells are divided into columns, and the columns are separated by dotted lines. This is for variable-length enumerations of (short) entries and planned to look approximately like this:

+-----------+------------------+
| A   . E   | H   . L   . P    |
| B   . F   | I   . M   .      |
| C   . G   | J   . N   .      |
| D   .     | K   . O   .      |
+-----------+------------------+

Because this table is generated from data, there are some factors that i can easily handle with the generating software, and since it is only a single table with like a hundred entries, i can manually fine-tune which table columns get one, two, or three sub-columns to optimize the appearance.

My idea is to use a minipage inside each table cell, thereby taking advantage of the fact that columns are filled in a balanced way; however, it would be perfectly acceptable to forego minipages and instead create a table with so-and-so many sub-cells and place each entry programmatically.

What I don't get working is the dotted dividers. These are intended to be dots, not dashes. Furthermore, whatever technique is used to draw them, they must get their coordinates from inside of XeLaTeX (it is conceivable to set absolute columns widths, but i'd rather avoid that; it is also conceivable to put the table at specific offset from the top of the page, but I really want to avoid that).

Also, I would love to draw each divider individually — if you just drew dashed or dotted dividers across the entire table, there would otherwise inevitably occur clashes between the verticals and the horizontals.

When I started out, I experimented with clines and the like, but I realized that drawing partial lines will cause small gaps in the borders of the cells that do not have a partial line — this is why I started to think about subtables and/or minipages.

Below is a MWE of what I have right now. It looks like this:

MWE output

What I'm trying to do here is to record the current position on the page, then look at the column widths and the minipage height, then derive the x and y values from those. I'm struggling with the units vs integers vs floats distinction and with the (apparently) differing frames of reference — sometimes -y seems to be 'down', sometimes -y seems to be 'up'. But at this point I'm so confused I can hardly tell up from down!

Before I waste another day on this, does anyone have ideas on how to improve on this code? I've tried so many packages, and each is pretty much a law unto itself — the macro syntax, whether integers or floats or lengths are required for parameters, whether you can do math with them, and so on.

\documentclass{book}
\usepackage{polyglossia}
\setdefaultlanguage{english}
\usepackage{multicol}
\setlength{\parindent}{0mm}

% http://tex.stackexchange.com/questions/56875/how-do-i-make-one-minipage-the-same-size-as-another
\usepackage{adjustbox}
% http://tex.stackexchange.com/a/37300/28067
\usepackage{zref-abspos}
\usepackage{zref-user}

\usepackage{calc}
\usepackage[absolute]{textpos}
\usepackage{epic}
\usepackage{fp}


% ----------------------------------------------------------------------------------------------------------
% http://tex.stackexchange.com/a/6424/28067
\makeatletter
\newcommand*{\DivideLengths}[2]{%
  \strip@pt\dimexpr\number\numexpr\number\dimexpr#1\relax*65536/\number\dimexpr#2\relax\relax sp\relax
}
\makeatother

% ----------------------------------------------------------------------------------------------------------
% http://tex.stackexchange.com/a/37317/28067
\catcode`@=11
\begingroup
  \catcode `P=12  % digits and punct. catcode
  \catcode `T=12  % digits and punct. catcode
  \lowercase{%
  \def\x{\def\rem@pt##1.##2PT{##1\ifnum##2>\z@.##2\fi}}}
     \expandafter\endgroup\x%
\def\strip@pt{\expandafter\rem@pt\the}
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1\relax\relax}
\catcode`@=12

% ##########################################################################################################
\begin{document}

% set units for package `textpos` (`textblock`)
\setlength{\TPHorizModule}{1mm}
\setlength{\TPVertModule}{1mm}
% set units for package `epic` (`dottedline`)
\unitlength1mm

% i set a definite width for the minipage here; in reality, that would be the text width inside a table
% cell:
\begin{minipage}[t]{20mm}
  \begin{multicols}{2}%
  \newcounter{flowX}
  \newcounter{flowY}
  \zsavepos{topleftcorner}%
  \FPround\resultc{\convertto{mm}{\the\linewidth}}{0}
  \setcounter{flowX}{\zposx{topleftcorner}/186450+\resultc+2} % `+2` to be replaced by 1/2 of columns divider width
  \setcounter{flowY}{\zposy{topleftcorner}/186450}
  \begin{textblock}{5}(\value{flowX},20)%
  \leavevmode\dottedline[.]{1}(0,0)(0,20)%
  \end{textblock}
  A\\B\\C\\D\\E\\F\\G\\H\\I\\J\\K\\L\\M\\
  \end{multicols}
\end{minipage}

% ##########################################################################################################
\end{document}
  • Did you have a look here? – Xavier Jun 23 '13 at 17:19
  • yes, i did. sadly, arydshln does not behave very well wrt other packages (you must use a definite loading order). also, it's all about dashed lines, and i want dotted lines. – flow Jun 23 '13 at 17:51
  • I can't comment on the compatibility aspect (I've never used arydshln myself), but Gonzalo mentions in his answer that you can get dotted lines with \hdashline[0.5pt/5pt]. – Xavier Jun 23 '13 at 18:27
10

It isn't really clear that multicol is what you really need in this table context, however to answer the question in the title, to use dots instead of a rule, you just need to replace the rule with \leaders. It is easiest to subvert the definition of \columnseprulecolor as that occurs at a convenient point.

enter image description here

\documentclass{article}

\def\a{\stepcounter{enumi}One two three four five six \roman{enumi}. }
\def\b{Red green yellow. \a\a\a\a\a}
\def\c{A, B, C. \b\par\b\b}
\def\d{\c\b\a\c\b\a}

\usepackage{multicol}

\makeatletter
\def\columnseprulecolor\vrule\@width\columnseprule{%
\vbox to \ht\mult@rightbox{\leaders\vbox{\kern2pt\hbox{.}\kern2pt}\vfill}}
\makeatother



\setlength\columnsep{20pt}

\begin{document}

\begin{multicols}{4}
\d
\end{multicols}

\end{document}
| improve this answer | |
  • thanks a lot indeed! i can tell you i couldn't have come up with anything like this! did you write the code just to answer this question or did you take the solution from your collection of useful TeX tricks / some website? one minor thing: as your example shows, there is a gap between the last dots and the descenders in the last row of type. i guess that could be dealt with by placing the dots closer to each other... but how? – flow Jun 24 '13 at 16:40
  • @flow I just made it up (but it's not the first time I have have modified Frank's column placement:-) the dot separation are the \kern2pt change to whatever you want. – David Carlisle Jun 24 '13 at 17:01
  • wah! the \kern works... i wasn't aware that there's vertical kerning in TeX... now i'm trying to set the column of dots a tad lower so they keep equal spacing from both top & bottom.— update ...\mult@rightbox{\kern1mm\leaders... will lower the top & leave the bottom in place. – flow Jun 24 '13 at 17:41
  • @flow the . is probably not centred in its bounding box, so you will need to make the first kern smaller than the second to compensate, whatever looks right.... – David Carlisle Jun 24 '13 at 17:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.