Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I’m working on a custom biblatex style as I have to meet very special requirements. The citation part (cbx) works really well, but I have a problem with the bibliography definition. I need a tabular bibliography (for an example see this template produced with BibTeX).

I cannot use a tabular environment as the & within a bibliograpghy line produces an error. Other approaches using e. g. list failed, too.

Do you have an idea how to produce a tabular bibliography with biblatex?

share|improve this question

1 Answer 1

up vote 12 down vote accepted

Typically you define a new bibliography format with \defbibenvironment:

\defbibenvironment{bibliography}{<begin code>}{<end code>}{<item code>}

Internally biblatex groups these code segments and uses & as an end-of-list marker in handling items. So the existing setup isn't suited for tabular.

One workaround is to use a list environment borrowing enumitem's multiline label format, but this doesn't cope with long labels and short items.

\defbibenvironment{bibliography}
  {\list{<label code>}{<list format code>}
   \renewcommand*{\makelabel}[1]{%
     \nobreak\strut\smash{\parbox[t]\labelwidth{\raggedright##1}}}}
  {\endlist}
  {\item}

A solution that allows use of tabular requires delving into biblatex internals. Here we define tabular variants of \defbibenvironment and \printbibliography: \defbibtabular and \printbibtabular. The former takes five arguments:

\defbibtabular{<name>}{<begin code>}{<end code>}{<label code>}{<item code>}

The latter permits the same list of options as \printbibliography, but with the default setting env=bibtabular.

\documentclass{article}
\usepackage{csquotes}
\usepackage[american]{babel}
\usepackage[style=authortitle]{biblatex}

\makeatletter

% user-level command for printing tabular bibliography
\let\printbibtabular\printbibliography
\patchcmd{\printbibtabular}{\blx@printbibliography}{\bbx@printbibtabular}{}{}
\patchcmd{\printbibtabular}{\blx@printbibliography}{\bbx@printbibtabular}{}{}
\let\bbx@printbibtabular\blx@printbibliography
\patchcmd{\bbx@printbibtabular}{\blx@bibliography}{\bbx@bibtabular}{}{}
\patchcmd{\bbx@printbibtabular}
  {\def\blx@theenv{bibliography}}{\def\blx@theenv{bibtabular}}{}{}

% underlying macros
\def\bbx@bibtabular#1{%
  \blx@bibheading\blx@theheading\blx@thetitle
  \blx@bibnote\blx@theprenote
  \begingroup
  \blx@bibinit
  \let\@noitemerr\@empty
  \let\blx@noitem\blx@warn@bibempty
  \ifnum\bibinitsep=\z@
    \let\blx@initsep\relax
  \fi
  \ifnum\bibnamesep=\z@
    \let\blx@namesep\relax
  \fi
  \csuse{blx@hook@bibinit}%
  % copy filtered list of entries to internal list macro
  \def\blx@do##1{%
    \blx@ifdata{##1}{%
      \begingroup
      \blx@getdata{##1}
      \blx@bibcheck
      \iftoggle{blx@skipentry}{}{%
        \global\let\blx@noitem\@empty
        \listadd\blx@tempa{##1}}%
      \endgroup}{}}
  \let\blx@done\relax
  \blx@listloop{#1}
  % tabular output for each item in list macro
  \def\do##1{\bbx@tab@label{##1} & \bbx@tab@item{##1} \\}
  \csuse{blx@env@\blx@theenv}%
  \dolistloop{\blx@tempa}
  \csuse{blx@endenv@\blx@theenv}%
  \blx@bibnote\blx@thepostnote
  \endgroup}

\def\bbx@tab@label#1{%
  \begingroup
  \blx@getdata{#1}%
  \blx@setoptions@type\abx@field@entrytype
  \blx@setoptions@entry
  \blx@thelabelnumber
  \blx@addprefixnumber
  \addtocounter{instcount}\@ne
  \csuse{bbx@tabenv@\blx@theenv}\relax
  \endgroup}

\def\bbx@tab@item#1{%
  \begingroup
  \blx@getdata{#1}%
  \blx@setoptions@type\abx@field@entrytype
  \blx@setoptions@entry
  \csuse{blx@item@\blx@theenv}\relax
  \blx@initsep
  \blx@namesep
  \csuse{blx@hook@bibitem}%
  \blx@execute
  \blx@initunit
  \blx@anchor
  \blx@beglang
  \bibsentence
  \blx@pagetracker
  \blx@driver\abx@field@entrytype
  \blx@postpunct
  \blx@endlang
  \endgroup}

% user-level command for defining tabular bibliography format
\newrobustcmd*{\defbibtabular}[5]{%
  \long\csdef{blx@env@#1}{#2}%
  \long\csdef{blx@endenv@#1}{#3}%
  \long\csdef{bbx@tabenv@#1}{#4}%
  \long\csdef{blx@item@#1}{#5}}

% user-level access to some entry options
\def\useeditorfalse{\togglefalse{blx@useeditor}}
\def\usetranslatorfalse{\togglefalse{blx@usetranslator}}

\makeatother

% sortname labels (a robust style should add provision for missing labelnames)
\newbibmacro*{sortname}{%
  \renewcommand*{\multinamedelim}{\addslash\break}%
  \let\finalnamedelim\multinamedelim
  \printtext[bold]{\printnames[last-first]{labelname}}}

% bibitem hook to suppress redundant sortname list
\newbibmacro*{omitsortname}{%
  \ifnameundef{labelname}{}{%
    \ifnameundef{author}
      {\ifnameundef{editor}
         {\ifusetranslator{\clearname{translator}}{}}}
         {\clearname{editor}}
      {\clearname{author}}%
    \useeditorfalse%
    \usetranslatorfalse}}

% demo new tabular bibliography format
\defbibtabular{bibtabular}
  {\begin{tabular}{p{0.3\textwidth}p{0.7\textwidth}}}
  {\end{tabular}}
  {\usebibmacro{sortname}}
  {\usebibmacro{omitsortname}}

% add multiline labels in default bibliography format
\defbibenvironment{bibliography}
  {\list
     {\usebibmacro{sortname}}
     {\setlength{\labelwidth}{0.3\textwidth}%
      \setlength{\leftmargin}{\labelwidth}%
      \setlength{\labelsep}{\biblabelsep}%
      \addtolength{\leftmargin}{\labelsep}%
      \setlength{\itemsep}{\bibitemsep}%
      \setlength{\parsep}{\bibparsep}}%
     \renewcommand*{\makelabel}[1]{%
       \nobreak\strut\smash{\parbox[t]\labelwidth{\raggedright##1}}}}
  {\endlist}
  {\item\usebibmacro{omitsortname}}

\addbibresource{biblatex-examples.bib}
\newcommand{\cmd}[1]{\texttt{\textbackslash #1}}
\begin{document}
\cite{vangennep:trans,companion,bertram}
\printbibliography[title={\cmd{printbibliography} with multiline labels}]
\printbibtabular[title={New \cmd{printbibtabular} command}]
\end{document}

enter image description here

share|improve this answer
    
Thank you for that great answer! It works exactly as I need it. But it will take some time for me to understand that code. ;) –  Robin Krahl Sep 14 '12 at 19:54
    
@RobinKrahl You're welcome. I prefer to avoid messing around with internals, but for your question and a few other recent ones there was no way around it. You can hide the mess between \makeatletter and \makeatother in your bbx file. –  Audrey Sep 14 '12 at 20:03
    
I already moved it there. For my citation customization I already had to deal with the biblatex internals. But I sometimes find it hard to understand code written by others as I am not too familar with LaTeX programming/coding patterns. –  Robin Krahl Sep 14 '12 at 20:26
    
@RobinKrahl By "internals" I meant the (largely undocumented) code in the biblatex sty files. The code here is closely based on definitions for \defbibenvironment and \printbibliography, but it uses an additional list handler for printing data. This ensures that groups (\begingroup, \endgroup pairs) don't break across rows or columns. –  Audrey Sep 14 '12 at 21:44
    
Thanks, this helped me as well. Is there a way to add text between the heading (Bibliography) and the table? I would like to use it to describe the citation methodology. –  Jonas Jan 20 at 2:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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