AppleScript for Numbers would write to cells but not read

So basically I trying write an automated script to run some functions for me


here is what I need it to do


To iterate through all rows in the first table of the active sheet and check if the text in column F contains “win” or “loss”. If it does, it will replace the corresponding value in column G with 1 or -1.1, respectively. If it doesn’t contain either, it will replace the value in column G with 0. It will then iterate through each unique name in column A and sum up the corresponding values in column G. The total value for each individual will be placed in column H. Finally, it will multiply the total for each individual in column H by 100 and place it in column I.


Can anyone show me why I getting errors, I have included screenshot of the error as well as the model I am trying to replicate using apple scripts. I have no results.


Thanks for attention to this...


So far I wrote:


tell application "Numbers"


tell the active sheet of the front document


set lastRow to the count of rows of table 1


repeat with i from 2 to lastRow


set cellValue to value of cell ("F" & i)


if cellValue contains "Win" then


set value of cell ("G" & i) to 1


else if cellValue contains "Loss" then


set value of cell ("G" & i) to -1.1


else


set value of cell ("G" & i) to 0


end if


end repeat



set nameList to {}


repeat with i from 2 to lastRow


set nameValue to value of cell ("A" & i)


if nameValue is not in nameList then


set end of nameList to nameValue


end if


end repeat



repeat with i from 1 to count of nameList


set totalValue to 0


repeat with j from 2 to lastRow


set nameValue to value of cell ("A" & j)


if nameValue is equal to item i of nameList then


set totalValue to totalValue + (value of cell ("G" & j))


end if


end repeat



set value of cell ("H" & (i + 1)) to totalValue



set value of cell ("I" & (i + 1)) to totalValue * 100



end repeat



end tell


end tell


Finally, when I run the above script, I get an error


MacBook Air, macOS 14.0

Posted on Oct 9, 2023 2:31 PM

Reply
Question marked as Top-ranking reply

Posted on Oct 9, 2023 4:11 PM

I think the beginning simply needs to be written like this. You can't get the cell of a sheet, it belongs to a table.


tell application "Numbers"

tell table 1 of active sheet of the front document

set lastRow to the count of rows

25 replies

Oct 21, 2023 6:22 AM in response to Recycleur

Now that it works; I like to modify this script to read range from sheet 1 table 1 and write the range to sheet 2 table 1 of the same document work book in numbers

How can I go about this without getting it confused about table 1


here is the script


set tblName to "Table 1"


set srceRng to "H2:H16"


set destRng to "A2:A16"




tell application "Numbers"


tell document 1 to tell active sheet


tell table tblName


set destCol to range destRng's column 1's address


repeat with c in range srceRng's cells


set v to c's value


set r to c's row's address


set row r's cell destCol's value to v


end repeat


end tell


end tell


end tell




Oct 21, 2023 7:55 AM in response to Stvylife

You can set variables that define objects:

set srceTable to a reference to table "Table 1" of sheet "Sheet 1"

set destTable to a reference to table "Table 1" of sheet "Sheet 2"


Since you work in the same document all the time enclose everything in

tell application "Numbers"

tell document 1

...

...

end tell

end tell



In the end the complete script is:


set srceSheetName to "Sheet 1"

set destSheetName to "Sheet 2"

set srceTblName to "Table 1"

set destTblName to "Table 1"

set srceRng to "H2:H16"

set destRng to "A2:A16"


tell application "Numbers"


tell document 1


set srceTable to a reference to table srceTblName of sheet srceSheetName

set destTable to a reference to table destTblName of sheet destSheetName

set destCol to a reference to destTable's range destRng's column 1


repeat with c in srceTable's range srceRng's cells

set v to c's value

set r to c's row's address

set destCol's cell r's value to v

end repeat


end tell

end tell



It doesn't change anything to the operations but for better comprehension of your spreadsheets (in general) you should give meaningful names to your sheets and tables. Instead of "Table 1" a table could have the name "Input data", a sheet could have the name "2023", etc. When you look at inter-table formulas you have a better grasp of where data comes from.

Oct 21, 2023 8:56 AM in response to Stvylife

Actually, as written the script is bound to have the source and destination ranges on the same rows. What if you want to copy from H2:H16 to A4:A18? This updated version makes the script more adaptable as the two ranges can be arbitrarily defined, even one vertically (H2:H9) and the other horizontally (A2:H2), or even linear to square (H2:H9 to A2:B5). The only limit (without error catching) is that the destination range must contain at least as many cells than the source range.


set srceSheetName to "Sheet 1"

set destSheetName to "Sheet 2"

set srceTblName to "Table 1"

set destTblName to "Table 1"

set srceRng to "H2:H16"

set destRng to "A4:A18" -- shape and location is not bound by srceRng's shape and location


tell application "Numbers"


tell document 1


set srceTable to a reference to table srceTblName of sheet srceSheetName

set destTable to a reference to table destTblName of sheet destSheetName

set srceRange to a reference to srceTable's range srceRng

set destRange to a reference to destTable's range destRng


