I'm seeing some unexpected (to me) behavior from SelectionEvaluate
. I've got a notebook with two sections. In section 2, I've got code that clears the notebook's context, selects and executes section 1 (using NotebookLocate
with a cell tag on the section's header, SelectionMove
to grab the entire cell group, and SelectionEvaluate
to execute the whole group). Successive cells in section 2 then do things on the assumption that whatever code is in section 1 have in fact been evaluated.
What I'm finding is that when I select my entire section 2 and evaluate it, section 1 does in fact get correctly selected and executed, but the effects of that code on the notebook's context do not take effect until after the remainder of section 2 have been evaluated. In other words, it seems that cells coming after the SelectionEvaluate
function take effect before the cells being evaluated by SelectionEvaluate
.
BTW, I've set my Mathematica preferences to give each notebook a unique context. I don't think this should matter, but I mention it just in case.
Here's a link to a proof-of-concept notebook:
(Because it relies on some notebook properties like cell tags and groups, I didn't know how to put the demo code directly into this post.)
So, my questions are: (1) Is this expected behavior in some way I'm not understanding, or is it a bug? and (2) Is there any way to get the effect I'm looking for, which is to programmatically force execution of a chunk of code elsewhere in the notebook and then do subsequent actions that depend on that code having been evaluated?
(For context, I'm trying to engineer a training notebook that lets students take a shot at writing some Mathematica code in one area of the notebook, and then execute code built into the notebook that tests out their code and offers feedback.)
SelectionEvaluate
queues some more cells, from section 1. But at this point the queue is not empty yet, it still contains cells from section 2, to be evaluated later. The SelectionEvaluate function inserts section 1 cells only at the end of the queue, after the section 2 cells. $\endgroup$SelectionEvaluate
with this function:ev[nb_] := Module[{r}, r = NotebookRead[nb]; ToExpression /@ Cases[r, Cell[boxes_, "Input", ___] :> boxes, {0, Infinity}] ]
. It will evaluate the contents of those cells. But: 1. This is very likely not the right way, and might break in some cases. I'm not experienced with notebook programming. 2. While it evaluates the contents of those cells, it does not link that content to the cells themselves. You won't get new In/Out labels and you won't get associated output cells. $\endgroup$NotebookRead
andToExpression
, and ran into a problem with the fact that the chunk of notebook content was "not a string or box". I suspect that's what yourCases
bit is for. I'll mess around with your latest suggestion, while hoping a notebook-programming wizard happens by. Thanks! $\endgroup$