Applescript to Excel Help

Here’s the complete code.

--Added to library on 01/19/2023
--This script takes my CD purchase data from the script and writes to excel
--https://www.macscripter.net/t/applescript-to-excel-help/74054/20

--Change file name as needed
set CDDoc to (path to desktop as text) & "Excel CD Input.xlsx"
set resultList to {}

tell application "Microsoft Excel"
	-- opens the file CDDoc
	open file CDDoc
	-- activate
	tell active sheet
		
		--this sets up column headings, so ensure the range A1:E1 and the number of headrange values are in alignment.
		--If you need more col headings expand range as needed and be sure to add to values inside{}
		
		set headRange to range "A1:E1"
		if value of cell "A1" is not "Date" then
			set value of headRange to {"Date", "Cost", "Title", "Band", "Location"}
			set bold of font object of headRange to true
			
		end if
		set curr to current region of cell "A1"
		set {maxRows, maxColumns} to {count rows, count columns} of curr
	end tell
end tell

-- enter either string e.g. "1/14/23" … 
-- or integer, with negative optional e.g. 5, -4
-- Will return date string as entered or modified by days entered
set enterWalkDate to (display dialog "Enter date" default answer dateHand(get current date) giving up after 10)
set testDate to the text returned of enterWalkDate

if testDate contains "/" then -- is it already a date string
	set walkDate to testDate
	--> "1/17/23"	
else
	set newDate to (get current date) + ((testDate as integer) * days)
	set walkDate to dateHand(newDate)
end if

--Change vales to your drop down list here...{}
if button returned of enterWalkDate is "OK" then
	set CDList to item 1 of (choose from list {"Loc A", "Loc B", "Loc C"} with title "Choose Location" default items "Loc A")
	
	-- enter data like the "^"
	set enterDataString to display dialog "Cost, Band, Album" default answer "4.99 ^The Who ^Who's Next"
	-- or 
	--set enterDataString to display dialog "Cost, Band, Album" default answer "4.99 ^The Who ^Live at Leeds"
	
	set AppleScript's text item delimiters to {" ^"}
	set dataWords to text items of text returned of enterDataString
	--> {"4.99", "The Who", "Who's Next"}
	--> {"4.99", "The Who", "Live at Leeds"}
	set AppleScript's text item delimiters to "" --had to add this bit to make it work
end if

set maxRows to maxRows + 1

set colDate to "A:A"
set colRange to "B:D" -- cost title band loc
set collocation to "E:E"
set rowRow to maxRows & ":" & maxRows as text

tell application "Microsoft Excel"
	set value of (intersect range1 colDate range2 rowRow) to walkDate
	set value of (intersect range1 colRange range2 rowRow) to dataWords
	set value of (intersect range1 collocation range2 rowRow) to CDList
end tell


on dateHand(cd)
	set {yr, m, dd} to {(year of cd) - 2000, month of cd as integer, day of cd}
	set AppleScript's text item delimiters to "/"
	set insertDate to {m, dd, yr} as text -- e.g. "1/18/23"
	set AppleScript's text item delimiters to ""
	
	return insertDate as text
	
end dateHand
-- handler accepts date object, e.g. date "Wednesday, January 18, 2023 at 20:55"
-- converts to string with format "1/14/23"
-- NB date format is m/d/yy

--saves workbook
tell application "Microsoft Excel"
	save workbook
