1
votes

I need to find all references to a Named Range (which is a single cell) in any cell in a sheet. Any method (or script) to do this?

Context: I'm calculating the lift forces on a boat sail at different wind strengths. The equation uses a "Coefficient of Lift" value (CL), which is my NamedRange. However, I now need to change that so at different wind speeds, a different CL is used, and scrap the NamedRange.

I can do that using nested IF() statements, no problem, but first I have to find all cells that currently use the NamedRange. MTIA!

1
I proposed 2 sample scripts as an answer. Could you please confirm it? If these were not the direction you expect, I apologize.Tanaike
Thanks for your time! I'm only using attached script in the spreadsheet.However, I get "TypeError: Cannot read property 'createTextFinder' of null (line 255, file "Code")"maxhugen
Thank you for replying. I apologize for the inconvenience. From your replying, I added one more sample script. At that script, the cells with the namedRange are retrieved using one namedRange. Could you please confirm it? If that was not the result you expect, I apologize again. By the way, I added a tag of google-apps-script for your question.Tanaike
Thank you for replying. I have to apologize for my poor English skill. From your replying and the current situation, I'm worry whether my suggested answer could resolve your issue. If my answer was not useful for your situation, I apologize. Can I ask you about your current situation for my answer?Tanaike
Your English is fine, better than some I know In Australia! Actually, I had upvoted your answer, but didn't realise that I should "Tick" it to "accept" the answer - which I have now done. Cheers mate!maxhugen

1 Answers

1
votes

I believe your goal as follows.

  • You want to retrieve the cells which have the formulas using NamedRange.
  • In order to achieve your goal, you can use Google Apps Script.

In this answer, I would like to propose the following flow using Google Apps Script.

  1. Retrieve all named ranges.
  2. Using TextFinder, retrieve the cells which have the formulas using NamedRange.

Please copy and paste the following script to the script editor of the container-bound script of the Spreadsheet. And run the function myFunction1 or myFunction2(). By this, you can see the result values at the log.

Sample script 1:

In this sample script, the A1Notations of cells which use the formulas with the NamedRanges are returned as an array.

function myFunction1() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName("Sheet1");  // Please set the sheet name.
  
  // 1. Retrieve all named ranges.
  const namedRanges = ss.getNamedRanges().map(e => e.getName());

  // 2. Using TextFinder, retrieve the cells which have the formulas using NamedRange.
  const values = namedRanges.reduce((ar, e) => {
    sheet.createTextFinder(e).matchCase(true).matchFormulaText(true).findAll().forEach(f => ar.push(f.getA1Notation()));
    return ar;
  }, []);
  const res = [...new Set(values)];

  console.log(res)
}

The sample output value is as follows.

["A1", "B1",,,]

Sample script 2:

In this sample script, the A1Notations of cells which use the formulas with the NamedRanges are returned as an JSON object.

function myFunction2() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName("Sheet1");  // Please set the sheet name.

  // 1. Retrieve all named ranges.
  const namedRanges = ss.getNamedRanges().map(e => ({name: e.getName(), range: `'${e.getRange().getSheet().getSheetName()}'!${e.getRange().getA1Notation()}`}));
  
  // 2. Using TextFinder, retrieve the cells which have the formulas using NamedRange.
  const res = namedRanges.reduce((o, {name, range}) => {
    sheet.createTextFinder(name).matchCase(true).matchFormulaText(true).findAll().forEach(f => {
      const r = f.getA1Notation();
      const temp = {namedRange: name, rangeOfNamedRange: range};
      o[r] = o[r] ? o[r].concat(temp) : [temp];
    });
    return o;
  }, {});

  console.log(res)
}

The sample output value is as follows. The A1Notation of cell which uses the NamedRange is used as the key. And the NamedRange and the range of NamedRange are used as the value. The values can be also retrieved from the cell which uses multiple NamedRanges.

{
  "A1":[{"namedRange":"sample1","rangeOfNamedRange":"'Sheet2'!A1"}],
  "B1":[{"namedRange":"sample1","rangeOfNamedRange":"'Sheet2'!A1"},{"namedRange":"sample2","rangeOfNamedRange":"'Sheet2'!B1"}],
  "C1":[{"namedRange":"sample3","rangeOfNamedRange":"'Sheet3'!A1"}],
  ,
  ,
  ,
}

References:

Added:

I would need to run it for just one Named Range, as it looks like all cells for ALL Named Ranges have been logged, so I don't now which is which?

From your above replying, I thought that the pattern 1 might be suitable. So when above script is modified, it becomes as follows.

Modified script:

function myFunction1() {
  const sheet = ss.getSheetByName("Sheet1");  // Please set the sheet name.
  const namedRange = "###";  // Please set the name of namedRange.

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const res = sheet.createTextFinder(namedRange).matchCase(true).matchFormulaText(true).findAll().map(f => f.getA1Notation());
  console.log(res)
}