For Pages, the script iterates over images, shapes, and body text. For images it checkes their description, for the shapes it checks in text, and deletes those that have a specific tag. For the body text, I face challenged to preserve the style and delete several paragraphs not necessarily containing the tag.
My solution was to work at the section level: if a particular tag is found in the body text of a section, the script clears all the content within that section. I then have to manually remove the section break later.
After processing the document’s content, I use GUI scripting to automate a find-and-replace operation. The script simulates pressing Command+F to open the search panel, clears the search field, enters the target search term, switches to the replacement field, clears it, and types in the new text before executing a “Replace All.”
For Keynote this is the same for the search/replace all. Instead of sections, I simple use a tag in the presenter notes to target a slide to delete it. For images I also use a tag in the description.
With Pages and Keynote my last little problem is the search & replace doesn't handle the line breaks. I'm stuck with this, but it's not such a huge problem for my project, I'll just have more constraints to deal with.
Finally with Keynote I failed to target specific shapes and text item to delete. I manage to get the text, to find the tag, but then the deletion process seems erratic. I either end with nothing deleted or almost everything (including shapes and text items not having the tag). Again this is a small constraint I can deal with.
Nonetheless, if some has a lead or a solution, I'd be happy to try it.
Post
Replies
Boosts
Views
Activity
Could be useful for someone, here's an example of script for Numbers to manipulate the content, cells and rows with placeholders:
set newList to {}
repeat with anItem in theList
set newList to {anItem} & newList
end repeat
return newList
end reverseList
on replaceText(theText, searchString, replacementString)
set AppleScript's text item delimiters to searchString
set textItems to text items of theText
set AppleScript's text item delimiters to replacementString
set newText to textItems as text
set AppleScript's text item delimiters to ""
return newText
end replaceText
tell application "Numbers"
tell document "TestNum"
repeat with s in sheets
tell s
repeat with t in tables
-- Create a static list of row indices
set totalRows to count of rows of t
set rowIndices to {}
repeat with i from 1 to totalRows
copy i to end of rowIndices
end repeat
set revIndices to my reverseList(rowIndices)
repeat with iRef in revIndices
set rowNum to iRef as integer
-- Directly use "row rowNum of t" to access the row
set numCells to count of cells of (row rowNum of t)
set deleteRowFlag to false
repeat with j from 1 to numCells
set cellRef to cell j of (row rowNum of t)
set cellContent to value of cellRef
if cellContent is not missing value then
if cellContent contains "[DELETE_ROW]" then
set deleteRowFlag to true
exit repeat
end if
end if
end repeat
if deleteRowFlag then
delete (row rowNum of t)
log "Row " & rowNum & " : [DELETE_ROW] -> row deleted."
else
repeat with j from 1 to numCells
set cellRef to cell j of (row rowNum of t)
set cellContent to value of cellRef
if cellContent is not missing value then
if cellContent contains "[REPLACE]" and cellContent contains "[/REPLACE]" then
try
set startPos to offset of "[REPLACE]" in cellContent
set endPos to offset of "[/REPLACE]" in cellContent
set beforeTag to ""
if startPos > 1 then set beforeTag to text 1 thru (startPos - 1) of cellContent
set afterStart to endPos + (length of "[/REPLACE]")
set afterTag to ""
if afterStart ≤ (length of cellContent) then set afterTag to text afterStart thru -1 of cellContent
set cellContent to beforeTag & "REPLACED" & afterTag
set value of cellRef to cellContent
log "Row " & rowNum & ", Column " & j & " : [REPLACE][/REPLACE] replaced by 'REPLACED'."
on error errMsg
log "Error for [REPLACE][/REPLACE] at row " & rowNum & ", column " & j & " : " & errMsg
end try
end if
if cellContent contains "[ADD_ROW_1]" then
try
tell (row rowNum of t)
set newRow to add row below
end tell
set value of cell j of newRow to "ROW ADDED"
set cellContent to my replaceText(cellContent, "[ADD_ROW_1]", "")
set value of cellRef to cellContent
log "Row " & rowNum & ", Column " & j & " : [ADD_ROW_1] -> row added."
on error errMsg
log "Error for [ADD_ROW_1] at row " & rowNum & ", column " & j & " : " & errMsg
end try
end if
if cellContent contains "[ADD_ROW_2]" then
try
tell (row rowNum of t)
set newRow1 to add row below
-- Add the second row below the first newly added row
set newRow2 to add row below newRow1
end tell
set value of cell j of newRow1 to "ROW ADDED"
set value of cell j of newRow2 to "ROW ADDED"
set cellContent to my replaceText(cellContent, "[ADD_ROW_2]", "")
set value of cellRef to cellContent
log "Row " & rowNum & ", Column " & j & " : [ADD_ROW_2] -> two rows added."
on error errMsg
log "Error for [ADD_ROW_2] at row " & rowNum & ", column " & j & " : " & errMsg
end try
end if
if cellContent contains "[KEEP]" and cellContent contains "[/KEEP]" then
try
set startPos to offset of "[KEEP]" in cellContent
set endPos to offset of "[/KEEP]" in cellContent
set beforeTag to ""
if startPos > 1 then set beforeTag to text 1 thru (startPos - 1) of cellContent
-- Extract content between the tags
set textStart to startPos + (length of "[KEEP]")
set keptText to ""
if endPos > textStart then set keptText to text textStart thru (endPos - 1) of cellContent
set afterStart to endPos + (length of "[/KEEP]")
set afterTag to ""
if afterStart ≤ (length of cellContent) then set afterTag to text afterStart thru -1 of cellContent
set cellContent to beforeTag & keptText & afterTag
set value of cellRef to cellContent
log "Row " & rowNum & ", Column " & j & " : [KEEP][/KEEP] -> content kept, tags removed."
on error errMsg
log "Error for [KEEP][/KEEP] at row " & rowNum & ", column " & j & " : " & errMsg
end try
end if
if cellContent contains "[DELETE]" and cellContent contains "[/DELETE]" then
try
set startPos to offset of "[DELETE]" in cellContent
set endPos to offset of "[/DELETE]" in cellContent
set beforeTag to ""
if startPos > 1 then set beforeTag to text 1 thru (startPos - 1) of cellContent
set afterStart to endPos + (length of "[/DELETE]")
set afterTag to ""
if afterStart ≤ (length of cellContent) then set afterTag to text afterStart thru -1 of cellContent
set cellContent to beforeTag & afterTag
set value of cellRef to cellContent
log "Row " & rowNum & ", Column " & j & " : [DELETE][/DELETE] -> content deleted."
on error errMsg
log "Error for [DELETE][/DELETE] at row " & rowNum & ", column " & j & " : " & errMsg
end try
end if
end if
end repeat
end if
end repeat
end repeat
end tell
end repeat
end tell
end tell
Update on my findings:
I’ve come to the conclusion that comments in iWork documents are simply not scriptable or accessible via AppleScript or ScriptingBridge.
I’m now working with a different approach using placeholders. In Numbers, I can manipulate the content as expected, though placeholders are less convenient than comments.
For Pages, I also managed to use placeholders, but it caused me to lose all styles because I had to switch to plain text.
My strategy to keep all style is to perform a simple find/replace on my placeholders within the body text. For images, I use the "description" field intended for VoiceOver. Again, not the most elegant solution, but it works.
However, I’m stuck on one issue: when my placeholders span multiple paragraphs, I can’t find a way to remove the content between them without losing styles.
Does anyone have an idea on how to delete content placed between two placeholders, even across multiple paragraphs, while preserving styles? Any suggestions would be greatly appreciated!