end tell
    ```

So I added another handler to this. I found a simple sort I copied from this site a while ago and inserted it into the script. My question is is there a way to make this run more efficient? Here’s the enhanced code with the simple sort.

--Added to library on 01/22/2023
--This script takes my CD purchase data from the script and writes to excel
--https://www.macscripter.net/t/applescript-to-excel-help/74054/20
--Added simple sort routine on 1/22/23

--Change file name as needed
set CDDoc to (path to desktop as text) & "Excel CD Input.xlsx"
set resultList to {}

tell application "Microsoft Excel"
	-- opens the file CDDoc
	open file CDDoc
	-- activate
	tell active sheet
		
		--this sets up column headings, so ensure the range A1:E1 and the number of headrange values are in alignment.
		--If you need more col headings expand range as needed and be sure to add to values inside{}
		
		set headRange to range "A1:E1"
		if value of cell "A1" is not "Date" then
			set value of headRange to {"Date", "Cost", "Title", "Band", "Location"}
			set bold of font object of headRange to true
			
		end if
		set curr to current region of cell "A1"
		set {maxRows, maxColumns} to {count rows, count columns} of curr
	end tell
end tell

-- enter either string e.g. "1/14/23" … 
-- or integer, with negative optional e.g. 5, -4
-- Will return date string as entered or modified by days entered
--((display dialog "Enter date in this format MM DD, yyyy hh:mm:ss AM or PM" default answer "9 17 2022 11:00:00 AM" buttons {"Continue"} default button "Continue")'s text returned)
set enterWalkDate to (display dialog "Enter date" default answer dateHand(get current date) giving up after 40)
set testDate to the text returned of enterWalkDate

if testDate contains "/" then -- is it already a date string
	set walkDate to testDate
	--> "1/17/23"	
else
	set newDate to (get current date) + ((testDate as integer) * days)
	set walkDate to dateHand(newDate)
end if

--Change vales to your drop down list here...{}
set CDList to {"Wildysworld", "Sdpickering", "Macromano", "Mojobundy", "Pop.market", "Sibylline Records", "Generation Records", "Gratitude_records", "Gruffsvinyl", "Recordnumber", "Framoka", "Redscroll", "Scratcherman", "Happymusiclover", "Endofanear", "Altcd", "Groovesland", "Left Around Records", "Disc Replay Crest Hill", "Disc Replay Naperville", "Disc Replay Orland", "Disc Replay LaGrange", "Half-Price Books Naperville", "Half-Price Books Downers Grove", "Half-Price Books Orland", "Half-Price Books LaGrange"}

set CDList to simple_sort(CDList)

set locationChoice to (choose from list CDList) -- Returns a list — or 'false' if the "Cancel" button's clicked.
if (locationChoice is false) then error number -128 -- Explicit "Cancel" error.
set CDList to item 1 of locationChoice -- Otherwise get the single item of text from the list.

-- Handler(s).

on simple_sort(my_list)
	set the index_list to {}
	set the sorted_list to {}
	repeat (the number of items in my_list) times
		set the low_item to ""
		repeat with i from 1 to (number of items in my_list)
			if i is not in the index_list then
				set this_item to item i of my_list as text
				if the low_item is "" then
					set the low_item to this_item
					set the low_item_index to i
				else if this_item comes before the low_item then
					set the low_item to this_item
					set the low_item_index to i
				end if
			end if
		end repeat
		set the end of sorted_list to the low_item
		set the end of the index_list to the low_item_index
	end repeat
	return the sorted_list
end simple_sort

if button returned of enterWalkDate is "OK" then
	
	-- enter data like the "^"
	set enterDataString to display dialog "Please Enter Cost, Band, Album Name Using ^ before Band & Album" default answer "4.99 ^The Who ^Who's Next"
	-- or 
	--set enterDataString to display dialog "Cost, Band, Album" default answer "4.99 ^The Who ^Live at Leeds"
	
	set AppleScript's text item delimiters to {" ^"}
	set dataWords to text items of text returned of enterDataString
	--> {"4.99", "The Who", "Who's Next"}
	--> {"4.99", "The Who", "Live at Leeds"}
	set AppleScript's text item delimiters to "" --had to add this bit to make it work
end if

set maxRows to maxRows + 1

set colDate to "A:A"
set colRange to "B:D" -- cost title band loc
set collocation to "E:E"
set rowRow to maxRows & ":" & maxRows as text

tell application "Microsoft Excel"
	set value of (intersect range1 colDate range2 rowRow) to walkDate
	set value of (intersect range1 colRange range2 rowRow) to dataWords
	set value of (intersect range1 collocation range2 rowRow) to CDList
end tell


on dateHand(cd)
	set {yr, m, dd} to {(year of cd) - 2000, month of cd as integer, day of cd}
	set AppleScript's text item delimiters to "/"
	set insertDate to {m, dd, yr} as text -- e.g. "1/18/23"
	set AppleScript's text item delimiters to ""
	
	return insertDate as text
	
end dateHand
-- handler accepts date object, e.g. date "Wednesday, January 18, 2023 at 20:55"
-- converts to string with format "1/14/23"
-- NB date format is m/d/yy

--saves workbook
tell application "Microsoft Excel"
	save workbook
end tell

I should have mentioned that sooner about resetting the delimiters. I’d included a reset in the date handler but didn’t think about it with the recent addition. Nice catch.

So the cause of the error is that as text inserts the delimiters between the various segments (i.e. where the ampersands are) which messes up the intersect command. When the delimiters are set to nothing, i.e. “”, then nothing gets inserted.

set rowRow to maxRows & ":" & maxRows as text

This is how the subsequent command resolves with <space>^ as the delimiters:

intersect range1 "A:A" range2 "4 ^: ^4"

This is how that command should resolve:

intersect range1 "A:A" range2 "4:4"

And just a reminder… you can set the delimiters to whatever you like, including a list of strings. I just randomly selected something that was unlikely to end up in a band or album name.

Looks good. One suggestion… if you plan on using ‘Loc A’ literally, then I would suggest reversing the order to ‘A Loc’, ‘B Loc’, etc…. This would allow you to select the items by typing a single letter.

Not sure whether these were included in your reading material but here are some of apple’s notes on delimiters.

These are from the Applescript Language Guide: first, the section on Text Item Delimiters under Fundamentals, and second, the section on the Text class under Class Reference. There are more references to delimiters within the site but I think that these are the two most useful. You might find others in the index.

And this is the Manipulating Text section from the Mac Automation Scripting Guide. It contains several examples for using delimiters.

Addendum:

Sorry, I replied to the message above the last one so I didn’t see your question on the sort. It looks fine. The list is short enough that performance shouldn’t be an issue. There are some posts on the site that look at sorting routines though should your list ever get really large. The one suggestion I’d make would be to sort the list and then edit the script so that your initialization of CDList was properly ordered. I think that would result in less work for the script when you run it.

Alright, thanks for the guidance. I have a lot to learn but this was a fun one to get working. Appreciate your comments.

1 Like