8

I have created a BibLaTeX library, which I use to organize all my oral and poster presentations. It is in fact a customized library with new data types and cite commands. I got all ideas from here and here.

After some time of programming, I got the following code, which works quite well. I can use my own command \printcontrib{BiB_entry} in any text, but also I can do some listing at the end by, e.g., calling all Bib entries via the latter command. Before I show the code, I would like to apologize already here that my code is probably some (evil?) hack. ;-)

MWE

\RequirePackage{filecontents}


% The BibTeX library
\begin{filecontents*}{\jobname.bib}
@Contribution{Oral_2016_1,
  Type      = {Oral},
  Invited   = {True},
  Author    = {{\textbf{Author, One} and Author, Two and Author, Three}},
  Presenter = {{Author, One}},
  Title     = {{Some cool stuff about the Nanoworld}},
  Event     = {{Conference about XYZ}},
  Eventtype = {Conference},
  Place     = {},
  City      = {Helsinki (Finland) - Stockholm (Sweden)},
  Country   = {},
  Date      = {May 1$^{\rm st}$ - June 2$^{\rm nd}$},
  Period    = {},
  Year      = {2016},
  Note      = {}
}

@Contribution{Oral_2015_1,
  Type      = {Oral},
  Invited   = {Ture},
  Author    = {{\textbf{Author, One}}},
  Presenter = {{Author, One}},
  Title     = {{Exciting research on cool Nanostuff}},
  Event     = {{6$^{\rm th}$ Nanotechnology workshop}},
  Eventtype = {Workshop},
  Place     = {},
  City      = {Giessen},
  Country   = {Germany},
  Date      = {September 24$^{\rm th}$},
  Period    = {},
  Year      = {2015},
  Note      = {}
}

@Contribution{Oral_2015_2,
  Type      = {Oral},
  Invited   = {False},
  Author    = {{Author, One and Author, Two and \textbf{Author, Three}}},
  Presenter = {{Author, Three}},
  Title     = {{Nanochemistry at its edge}},
  Event     = {{18$^{\rm th}$ Summer School of Nanochemistry}},
  Eventtype = {School},
  Place     = {},
  City      = {Cassis},
  Country   = {France},
  Date      = {September 9$^{\rm th}$},
  Period    = {},
  Year      = {2015},
  Note      = {}
}
\end{filecontents*}

% The declaration of the entries.
\begin{filecontents}{contribution.dbx}
\DeclareDatamodelEntrytypes{contribution}
\DeclareDatamodelFields[type=field,datatype=literal]{
  type,
  invited,
  title,
  event,
  eventtype,
  place,
  city,
  country,
  date,
  period,
  year,
  note
}

\DeclareDatamodelFields[type=list,datatype=name]{
  author,
  presenter
}
\DeclareDatamodelEntryfields[contribution]{
  type,
  invited,
  author,
  presenter,
  title,
  event,
  eventtype,
  place,
  city,
  country,
  date,
  period,
  year,
  note}
\end{filecontents}



% The standard LaTeX head, with a link to the chem-acs style and biber. The
% datamodel 'contribution' is also declared.
\documentclass[english]{book}
\usepackage{babel}
\usepackage{ifmtarg}
\usepackage{xstring}
\usepackage{ifthen}
\usepackage[datamodel=contribution,
            style=chem-acs,
            natbib=true,
            backend=biber]
           {biblatex}
\addbibresource{\jobname.bib}



% Declare cite commands, the most important ones. Others will be added.
\DeclareCiteCommand{\citeevent}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{event}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citedate}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{date}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citeyear}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{year}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citecity}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{city}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citecountry}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{country}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citetitle}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{title}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand*{\citeauthor}
    {\defcounter{maxnames}{99}%
     \defcounter{minnames}{99}%
     \defcounter{uniquename}{2}%
     \boolfalse{citetracker}%
     \boolfalse{pagetracker}%
     \usebibmacro{prenote}}
    {\ifciteindex{\indexnames{labelname}}{}\printnames{labelname}}
    {\multicitedelim}
    {\usebibmacro{postnote}}




