4
$\begingroup$

I want to create a new notebook by evaluating an expression, not from the front-end GUI, and I want to specify all styles for the notebook in the expression, using only stylesheets supplied with the Mathematica installation. The use case is zero-touch installations on fresh machines, no interactions with the style GUI and no installations of user-supplied style sheets in special, magical directories. The new user walks up to the fresh machine, gets a single notebook with a single expression from me, evaluates that expression, and al-a-khazam gets a new notebook with all the styles that I specify.

EDIT:

Here is an example use-case scenario (not my actual one, but very very close):

My scenario is similar to a classroom: IT department installs stock Mathematica on stock operating systems on stock PCs, and they will not do user-specific installations. The user accounts are network accounts and the user folders don't even exist until the users log on the first time.

The stock styles supplied by Mathematica are unacceptable for a variety of reasons. For example, Arial and Helvetica fonts are banned by our staff because their spacing on narrow letters is too condensed; but there are lots of little things like this. I got really tired of setting the styles manually in the GUI and then propagating the style sheets to the students and then teaching them about the canonical, magical, user-specific directory structure and then dealing with their mistakes on installing and using the style sheets.

I decided to automate the distribution of notebooks with customized notebook styles. My requirements on the automation scenario are:

  1. Users must be able to create new notebooks in a style supplied by me on fresh machines that have the stock operating system and the stock installation of Mathematica, with no user-specific customizations of any kind.

  2. Users must NOT be required to learn and use the style GUI ("Format > Edit Stylesheet...") and must not be required to install and use a stylesheet.

  3. Users receive a single file from me (say from a gist or from a Dropbox folder) with the smallest possible instructions for creating properly styled notebooks. In particular, they can put this file any place they want in their folders; they don't have to put it in a special place.

Users complete their assignments by filling out some work in the properly-styled notebooks and returning them to me.

$\endgroup$
6
  • $\begingroup$ What you have does not differ so much what one can get from Format / Stylesheet / Stylesheet Chooser.... In this case "Standard Report". But I must admit I don't quite get your point. $\endgroup$
    – Kuba
    Apr 14, 2016 at 12:52
  • $\begingroup$ See How to create a notebook with a properly formatted expression $\endgroup$ Apr 14, 2016 at 13:04
  • $\begingroup$ @Kuba The point is to customize styles without the GUI and without installing style sheets in user-specific magical directories. The user can modify this expression to produce any styles he/she wants -- this particular one does not differ much from the standard one, but other examples could differ in every regard. $\endgroup$
    – Reb.Cabin
    Apr 14, 2016 at 13:29
  • $\begingroup$ @Reb.Cabin Sorry, I'm missing the big picture here. That's quite often in my case :) but if I'm not the only one maybe it could be usefult to provide a short example of situation where this is useful and better than... well let's say a standard way because I don't know yet what is the goal. $\endgroup$
    – Kuba
    Apr 14, 2016 at 13:35
  • $\begingroup$ @Kuba Ok, let me think of a better way to explain it ... it's crystal clear to me, I just need to explain it better :) I will get back to it later today (gotta catch the train right now) $\endgroup$
    – Reb.Cabin
    Apr 14, 2016 at 13:39

1 Answer 1

2
$\begingroup$

Here is a Mathematica expression in a meta-notebook, based on the Wolfram-supplied "StandardReport" style, as an example that creates another Notebook with all the styles set up the way I want them. I store this meta-notebook in the same place I store all my other notebooks instead of in a magical directory on my path, so it gets backed up and survives machine wipes. It could be distributed to users in a similar way, say through a gist or a Dropbox folder.

To adapt this to your own needs, just edit and evaluate the expression! A good way to figure out how to change the expression is to create and style a notebook in the usual way, through the GUI, open it up with an ordinary text editor like vim or emacs, and find the bits that you want to copy over to your meta-notebook. I've endeavored to include samples of every element that has a style so that the newly created notebooks can be visually checked. Much easier (at least for me) than messing around with a GUI and magical directories.

Here is a gist https://gist.github.com/rebcabin/0b9ddf27e1354cbded215594d6f59056

Here is another gist with a functional refactoring (installs MMA symbols and has multiple expressions, but is a little more flexible; the gist above and the code below is just a single expression and installs only the symbol myNotebook in the MMA context):

https://gist.github.com/rebcabin/6ba697716ea2bcbfbe9a3253be4d1a01