repeat with c from 1 to the count of cells of srceRange

set destRange's cell c's value to srceRange's cell c's value

end repeat


end tell

end tell

Oct 21, 2023 11:13 AM in response to Stvylife

I saw your other questions in the other post Looking for a good sample of an apple scr… - Apple Community. This answers them as well.




set srceSheetName to "Sheet 1"

set destSheetName to "Sheet 2"

set srceTblName to "Table 1"

set destTblName to "Table 1"

set srceRng to "H2:H16"

set destRng to "A2:A16"


tell application "Numbers"


tell document 1


set srceTable to table srceTblName of sheet srceSheetName

set srceRange to srceTable's range srceRng


if exists sheet destSheetName then

set destSheet to sheet destSheetName

else

set destSheet to (make new sheet with properties {name:destSheetName})

tell destSheet to delete table 1

end if


tell destSheet

if exists table destTblName then

set destTable to table destTblName

set locked of destTable to false

else

set destTable to (make new table with properties {name:destTblName})

end if

end tell


tell destTable

set row count to srceTable's row count

set column count to srceTable's column count

set header row count to srceTable's header row count

set header column count to srceTable's header column count

set footer row count to srceTable's footer row count

end tell


set destRange to destTable's range destRng


set dc to 0


repeat with c from 1 to the count of cells of srceRange

set v to srceRange's cell c's value

if v is not missing value then

set dc to dc + 1

set destRange's cell dc's value to v

end if

end repeat


end tell


end tell


Oct 21, 2023 11:42 AM in response to Recycleur

Makes a ton of sense, thanks for the speedy response and most of all for taking the time to explain the concept about the operations; I feel like I am walking away with more than I bargained for. Wow, so set the variable just like that, and it knows, it looks simple after all. I need to not over think it, and yes it will definitely help in naming the table with a purpose, which will contribute to a streamline process. Yup that problem started there in the naming, like explaining something using the same word, I see. Thanks again for the rescue again.

Oct 21, 2023 1:20 PM in response to Stvylife

Explanations about the last script I posted at 2:13 PM.


I had to consider these conditions:

1a) sheet destSheetName exists -> OK

1b) sheet destSheetName doesn't exist -> create a sheet with that name automatically including a default table named "Table 1"; delete that table.

2a) sheet destSheetName already has a table named destTblName -> OK

2b) sheet destSheetName doesn't have a table named destTblName -> create a table with that name.

3) resize table destTblName according to table srceTblName. To be more elaborate I could have avoided to resize a pre-existing table destTblName, but oh well...


All this to make sure at first that I get a sheet named destSheetName with a table named destTblName.


Sure, instead of deleting table "Table 1" after creating destSheetName I could have kept it and just changed its dimensions, but this a two-step process. There could have been a table "Table 1" on an existing destSheetName and I didn't want to mess with it. Remember that sheets and tables can have any name and nothing is to be assumed about existing conditions when making foolproof programs.


Finally, to prevent program crashes if destRange contains less cells than srceRange I would enclose the value setting in try like this:

try

set destRange's cell dc's value to v

end try




Oct 22, 2023 5:56 PM in response to Recycleur

relaxing and playing all version of the script... hope you're having a nice weekend at least what's left.

I've got another question but didn't know where to post it, but it applies to everything we've done so far. So I've noticed that works well, until I try to copy a date. It appears to reformat the date and adds time to it. Can you explain why this happens, and how to mitigate that; as I may want to copy dates too in the future. I thought it would copy just the string. Normally I use the paste results function when I do dates manually, that or a match format. I like it to remain in the automatic format though.

Anyway, what are my options...


Back to the first simple script

set tblName to "Table 1"
set srceRng to "H2:H16"
set destRng to "A2:A16"
tell application "Numbers"
	tell document 1 to tell active sheet
		tell table tblName
			set destCol to range destRng's column 1's address
			repeat with c in range srceRng's cells
				set v to c's value
				set r to c's row's address
				set row r's cell destCol's value to v
			end repeat
		end tell
	end tell
end tell

Oct 22, 2023 7:27 PM in response to Stvylife

Applescript receives dates from Numbers relative to GMT, which means that the result is different whether your current time is in standard or daylight saving period, and whether the dates you're reading are in standard or daylight saving period.


Whenever I have a script that deals with dates obtained from a Numbers spreadsheet I use the following to standardize everything.


use scripting additions -- essential to use (current date) with framework "Foundation"
use framework "Foundation"

global sysZone

on run
	set sysZone to current application's NSTimeZone's systemTimeZone()

	-- rest of the script
	
	tell application "Numbers"

        -- Example of use of the handler
        tell table 1 of sheet 1 of document 1
			
			set aDate to value of cell "D4"
            -- D4 only shows a date (with hidden time 00:00 unless entered explicitely)
			set aTime to value of cell "E4"
            -- E4 only shows a time (with hidden date of when cell entry was made)

            -- combining both informations
			set goodDate to my correctedDate(aDate)
			set time of goodDate to time of my correctedDate(aTime)

         end tell 

	end tell

