4
$\begingroup$

I'm writing some code that programmatically modifies the contents of the notebook it's running in. My code uses NotebookLocate to select all the cells in the notebook that have a particular tag — in my case, they happen to be several non-adjacent Input cells (but not necessarily all input cells in the notebook). Now, I want to clear the contents of those cells, but not delete the cells themselves.

This seems to me like something that ought to be fairly easy, but I'm having a dickens of a time figuring out a way. I know I can get a list of CellObject expressions for the selected cells by calling SelectedCells, but is there some way to write a function I could map onto that list, which takes a CellObject and erases its contents? Or… Ideas?

$\endgroup$

2 Answers 2

3
$\begingroup$

Updated to address BoxData issue

An alternative to using NotebookDelete is to use NotebookWrite/NotebookRead. Here is a function that clears the contents of a cell:

eraseCellContents[cell_] := NotebookWrite[
    cell,
    Replace[NotebookRead[cell], Cell[h_, r___] :> Cell[emptyCell[h], r]]
]

emptyCell[_BoxData] := BoxData[""]
emptyCell[_] := ""

The helper function emptyCell makes sure that cells which use 2D typesetting (e.g., StandardForm) retain their 2D typesetting capabilities.

Example usage:

NotebookLocate["FOO"]
eraseCellContents /@ SelectedCells[]
$\endgroup$
1
  • $\begingroup$ Wow. I wouldn't have thought of doing something so cryptic -- I guess I'm not yet fluent enough with patterns, delayed rules, and the like. $\endgroup$
    – ibeatty
    Aug 23, 2017 at 19:45
4
$\begingroup$

Assuming they are all "Input" cells you can do:

Scan[
   (SelectionMove[#, All, CellContents]; NotebookDelete[]) &
 , SelectedCells[(*notebook*)]
]

instead of NotebookDelete you can use FrontEndTokenExecute["Clear"]

The assumption about input cell is important because otherwise DefaultDuplicateCellStyle will replace the modified cell's style. (1)

So in general you may want to use this:

Scan[
    ( SelectionMove[#, All, CellContents]
    ; Internal`WithLocalSettings[
          CurrentValue[#, DefaultDuplicateCellStyle
          ] = Lookup[Developer`CellInformation[#], "Style", "Input"] (*(2)*)
        , NotebookDelete[]
        , CurrentValue[#, DefaultDuplicateCellStyle] = Inherited
      ]
     ) &
   , SelectedCells[]
]

One could argue that it may erase explicit DefaultDuplicateCellStyle set for Cell, but this option is usually set at notebook's level.

(2) How can I get the style of selected cells?

$\endgroup$
4
  • $\begingroup$ Might also be worth mentioning the issue if Editable->False is set $\endgroup$
    – b3m2a1
    Aug 23, 2017 at 19:18
  • $\begingroup$ @b3m2a1 worth a comment for sure, not sure if more attention is required ;) should be obvious. $\endgroup$
    – Kuba
    Aug 23, 2017 at 19:32
  • $\begingroup$ Aah. I had been afraid of NotebookDelete because I thought it would always delete the entire cell. $\endgroup$
    – ibeatty
    Aug 23, 2017 at 19:39
  • $\begingroup$ @ibeatty I see, don't forget CellContents then :) $\endgroup$
    – Kuba
    Aug 23, 2017 at 19:40

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.