Note: Spelunking will likely be needed.

Execute the following. You should get back and error along the lines of First::first:... This error is unimportant except it helps illustrate a potential issue with Cases internal code.

Print[Button["Print Cell",
        Cell[___, CellTags -> "MyCode", ___]]
     ], "Input", CellTags -> "MyGraphic"]
      Cell[___, CellTags -> "MyGraphic", ___], Infinity], StandardForm]
    ], "Output", CellTags -> "MyCode"];

Now ultimately although the notebook is outputting an error the Notebook itself should have a valid structure, considering the notebook can be saved and duplicated like so NotebookPut@NotebookGet[EvaluationNotebook[]].

Interestingly if execute the following code in the same Notebook.

 , Cell[__, CellTags -> "MyGraphic"], Infinity]

Cases return the appropriate values and you get back a First::first error.

My question: Why does Cases return a message from a perfectly valid Notebook structure. Other then using Quiet to suppress an error, how might I solve such a problem?

  • $\begingroup$ You're not calling Cases at the proper level. See the third argument of Cases... use level Infinity $\endgroup$
    – rm -rf
    Aug 8, 2013 at 18:33
  • $\begingroup$ @rm-rf I'm sorry not sure what you mean Infinity means at calling at every level, yes? $\endgroup$
    – William
    Aug 8, 2013 at 18:35
  • $\begingroup$ See the difference between Cases[{{Cell["foo", CellTags -> "bar"]}}, Cell[__, CellTags -> "bar", ___]] and Cases[{Cell["foo", CellTags -> "bar"]}, Cell[__, CellTags -> "bar", ___]]... by default Cases operates at level spec {1}, which is why the first returns {} whereas the second returns a cell. In a generic notebook expression, the cell tag rule is at an arbitrary depth, which you may or may not know in advance. It certainly isn't at level {1}. So you use Infinity to tell Cases to look for the pattern at all levels. $\endgroup$
    – rm -rf
    Aug 8, 2013 at 18:40
  • $\begingroup$ @rm-rf but the 2nd Cases is set to Infinity. Read the question again. My question isn't why the 1st error is outputted, but why a perfectly valid Notebook structure causes the 2nd Cases to return a message in addition to returning the output. Something internally on how Cases is structure is causing the issue. $\endgroup$
    – William
    Aug 8, 2013 at 18:43
  • $\begingroup$ @rm-rf In the following example the Notebook structure is somehow causing Cases to fail pastebin.com/uP7CNrUS $\endgroup$
    – William
    Aug 8, 2013 at 18:47

2 Answers 2


This "answer", if it can be considered an answer, consists of a mixture of comments and suggestions.

Aside from dealing with levels as rm-rf has shown in another answer, one probably ought to deal with the possibility of Cases returning {}, even if it should not happen. How to deal with it is something you should decide. Here's a way to return Null, if it's of any help:

First[Cases[..] /. {} -> {Null}]

You can avoid the Cell pattern matching itself if, as I surmise, the "MyCode" and "MyGraphics" tags indicate the type of cells. Code and graphics cells start Cell[BoxData[..],..]. So the patterns could be these:

Cell[_BoxData, ___, CellTags -> "MyCode", ___]
Cell[_BoxData, ___, CellTags -> "MyGraphic", ___]

You can get the cells in a notebook, except inline cells, at level 1 in a List, with the following (not extensively tested, however):

cells[nb_NotebookObject] := cells[nb, _];
cells[nb_NotebookObject, pat_] := Flatten @ cells[First @ NotebookGet[nb], pat];
cells[cellList_List, pat_] := cells[#, pat] & /@ cellList;
cells[Cell[CellGroupData[group_List, ___]], pat_] := cells[#, pat] & /@ group;
cells[c_Cell, pat_] := If[MatchQ[c, pat], c, {}];
cells[__] := {};

All cells:


You can even get only the cells matching a pattern:

      _?(MemberQ[Flatten[{CellTags} /. Options[#]], "MyCode"] &)]
  • $\begingroup$ This question was a follow up from here mathematica.stackexchange.com/questions/30069/… If you would like you are welcome to post an answer and receive more points (like you really need them) $\endgroup$
    – William
    Aug 10, 2013 at 1:59
  • $\begingroup$ Genious technique, you are welcome to the following function as an answer at the above question. pastebin.com/mvFPqvVY $\endgroup$
    – William
    Aug 10, 2013 at 2:37
  • $\begingroup$ @Liam Thanks for pointing it out. I've been busy and haven't kept up with all the questions. $\endgroup$
    – Michael E2
    Aug 10, 2013 at 14:10

The following expression should result in an error:

First@Cases[NotebookGet[EvaluationNotebook[]][[1]], Cell[___, CellTags -> "MyCode", ___]]]

because Cases, by default, operates at level {1} and in a notebook's expression, CellTags will never be at level {1}. Thus, Cases returns {} and First throws an error. The solution here, is to use level Infinity.

Now coming to the second Cases — you've now evaluated the first code block and you have a button in your notebook. This button's expression is:

ButtonBox["\"Print Cell\"", Appearance -> Automatic, 
    ButtonFunction :> Cell[
               Cell[___, CellTags -> "MyCode", ___]]]
       "Input", CellTags -> "MyGraphic"
   ], Evaluator -> Automatic, Method -> "Preemptive"

Note that this expression is stored as an input expression instead of parsed boxform expression. As Cases walks through the tree, it evaluates the leaves and the RHS of ButtonFunction gets evaluated, which is what results in the error (for reasons explained above).

  • $\begingroup$ @Liam The "fix" is to use the correct levelspec in the 1st Cases... As I said, in general you'll not find a cell tag at that level, so this button is designed to generate an error. So as long as that incorrect button is present, the 2nd Cases will throw an error. You should also read this answer by Leonid. You might be able to use it to "shield" certain expressions (like ButtonFunction's RHS, for example). $\endgroup$
    – rm -rf
    Aug 8, 2013 at 19:10

Your Answer

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

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