Module[{myNotebook, myCells, myStyles, myDemoIntegral, myDemoSolution,
    myMathGroup, myItemGroup, myNumberedGroup, myCode, myProgramText, 
   myMeatyContentGroup, mySectionGroup, myDocumentGroup, 
   myFontFunction, myDefaultStyles, myNonDefaultStyles},
  myDemoIntegral = RowBox[{
     RowBox[{"\[Integral]", 
       RowBox[{"x", RowBox[{"\[DifferentialD]", "x"}]}]}],
     "+", SqrtBox["z"]}];
  myDemoSolution = RowBox[{
     FractionBox[SuperscriptBox["x", "2"], "2"],
     "+", SqrtBox["z"]}];
  myMathGroup = CellGroupData[{
     Cell[BoxData[myDemoIntegral], "Input"],
     Cell[BoxData[myDemoSolution], "Output"]},
    Open];
  myItemGroup = CellGroupData[{
     Cell["Item", "Item"],
     Cell["ItemParagraph", "ItemParagraph"],
     Cell[CellGroupData[{
        Cell["Subitem", "Subitem"],
        Cell["SubitemParagraph", "SubitemParagraph"],
        Cell[CellGroupData[{
           Cell["Subsubitem", "Subsubitem"],
           Cell["SubsubitemParagraph", "SubsubitemParagraph"]},
          Open]]},
       Open]]},
    Open];
  myNumberedGroup = CellGroupData[{
     Cell["ItemNumbered", "ItemNumbered"],
     Cell["ItemParagraph", "ItemParagraph"],
     Cell[CellGroupData[{
        Cell["SubitemNumbered", "SubitemNumbered"],
        Cell["SubitemParagraph", "SubitemParagraph"],
        Cell[CellGroupData[{
           Cell["SubsubitemNumbered", "SubsubitemNumbered"],
           Cell["SubsubitemParagraph", "SubsubitemParagraph"]},
          Open]]},
       Open]]},
    Open];
  myCode = RowBox[{RowBox[{"fun", "[", "x_", "]"}], ":=", "1"}];
  myProgramText = 
   "\<DLLEXPORT int fun(WolframLibraryData libData, mreal A1, mreal \
*Res)
   {
    mreal R0_0;
    mreal R0_1;
    R0_0 = A1;
    R0_1 = R0_0 * R0_0;
    *Res = R0_1;
    funStructCompile->WolframLibraryData_cleanUp(libData, 1);
    return 0;
   }\>";
  myMeatyContentGroup = CellGroupData[{
     Cell["Subsubsection", "Subsubsection"],
     Cell["Text", "Text"],
     Cell[myMathGroup],
     Cell[myItemGroup],
     Cell[myNumberedGroup],
     Cell["DisplayFormula", "Text"],
     Cell[BoxData[FormBox[myDemoIntegral, TraditionalForm]], 
      "DisplayFormula"],
     Cell[TextData[{
        "InlineFormula: ",
        Cell[BoxData[FormBox[myDemoSolution, TraditionalForm]]],
        "."}],
      "Text"],
     Cell["NumberedDisplay", "Text"],
     Cell[BoxData[FormBox[myDemoIntegral, TraditionalForm]], 
      "DisplayFormulaNumbered"],
     Cell["Code", "Text"],
     Cell[BoxData[myCode], "Code"],
     Cell["Program", "Text"],
     Cell[myProgramText, "Program"]},
    Open];
  mySectionGroup = CellGroupData[{
     Cell["Section", "Section"],
     Cell[CellGroupData[{
        Cell["Subsection", "Subsection"],
        Cell[myMeatyContentGroup]},
       Open]]},
    Open];
  myDocumentGroup = CellGroupData[{
     Cell["Title", "Title"],
     Cell["Subtitle", "Subtitle"],
     Cell["Subsubtitle", "Subsubtitle"],
     Cell["Author", "Author"],
     Cell["Department", "Department"],
     Cell["Date", "Date"],
     Cell["Chapter", "Chapter"],
     Cell["Subchapter", "Subchapter"],
     Cell[mySectionGroup]},
    Open];
  myCells = {Cell[myDocumentGroup]};
  myFontFunction[siz_, fam_: "Candara", wgt_: "Plain", 
    slt_: "Plain"] := {FontFamily -> fam, FontSize -> siz, 
    FontWeight -> wgt, FontSlant -> slt};
  myDefaultStyles = {
    {"Title", 44}, {"Subtitle", 24}, {"Subsubtitle", 16},
    {"Author", 14}, {"Department", 11}, {"Date", 11},
    {"Chapter", 34}, {"Subchapter", 28},
    {"Section", 28}, {"Subsection", 20}, {"Subsubsection", 19},
    {"Text", 14},
    {"Item", 15}, {"ItemParagraph", 14},
    {"Subitem", 13.5}, {"SubitemParagraph", 13.5},
    {"Subsubitem", 13}, {"SubsubitemParagraph", 13},
    {"ItemNumbered", 15}, {"SubitemNumbered", 
     13.5}, {"SubsubitemNumbered", 13},
    {"DisplayFormula", 14}, {"DisplayFormulaNumbered", 14}};
  myNonDefaultStyles = {
    {"InlineFormula", 12.6, "Palatino", "Plain"},
    {"Code", 12, "Inconsolata", "Bold"},
    {"Program", 12, "Courier", "Plain"},
    {"Input", 13, "Inconsolata", "Bold"},
    {"Output", 13, "Inconsolata", "Plain"}};
  myStyles = {
    Cell[StyleData[
      StyleDefinitions -> 
       FrontEnd`FileName[{"Report"}, "StandardReport.nb", 
        CharacterEncoding -> "UTF-8"]]],
    Sequence @@ MapThread[
      Cell[StyleData[#1], myFontFunction[#2]] &,
      Transpose[myDefaultStyles]],
    Sequence @@ MapThread[
      Cell[StyleData[#1], myFontFunction[#2, #3, #4]] &,
      Transpose[myNonDefaultStyles]]};
  CreateDocument[
   myNotebook = Notebook[
     myCells,
     StyleDefinitions -> Notebook[
       myStyles,
       Visible -> False]]]];
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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