MacOS – How to write text to an RTF file, while maintaining the style of a document template, in AppleScript

applescriptmacostext;

I have an AppleScript code that I am having trouble writing.

I would like a new, blank .rtf file to be created with a user-defined filename, saved to a predetermined location, with a predetermined document template. I already know how to accomplish all of these functions in AppleScript.

I would then like the plain text on the clipboard to be written to the document and the plain text to match the style of the predetermined document template. It is this desire that creates difficulty.

If the clipboard contains any formatting (such as font style, font size, emphasis style, text color, or highlight color), I would like this information to be ignored and instead have the clipboard text match the predetermined formatting of the RTF file.

Here's the code that I have at this point. Feel free to abandon my approach, as I cannot get it to work.

(The following AppleScript code is almost identical to this code by user3439894. I've flagged my (flawed) additions by introducing lines of code that I wrote myself with "My new code.")

global theCustomRichTextFilePathname
global customFilename
global fullDataToWriteToRTFfile




repeat
    set customFilename to the text returned of (display dialog "Save as:" with title "Do you want to create a new, blank TextEdit RTF document?" default answer "")
    if customFilename is "" then
        beep
        display alert "The filename cannot be empty!" message "Please enter a name to continue..."
    else
        exit repeat
    end if
end repeat


set theCustomRichTextFilePathname to ((path to desktop) & customFilename & ".rtf") as string




-- My new code:

set hexOfTheClipboardText to convertATextStringToItsHexFormat()

set hexOfTheClipboardText to (hexOfTheClipboardText & "7D")
-- The 7D in the above line represents the hex code of the closing bracket } that must be the last character of the RTF data string.

set dataForTheRTFDocumentTemplateThatIWant to "7B5C727466315C616E73695C616E7369637067313235325C636F636F61727466313430345C636F636F617375627274663437300A7B5C666F6E7474626C5C66305C6673776973735C6663686172736574302048656C7665746963613B7D0A7B5C636F6C6F7274626C3B5C7265643235355C677265656E3235355C626C75653235353B7D0A5C6D6172676C313434305C6D61726772313434305C766965777731303830305C7669657768383430305C766965776B696E64300A5C706172645C74783732305C7478313434305C7478323136305C7478323838305C7478333630305C7478343332305C7478353034305C7478353736305C7478363438305C7478373230305C7478373932305C7478383634305C7061726469726E61747572616C5C7061727469676874656E666163746F72300A0A5C66305C66733336205C636630205C0A"

set fullDataToWriteToRTFfile to (dataForTheRTFDocumentTemplateThatIWant & hexOfTheClipboardText)


-- End of my new code.




tell application "Finder"
    try
        if exists file theCustomRichTextFilePathname then
            tell current application
                display dialog "The file \"" & POSIX path of theCustomRichTextFilePathname & "\" already exists!" & return & return & "Do you want to overwrite the file?" buttons {"No", "Yes"} default button 1 with title "File Already Exists..." with icon caution
                if the button returned of result is "No" then
                    --  # The file already exists, chose not to overwrite it, just open the document.
                    my openDocument()
                else
                    --  # The file already exists, chose to overwrite it, then open the document.
                    my createCustomRTFDocument()
                    my openDocument()
                end if
            end tell
        else
            --  # The file does not already exist. Create and open the document.
            tell current application
                my createCustomRTFDocument()
                my openDocument()
            end tell
        end if
    on error eStr number eNum
        activate
        display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
        return
    end try
end tell







on createCustomRTFDocument()
    tell current application

         -- My new line of code:
        set customRTFDocumentTemplate to «data RTF fullDataToWriteToRTFfile»
         -- THE ABOVE LINE DOES NOT WORK AND SENDS AN ERROR.



            try
                set referenceNumber to open for access theCustomRichTextFilePathname with write permission
                write customRTFDocumentTemplate to referenceNumber
                close access referenceNumber
            on error eStr number eNum
                activate
                display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with title "File I/O Error..." with icon caution
                try
                    close access referenceNumber
                end try
                return
            end try
        end tell
    end createCustomRTFDocument






