Jimforxst

Q: Applescript for Compiling Numbers Documents

Hi!

 

I just finished completing my first "Real" Applescript to do something that I thought would be fairly simple.

It only took me 5 days to figure out!

 

Anyway, I regularly create new Numbers documents every time I make a money deposit to the campus bookkeeper

(I am a teacher/middle school band director and am constantly receiving payments from kids for t-shirts, band uniform fees, trip costs, etc.)

 

I have tried for years to find a way to compile all the deposit slips into one document to keep track of who has paid for what over the course of the school year and I have always just ended up having to manually copy and paste the data from each doc into the master list (Last year I had over a hundred different deposit slip files in a folder on my desktop).

 

Long story short, I discovered Automator and Applescript a few weeks ago and have been playing around with them. Who knew these tools had been on my mac the whole time!

 

If someone (much more skilled than I) could take a look at the code I came up with below to see if it is sound, of if there is a more efficient way of doing this, I would very much appreciate it!

 

The code works for now, but if there are any weaknesses or something that might break in a future update, I'd like to know about it.

 

CODE BELOW:

-------------------------------------------------

     -- This is my attempt at creating an AppleScript for copying data from multiple Numbers documents and compiling it into one database for use within a single master Numbers Document.

     -- The way this is setup now, every time a new data document is added to the source Folder, I have to double click an icon on the desktop which will run this script.


 

set sourceFolder to (POSIX file "/Users/my_name/Library/2016-2017 Financial Documents/TO BE ADDED/" as alias)

     -- source folder for documents to be added to master list

 


set targetFolder to (POSIX file "/Users/my_name/Library/2016-2017 Financial Documents/DONE/" as alias)

     -- place for documents to go after they are added to the master list.

 


set theFile to (choose file with prompt "Choose a Numbers Document to be copied to the Master List." as text default location sourceFolder)

     -- The script will prompt me to select a file out of the source folder to copy

 

 


tell application "Numbers"

activate

  set doc to open theFile

  tell table 1 of active sheet of doc

  set thisRangeName to "3:37"

       -- the range i want to copy

  set the selection range to range thisRangeName

       -- selects the range i want to copy

  end tell

end tell

tell application "System Events" to keystroke "c" using command down

     -- copies the selected range to the clipboard.

 

 

property docTarget : "/Users/my_name/Library/2016-2017 Band Documents/2016-2017 Student List.numbers"

     --Location of the Master File

 

property today : current date

     --variable to be used when entering information in the master file. This will aid in sorting objects added to the master file.

 


tell application "Numbers"

open docTarget

  tell table 1 of sheet "MONIES COLLECTED" of front document

  add row below last row

       --creates a new row to receive the new information.

  set the value of last row's first cell to (current date) as string

       --enters current date in first column of table

  set selection range to last row's second cell

       --moves the selected cell to the one that will recieve the data from the clipboard.

  tell application "System Events" to keystroke "v" using command down

       --pastes data from clipboard

  tell application "System Events" to keystroke "ESC"

       --clears the currently selected cells

  end tell

 


--we will now check for empty rows that were pasted from the source document to clean up our Master Document.

 

 

tell table 1 of sheet "MONIES COLLECTED" of front document

  set rowCount to (every row of selection range)

       --how many rows to check? Row Count is determined by the amount from the previous selection range.

  repeat with i from 3 to the count of rowCount

       --skips the first 2 rows, which are header rows, from the count

  set maybe to (value of fifth cell in last row)

       --checks the fifth column (reason for activity) value to see if it is empty.

  if maybe is missing value then set gone to last row

       --starting with the last row of the document, if the fifth column is empty, it is tagged for deletion.

  remove gone

       --remove the empty row

  end repeat

  set done to (value of fifth cell in last row)

       --when the repeated deletions are finished, if there is an additional empty row remaining, this will look for it.

  if done is missing value then remove last row

       --the if statement that will remove the last extra row

  end tell

 

end tell

quit application "Numbers"

     --closes all Numbers documents and quits the application

 

tell application "Finder"

move file theFile to folder targetFolder

      -- moves the Source File out of the "TO BE ADDED" Folder and into the "DONE" Folder.

end tell


--------------------------------------------------


Thanks for the help and advice to an Applescript Newbie!

- Jimforxst

MacBook Pro, OS X El Capitan (10.11.6)

Posted on Sep 4, 2016 5:52 PM

Close