end run


to correctedDate(_date)
	if class of _date is date then
		return _date + sysZone's secondsFromGMT() - (sysZone's secondsFromGMTForDate:_date)
	else
		return _date
	end if
end correctedDate



Oct 23, 2023 7:15 AM in response to Stvylife

I missed an item from your previous post, where you said "I thought it would copy just the string" (of the date).


That's fine if your only intent is to copy a date value from one cell to the other without using it for calculations in the script, in that case you don't need to apply any correction (reading and writing will cancel each other's offset). But if you use the date for any kind of calculation or to output it to a text file or a Calendar event the correction is necessary.


You can read either a cell's formatted value (as it is shown) or its value (as it is stored), for every kind of cell content actually. Using formatted value with dates might be dangerous because while the underlying value is always the same how it's presented changes with the format applied to it in the cell and AppleScript may misinterpret some formats. For example if the format omits the year then the year of the formatted value will be set to the current year and not the year of the date in the cell. Or if the format inverts month and day the result will be wrong. Just be aware of these possibilities.


I also modified my handler following these tests. I had never before written date values back to a cell (only to text files as text) so I had missed a point: a reverse correction is needed. So here is a better version.


to correctedDate(_date, _fromNumbers)
	-- _fromNumbers must be 1 when reading from Numbers or -1 when writing to Numbers
	if class of _date is date then
		return _date + _fromNumbers * ((sysZone's secondsFromGMT()) - (sysZone's secondsFromGMTForDate:_date))
	else
		return _date
	end if
end correctedDate


And to use it for reading and writing:


set goodDate to my correctedDate(value of cell "D4", 1)
set value of cell "D5" to my correctedDate(aDate, -1)



Oct 24, 2023 7:24 PM in response to SGIII

Yes. But it's only necessary with dates exchanged with Numbers, because within Applescript itself you don't have to worry about that (unless you want to explicitly deal with different time zones or daylight saving settings for other purposes).


For example if in summer you put 2023-12-01 in a cell (which in reality is 2023-12-01 00:00) and you read it, the Applescript variable will be set to 2023-11-30 23:00. So there start problems with date comparisons, text output, etc. The date correction handler avoids all this.


But as I said in the other post, if your only intent is to copy a date value from one cell to the other without using it for other purposes in the script, you don't need to apply any correction because reading and writing will cancel each other's offset.


You use these two functions of framework "Foundation":

current application's NSTimeZone's systemTimeZone()'s secondsFromGMT() -- for this moment

current application's NSTimeZone's systemTimeZone()'s secondsFromGMTForDate:_date -- for a specified date


Oct 24, 2023 9:01 PM in response to Recycleur

Not sure I follow entirely, and I know this wasn't the original focus of this thread, but I know about time zone problems that can occur when using AppleScript to access date-times in Numbers because I go back and forth between time zones.


What is the difference between what you are doing using NSTimeZone, and correcting by adding or subtracting (time to GMT) in plain AppleScript?


(time to GMT) seems to be the current offset (when the script is run). I've had trouble correcting past date-times because of daylight savings time.


Lets' say you have a series of past date-times entered in Numbers when your machine was set to a different time zone (for example, when you were traveling). Some of those date-times were entered when daylight savings time was in effect, some after the switch back to standard time.


Now you find yourself in a different time zone and you want to "correct" the date-times. Does secondsFromGMTForDate: really know about the offset of local time to GMT/UTC at different dates in different locations, accounting for daylight savings time and all that?


SG

Oct 26, 2023 9:52 AM in response to SGIII

AppleScript's (time to GMT) is the same thing than current application's NSTimeZone's systemTimeZone()'s secondsFromGMT(). The new interesting player is secondsFromGMTForDate because it allows you to know what will be the effect of daylight-saving at a certain date.


From the Apple document referenced below:

The system class property returns the time zone currently used by the system, if known. This value is cached once the property is accessed and doesn't reflect any system time zone changes until you call the resetSystemTimeZone() method. The local class property returns an autoupdating proxy object that always returns the current time zone used by the system. You can also set the default class property to make your app run as if it were in a different time zone than the system.


I started getting interested in that because I built a sports schedule in Numbers with games running from September to April. At one point I noticed that all games between November and March were on the wrong day when output in a text file. I was reading the date in a cell (which by default had time 00:00) and was combining it with the time from another cell (which had the date from when I had typed it). So summer to summer was ok, winter to winter was ok, but reading a date from the other season was always producing the wrong result.


By using the date correction handler I was able to cancel all the introduced offsets, no matter at what date I was executing the script. Basically it subtracts the GMT offset at the specified date from the GMT offset today. Same season, result is 0. Different seasons, result is +1h or -1h (here anyway).


I got some inspiration from this MacScripter post and read this Apple documentation for more details. I also got help on AskDifferent about defaultTimeZone.


Start with this and have fun. If you have other questions don't hesitate to ask.


This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

AppleScript for Numbers would write to cells but not read

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.