The `getRange` function is the go-to utility for getting data from a spreadsheet. You can pass simply a row and column to get a 1-d array or you can pass optional parameters for number of row and number of columns. Use `getLastRow()` to identify the number of rows if unknown.
```JavaScript title="Code.gs"
function getData(){
var ss = SpreadsheetApp.openById(id); // id is defined globally
var ws = ss.getSheetByName('data');
var data = ws.getRange(1, 1, ws.getLastRow(), 2).getValues();
for (var row in data) {
for (var col in data[row]) {
Logger.log(data[row][col]);
}
}
}
```
Alternatively, you can use `getDataRange` to grab the entire contents of a sheet.
```JavaScript title="Code.gs"
function getData(){
var ss = SpreadsheetApp.openById(id); // id is defined globally
var ws = ss.getSheetByName('data');
var data = ws.getDataRange().getValues();
}
```
Finally, you can use "A1" notation instead of numbers of rows and columns if that is more convenient
```JavaScript title="Code.gs"
function getData(){
///
var data = ws.getRange("A1:C").getValues();
}
```
Note that this will not detect the last row, but rather give you all data to the bottom of the spreadsheet.
You can combine non-consecutive ranges with `getRangeList`
```JavaScript title="Code.gs"
function getData(){
///
var data = ws.getRangeList(["A1:C", "E1:F").getValues();
}
```
Use `shift` method to pop (remove and return) the header row from an array. This will both save the first row to its own array and delete it from the data.
```JavaScript title="Code.gs"
function getData(){
var data = ws.getDataRange().getValues();
var headers = data.shift()
}
```
> [!Warning]
> You're client-side code will succeed but [mysteriously fail](https://stackoverflow.com/questions/56895811/google-script-run-executes-but-it-returns-null-while-code-gs-function-does-hav) on the app side if you try to pass [restricted data types](https://developers.google.com/apps-script/guides/html/reference/run) including datetime objects in your array!