// Sheets · Apps Script

Work with multiple ranges at once using getRangeList.

getRangeList lets you clear, format, or check/uncheck several disjoint ranges in a single Apps Script call — but it cannot read cell values. Learn when to use it and what to reach for instead.

I want to apply the same formatting or clear several non-contiguous ranges in one shot without looping through each one individually.

The script

copy · paste · trigger
rangelist-demo.gs
Apps Script
// Clear highlights and reset borders on three disjoint input zones
function resetInputZones() {
  var sheet = SpreadsheetApp.getActiveSheet();

  // getRangeList accepts any mix of A1 and named ranges
  var zones = sheet.getRangeList(['B2:B10', 'D2:D10', 'F2:F10']);

  zones.setBackground(null);
  zones.setBorder(false, false, false, false, false, false);
  zones.setFontWeight('normal');

  // RangeList cannot return values — loop individual ranges for that
  var values = [];
  zones.getRanges().forEach(function(r) {
    values.push(r.getValues());
  });

  Logger.log('Collected ' + values.length + ' range blocks');
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

What getRangeList actually does (and doesn't do)

Sheet.getRangeList() takes an array of A1-notation strings and returns a RangeList object. Every setter you call on that object — setBackground, setBorder, setFontWeight, setValue, setNumberFormat, insertCheckboxes — fans out to all the member ranges in a single batch. Sheets queues one network roundtrip instead of one per range, which matters when your script is already bumping against the 6-minute execution limit.

The catch that trips people up every time: RangeList has no getValues(), no getValue(), no getFormulas(). Those methods do not exist on the object. If you call one you will get a TypeError at runtime, not a compile-time hint. The object is write-only from a data perspective. For reading you drop back to getRanges() and iterate.

I keep a comment near every getRangeList call that says 'write-only' just to save my future self the five-minute debugging session.

Applying format resets across disjoint columns

The most common use is a form-reset pattern: a user fills in columns B, D, and F, submits, and you want to wipe conditional formatting artifacts before the next entry. Without getRangeList you write three nearly identical blocks or a loop that builds a Range array and calls the same method three times anyway.

With getRangeList the call surface collapses. Pass the A1 strings as an array literal, call your setters once each, done. You can mix contiguous and non-contiguous ranges in the same list — 'B2:B10', 'D2:F4', 'H1' are all valid together. Named ranges work too, provided they exist on the sheet you're calling getRangeList on.

One real gotcha: setBackground(null) clears any explicit background but does not remove conditional-formatting rules. If your columns are colored by a conditional rule, you need deleteConditionalFormatRules() on each Range separately — that method also isn't on RangeList.

Reading values from the same set of ranges

Once you accept that RangeList is write-only, the pattern for reading is straightforward. Call getRanges() on the RangeList — it returns the original Array of Range objects in the same order you passed the A1 strings. From there you can call getValues() on each one normally.

If you need a flat list of every non-empty value across all the ranges, a reduce over the getRanges() array works cleanly. Each getValues() call returns a 2D array (rows × columns), so flatten as needed. Each call is a separate Sheets API read, so if you have many ranges and quota is tight, consider whether a single bounding-range read plus post-filter is cheaper — but for three or four named zones, individual reads are fine.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
Why does calling getValues() on a RangeList throw a TypeError?
RangeList is a write-fanout object, not a Range proxy. The Sheets API intentionally omits read methods on it because returning a merged multi-range value structure would be ambiguous. Call getRanges() first to get the underlying Range array, then call getValues() on each element.
Can I pass named ranges to getRangeList instead of A1 notation?
Yes. Named ranges that exist on the sheet are valid entries in the array. You can mix A1 strings and named-range strings freely in the same getRangeList call. If a named range doesn't exist on that sheet, the call throws a runtime error — it won't silently skip it.
Does getRangeList work across multiple sheets?
No. getRangeList is a method on a Sheet object, so all ranges in the list must belong to that sheet. To operate on ranges across sheets you need a separate getRangeList call per sheet, or individual Range calls.
Is getRangeList faster than looping over individual Range objects?
For write operations, yes — each setter on a RangeList issues one batched Sheets API call rather than one call per range. For three ranges the difference is small, but at ten or more ranges (or inside a trigger that runs frequently) the reduced roundtrip count is meaningful against the 6-minute script limit and the Sheets API quota of roughly 100 read/write requests per 100 seconds per user.
// one good script a week

Get a working Apps Script snippet in your inbox, weekly.