AppleScript to Add Blank Rows After Existing


#1

I love working in OmniOutliner for my teaching lesson plans. I have to submit lesson plans through a Web site which provides very limited styling (one font face, one size, no colors, etc.). I don’t want to simply export plaintext because having some styling is helpful when my lesson plans get reviewed.

I’ve found that MS Word export gets closest to the export format I want. However, although OmniOutliner allows for intricate padding options when viewing, they don’t come through in the export. If I had a blank line between each of the rows on my outline, my need to reformat in the Web site form after export would be greatly minimized.

I searched but didn’t find a solution, so I cobbled something together from a few scripts that could be found (from much smarter folks). It works for the most part, although I am sure it could be improved. For posterity:

tell application "OmniOutliner"
	set oDoc to front document
	expandAll
	set oSeln to every row of oDoc
	repeat with oRow in oSeln
		tell oRow
			make new row of oRow
			set expanded to true
		end tell
	end repeat
end tell

The following script which the community provided will then delete the empty rows:

tell front document of application "OmniOutliner"
	delete (rows whose topic is "")
end tell

#2

If you need to improve the script or optimize it, just tell me @TheWart. I really like Applescript and OmniOutliner.
P.S. In this script, you are creating blank rows as childs of the document rows. Is that exactly what you need or is it better to create blank rows as siblings?


#3

Thanks for the offer, @unlocked2412. I would like to tweak it.

I started with the “Stylish with Level Styles” template in OO5.

Running my script produces the following:

What I really would like would be blank rows created where the red lines indicate:


#4

You’re welcome, @TheWart .
That’s a good explanation. Maybe this helps. If not, I can change it.
Code:

tell application "OmniOutliner"
	tell front document
		set lst_ids to id of every row
		repeat with i in lst_ids
			set the_row to (first row whose (id = i))
			make new row at (beginning of every child of the_row)
		end repeat
	end tell
end tell

#5

That’s a definite improvement, @unlocked2412!

Would it be possible to to make the rows selected in this image…

…not be created as children? The ideal would be this (after ⌘[ on the selection above):


#6

Again, very clear explanation.
Sure, it’s possible (although a little more complex).
Code:

tell application "OmniOutliner"
	tell front document
		set lst_ids to id of every row
		repeat with i in lst_ids
			set the_row to (first row whose (id = i))
			if (has subtopics of the_row) = true then
				make new row at (beginning of every child of the_row)
			else
				make new row at (after the_row)
			end if
		end repeat
	end tell
end tell

#7

FWIW, in passing a couple of quick thoughts:

You could, if you wanted, abbreviate:

first row whose (id = i)

to

row id i

and perhaps:

if (has subtopics of the_row) = true then

as

if (has subtopics of the_row) then

(With advancing age I have become so lazy as to delegate most things to pasted generic functions – but that would probably just be complicating things here:
tell front document of application "OmniOutliner"
    set oDoc to it
    
    script blankRows
        on |λ|(i)
            tell oDoc
                set oRow to row id i
                
                if (has subtopics of oRow) then
                    make new row at (beginning of every child of oRow)
                else
                    make new row at (after oRow)
                end if
            end tell
        end |λ|
    end script
    
    my map(blankRows, id of rows)
end tell


-- GENERIC FUNCTIONS ---------------------------------------------------------
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

#8

Thank you so much, @unlocked2412 & @draft8 !

Both scripts accomplish just what I wanted upon Word export. Now I will be able to chain the AppleScripts together to add rows, export to Word, and delete the empty rows with a shortcut in Keyboard Maestro.


#9

You’re welcome, @TheWart! I’m glad It is working for you.


#10

That’s a good suggestion.

You’re right but I wanted to make clear that the expression (has subtopics of the_row) returns a boolean value for the occasional reader.

P.S.: Thanks for the valuable insight, @draft8.


#11

An another, slightly more succinct, approach:

tell application "OmniOutliner"
	tell front document
		set rowIDs to rows's id
		repeat with i in rowIDs
			tell row id i
				if exists children then
					make new row at beginning of children
				else
					make new row at (after it)
				end if
			end tell
		end repeat
	end tell
end tell

SG