Q: Applescript for Compiling Numbers Documents

  • All replies
  • Helpful answers

  • by Camelot,

    Camelot Camelot Sep 4, 2016 9:56 PM in response to Jimforxst
    Level 8 (47,233 points)
    Mac OS X
    Sep 4, 2016 9:56 PM in response to Jimforxst

    First and foremost, if the script works for you, then that's good enough

     

    Even experienced/veteran AppleScripters can spend an inordinate amount of time 'perfecting' scripts, so it's important to balance how much time it will take to get to a 'perfect' solution.

     

    If you're looking for pointers of what might work 'better', here are a couple of thoughts.

     

    First, your script relies on literally copying and pasting the data from the source file to the master file. I'm never a fan of this approach. While it (clearly) does work, it is prone to errors, and changes the system's state - you don't know if what was on the clipboard when the script started was wanted, and the operator (if it weren't you) might not expect that running the script would change the clipboard contents. In general I think it's better to reference the data directly ('set data2Copy to (get rows 1 through 37 of table 1...)'), although this works for now.

     

    Also, your script is somewhat dependent on the specifics of the source and master files. There's no error checking to make sure the source data is valid before copying it.

    On a similar subject you have a significant amount of code to check if column 5 is blank. I'd consider doing this check up front - in other words only copy the data that's needed, rather than copy more and have to clean up afterwards. Again, the specifics of this depend somewhat on the data.

     

    Lastly, for now, the script runs on a single file at a time - opens the source file, opens the master file, copies the data, closes the files and quits Numbers.

    What if there were multiple source files to process? You might consider looping through the files, copying the data and just closing/quitting at the end. That would save some time.

  • by Jimforxst,

    Jimforxst Jimforxst Sep 5, 2016 8:32 AM in response to Camelot
    Level 1 (8 points)
    Mac OS X
    Sep 5, 2016 8:32 AM in response to Camelot

    Camelot,

     

    Thanks for the tips!

    I don't know much about coding, even with something fairly simple like applescript, so your advice is appreciated.

    I've mostly just been using trial and error (with a little bit of reading sites like this one and watching youtube videos) to figure out what I need to do.

     

    On the idea of referencing the data directly instead of using the clipboard, what command would I give to add the "data2Copy" to the master file? I have tried the following Code (listed down below) but it only causes an error (which causes Script Editor to lock up completely):

     

              Error: Numbers got an error: Can’t make {HERE IT LISTS EVERY ROW of Table 1 of Sheet of Document ID ""} into type number, date, text, boolean or missing value.

     

    Code I tried:

    --------------------------------------

     

    tell application "Numbers"

    activate

      set doc to open theFile

      set data2Copy to (get rows 3 through 37 of table 1 of active sheet of doc)

    end tell

     


    property docTarget : "/Users/my_name/Library/2016-2017 Band Documents/2016-2017 Student List.numbers"

         --Location of the Master File

     

    property today : current date

         --variable to be used when entering information in the master file. This will aid in sorting objects added to the master file.


     

    tell application "Numbers"

    open docTarget

      tell table 1 of sheet "MONIES COLLECTED" of front document

      add row below last row

           --creates a new row to receive the new information.

      set the value of last row's first cell to (current date) as string

           --enters current date in first column of table

      set the value of last row's second cell to data2Copy

           --NOT SURE WHAT IS HAPPENING HERE. THIS CODE DOESN'T WORK YET.

     

      end tell


     

    --------------------------------------


    Thanks!

    -Jimforxst

  • by Jimforxst,

    Jimforxst Jimforxst Sep 5, 2016 6:31 PM in response to Jimforxst
    Level 1 (8 points)
    Mac OS X
    Sep 5, 2016 6:31 PM in response to Jimforxst

    Also, to eliminate the need to delete rows after copying, I have tried the following:

     

    tell application "Numbers"

    activate

      set doc to open theFile

     

      tell table 1 of active sheet of doc

     

      set rowCount to (every row of table 1 of active sheet of doc)

      --how many rows to check? all of the ones in the table.

     

      --[  set newRowCount to (rows with data in the fourth column)  ]

     

      repeat with i from 3 to the count of rowCount

      if (value of fourth cell of row i is missing value) then {}  --remove that row from the rowCount????  

      --if the fourth cell of the row is empty, it must be ignored from the selection that will become data2Copy - HOW TO DO THIS????

      end repeat

      set data2Copy to (get newRowCount)

     

      end tell

    end tell

  • by Camelot,

    Camelot Camelot Sep 6, 2016 10:28 AM in response to Jimforxst
    Level 8 (47,233 points)
    Mac OS X
    Sep 6, 2016 10:28 AM in response to Jimforxst

    On the idea of referencing the data directly instead of using the clipboard, what command would I give to add the "data2Copy" to the master file?

     

    My apologies. I admit I spoke without actually trying it myself since it seems like such a simple/obvious thing to do. However, upon investigation, there doesn't seem to be any clear direct way to copy ranges of data from one sheet to another. This seems like a huge omission to me.

    The only way I can see to get it to work is to copy cell-by-cell, which is probably unwieldy and overkill for your purposes, so copy/paste may be the way to go here.

    Hopefully someone on the Numbers team are listening and can fix this.

     

    As for the validation of data before copying, the specifics of that depend somewhat on your source data. How many rows are you copying in a typical run? 1 row? many rows?

    Ultimately you'll need to iterate through the rows since Numbers doesn't seem to support 'whose' filtering.