NEEDLES TO SAY, I am very new to this, but trying my hardest to figure all this out. I have a script right now which actively removes all empty rows from an entire workbook. But I'm hoping someone can assist is narrowing this down to a single sheet within that workbook.
function removeEmptyRows() {
SpreadsheetApp.getActive()
.getSheets()
.forEach(function (s) {
c = 0;
s.getRange(1, 1, s.getMaxRows(), s.getMaxColumns())
.getValues()
.forEach(function (r, j) {
if (r.toString()
.replace(/,/g, "")
.length == 0) {
s.deleteRow((j += 1) - c)
c += 1;
}
})
})
}
Ideally I would like for this to remove only blank rows on one sheet within my workbook called 'Racing Results'. The reason I'm need this, is due to how the spreadsheet is setup and having multiple rows merged together. So when I copy these results over to a different sheet, there are gaps between them and I'd like them removed. Here is the script I'm using to copy the data to another sheet.
function Copy() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A32:E36');
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
If not to throw one final monkey wrench into this colossal mess, I have been attempting to copy two different cell ranges within the same script and I feel like this isn't possible because only the latter one gets copied and the initial one is discarded. Here is the other copy script I am using which runs before the one above this.
function Copy() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A1:A1');
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
Score Card Screenshot
In a perfect world, what I'm trying to get setup is the following. Above is a screenshot of the scorecard we are using. I am wanting to copy the Current Date (A1) to the 'Racing Results' sheet, then I want to copy the final score with the team names (A32:E36) and move them to the 'Racing Results' sheet right under it. Once that has been done, I want to remove the empty rows between the results because as of right now this is how it looks when copying over. (see image below)
Race Results Screenshot
Thanks in advance to anyone who is able to assist with any of this in any way shape or form.
Edit:
Removing Empty Rows from a spreadsheet is functioning as intended. Still having issues with Copying multiple times in the same action even when giving them different names. Here is my updated script.
function CopyDate() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A1:A1');//This range is only one cell
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
function CopyScore() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A32:E36');
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
function delBlankRows(shtname){
var shtname=shtname || 'Race Results';
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(shtname);
var rg=sh.getRange(1,1,sh.getMaxRows(),sh.getLastColumn());
var vA=rg.getValues();
var n=0;
for(var i=0;i<vA.length;i++){
if(!vA[i].join("")){
sh.deleteRow(i-n+1);
n++;
}
}
}
function Sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function SaveRaceResults() {
CopyDate();
Sleep(5000);
CopyScore();
Sleep(5000);
delBlankRows();
}
Deleting All Blank Rows on a Sheet
function delBlankRows(shtname){
var shtname=shtname || 'Sheet1';
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(shtname);
var rg=sh.getRange(1,1,sh.getMaxRows(),sh.getLastColumn());
var vA=rg.getValues();
var n=0;
for(var i=0;i<vA.length;i++){
if(!vA[i].join("")){
sh.deleteRow(i-n+1);
n++;
}
}
}
Copy function:
function Copy() {
var sss = SpreadsheetApp.getActive();
var ss1 = sss.getSheetByName('Score Card');
var range1 = ss1.getRange('A1');//This range is only one cell
var data1 = range1.getValues();
var ts1 = sss.getSheetByName('Race Results');
ts1.getRange(ts1.getLastRow()+1, 1, data1.length, data1[0].length).setValues(data1);
var ss2 = sss.getSheetByName('Score Card');
var range2 = ss2.getRange('A32:E36');
var data2 = range2.getValues();
var ts2 = sss.getSheetByName('Race Results');
ts2.getRange(ts2.getLastRow()+1, 1, data2.length, data2[0].length).setValues(data2);
}
Related
EDIT: I need help combining functions into 1 and adding a trigger.
In my spreadsheet I have rows 4-100 for customer service calls that are filtered from a "ServiceData" worksheet by either choosing a "Service Month" or "Service Day" (ie. "7/11" shows only 5 rows where "July" would show 65 rows) . Each row item has corresponding Place IDs for origin/destination in column K and L with an order # (as in 1st, 2nd, 3rd... service call of the day) in column J .
TravelTime spreadsheet
I'm using the following custom function travelTime() in cells M4:M100 to calculate driving duration and distance between 2 place IDs:
function travelTime(origin,destination) {
var API_KEY = PropertiesService.getScriptProperties().getProperty('keyMaps');
var baseUrl = "https://maps.googleapis.com/maps/api/distancematrix/json? units=imperial&origins=";
var queryUrl = baseUrl + "place_id:" + origin + "&destinations=" +
"place_id:" + destination + "&mode=driving" + "&key=" + API_KEY;
var response = UrlFetchApp.fetch(queryUrl);
var json = response.getContentText();
var time = JSON.parse(json);
return [[ time.rows[0].elements[0].duration.text,
time.rows[0].elements[0].distance.text ]] ;
A major issue is that many unnecessary service calls are being made to the API when I'm making edits to the "ServiceData" spreadsheet (ie. service date changes when a particular day is over-scheduled) and not needing the travel time updated until I'm done working through a schedule .
After researching quite a bit there seems to be several options I could be using; caching, looping, arrays, and putting everything into a script then attach to a button to only run when ready. Considering I'm a newbie, putting all these options together are definitely beyond my skill level and could really use some help.
EDIT with new functions:
So after more researching I have been able to put together the following functions that when each are run independently work great. Now the problem I'm having is putting these all together in particular adjusting the original travelTime()into newTravelTime(). I have made an attempt towards the right direction below but can't figure out how to get the API call in there .
function newTravelTime() {//<--**having issues how to write this function
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MonthlySA");
var sourceR = sourceSheet.getRange(4, 11, sourceSheet.getLastRow()-3, 4);
var sourceV = sourceR.getValues();
var array = [];
for (var i = 0; i < sourceV.length; i++) {
if (sourceV[i][2] == "") {
var origin = sourceV[i][0];//ori place IDs for API query
var destination = sourceV[i][1];//des place IDs API api query
}
array.push([sourceV[i][2]]);
}
sourceSheet.getRange(4, 13, array.length, 1).setValues(array);
I'd like to create a final getTravelTime() with all the functions and add an OnEdit trigger when either "Service Month" or "Service Day" changes in cells B1 or B2 to run them. If there is any advice with my functions themselves I would really appreciate some help, I am very new with this and trying.
///checks if origin/destination are already in the cacheSheet then return travel time to sourceSheet
function getCachedTravelTime() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MonthlySA");
var sourceR = sourceSheet.getRange(4, 11, sourceSheet.getLastRow()-3, 4);
var sourceV = sourceR.getValues();
var cacheSheet = ss.getSheetByName("TravelTimeCache");
var cacheR = cacheSheet.getRange(2, 1, cacheSheet.getLastRow()-1, 4);
var cacheV = cacheR.getValues();
var array = [];
for (var i = 0; i < sourceV.length; i++) {
for (var j = 0; j < cacheV.length; j++) {
//if origin/destination columns from sourceSheet match columns on cacheSheet
if (sourceV[i][0]+sourceV[i][1] == cacheV[j][0]+cacheV[j][1]) {
sourceV[i][2] = cacheV[j][2]; //column with travel duration
sourceV[i][3] = cacheV[j][3]; //column with travel distance
}
}
array.push([sourceV[i][2], sourceV[i][3]]);
}
sourceSheet.getRange(4, 13, array.length, 2).setValues(array);
}
///if origin or destination are blank, label as 'missing value'
function missingOD() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MonthlySA");
var sourceID = sourceSheet.getRange(4, 3, sourceSheet.getLastRow()-3, 12);
var sourceV = sourceID.getValues();
var array = [];
for (var i = 0; i < sourceV.length; i++) {
// if ID has a value
if (sourceV[i][0] != "") {
// if origin or destination is blank
if (sourceV[i][8] == "" || sourceV[i][9] == "") {
sourceV[i][10] = 'missing value';
}
}
array.push([sourceV[i][10]]);
}
sourceSheet.getRange(4, 13, array.length, 1).setValues(array);
}
///if cache not found - get the new travelTime for that origin/destination on sourceSheet...
function newTravelTime() {//<--
}
///...and store the new travelTime() in cacheSheet
function storeTravelTime() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MonthlySA");
var sourceR = sourceSheet.getRange(4, 11, sourceSheet.getLastRow()-3, 4);
var sourceV = sourceR.getValues();
var cacheSheet = ss.getSheetByName("TravelTimeCache");
var cacheR = cacheSheet.getRange(2, 1, cacheSheet.getLastRow()-1, 4);
var cacheV = cacheR.getValues();
var array = [];
for (var i = 0; i < sourceV.length; i++) {
var duplicate = false;
for (var j = 0; j < cacheV.length; j++) {
if (sourceV[i][0]+sourceV[i][1] == cacheV[j][0]+cacheV[j][1]) {
duplicate = true;
}
}
if(!duplicate){ //if origin/destination columns from sourceSheet are NOT matched on cacheSheet
array.push([sourceV[i][0], sourceV[i][1], sourceV[i][2], sourceV[i][3]]);//columns with new data
}
}
//add new data to last row of cacheSheet
cacheSheet.getRange(cacheSheet.getLastRow()+1, 1, array.length, 4).setValues(array);
}
One of the easiest solution thats coming to mind is Caching. Instead of making API calls everytime check if we have already made that call previously.
Something like this
function getTravelTime(origin, destination) {
var travelTime = getTravelTimeFromPreviousCall(origin, destination);
if (travelTime != null) {
return travelTime;
} else {
var travelTime = fetchTravelTime(origin, destination);
storeTravelTime(origin, destination, travelTime);
return travelTime;
}
}
function fetchTravelTime(origin, destination) {
var API_KEY = PropertiesService.getScriptProperties().getProperty('keyMaps');
var baseUrl = "https://maps.googleapis.com/maps/api/distancematrix/json? units=imperial&origins=";
var queryUrl = baseUrl + "place_id:" + origin + "&destinations=" + "place_id:" + destination + "&mode=driving" + "&key=" + API_KEY;
var response = UrlFetchApp.fetch(queryUrl);
var json = response.getContentText();
var time = JSON.parse(json);
return time.rows[0].elements[0].duration.text;
}
For this we can define our cache something like :
A sheet with column -
origin
destination
travel time
And we need to define following functions:
getTravelTimeFromPreviousCall(origin, destination) : In this we need to check cache and return travel time for that origin & destination, if not found then return null
storeTravelTime(origin, destination, time) : This will only store travel time for future use in cache sheet
You can try something like this :
function getTravelTimeFromPreviousCall(origin, destination) {
var cacheSheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(CACHE_SHEET_NAME);
var cacheData = sheet.getDataRange().getValues();
for (var i=0; i<cacheData.length; i++) {
if (cacheData[i][ORIGIN_COLUMN_INDEX]==origin && cacheData[i][DESTINATION_COLUMN_INDEX]==destination) {
return cacheData[i][TRAVEL_TIME_COLUMN_INDEX];
}
}
return null;
}
function storeTravelTime(origin, destination, travelTime) {
var cacheSheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(CACHE_SHEET_NAME);
sheet.appendRow([origin, destination, travelTime]);
}
Please fix loop variable, array indexes & constants, as per your sheet.
I created a function that whenever I run the AppendRow script every row that does not have a dot (".") at the AY column, an array with every information/column that I want from that sheet will be transfered to my main sheet that has around 13k rows atm.
Usually about 20-40 rows get pasted into the first sheet everyday and this script automatically re-arranges the columns to my main sheet.
PROBLEM:
The problem is that each row that gets appended to my main sheet takes around 8-15sec to get transfered and sometimes I get this "exceeded-maximum-execution-time" error thats its really annoying.
Is there any way to make my code run faster or maybe just a way to make the script run more than 5 minutes?
function AppendRow() {
var app = SpreadsheetApp;
var Sheet = app.getActiveSpreadsheet().getSheetByName("Sheet1");
var ss2017 = SpreadsheetApp.openById("");
var sheet2017 = ss2017.getSheetByName("2017");
var lastSourceRow = Sheet.getLastRow();
var lastSourceCol = Sheet.getLastColumn();
var sourceRange = Sheet.getRange(1, 1, lastSourceRow, lastSourceCol);
var sourceData = sourceRange.getValues();
var lenght = sourceData.length;
//Logger.log(lenght);
var time = new Date();
time = Utilities.formatDate(time, "GMT+01:00", "dd/MM/yy, HH:mm:ss");
for(i=5326;i<=lenght;i++)
//my i=5326 is just cuz I had already
// information on my sheet that was transfered before this script existed
{
var columnAY = Sheet.getRange(i,51).getValue();
var checkReservation = Sheet.getRange(i,2).getValue();
if(columnAY == ".")
{
}
else
{
var B = Sheet.getRange(i,2).getValue();
var F = Sheet.getRange(i,6).getValue();
var E = Sheet.getRange(i,5).getValue();
var K = Sheet.getRange(i,11).getValue();
var L = Sheet.getRange(i,12).getValue();
var V = Sheet.getRange(i,22).getValue();
var O = Sheet.getRange(i,15).getValue();
var P = Sheet.getRange(i,16).getValue();
var Q = Sheet.getRange(i,17).getValue();
var AF = Sheet.getRange(i,32).getValue();
var AG = Sheet.getRange(i,33).getValue();
var N = Sheet.getRange(i,14).getValue();
var AI = Sheet.getRange(i,35).getValue();
var AB = Sheet.getRange(i,28).getValue();
var AC = Sheet.getRange(i,29).getValue();
var array = ["",B,F,E,K,L,"",V,O,P,Q,AF,AG,"","",N,N,AI,"","",AB,AC,"","","","",time];
sheet2017.appendRow(array);
Sheet.getRange(i,51).setValue(".");
}
}
}
p.s.: I also have a menu in my spreadsheet to run the script every time i want to not sure if that is any relevant to the question :P
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('My Menu')
.addItem('Copy to 2017', 'AppendRow')
.addToUi();
Every comment is appreciated !! :)
I must admit to having a bit of a problem figure out how my i's coordinated with your's but I think my columns are correct. So check it out but this should run a bit faster.
function AppendRow()
{
var ss0=SpreadsheetApp.getActive();
var sh0=ss.getSheetByName('Sheet1');
var rg0=sh0.getDataRange();
var vA0=rg0.getValues();
var ss1=SpreadsheetApp.openById(id);
var sh1=ss1.getSheetByName('2017');
var TimeStamp=Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "dd/MM/yy HH:mm:ss");
for(i=5326;i<vA0.length;i++)
{
var columnAY=vA0[i][50];
var checkReservation=vA0[i][1];
if(vA0[i][50]!='.')
{
var B = vA0[i][1];//Sheet.getRange(i,2).getValue();
var F = vA0[i][5];//Sheet.getRange(i,6).getValue();
var E = vA0[i][4];//Sheet.getRange(i,5).getValue();
var K = vA0[i][10];//Sheet.getRange(i,11).getValue();
var L = vA0[i][11];//Sheet.getRange(i,12).getValue();
var V = vA0[i][21];//Sheet.getRange(i,22).getValue();
var O = vA0[i][14];//Sheet.getRange(i,15).getValue();
var P = vA0[i][15];//Sheet.getRange(i,16).getValue();
var Q = vA0[i][16];//Sheet.getRange(i,17).getValue();
var AF = vA0[i][31];//Sheet.getRange(i,32).getValue();
var AG = vA0[i][32];//Sheet.getRange(i,33).getValue();
var N = vA0[i][13];//Sheet.getRange(i,14).getValue();
var AI = vA0[i][34];//Sheet.getRange(i,35).getValue();
var AB = vA0[i][27];//Sheet.getRange(i,28).getValue();
var AC = vA0[i][28];//Sheet.getRange(i,29).getValue();
var array = ["",B,F,E,K,L,"",V,O,P,Q,AF,AG,"","",N,N,AI,"","",AB,AC,"","","","",TimeStamp];
sh1.appendRow(array);
sh0.getRange(i+1,51).setValue(".");
}
}
}
I have a script that gets information from an API and writes it to google sheets. In the data from the API the numbers all look normal but once written to google sheets they are all changed. for example 4319.05 is written back as 4319:05:00.000.
When I try to format the range after its been pasted to the sheet I get really strange results where 4319:05:00.000 formatted as number, gives the value of 179.96.
The API can be found at:
https://api.coinmarketcap.com/v1/ticker/
The code used is as follows:
function getCoinMarketCapAPI() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
Logger.log(sheets)
var url="https://api.coinmarketcap.com/v1/ticker/";
var response = UrlFetchApp.fetch(url); // get feed
var dataAll = JSON.parse(response.getContentText()); //
var dataSet = dataAll;
Logger.log(dataSet)
var rows = [],
data;
Logger.log(rows)
for (i = 0; i < dataSet.length; i++) {
data = dataSet[i];
rows.push([data.id,data.name,data.symbol,data.rank,data.price_usd,data.price_btc,data.percent_change_1h,data.percent_change_24h,data.percent_change_7d,data.last_updated]);
}
dataRange = sheet.getRange(6, 1, rows.length, 10);
dataRange.setValues(rows);
}
Any help would be so appreciated! =)
Thanks in advance!
Your script worked fine for the numbers. I did have to fix the date. Format for my sheet is automatic.
function getCoinMarketCapAPI() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var url="https://api.coinmarketcap.com/v1/ticker/";
var response = UrlFetchApp.fetch(url); // get feed
var dataAll = JSON.parse(response.getContentText()); //
var dataSet = dataAll;
var rows = [],data;
for (i = 0; i < dataSet.length; i++) {
data = dataSet[i];
var d=new Date(data.last_updated*1000)// convert to date
rows.push([data.id,data.name,data.symbol,data.rank,data.price_usd,data.price_btc,data.percent_change_1h,data.percent_change_24h,data.percent_change_7d,d]);
}
dataRange = sheet.getRange(6, 1, rows.length, 10);
dataRange.setValues(rows);
}
Here is my test spreadsheet you can copy and try.
https://docs.google.com/spreadsheets/d/1dg2opJG3NEc_Ud5MrXnuFplDXnVoO9_ul-QW_MczWZ8/edit?usp=sharing
I'm trying to insert some data from a spreadsheet into a different spreadsheet, the problem is that the loop is not behaving as expected, it only gives me one entry in the target spreadsheet. I've tried using while and no function but it didn't work.
Here is the code:
function move(){
var homeBook = SpreadsheetApp.getActiveSpreadsheet();
var sheet = homeBook.getSheets()[0];
var limit = sheet.getLastRow(); //number of rows in the sheet
var evento = sheet.getRange(2, 1, limit-1).getValues(); //event list
var descript = sheet.getRange(2,2,limit-1).getValues(); //description list
var tags = sheet.getRange(2,3,limit-1).getValues(); //tag list
var sheetsIDHome = sheet.getRange(2,4,limit-1).getValues(); //ID list
var targetBook = SpreadsheetApp.openById("1t3qMTu2opYffLmFfTuIbV6BrwsDe9iLHZJ_ZT89kHr8"); //target workbook
var target = targetBook.getSheets()[0]; //Sheet1
var targetLimit =target.getLastRow(); //Rows with content
var sheetsIDTarget = target.getRange(targetLimit, 4); // ID list
var targetRow = targetLimit+1; //row where content is going to be inserted
for(i = 2;i <= limit;i++){//loop for each value to be inserted in each row of the target sheet
(function(x){
target.getRange(targetRow,1).setValue(x);
target.getRange(targetRow,2).setValue(descript[2]);
target.getRange(targetRow,3).setValue(tags[3]);
target.getRange(targetRow,4).setValue(sheetsIDHome[4]);
targetRow = targetRow++;
})(i);
};
You're trying to access the four arrays created from the values for columns 1-4.
Your for statement needs to match their structure, starting with the first array instance of 0. You can use any of the arrays for the iteration, I've chosen the first.
In addition, I've removed the function and replaced x with the instance from evento.
++ increments the value of the variable, no need for assignment there.
for (var i = 0; i < evento.length; i++) {
target.getRange(targetRow,1).setValue(evento[i]);
target.getRange(targetRow,2).setValue(descript[i]);
target.getRange(targetRow,3).setValue(tags[i]);
target.getRange(targetRow,4).setValue(sheetsIDHome[i]);
targetRow++;
}
there is a code that has been mis-placed, kindly check my code below:
function UpdateBSRSpecial()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var testForm = ss.getSheetByName("ENTRY FORM");
var testTable = ss.getSheetByName("BSR DATA");
var testFormValue = testForm.getRange("G6").getValue();
var rangeData = testTable.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
for(var i=2;i<=lastRow;i++){
var dataID = testTable.getRange(i,1).getValue();
if(testFormValue == dataID)
{
testTable.getRange(i,6).setValue("new value");
};
};
};
hope this helps
I wish to get a couple of properties of all the folders in my GDrive and write these properties to a spreadsheet. Because of the large number of folders (over 300) I have decided to use Paging and Batch processing. This seems to be working but I can't seem to write the Array[][] I've created in the batch processing to the spreadsheet.
I'm am getting the following error when I try to set the values in my spreadsheet:
Cannot convert (class)#3cc8188e to Object[][].
I did not find any listed questions that were similar to my problem.
The last line of the script is highlighted when the error appears. Code is:
function myFunction() {
var folder = DocsList.getFolder('MyFolder');
var subfolders = null;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getRange('a1');
var x = 0;
var pageSize = 250;
var token = null;
var xfolders = new Array(500);
do {
var resultset = folder.getFoldersForPaging(pageSize, token);
subfolders = resultset.getFolders();
token = resultset.getToken();
x = subfolders.length;
for (var a = 0; a < subfolders.length; a++) {
var contents = subfolders[a].getFiles();
xfolders[a] = new Array(6);
if(contents.length>0) {
xfolders[a][0] = subfolders[a].getName();
xfolders[a][1] = subfolders[a].getDateCreated();
xfolders[a][2] = subfolders[a].getLastUpdated();
xfolders[a][3] = contents.length;
xfolders[a][4] = subfolders[a].getSize();
xfolders[a][5] = a;
}
}
} while (subfolders.length > pageSize)
sheet.getRange(1, 1, x, 6).setValues(xfolders);
}
You've started with an array xfolders for which you've initialized a length. There's no need to do this - it's enough to know that it's an array. Later you call getRange() with rows==x, where x = subfolders.length... and if that isn't 500 (the length of xfolders) you will end up with your error. (...because you have undefined array elements.)
What you need to do is make sure that the range you're writing to has the same dimensions as the values you're presenting. One way to do that is to calculate the range dimensions using xfolders itself.
Here's your function, refactored to grow xfolders dynamically, and then to use its dimensions for output to the spreadsheet.
function myFunction() {
var folder = DocsList.getFolder('MyFolder');
var subfolders = null;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getRange('a1');
var pageSize = 250;
var token = null;
var xfolders = [];
do {
var resultset = folder.getFoldersForPaging(pageSize, token);
subfolders = resultset.getFolders();
token = resultset.getToken();
for (var a in subfolders) {
var contents = subfolders[a].getFiles();
xfolders[a] = [];
if(contents.length>0) {
xfolders[a][0] = subfolders[a].getName();
xfolders[a][1] = subfolders[a].getDateCreated();
xfolders[a][2] = subfolders[a].getLastUpdated();
xfolders[a][3] = contents.length;
xfolders[a][4] = subfolders[a].getSize();
xfolders[a][5] = a;
}
}
} while (subfolders.length == pageSize) // Quit when we aren't getting enough folders
sheet.getRange(1, 1, xfolders.length, xfolders[0].length).setValues(xfolders);
}