4

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?

ibeatty
  • 2,533
  • 11
  • 22

2 Answers2

4

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?

Kuba
  • 136,707
  • 13
  • 279
  • 740
3

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[]
Carl Woll
  • 130,679
  • 6
  • 243
  • 355
  • 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. – ibeatty Aug 23 '17 at 19:45