# How to programmatically clear the contents of a set of selected, non-contiguous notebook cells?

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?

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[]

• 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

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]
; InternalWithLocalSettings[
CurrentValue[#, DefaultDuplicateCellStyle
] = Lookup[DeveloperCellInformation[#], "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.

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