% My own command, which puts into format and prints the contribution.
\newcommand{\printcontrib}[1]{
    \citeauthor*{#1}, 
    \citetitle*{#1}, 
    \citeevent{#1},
    \citecity{#1} 
%
%   This works, but there is no 'if' that might find an empty 'country' field.
%   I would like to have:
%   If  : Country   = {} => Do not print '(\citecountry{#1})' 
%   Else: print (\citecountry{#1})
    (\citecountry{#1}),
%
%
%   Here is my first test amongst many others:
%   It works but there is a error: "! Illegal unit of measure (pt inserted)." 
%
%   \newlength{\strlen}\settowidth{\strlen}{\citecountry{#1}}
%   \ifdim\strlen=0\else(\citecountry{#1})\fi,
%   \let\strlen\relax 
%    
    \citedate{#1} (\citeyear{#1})
} 




\begin{document}

\chapter{Oral contributions}

\printcontrib{Oral_2016_1}\\\\
%
\noindent\printcontrib{Oral_2015_2}\\\\
%
\noindent\printcontrib{Oral_2015_1}\\\\
%

\end{document}

The output looks like this: The output of the code from above

So far so good. Now, there might be some entries in one BibLaTeX entry (see, e.g., Oral_2016_1 => Country = {}), that have no text inside the two {} because some info is missing (note that I would like to keep these brackets due to a couple of reasons ... .)

I would like to have a 'if ... do ... else do ...' part in the code, which checks if an entry is 'empty', so here Country = {}. Otherwise, as it is the case here, the are two brackets displayed in the text ().

I would like to have this if conditioning in particular in this command:

% My own command, which puts into format and prints the contribution.
\newcommand{\printcontrib}[1]{
    \citeauthor*{#1}, 
    \citetitle*{#1}, 
    \citeevent{#1},
    \citecity{#1} 
%
%   This works, but there is no 'if' that might find an empty 'country' field.
%   I would like to have:
%   If  : Country   = {} => Do not print '(\citecountry{#1})' 
%   Else: print (\citecountry{#1})
    (\citecountry{#1}),
%
%
%   Here is my first test amongst many others:
%   It works but there is a error: "! Illegal unit of measure (pt inserted)." 
%
%   \newlength{\strlen}\settowidth{\strlen}{\citecountry{#1}}
%   \ifdim\strlen=0\else(\citecountry{#1})\fi,
%   \let\strlen\relax 
%    
    \citedate{#1} (\citeyear{#1})
} 

The (\citecountry{#1}) command (note the ( and ) brackets) shall be only executed, if the entry country has some text, in other words, is not Country = {} in the BibLaTeX file.

I tried out a dozen of things. For instance, I tried several if conditions with help of the ifmtarg, xstring and ifthen packages but without any success. The only half-solution in the % quotation (below the text % Here is my first test in the MWE) somewhat works, however, with errors (you have to uncomment this such that it is compiled by LaTeX).

Krumpel
  • 177
  • 3

2 Answers2

4

You should check whether the field exists as part of the \DeclareCiteCommand using \iffieldundef (or something similar; see section 4.6.2 Stand-alone Tests in the biblatex documentation):

\DeclareCiteCommand{\citecountry}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\iffieldundef{country}{}{(\printtext{\printfield{country}})}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

and here is \printcontrib:

\newcommand{\printcontrib}[1]{%
  \citeauthor*{#1}, 
  \citetitle*{#1}, 
  \citeevent{#1},
  \citecity{#1} 
  \citecountry{#1},
  \citedate{#1} (\citeyear{#1})
} 

You may also write a larger \DeclareCiteCommand rather using \printcontrib.

enter image description here

Werner
  • 603,163
  • Perfect (+100 points) and thanks a lot! - In fact, I also tried this directly in the '\DeclareCiteCommand' environment with '\iffieldundef' but I got somewhat lost. And yes, I will consider 'You may also write a larger \DeclareCiteCommand rather using \printcontrib.', I will report on this - Question: in my code, how can I change '\DeclareCiteCommand*{\citeauthor}' such that LaTeX uses the style specified in '\usepackage[..., style=chem-acs,', ...]'? – Krumpel Jan 21 '17 at 23:15
  • Okay, I didn't know. - Thanks a lot for your very quick help that has lead to a rolling stone: I'm currently exploring the vast possibilities of CV data automation in research via TeX/LaTeX/BibLaTeX/Python and without using MSWord etc.! When I have a suitable hack, I will present it here ... . – Krumpel Jan 21 '17 at 23:46
  • Please note that writing cite commands as \printcontrib with \newcommand by sticking several \cite... together is really bad style in biblatex. A command like this will not be able at all to handle pre or postnotes and multiple citations properly without much extra work, one should always use \DeclareCiteCommand. – moewe Jan 25 '17 at 08:15
3

In biblatex, field formatting such as brackets or emphasis or italics should not be written into the macro directly in most cases, they should be achieved with \DeclareFieldFormat. That way you make sure that biblatex can properly detect empty fields and do nothing in that case.

You could just do

\DeclareFieldFormat{country}{\mkbibparens{#1}}

\DeclareCiteCommand{\citecountry}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printfield{country}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

The field is then wrapped in brackets whenever it is shown and ignored otherwise. Note that there is no need to wrap a single \printfield into a \printtext without argument, \printfield{country} will do the same as \printtext{\printfield{country}}.

Instead of defining \citecontrib as you do now, you should probably just define a bibliography driver for @contribution like so (this is just a first rough shot at this, but you get the idea)

\DeclareFieldFormat{country}{\mkbibparens{#1}}
\DeclareFieldFormat[contribution]{title}{\mkbibemph{#1}}

\newbibmacro*{event+venue+city+country+date}{%
  \printfield{eventtitle}%
  \newunit
  \printfield{eventtitleaddon}%
  \newunit
  \printeventdate
  \newunit
  \printfield{city}
  \setunit{\addspace}%
  \printfield{country}
  \newunit}

\DeclareBibliographyDriver{contribution}{%
  \usebibmacro{bibindex}%
  \usebibmacro{begentry}%
  \usebibmacro{author/editor+others/translator+others}%
  \setunit{\printdelim{nametitledelim}}\newblock
  \usebibmacro{title}%
  \newunit
  \printlist{language}%
  \newunit\newblock
  \usebibmacro{byauthor}%
  \newunit\newblock
  \usebibmacro{event+venue+city+country+date}%
  \newunit\newblock
  \printfield{howpublished}%
  \newunit\newblock
  \printfield{note}%
  \newunit\newblock
  \usebibmacro{location+date}\printdate%
  \newunit\newblock
  \iftoggle{bbx:url}
    {\usebibmacro{url+urldate}}
    {}%
  \newunit\newblock
  \usebibmacro{addendum+pubstate}%
  \setunit{\bibpagerefpunct}\newblock
  \usebibmacro{pageref}%
  \newunit\newblock
  \iftoggle{bbx:related}
    {\usebibmacro{related:init}%
     \usebibmacro{related}}
    {}%
  \usebibmacro{finentry}}

Then you can just use \fullcite and you are done.

moewe
  • 175,683
  • For moewe: Question: If I work with '\newbibmacro' and '\DeclareBibliographyDriver' I automatically agree to all styles that are described in, e.g., '\usepackage[...]{biblatex}', '\documentclass' ... . E.g., the type of style for author and title can be changed by using '\usepackage[style=chem-acs]{biblatex}'. Furthermore date can be changed from '\documentclass[american]{book}' to '\documentclass[english]{book}'. So, If I want this I would do it. However, if I want to keep a specific style I rather make use of '\DeclareFieldFormat' and '\DeclareCiteCommand'. Is that right? – Krumpel Jan 26 '17 at 08:52
  • @Krumpel I'm not entirely sure if I follow you, but I don't think you can say that in all generality. \newbibmacro, \DeclareBibliographyDriver, \DeclareFieldFormat and \DeclareCiteCommand do different things and work at different code levels. Which is prerenal depends on what exactly you want to achieve. It is true that \newbibmacro and \DeclareBibliographyDriver use the formats declared by \DeclareFieldFormat, expect if you explicitly disable that. – moewe Jan 26 '17 at 17:34
  • @ moewe: Sorry for having confused you. It has taken a rather long time for me to understand, how things work in BibLaTeX. On that day, I was quite confused. Things are clear now, thx for your help. Later, I will show my solution ... . – Krumpel Jan 30 '17 at 10:28