on openDocument()
    try
        tell application "TextEdit"
            open file theCustomRichTextFilePathname
            activate
            tell application "System Events"
                set displayedName to get displayed name of file theCustomRichTextFilePathname
                if displayedName contains ".rtf" then
                    tell application "TextEdit"
                        set bounds of window (customFilename & ".rtf") to {160, 22, 883, 639}
                    end tell
                    key code 125
                else
                    tell application "TextEdit"
                        set bounds of window customFilename to {160, 22, 883, 639}
                    end tell
                    key code 125
                end if
            end tell
        end tell
    on error eStr number eNum
        activate
        display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
        return
    end try
end openDocument





-- New code:

on convertATextStringToItsHexFormat()
    set hexOfText to ""
    set letters to every character in the clipboard
    repeat with letter in letters
        set numberRepresentingTheID to (id of letter)
        set hexOfText to hexOfText & list2hex(numberRepresentingTheID)
    end repeat
    return hexOfText
end convertATextStringToItsHexFormat

on list2hex(X)
    set y to ""
    repeat with Z in {} & X
        set y to y & num2hex(Z) & ","
    end repeat
    set y to text 1 thru -2 of y
    return y
end list2hex

on num2hex(X)
    set y to ""
    repeat until X = 0
        set n to X mod 16
        if n > 9 then
            set y to character id (55 + n) & y
        else
            set y to character id (48 + n) & y
        end if
        set X to X div 16
    end repeat
    return y
end num2hex

-- End of new code

I know that perhaps the easiest way to accomplish what I want is to simply keystroke the keyboard shortcut to "Paste and Match Style" in TextEdit.app, i.e., ⌥ option + + ⌘ command + V. But I was hoping for a "back end" and more sophisticated method, since keystroking carries with it a noticeable delay.

Best Answer

Here's another method with a Cocoa-AppleScript applet, this script create the RTF file with the methods from the Objective-C code.

-- Cocoa-AppleScript
use framework "Foundation"
use scripting additions
repeat
    set customFilename to the text returned of (display dialog "Save as:" with title "Do you want to create a new, blank TextEdit RTF document?" default answer "")
    if customFilename is "" then
        beep
        display alert "The filename cannot be empty!" message "Please enter a name to continue..."
    else
        exit repeat
    end if
end repeat
set theCustomRichTextFilePathname to ((path to desktop as string) & customFilename & ".rtf")

tell application "Finder" to set b to exists file theCustomRichTextFilePathname
tell current application
    try
        if b then
            display dialog "The file \"" & POSIX path of theCustomRichTextFilePathname & "\" already exists!" & return & return & "Do you want to overwrite the file?" buttons {"No", "Yes"} default button 1 with title "File Already Exists..." with icon caution
            if the button returned of result is "No" then
                --  # The file already exists, chose not to overwrite it, just open the document.
                my openDocument(theCustomRichTextFilePathname)
                return
            end if
        end if
        -- else, the file already exists, chose to overwrite it or the file does not already exist
        my createCustomRTFDocument(theCustomRichTextFilePathname)
    on error eStr number eNum
        activate
        display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
        return
    end try
end tell

on openDocument(f)
    tell application "TextEdit"
        set theDoc to open file f
        set bounds of (first window whose its document is theDoc) to {160, 22, 883, 639}
        activate
    end tell
    tell application "System Events" to key code 125 using command down --put the blinking cursor at the end of the document
end openDocument

on createCustomRTFDocument(f)
    set myText to return & (the clipboard as string) -- Concatenation of an empty line and the text in the clipboard
    set theFile to POSIX path of f
    tell current application
        set myFont to its (NSFont's fontWithName:"Helvetica" |size|:18) -- font and size of the rtf document
        set myColor to its (NSColor's blackColor()) -- color of the text of the rtf document
        set theDict to its (NSDictionary's alloc()'s initWithObjectsAndKeys_(myColor, its NSForegroundColorAttributeName, myFont, its NSFontAttributeName, missing value))
        set AttrString to its ((NSAttributedString's alloc)'s initWithString:myText attributes:theDict) -- create an attributed string
        set rtfData to AttrString's RTFFromRange:{0, AttrString's |length|()} documentAttributes:{NSRTFTextDocumentType:(its NSDocumentTypeDocumentAttribute)} -- create the data from an attributed string
    end tell
    rtfData's writeToFile:theFile atomically:true -- write the data to the RTF file
    if the result then my openDocument(f) -- open the file 
end createCustomRTFDocument