5

With biblatex and Biber, how to create a loop on the years to print bibliography year after year in the following manner:

\section{2016}
    \subsection{Article}
        \printbibliography of all articles published in 2017
    \subsection{inproceedings}
        \printbibliography of all papers in proceedings published in 2017
    \subsection{in Misc}
        \printbibliography of all misc published in 2017

\section{2015} etc. for all bib entries and all years.

Here is an example of the desired result: https://malti.fr/index.php/publication-list-per-year.

Some further enhancements could be:

  • The starting year automatically set up to the older entry year of the bib file,
  • The end year automatically set up to the most recent entry year of the bib file,
  • In case there is no paper published corresponding to a given (sub-)section, then that (sub-)section does not appear, (i.e.) no (sub-)section appears empty.

Printing bibliography between two years was resolved here. Thanks.

EDITED. Here is a MWE borrowed and modified from here to answer @samcarter.

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}

@Article{a, date = 2001, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{b, date = 2003, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{c, date = 2004, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{d, date = 2007, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{e, date = 2009, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{f, date = 2011, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{g, date = 2013, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{h, date = 2015, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{i, date = 2016, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@patent{l, year = 2016, author = {Author, Amy}, title = {Patent 1}, number = 4, pages = {100-141}}

@inproceedings{j, date = 2016, author = {Author, Amy}, title = {Title 1}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@patent{o, year = 2016, author = {Author, Amy}, title = {Patent 1}, number = 4, pages = {100-141}}

@patent{m, year = 2016, author = {Author, Amy}, title = {Patent 2}, number = 4, pages = {100-141}}

@Article{n, date = 2016, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

\end{filecontents*}

\usepackage[backend=biber,defernumbers=true,sorting=ydnt]{biblatex} \addbibresource{\jobname.bib}

\DeclareSourcemap{ \maps[datatype=bibtex]{ \map[overwrite=true]{ \step[fieldsource=author,match=Amy,final] \step[fieldset=keywords, fieldvalue={,}, append] \step[fieldset=keywords, fieldvalue=own, append] }}}

\defbibcheck{2016}{%There must be a better way to code "different from" 2016 \ifnumless{\thefield{year}}{2016} {\skipentry} {\ifnumgreater{\thefield{year}}{2016} {\skipentry} {} } }

\defbibcheck{2015}{%There must be a better way to code "different from" 2015 \ifnumless{\thefield{year}}{2015} {\skipentry} {\ifnumgreater{\thefield{year}}{2015} {\skipentry} {} } }

\begin{document} \nocite{} \section{2016} \printbibliography[check=2016, keyword=own, resetnumbers=true, type=article, heading=subbibliography, title={Articles}] \printbibliography[check=2016, keyword=own, resetnumbers=true, type=inproceedings, heading=subbibliography, title={Inproceedings}] \printbibliography[check=2016, keyword=own, resetnumbers=true, type=patent, heading=subbibliography, title={Patent}] \section*{2015} \printbibliography[check=2015, keyword=own, resetnumbers=true, type=article, heading=subbibliography, title={Articles}] \printbibliography[check=2015, keyword=own, resetnumbers=true, type=inproceedings, heading=subbibliography, title={Inproceedings}] \printbibliography[check=2015, keyword=own, resetnumbers=true, type=patent, heading=subbibliography, title={Patent}]

\end{document}

However, I've got an undesired output with headings Inproceedings and Patent printed with an empty content in year 2015. I'd like not to have any heading if the content is empty.

Back to my request. How to create a loop from 2016 down to 2001 printing the bibliography year after year according to the types (Article, Inproceedings, Patent, Misc, ...)?

Another enhancement would be:

  • to create an inner loop which loops around the different types (Article, Inproceedings, Patent, Misc, ...) for each year.

EDITED

Find below a MWE, with the proposed solutions, which however points out the compilation pb when using htlatex/biber/htlatex. See the comment below posted on Feb, 22nd, 2020.

RE-EDITED on March, 12th, 2020: a misc ref is added:

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}

@Article{b, date = 2003, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@misc{ccc, date = 2003, author = {misc, LLL}, title = {MISC}, journaltitle = {Journal-misc}, volume = 10, number = 4, pages = {100-141}}

@Article{c, date = 2003, author = {Author, BBB}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{d, date = 2003, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@Article{i, date = 2016, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@patent{l, year = 2016, author = {Author, Amy}, title = {Patent 1}, number = 4, pages = {100-141}}

@inproceedings{j, date = 2016, author = {Author, Amy}, title = {Title 1}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

@patent{o, year = 2016, author = {Author, Amy}, title = {Patent 1}, number = 4, pages = {100-141}}

@patent{m, year = 2016, author = {Author, Amy}, title = {Patent 2}, number = 4, pages = {100-141}}

@Article{n, date = 2016, author = {Author, Amy}, title = {Title}, journaltitle = {Journal}, volume = 10, number = 4, pages = {100-141}}

\end{filecontents*}

\usepackage[backend=biber,defernumbers=true,sorting=ydnt]{biblatex} \addbibresource{\jobname.bib}

\DeclareSourcemap{ \maps[datatype=bibtex]{ \map{ \pertype{article} \step[fieldset=presort,fieldvalue=article] } \map{ \pertype{inproceedings} \step[fieldset=presort,fieldvalue=inproceedings] } \map{ \pertype{patent} \step[fieldset=presort,fieldvalue=patent] } } }

\DeclareSortingTemplate{rasha}{ \sort[direction=ascending]{ \field{year}} \sort{\field{presort}} }

\defbibenvironment{bibliography} {\begin{enumerate}} {\end{enumerate}} {}

\newcounter{myyear} \setcounter{myyear}{0}

\renewbibmacro{begentry}{% \ifnumgreater{\thefield{year}}{\value{myyear}} {\section{\hspace{-\leftmargin}\printfield{year}} \setcounter{myyear}{\thefield{year}}% \setcounter{enumi}{0}% \xdef\mylastentrytype{}% }% {}% \iffieldequals{entrytype}{\mylastentrytype} {} { \iffieldequalstr{entrytype}{article} {\subsection{\hspace{-\leftmargin}Journal Articles}} { \iffieldequalstr{entrytype}{inproceedings} {\subsection{\hspace{-\leftmargin}Conference Papers} \setcounter{enumi}{0}% } {\iffieldequalstr{entrytype}{patent} {\subsection{\hspace{-\leftmargin}Patents} \setcounter{enumi}{0}
} {} } } \xdef\mylastentrytype{\thefield{entrytype}} } \item }

\begin{document} \nocite{*} \begin{refcontext}[sorting=rasha] \printbibliography[title={Publication list by year}] \end{refcontext} \end{document}

rasha
  • 704

1 Answers1

7

Here is a solution (proof of concept) that cycles inside a single \printbibliography.

The solution depends on a specifically created sorting schema (here, we use the fact that article lexicographically precedes inproceedings which in turns proceeds patent). A more robust would define a specified sorting schema (and eventually a Source Map) for an appropriate ordering over the entry types.

Also, for simplicity, the solution assumes that only article, inproceedings and patents entries are presented in the bibliography file (easy to extend with a "Other publications" category).

The first step is to define the sorting order:

\DeclareSortingScheme{rasha}{
  \sort[direction=ascending]{
    \field{year}
    \field{entrytype}
  }
}

Then, we redefine the bibliography environment.

\defbibenvironment{bibliography}
  {\begin{enumerate}}
  {\end{enumerate}}
  {}

The trick here is to remove \item from the last element (the iteration over the bib item). This is delegated to the single entries.

The final step is to redefine the begentry macro (which is executed at the begin on standard bibliography drivers.

\def\mylastentrytype{}

\newcounter{myyear}
\setcounter{myyear}{0}

\renewbibmacro{begentry}{%
\ifnumgreater{\thefield{year}}{\value{myyear}}
  {\section*{\hspace*{-\leftmargin}\printfield{year}}
   \setcounter{myyear}{\thefield{year}}%
   \setcounter{enumi}{0}%
   \xdef\mylastentrytype{}%
   }%
  {}%
  \iffieldequals{entrytype}{\mylastentrytype}
    {}
    { \iffieldequalstr{entrytype}{article}
        {\subsection*{\hspace*{-\leftmargin}Journal Articles}}
        { \iffieldequalstr{entrytype}{inproceedings}
            {\subsection*{\hspace*{-\leftmargin}Conference Papers}
             \setcounter{enumi}{0}%
            }
            {\iffieldequalstr{entrytype}{patent}
                {\subsection*{\hspace*{-\leftmargin}Patents}
                 \setcounter{enumi}{0}  
                }
                {}
            }
        }
      \xdef\mylastentrytype{\thefield{entrytype}}
    }
  \item
}

Given that the sorting schema use year as first parameter, the initial condition checks whether we have an increment in the year, if so it emits a \section command, and the set the counter for the year to the year of the last entry processed.

The second parameter of the sorting schema is the entrytype of the entry. Thus we have to check if the current entry is of the same type of the previous one (stored in \mylastentrytype). If this is not the case, we check if the entry type is one of article, inproceedings or patent. If it is then, we print the corresponding section (reseting the counter for the enumeration)

Finally, we have to instruct to use the sorting schema.

\nocite{*}

\begin{refcontext}[sorting=rasha]
\printbibliography[title={Publication list by year}]
\end{refcontext}

With the bibliography given in the MWE this produce the following output (in a two column format)

enter image description here

EDIT Apparently \sort{\field{entrytype}} is not recognised during the sorting phase. Thus an alternative is to declare a source map to populate the presort field using the \pertype specification, namely:

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map{
      \pertype{article}
      \step[fieldset=presort,fieldvalue=article]
    }
    \map{
      \pertype{inproceedings}
      \step[fieldset=presort,fieldvalue=inproceedings]
    }
    \map{
      \pertype{patent}
      \step[fieldset=presort,fieldvalue=patent]
    }
  }
}

and change the sorting template (notice the \DeclareSortingSchema is now deprecated) to

\DeclareSortingTemplate{rasha}{
  \sort[direction=ascending]{
    \field{year}}
  \sort{\field{presort}}
}

The output, with the extended MWE, is:

enter image description here

Guido
  • 30,740
  • Thanks a lot Guido. Your solution works fine when the bib file contains an ordered bibliography. However, if the bibliography is not ordered, there is a problem because let's say in 2016, we'll find "Journal articles", "conference papers", then "Journal articles" again ... Could you please elaborate a work around regarding this problem. – rasha Dec 19 '17 at 11:37
  • I've modified the MWE to show the problem that appears in 2016 when the bibliography is not ordered. – rasha Dec 19 '17 at 11:55
  • @rasha I guess the only change needed is \DeclareSortingScheme{rasha}{ \sort[direction=ascending]{ \field{year} } \sort{ \field{entrytype} } } (modulo line breaks) – moewe Dec 19 '17 at 14:31
  • @moewe Apparently \sort{\field{entrytype}} has no effect on sorting. According to the documentation it should, but it does not. Is this a bug in biber/biblatex? – Guido Dec 20 '17 at 01:42
  • I reported this to PLK https://github.com/plk/biber/issues/206 – moewe Dec 20 '17 at 09:51
  • @moewe I saw the latest comments in github.com/plk/biber/issues/206 could you please tell me, when you talk about v.2.10, you mean the version of what package? Could you send me the fix you downloaded from sourceforge or inform me in how much time is it usually available in CTAN? Thanks. – rasha Dec 20 '17 at 16:39
  • @rasha I was talking about Biber 2.10. It will hopefully be on CTAN and MikTeX/TeX live by the end of the week, but I can't promise anything. – moewe Dec 20 '17 at 16:55
  • @moewe, 2 years later, I came across another problem. Everything works fine when compiling with the sequence latex/biber/latex. However, I need to generate an html based on the mentioned code, and when I try to compile with the sequence: htlatex/biber/htlatex, I get some ugly messages at the second htlatex compilation of the kind: ``(./MWE.bbl) ! Missing number, treated as zero. \c:\end:itm l.147 ...ography[title={Publication list by year}] ?'' The obtained html file misses numbers and there is no newline at each new entry. – rasha Feb 22 '20 at 22:44
  • You can use the last EDITED MWE example with the suggested solutions. – rasha Feb 22 '20 at 23:19
  • 1
    @rasha If it works with LaTeX (and it does, I just checked) but not with htlatex then this is most likely a htlatex incompatibility or bug. I can't help you there and suggest you ask about the issue at the mailing list https://tug.org/mailman/listinfo/tex4ht or report it directly at https://puszcza.gnu.org.ua/bugs/?group=tex4ht – moewe Feb 23 '20 at 07:40
  • @moewe, I'm facing a new problem and spent yesterday all day long trying to figure it out without success. I've updated my MWE (check above), by adding 1 reference of misc-type. I'd like this reference to be ignored because it is not of (Article, Inproceeding, or Patent type). Instead of ignoring it, the macro prints it at the end of the last type of references by reseting the numbering. This pb was first pointed out as a comment here: https://tex.stackexchange.com/questions/529782/htlatex-biber-htlatex-compilation-error-not-present-in-latex-biber-latex?noredirect=1#comment1345795_529782 – rasha Mar 12 '20 at 06:59
  • 1
    @rasha you can define a filter or a check to exclude references that are not of the appropriate type. \defbibfilter{include}{type=journal or type=patent or type=inproceedings} or \defbibcheck{exclude}{\ifentrytype{misc}{}{\skipentry}} – Guido Mar 12 '20 at 19:04
  • @Guido, I'm having an issue with the solution you proposed 3 years ago, as I cannot simultaneously choose an authors name and do the pre-sorting. What I tried at each of the 3 map(s) is:
    \map{ \pertype{inproceedings} \step[fieldsource=author,match={Malti}] \step[fieldset=presort,fieldvalue=inproceedings] } But it did not work.

    How can I additionally print all the entries of only one author (say Amy in the MWE, above)?

    Thank you sooo much for helping.

    – rasha Aug 18 '23 at 18:52