How to Get the Selected Range in Numbers.app with AppleScript

Hi all,
first post...I'm sure I'm not posting in right place AND Im hoping someone will direct me

BUT; OK
I am trying to develop a script and I intend to use 'selected range' from number spreadsheet.

However, once the selected range is passed to the script, I want to do a few things with it.
First I'd like to show it is display alert
maybe something like: (BTW # placed to prevent system from trying to evaluate the script)
range is acquired by:

try
	tell application "Numbers" to tell front document to tell active sheet
		tell (first table whose selection range's class is range)
			set sr to selection range

Then later

display alert "selected range is ' &s& 

BUT when I try to run it, nothing shows up in the popup in fact the popup doesnt popup

I'd also like to tear it into its pieces and make changes to it. So for example if selected range turns out to be k5:l9, then maybe I'd like to 'reduce/increase by some number of columns or rows such as -1 so that the final range is actually j5:k9

I have been able to successfully "force" range to some value such as
set sr to range "k5:l9"
and when it shows in display it is fine, but when I try to use sr, it doesnt.

Please help

Hi @Capchap, this seems like predominantly an AppleScript question. There are plenty of AppleScript connoisseurs on this forum, so someone might chime in. But your best option for a question like this is to post it on Stackoverflow, which is the home of coding questions and answers.

However, bear in mind, you should format your posts properly to make them more readable. This includes (especially includes) the code sample: include the rest of the code, because it might be important to the problems you're experiencing without you being aware. It's also important because a person trying to help wants to just copy/paste your code sample into their editor, and have it compile and run straight away: currently, yours doesn't do this and for someone to get it running, they have to first write extra parts of the script themselves, which defeats the point of diagnosing a problem.

To illustrate this, I'm going to say that your script has two glaring errors in it, which is that display alert "selected range is ' &s& doesn't have anything after the second &. But, I'm guessing in your actual script, it does, and you just left it out here. (The second error is your mismatched quotes: the first is a double quote, the second is a single quote; they should both be doubles).

Also, I don't know what variable s is, because it never occurs in the script before that line.

Anyway, good luck with it and do let us know how your KM macro turns out, or perhaps consider sharing it if you think others will find it useful.

Thanks so much.

I’ll get onto stackoverflow right away.

And also thanks for guiding me about providing full script. I didn’t think about how someone might actually use it too help me... guess I thought genius coders could mentally synthesize the rest ... I didn’t give whole code because I didn’t want to come across as asking someone to fix my code so much as I wanted to understand how things interacted.

For example when I wrote stuff in c (30 years ago) we had to pay attention to the variable type. So Type could be integer, real, float, char, etc each type had its own way of being able to display.

Anyway I’m rambling. Thanks again for directing me. Greatly appreciated.

I rarely use Apple Numbers (prefer Excel), so my Numbers AppleScript is suspect. But your AppleScript doesn't look right to me. I could very well be wrong, but try this:

tell application "Numbers"
  --  activate
  try
    if not (exists document 1) then error number 1000
    tell document 1
      try
        tell active sheet
          set the selectedTable to ¬
            (the first table whose class of selection range is range)
        end tell
      on error
        error number 1001
      end try
      
      tell selectedTable
        set the selectedRange to the selection range
        set selRngName to name of selectedRange
        
        display dialog "Selected Range is: " & selRngName buttons {"Cancel", "OK"} default button "OK"
        
        -- get the parent columns and rows of the selection
        set selectedCols to the columns of selection range
        set selectedRows to the rows of selection range
        
      end tell
    end tell
  end try
end tell

For more help/examples, do a 'net search of "applescript numbers get selection"

1 Like

THANKS! I’ll check that out.

The big issue didn’t seem to be getting the selection range bc the app works. I couldn’t figure out how to show what the selected range was received (just in case it was wrong, or just wanted to have user confirm)

Thanks again, I’ll post kudos after checking it out

and in a Keyboard Maestro Execute a JavaScript for Automation action, you could write something like this:

Choose from menu of selected Numbers cells.kmmacros (21.3 KB)

16
Untitled

Javascript source

(() => {
    'use strict';

    const main = () => {

        const
            docs = Application('Numbers').documents,
            lrChoice = bindLR(
                0 < docs.length ? (
                    Right(docs.at(0))
                ) : Left('No documents open in Numbers.'),

                // If we have a Right channel value,
                // bind the name 'doc' to it.

                // (Left channel values pass straight through to the end)
                doc => {
                    const
                        tbls = filter(
                            tbl => Boolean(tbl.selectionRange()),
                            doc.activeSheet.tables()
                        );

                    return bindLR(
                        0 < tbls.length ? (
                            Right(tbls[0])
                        ) : Left('Nothing selected in Numbers'),

                        // If we have a Right channel value,
                        // bind the name 'tbl' to it.

                        // (Left channel values pass straight through)
                        tbl => {
                            const
                                rngSeln = tbl.selectionRange(),
                                cellValues = rngSeln.cells.value(),
                                sa = standardSEAdditions(),
                                choice = (
                                    sa.activate(),
                                    sa.chooseFromList(
                                        cellValues, {
                                            withTitle: tbl.name(),
                                            defaultItems: cellValues[0],
                                            multipleSelectionsAllowed: true
                                        }
                                    )
                                );

                            return choice !== false ? (
                                Right(choice)
                            ) : Left('User cancelled')
                        }
                    );
                }
            );
        // Either a message string, or an Array of chosen cell values
        return (
            lrChoice.Left || lrChoice.Right
        );
    };

    // GENERIC FUNCTIONS --------------------------------------

    // Left :: a -> Either a b
    const Left = x => ({
        type: 'Either',
        Left: x
    });

    // Right :: b -> Either a b
    const Right = x => ({
        type: 'Either',
        Right: x
    });

    // bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
    const bindLR = (m, mf) =>
        m.Right !== undefined ? (
            mf(m.Right)
        ) : m;

    // filter :: (a -> Bool) -> [a] -> [a]
    const filter = (f, xs) => xs.filter(f);

    // JXA --------------------------------------

    // standardSEAdditions :: () -> Application
    const standardSEAdditions = () =>
        Object.assign(Application('System Events'), {
            includeStandardAdditions: true
        });

    // MAIN ---
    return main();
})();

While in a KM Execute an Applescript action, another variant might be:

Choose from menu of selected Numbers cells AS.kmmacros (21.0 KB)

Untitled%202

Applescript source

-- numbersSelectionLR :: () -> Either String [a]
on numbersSelectionLR()
    tell application "Numbers"
        set docs to documents
        if 0 < length of docs then
            set lrDoc to my |Right|(item 1 of docs)
        else
            set lrDoc to my |Left|("No documents open in Numbers.")
        end if
    end tell
    
    bindLR(bindLR(lrDoc, my selectedTableLR), my chosenCellsLR)
end numbersSelectionLR


on run
    
    tell numbersSelectionLR()
        if its |Right| is not missing value then
            its |Right|
        else
            its |Left|
        end if
    end tell
    
end run


-- FUNCTIONS FOR NUMBERS ------------------

-- isSelected :: NumbersTable -> Bool
on isSelected(oTable)
    using terms from application "Numbers"
        missing value is not selection range of oTable
    end using terms from
end isSelected

-- selectedTableLR :: NumbersDocument -> Either String NumbersTable
on selectedTableLR(doc)
    using terms from application "Numbers"
        
        set tbls to filter(my isSelected, tables of active sheet of doc)
        
        if 0 < length of tbls then
            |Right|(item 1 of tbls)
        else
            |Left|("Nothing selected in Numbers")
        end if
    end using terms from
end selectedTableLR

-- chosenCells :: NumbersTable -> Either String -> [a]
on chosenCellsLR(tbl)
    using terms from application "Numbers"
        set xs to value of cells of selection range of tbl
        tell application "System Events"
            activate
            set choice to choose from list xs with title (name of tbl) ¬
                default items (item 1 of xs) ¬
                with multiple selections allowed
        end tell
        if choice is not false then
            |Right|(choice)
        else
            |Left|("User cancelled")
        end if
    end using terms from
end chosenCellsLR


-- GENERIC FUNCTIONS --------------------------------------

-- https://github.com/RobTrew/prelude-applescript

-- Left :: a -> Either a b
on |Left|(x)
    {type:"Either", |Left|:x, |Right|:missing value}
end |Left|

-- Right :: b -> Either a b
on |Right|(x)
    {type:"Either", |Left|:missing value, |Right|:x}
end |Right|

-- bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
on bindLR(m, mf)
    if missing value is not |Right| of m then
        mReturn(mf)'s |λ|(|Right| of m)
    else
        m
    end if
end bindLR

-- filter :: (a -> Bool) -> [a] -> [a]
on filter(f, xs)
    tell mReturn(f)
        set lst to {}
        set lng to length of xs
        repeat with i from 1 to lng
            set v to item i of xs
            if |λ|(v, i, xs) then set end of lst to v
        end repeat
        return lst
    end tell
end filter

-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn
1 Like

Here's a simpler JXA script that does exactly what you ask, but is perhaps easier to read and modify:


Example Output

image


var ptyScriptName   = "Get Selected Range in Apple Numbers Table";
var ptyScriptVer     = "1.0";
var ptyScriptDate   = "2018-06-29";
var ptyScriptAuthor = "JMichaelTX";

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PURPOSE:
  • Get Selected Range in Apple Numbers Table
  
RETURNS:  Cell Range of Selection (B1:D3)

REQUIRED:
  1.  macOS 10.11.6+
  2.  Mac Applications
      • Apple Numbers
      
TAGS:  @CAT.Selection @SW.ANumbers @type.Example @Auth.JMichaelTX

REF:  The following were used in some way in the writing of this script.

  1.  2018-06-29, Keyboard Maestro Forum
      How to Get the Selected Range in Numbers.app with AppleScript
      https://forum.keyboardmaestro.com/t/how-to-get-the-selected-range-in-numbers-app-with-applescript/10657

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
(function myMain () {
    
'use strict';
var scriptResults = "TBD";

// --- Get Ref to Current App (needed for Dialogs, etc) ---
const app = Application.currentApplication()
app.includeStandardAdditions = true

const numApp   = Application('Numbers');
const oDoc    = numApp.documents[0];  // active document
const oSheet  = oDoc.activeSheet();    // active sheet
var tableList  = oSheet.tables();      // all tables on sheet

// --- Get FIRST Table That Contains the Selected Range ---
var oSelTable = tableList.filter(tbl => tbl.selectionRange())[0];

if (oSelTable) {

var oSelRange = oSelTable.selectionRange();    // Selection Range in Table
var selRngName  = oSelRange.name();            // Name (cell ref) of Selection
scriptResults    = "Selected Range is:  " + selRngName;

} else { scriptResults = "❯❯❯ ERROR ❮❮❮\nNothing is selected in Numbers Sheet"; }

var msgTitleStr = "Get Selected Range";

app.beep()
var oAns = app.displayDialog(scriptResults,
            {
              withTitle:      msgTitleStr
              ,withIcon:      "caution"
              ,buttons:       ["Cancel","OK"]
              ,defaultButton: "OK"
              ,cancelButton:  "Cancel"
            });
var btnStr = oAns.buttonReturned;


return selRngName;

  })();