How to write text to an RTF file, while maintaining the style of a document template, in AppleScript?
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
This script create a new document in TextEdit and it use the properties of the text to change the formatting of the RTF document (look at the createCustomRTFDocument() handler) :
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
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
activate
set bounds of (first window whose its document is theDoc) to {160, 22, 883, 639}
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)
close access (open for access f) -- create a blank file , this command do nothing on an existing file
-- delay 0.5 -- use the delay command, If you have permission issues (you can increase the number of seconds).
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 application "TextEdit"
set theDoc to make new document with properties {path:theFile} -- create new document
-- this put the text in the document, *** use (font, size and color) properties to set the predetermined formatting of the RTF document *** {0, 0, 0} = black color
make new attribute run at beginning of theDoc with data myText with properties {font:"Helvetica", size:18, color:{0, 0, 0}} -- this put the blinking cursor at the end of the document
set bounds of (first window whose its document is theDoc) to {160, 22, 883, 639}
save theDoc in theFile
activate
end tell
end createCustomRTFDocument
This answer incorporates the existing code from my answer you linked in your question with the following modifications.
In the openDocument()
handler, key code 125
was changed to key code 125 using command down
so as to send the cursor to the last line in the document upon being opened.
The createCustomRTFDocument()
handler has my addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument()
added after the closing of the newly created RTF Document, having been created from the Template. The creating of the RTF Document is now a two step process, first step creates the document from the template the second step adds text from the Clipboard as plain text, if text exists, which is done before the first time the document is opened for the User by the openDocument()
handler.
A new handler was created and named addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument()
and coded to do just as its name reads. It will get the text from the clipboard as plain text, if it exists, and write it to the end of the newly created RTF document created by the first part customRTFDocumentTemplate()
handler.
I found a bug in my original code, the file was being overwritten internally not deleting the file and recreating it as it really should be in this case. I've added code to fix that in this code and will edit the other answer to add to that code. To account for the bug, I've added & return & return & "If yes, the file will be placed in the Trash."
to the "Do you want to overwrite the file?"
display dialog
command in the primary tell application "Finder"
block. Also added the following code within the else
clause of the if the button returned of result is "No" then
statement to handle the bug.
tell application "Finder"
delete the file theCustomRichTextFilePathname
end tell
This too is within the primary tell application "Finder"
block.
With the aforementioned changes, here is the new code:
-- # The variables for the target file's fully qualified pathname and custom filename needs to be global as they are called from both the handlers and other code.
global theCustomRichTextFilePathname
global customFilename
-- # The createCustomRTFDocument handler contains a custom template for the target RTF document.
on createCustomRTFDocument()
tell current application
set customRTFDocumentTemplate to «data RTF 7B5C727466315C616E73695C616E7369637067313235325C636F636F61727466313530345C636F636F617375627274663736300A7B5C666F6E7474626C5C66305C6673776973735C6663686172736574302048656C7665746963613B7D0A7B5C636F6C6F7274626C3B5C7265643235355C677265656E3235355C626C75653235353B7D0A7B5C2A5C657870616E646564636F6C6F7274626C3B3B7D0A5C706172645C74783732305C7478313434305C7478323136305C7478323838305C7478333630305C7478343332305C7478353034305C7478353736305C7478363438305C7478373230305C7478373932305C7478383634305C7061726469726E61747572616C5C7061727469676874656E666163746F72300A0A5C66305C66733336205C636630205C0A7D»
try
set referenceNumber to open for access theCustomRichTextFilePathname with write permission
write customRTFDocumentTemplate to referenceNumber
close access referenceNumber
my addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument()
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
-- # The addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument handler attemps to get plain text from the clipboard
-- # and if there is some, it's added to the end of the newely created RTF document created by the customRTFDocumentTemplate
-- # handler so as to maintain a valid RTF Docuemnt. The addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument handler
-- # is called from the createCustomRTFDocument handler after it has created the new RTF document from the Template.
on addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument()
tell current application
set plainTextFromClipboard to (get the clipboard as «class utf8»)
if plainTextFromClipboard is not equal to "" then
set plainTextFromClipboard to return & plainTextFromClipboard & return & "\\
}" as «class utf8»
try
tell application "Finder"
set eofMinusOne to (size of file theCustomRichTextFilePathname) - 1
end tell
set referenceNumber to open for access theCustomRichTextFilePathname with write permission
write plainTextFromClipboard to referenceNumber starting at eofMinusOne
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 if
end tell
end addPlainTextFromClipboardToEndOfNewelyCreatedRTFDocument
-- # The openDocument handler opens and set the bounds of the theCustomRichTextFilePathname document while placing the cursor on the second line.
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 using command down
else
tell application "TextEdit"
set bounds of window customFilename to {160, 22, 883, 639}
end tell
key code 125 using command down
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
-- # Get the name for the RTF document, ensuring it is not blank.
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
-- # Concatenate the default location (the User's Desktop) with the chosen filename while adding the proper file extension.
set theCustomRichTextFilePathname to ((path to desktop) & customFilename & ".rtf") as string
-- # Check to see if the target file already exists. If it does not exist, create and open it. If it does exist, either open it or overwrite it and open it, based on decision made.
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?" & return & return & "If yes, the file will be placed in the Trash." 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.
tell application "Finder"
delete the file theCustomRichTextFilePathname
end tell
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