I just created part 1 of a script, which is to transfer Data from application Notes into a FileMaker Pro database.
The script runs without any error, but the variables which should contain the data to transfer are left empty as shown with the inserted dialogs.
tell application "Notes"
activate
set DocNum to (the count of notes of folder "Notes" of account "iCloud")
set folderList to (get the (id of every note of folder "Notes" of account "iCloud") as list)
repeat with i from 1 to DocNum
set selectedNote to item i of folderList
display dialog (selectedNote) --the id is correctly shown in the dialog
set Datum to (the creation date of note of folder "Notes" of account "iCloud" whose id = selectedNote)
display dialog (Datum as string)
set Headline to (the name of note of folder "Notes" of account "iCloud" whose id = selectedNote)
display dialog (Headline as string)
set Bodytext to (the body of note of folder "Notes" of account "iCloud" whose id = selectedNote)
end repeat
end tell
I can’t see any mistake with this script, since ist runs without any error message. Do I have to use more brackets?
note of folder “Notes” of account “iCloud” whose id = selectedNote
returns an empty list while first note of folder “Notes” of account “iCloud” whose id = selectedNote
return a note descriptor.
You may use the code :
tell application "Notes"
activate
set DocNum to (the count of notes of folder "Notes" of account "iCloud")
set folderList to (get the (id of every note of folder "Notes" of account "iCloud") as list)
repeat with i from 1 to DocNum
set selectedNote to item i of folderList
display dialog (selectedNote) --the id is correctly shown in the dialog
set Datum to (the creation date of first note of folder "Notes" of account "iCloud" whose id = selectedNote)
display dialog (Datum as string)
set Headline to (the name of first note of folder "Notes" of account "iCloud" whose id = selectedNote)
display dialog (Headline as string)
set Bodytext to (the body of first note of folder "Notes" of account "iCloud" whose id = selectedNote)
end repeat
end tell
but my own choice would be :
tell application "Notes"
activate
set folderList to (get the (id of every note of folder "Notes" of account "iCloud")) # no need to coerce as list, it's already a list
repeat with selectedNote in folderList # no need to use an index in the loop
display dialog (selectedNote) --the id is correctly shown in the dialog
tell (first note of folder "Notes" of account "iCloud" whose id = selectedNote) # get access to the note only once
set Datum to its creation date
display dialog (Datum as string)
set Headline to its name
display dialog (Headline as string)
set Bodytext to its body
display dialog Bodytext
end tell
end repeat
end tell
I had a little doubt upon my change to the instruction setting folderList, so I deleted my existing notes minus one and the result was a list. I deleted the last note and the result was a list too.
it is a pity, that AppleScript syntax of most applications (particularly those of Apples own) is so poorly documented, that even advanced AS programmers hardly will find the correct syntax at once. I experienced that with nearly 90% of the applications it needs a lot of “try and error” to succeed at end. The AppleScript functions lists are not very helpful in this case, since there a no samples for complete instructions. There are only few exceptions, like with FileMaker Pro, where you can get a perfect documentation with al lot of instruction samples or with RagTime, which is completely recordable, so you can look at the results to get the right feeling for the syntax. “ I wonder why Apples applications are not recordable :-((
Since your hint was somewhat late and I had to proceed, totally dispaired, I tried the following and, great miracle, it works:
tell application "Notes"
activate
set DocNum to (the count of every note of folder "Notes" of account "iCloud")
set dateList to (get the (creation date of every note of folder "Notes" of account "iCloud") as list)
set nameList to (get the (name of every note of folder "Notes" of account "iCloud") as list)
set textList to (get the (body ofevery note of folder "Notes" of account "iCloud") as list)
repeat with i from 1 to DocNum
set Datum to ((item i of dateList) as string)
set Headline to ((item i of nameList) as string)
set Inhalt to ((item i of textList) as string)
my transfer(Datum, Headline, Inhalt)
end repeat
end tell
on transfer(Datum, Headline, Inhalt)
tell application "FileMaker Pro Advanced"
create new record at end
go to last record
set cell "Datum" of current record to Datum
set cell "Headline" of current record to Headline
set cell "Bodytext" of current record to Inhalt
end tell
end transfer
I run this under MacOS El Capitan and it was rather fast. I was afraid, that this possibly won’t run, since there were about 650 notes, most of them rather large (more than 2000 characters), what, I thought, could be to much for the variable “textList” - but no problem
As I practice AppleScript for many years, I don’t remember where I learnt that specifying first was required.
As I am lazy I would edit your code as :
tell application "Notes"
activate
set {dateList, namelist, textlist} to ({creation date, name, body} of every note of folder "Notes" of account "iCloud") --as list # no need to coerce as list because it IS agroup of 3 lists
set DocNum to count dateList
repeat with i from 1 to DocNum
set Datum to ((item i of dateList) as string)
set Headline to ((item i of namelist) as string)
set Inhalt to ((item i of textlist) as string)
my transfer(Datum, Headline, Inhalt)
end repeat
end tell
on transfer(Datum, Headline, Inhalt)
tell application "FileMaker Pro Advanced"
create new record at end
go to last record
tell current record # I don't own FileMaker so I can't test this syntax
set cell "Datum" to Datum
set cell "Headline" to Headline
set cell "Bodytext" to Inhalt
end tell
end tell
end transfer
About the FileMaker code, maybe it may reduced to
tell application "FileMaker Pro Advanced"
create new record at end
tell last record
set cell "Datum" to Datum
set cell "Headline" to Headline
set cell "Bodytext" to Inhalt
end tell
end tell
Keep in mind that higher level programming languages will increase efficiency but hardly decrease difficulty. It’s the inevitable failure of higher programming languages because they were designed to make programming easier while they only increase efficiency as they grow. The trivial aspects of programming can only be automated in higher level programming languages but the essence and complex parts of programming remains for the programmer.
But you example shows an different problem which is described in the ASLG:
note of folder "Notes" of account "iCloud" whose id = selectedNote
This is an object specifier with a whose clause. That means an filter will be applied to an range of objects. note doesn’t indicate object but a class while it’s plural form notes is shorthand for the range every note. I’m even surprised that FileMaker doesn’t throw an error on that line but simply returns an empty list (which is wrong if you ask me). This is something that is well described in ASGL. Here another example look at the last line that will throw an error, it doesn’t indicate a range:
tell application "System Events"
name of processes whose frontmost = true -- Result: {"AppleScript Editor"}
name of every process whose frontmost = true -- Result: {"AppleScript Editor"}
name of first process whose frontmost = true -- Result: "AppleScript Editor"
name of last process whose frontmost = true -- Result: "AppleScript Editor"
name of process 1 whose frontmost = true -- Result: "AppleScript Editor"
name of processes 1 thru 1 whose frontmost = true -- Result: {"AppleScript Editor"}
name of some process whose frontmost = true -- Result: "AppleScript Editor"
name of middle process whose frontmost = true -- Result: "AppleScript Editor"
name of process whose frontmost = true -- Result: error
end tell
It was about a preceding message in which I wrote :
note of folder “Notes” of account “iCloud” whose id = selectedNote
returns an empty list while first note of folder “Notes” of account “iCloud” whose id = selectedNote
return a note descriptor.
I think Yvan means that when referring to an element (a ‘note’ is an element in Notes), the correct syntax is to specify which element is meant, even if only one is expected to be at the given location in the situation being scripted. The OP’s script in post #1 omits to do this in some lines:
-- OP:
set Datum to (the creation date of note of folder "Notes" of account "iCloud" whose id = selectedNote)
-- Yvan's correction in post #2:
set Datum to (the creation date of first note of folder "Notes" of account "iCloud" whose id = selectedNote)
It’s customary to use ‘first’ in such cases, although ‘last’, ‘middle’, and ‘some’ usually work as well (if possibly not as efficiently).
However, since the notes are identified here by their ‘id’ property, it may be possible to use an ID reference rather than a filter reference (although I’m not in a position to test it myself):
set Datum to (the creation date of note id selectedNote of folder "Notes" of account "iCloud")
If the whose clause will return a single element in a list you still need to specify the element from that list. Code like item of {true} will throw an error as well. So to get the only item from the list you can use first, last, middle, some or n (where n = 1 or -1) as in my example code in the previous post. You don’t need to use first per se, any range mentioned is fine.
Many thanks to each of you for responding to my question, and making this very clear.
I learned a lot from this, and I know that others who read it in the future will as well.
Could a moderator take these three posts, and put them in a thread pinned to the top so it would be easy for others to find?
I have clipped it to my Evernote account for future reference.