49

This is my oldest question on SO. It still hasn't generated a useful answer there, so I thought I'd give it a try here.

The question was: I don't seem to be able to find the method to generate the table of contents for a Mathematica notebook. AuthorTools, an old v5.1 utility package is still hidden in Mathematica, but it doesn't work for me. The TOC should contain correct section numbers (if present in the stylesheet) and list page numbers (this requires taking page size settings into account).

Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
  • @Nasser This is for printing purposes (and making PDF's). So I want the TOC to be interpreted in terms of the page settings in File>Printing settings>Page Setup. Mathematica is aware of the page breaks because you can have them shown using the option File>Printing settings>Show page breaks. And indeed, I'm looking for an automatic method. It used to be possible, and it looks like all MMA books written in MMA have there TOC made up with MMA. So, how do they do it? – Sjoerd C. de Vries Jan 22 '12 at 12:49
  • I was going to ask this as well. I also want to know how to generate a list of all the functions used in a notebook, to check coverage of topics for a chapter, for example. – cormullion Jan 22 '12 at 16:46
  • There must be an easy way to do this because WRI does have a couple of downloadable PDFs, which have a ToC with page numbers, that were generated from notebooks: http://www.wolfram.com/learningcenter/tutorialcollection/GraphDrawing/GraphDrawing.pdf (this is from some help browser notebooks) – Szabolcs Jan 22 '12 at 21:31
  • @SjoerdC.deVries have you tried hacking the old AuthorTools code to see if you can update the bits you need? I hope Wolfram are reading this and will give us a working AuthorTools in version 9. – Mike Honeychurch Jan 22 '12 at 22:54
  • @MikeHoneychurch If I would have a couple of weeks of free time (or someone pays me, like WRI payed me as an external consultant to write part of the first version of AuthorTools 15 years ago) I would start here and then test on all kind of platforms with different notebooks: http://library.wolfram.com/infocenter/Conferences/4878/ – Rolf Mertig Jan 23 '12 at 02:12
  • @RolfMertig and everyone else. I suppose WRI can only know that people want this tool back if you contact them and ask for it. Who knows why it wasn't kept updated but we need it. If they don;t have sufficient development resources they may well hire someone to do this. (just guessing). – Mike Honeychurch Jan 23 '12 at 03:08

1 Answers1

32

A bit of warning from the OP: this code locked-up my Mathematica session, so be sure to save everything before you try this. Update: Problem seems to be related to a problem MMA has with paginating a particular notebook of mine (see comments).

This code creates a separate TOC for a notebook saved at the location bookUrl. It works by iterating over all the cells in the book. If a cell is encountered whose type is in typeList, a tag is added to the cell and a line is written to the TOC notebook. We use CounterBox["Page", {bookUrl, tag}] to print the appropriate page number.

Note that due to the nature of CounterBox, the page numbers are only shown in the TOC is the notebook of the book is open and ShowPageBreaks -> True is set, but you should be able to print the TOC to a pdf.

createToc[bookUrl_, typeList_] :=
  Module[{toc, book, createCell, counter, cell, type, tag},

    (*create TOC file and open book*)
    toc = CreateDocument[];
    book = NotebookOpen[bookUrl];
    SetOptions[book, ShowPageBreaks -> True];

    (* helper file for creating cell *)
    createCell[text_, tag_, level_] := Cell[BoxData[
         TagBox[GridBox[{{"", text, CounterBox["Page", {bookUrl, tag}]}},  
           GridBoxAlignment -> {"Columns" -> {Left, Left, Right}}, 
           GridBoxItemSize -> {"Columns" -> {2 level - 1, 35 - 2 level, 5}}], 
          "Grid"]], "Text"];

    (* iterate over cells to set tags and write lines to TOC *)
    Scan[(counter[#] = 0) &, typeList];
    SelectionMove[book, Before, Notebook];
    SelectionMove[book, Next, Cell];
    While[(cell = NotebookRead[book]) =!= {},
      If[Length[cell] >= 2,
       type = cell[[2]];
       If[MemberQ[typeList, type],
        counter[type] += 1;
        tag = type <> ToString[counter[type]];
        SetOptions[NotebookSelection[book], 
         CellTags -> Union[Flatten[{Options[NotebookSelection[book], 
           CellTags][[1, 2]], tag}]]];
        SelectionMove[book, All, CellContents];
        NotebookWrite[toc, 
         createCell[NotebookRead[book], tag, 
          Position[typeList, type][[1, 1]]]]];
       SelectionMove[book, Next, Cell]]];
    SetSelectedNotebook[toc]];

To see the code in action, lets create a very simple document with 2 sections and 3 subsections on 3 pages

book = CreateDocument[];
NotebookWrite[book, Cell["This is section 1", "Section"]];
NotebookWrite[book, Cell["This is a subsection", "Subsection"]];
NotebookWrite[book, Cell["This is some text", "Text"]];
NotebookWrite[book, 
  Cell["Another section which begins on a new page", "Section", 
   PageBreakAbove -> True]];
NotebookWrite[book, 
  Cell["Subsection 2.1", "Subsection", PageBreakBelow -> True]];
NotebookWrite[book, Cell["Subsection 2.2", "Subsection"]];
bookUrl = ExpandFileName["book1.nb"];
NotebookSave[book, bookUrl];

Then createToc[bookUrl, {"Section", "Subsection"}] creates something like this

Mathematica graphics

Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
Heike
  • 35,858
  • 3
  • 108
  • 157
  • It looks very promising but it just locked-up my Mathematica session, so I'm going to insert a warning above first. – Sjoerd C. de Vries Jan 22 '12 at 21:15
  • @SjoerdC.deVries I'm sorry about that. I've only tried it on small examples but for those it seems to work fine on my machine. – Heike Jan 22 '12 at 21:25
  • Did some further testing. It's probably not the code itself that is the problem. It seems that setting the pagebreak option (SetOptions[book, ShowPageBreaks -> True]) is a problem for this particular file. Same lock-up happens when you do it manually, with File>Printing settings. It never finishes repagination. I made it under MMA7, using a tweaked Article/JournalArticle style file (mostly counter boxes for section numbering). – Sjoerd C. de Vries Jan 22 '12 at 21:35
  • I put a minimal version of the problem notebook at http://dl.dropbox.com/u/3675222/test6.nb. Please don't forget to save your other stuff before you try this. – Sjoerd C. de Vries Jan 22 '12 at 23:29
  • 1
    Maybe we should petition to have something like this done more simply. All this code just to generate a TOC? Surely there should be an easier way. – Eric Jan 28 '12 at 04:36
  • I too am interested in this process. the solution provided worked fine for me with the sample notebook, but didn't work at all with a 'real' document that had automatically numbered section cells, etc. I too had used Author Tools just enough to see that it had a lot of promise, then found it no longer works when MMA was updated. I recently tried to produce a longer document in Word, and though it has all the "tools" I just use something that crashes all the time. But MMA is missing some essential tools for creating a PRINT DOCUMENT. – Tom De Vries Nov 04 '12 at 16:41
  • I love this notebook. However it fails if headlines encounter TextData, e.g.have the form Cell[TextData[{StyleBox["something ",...],StyleBox["something else",...],...},"Section", ...] instead of Cell["something something else", "Section"]. The error message in this case is "An unknown box name (List) was sent as the BoxForm for the expression. Check the format rules for the expression." Such cells arise if direct formatting (e.g. bold) took place in the history of the headline. – Adalbert Hanßen Jun 17 '16 at 17:48
  • A TOC with hyperlinks instead of pagenumbers would be better. The notebook already applies tags to all headlines, e.g.CellTags->{"Section16", "Subchapter25"} which could serve this purpose. I would like to manually transfer a generated TOC with hyperlinks to my notebook. LibreOffice and MS-Word can create PDF files with functioning hyperlinks from a TOC to the headlines. I frequently use this feature and look for a simila one in Mma. However in Mma hyperlinks notebooks saved as .PDF don't work, although looking like being equiped with hyperlinks. – Adalbert Hanßen Jun 17 '16 at 19:13
  • @Adalbert Hanssen The problem of the hyperlinks not saved to pdf seems to be fixed. See 2 last comments here – andre314 Sep 03 '16 at 21:18