Auto number input to google spreadsheet using array - google-apps-script

I have started studying GAS recently.
I wrote Auto number script using Low number.
There is spreadsheet has some datas, I want put A Column including batch ID number at one time.
function autoID() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastrow = sheet.getLastRow();
for(i=1; i<= lastrow-1; i++)
{
var num = sheet.getRange(i,1);
num.setValue(i);
}
Browser.msgBox("This is end!");
}
This in no good example,it takes too much time.
I wonder I should use Array() ..
may be ↓ this is hint..
https://developers.google.com/apps-script/best_practices
But this Best Practices doesn't work, I tried this...
function autoID() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastrow = sheet.getLastRow();
var num = new Array();
idrange = sheet.getRamge("A2:A"+(lastrow-1));
idrange = idrange.getValues();
for(i=1; i<= lastrow-1; i++)
{
var num = sheet.getRange(i,1);
num[(i)]=i;
}
Browser.messageBox(num[1]); // this is 1;
idrange.setValues(num); // this is error
}
How is change type?
Please help me..
I think this must be so easy.

Not sure I understood exactly what you want to do but here is how it works without code errors :
function autoID() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastrow = sheet.getLastRow();
var num = new Array();
var idrange = sheet.getRange("A2:A"+(lastrow));
var idrangeVal = idrange.getValues()
for(var i in idrangeVal){
num.push([i]);
}
idrange.setValues(num);
}
edit following your comment :
Here is a version the (I hope) does what you expected...
function autoID() {
var sheet = SpreadsheetApp.getActiveSheet();
var valuesInrangeA = sheet.getRange('A2:A').getValues();
var maxA = 0
for(var n=0 ;n<valuesInrangeA.length ; n++){
if(valuesInrangeA[n][0]!=''){maxA=n+2};
};
var num = new Array();
for(var i=1 ; i<maxA ; i++){
num.push([i]);
}
sheet.getRange("B2:B"+maxA).setValues(num);
}

Related

Google Apps Script mysteriously stops functioning in for loop

I am building a system to copy data from one sheet to another sheet (On a different spreadsheet). It works well, until it is supposed to copy the data. Afterward, it does nothing. No error is thrown, but no alert boxes pop up in the for loop. Here is my code:
function onEdit() {
var sheet = SpreadsheetApp.getActiveSheet();
var master = SpreadsheetApp.openById('13x7AvyYTaocCVBxVZ3ckBjzgxcZfjg9RYM1cE_0VNbU');
var sheets = master.getSheets();
var test = DriveApp.createFile('Test', 'fetching user data...');
var name = test.getOwner().getName();
test.setTrashed(true);
var add = true;
for (var i = 0, n; i < sheets.length; i++) {
n = sheets[i];
if (n.getName() == name) {
add = false;
updateSheet(n, name);
}
}
if (add) {
newSheet(master, name);
}
}
function updateSheet(m, name) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
var nr = range.getNumRows();
var nc = range.getNumColumns();
for (var i = 1; i <= nr.length; i++) {
for (var n = 1, s; n <= nc.length; n++) {
s = range.getCell(i, n);
m.getRange(i, n).getCell(1, 1).setValue(s.getValue());
}
}
}
function newSheet(master, name) {
var m = master.insertSheet(name);
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
var nr = range.getNumRows();
var nc = range.getNumColumns();
for (var i = 1; i <= nr.length; i++) {
for (var n = 1, s; n <= nc.length; n++) {
s = range.getCell(i, n);
m.getRange(i, n).getCell(1, 1).setValue(s.getValue());
}
}
}
I have searched the code, but can't find anything wrong.
On google documentation at https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#insertsheetsheetname, it says ...
insertSheet(sheetName)
Inserts a new sheet into the spreadsheet with the given name. The new sheet becomes the active sheet.
In your code
function newSheet(master, name) {
var m = master.insertSheet(name); // after calling this function m becomes the active sheet
var sheet = SpreadsheetApp.getActiveSheet(); // you've assigned m to sheet
I would recommend using getSheetByName('SheetName').
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetName");
Refer to this link https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getsheetbynamename
The obvious answer (Thanks #Rubén)
In the for loop, it says nc.length and nr.length. Both getNumRows and getNumColumns return numbers. Since these are integers, .length is not necessary.

Method is heavily used by the script

I am very new on using Google Apps Script and has a shallow knowledge on programming. What I am trying to do is copy the values of specific columns to a different Spreadsheet. Here's my code:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var x=2, y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
for (j=0; j<maxRows; j++){
var eventID = selectedSheets[i].getRange(y,2).getValue();
var employeeName = selectedSheets[i].getRange(y,3).getValue();
var productionDate = selectedSheets[i].getRange(y,4).getValue();
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,1).setValue(eventID);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,2).setValue(employeeName);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,3).setValue(productionDate);
y++;
lastRow++;
}
}
}
However, I am experiencing this notification on the Execution hints (light bulb icon):
screenshot of the message. I am thinking that my code can be simplified. I am just not sure how to do it. Thank you in advance.
Every line with .getRange().getValue() and getRange.setValue() is a call to the file. Since you have these inside a for(){} loop, they are being called many times. Your goal is to limit these to as few as possible. Since you can read and write a range, you could do something similar to this:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
var copyValues = selectedSheets[i].getRange(y,2, maxRows, 4).getValues();
consolidatedSheet.getRange(lastRow,1, maxRows, 4).setValues(copyValues);
}
}

compare rows on google spreadsheets

I want to identify equal rows in two different sheets on same spreadsheet. I tried below code, it doesn't work.
function getMyEqualRows()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheets()[0];
var sheet2 = ss.getSheets()[1];
var sheetOneValues = sheet1.getRange('A1:G20').getValues();
var sheetTwoValues = sheet2.getRange('A1:G20').getValues();
var equalRows = [];
for (var i = 0; i <= sheetOneValues.length; i++) {
for(var j = 0; j <= sheetTwoValues.length; j++){
if(sheetOneValues[i] == sheetTwoValues[j]) {
equalRows.push(sheetOneValues[i]);
}
}
return equalRows;
}
}
You can't compare two arrays for equality with ==. Instead you can use .join() method. It concatenates all elements in these arrays to a string. This check string arrays for equality. I'm not sure if this is the best way.
function getMyEqualRows()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheets()[0];
var sheet2 = ss.getSheets()[1];
var sheetOneValues = sheet1.getRange('A1:G20').getValues();
var sheetTwoValues = sheet2.getRange('A1:G20').getValues();
var equalRows = [];
for(var i in sheetOneValues)
{
var anEqualRow = false;
for(var j in sheetTwoValues)
{
if(sheetOneValues[i].join() == sheetTwoValues[j].join()){
anEqualRow = true;
}
}
if(anEqualRow){
equalRows.push(sheetOneValues[i]);
}
}
return equalRows;
}
Hope this would work!

GetCell -> GetValue -> SetValue fails

I want to make the below mentioned code working but it doesn't - nothing happens when I run it (also no error), that means the username (sUserName) doesn't get saved in the spreadsheet... And also I don't understand why the columns cant start with 2, 3, 4 (then the timestamp can stay in column #1) instead 1, 2, 3 - if so I get an error.
Here is the code:
var userNameColumn = 1; //Column where the user name is written
var subTypeColumn = 2; //Column where the submitter type is written ex. "Requester"
var sUserNameColumn = 3; //Column where the user name is saved
function saveUserName() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
for (var i = 1; i <= numRows; i++) {
var userNameCell = rows.getCell(i, userNameColumn);
var subTypeCell = rows.getCell(i, subTypeColumn);
var sUserNameCell = rows.getCell(i, sUserNameColumn);
if(sUserNameCell.isBlank() && subTypeCell.getValue() === 'Requester') {
sUserNameCell.setValue(userNameCell)
};
}
}
Here is the link for my spreadsheet and code:
Google Spreadsheet
See if this helps
function saveUserName() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var rows = sheet.getDataRange().getValues();
for (var i = 1; i < rows.length; i++) {
var userNameCell = rows[i][1];
var subTypeCell = rows[i][2];
var sUserNameCell = rows[i][3];
if (!sUserNameCell && subTypeCell === 'Requester') sheet.getRange(i+1,4).setValue(userNameCell)
}
}

Google Apps Script: Function to update names from one sheet to another times out. Please refine my loops

I have an app through google docs that I use to record student attendance to my after school tutoring center. I have had higher than usual attendance and my code is not efficient enough to run before timing out. Please assist me in editing my code so that it runs more effectively.
I have to note that I am an absolute beginner, so if this is inappropriately posted, please give me constructive feedback on how to get help with this problem. And I apologize in advance for the (I assume) horrible code you are about to see - it's the best I could do and I worked very hard to create this.
Thank you.
Code:
function updateAttendance(){
var itemSpreadsheetKey = '';
var openedSS = SpreadsheetApp.openById(itemSpreadsheetKey);
var sheetStudentNames = openedSS.getSheetByName("StudentNames");
var sheetDailyData = openedSS.getSheetByName("DailyData");
var app = UiApp.getActiveApplication();
var ss = SpreadsheetApp.openById(itemSpreadsheetKey);
var dailyDataSheet = ss.getSheetByName("DailyData");
var studentNameSheet = ss.getSheetByName("StudentNames");
var dailyData = dailyDataSheet.getDataRange();
var studentNames = studentNameSheet.getDataRange();
var dailyLastRow = dailyData.getLastRow();
var studentNamesLastRow = studentNames.getLastRow();
var studentNamesLastColumn = studentNames.getLastColumn();
var dailyDataNamesArray = sheetDailyData.getRange(2, 1, dailyLastRow).getValues();
for (var i=1; i<=dailyDataNamesArray.length; i++) {
if (i != ""){
var dailyTime = dailyData.getCell(i, 5).getValue();
for (var j=2; j<=studentNamesLastRow; j++) {
var today = dailyData.getCell(1, 8).getValue();
if (dailyData.getCell(i, 1).getValue() == studentNames.getCell(j, 1).getValue()) {
studentNames.getCell(1, studentNamesLastColumn).offset(0, 1).setValue(today);
studentNames.getCell(j, studentNamesLastColumn).offset(0, 1).setValue(dailyTime);
}
}
}
}
return app;
}
If you want your script to go faster you must use array manipulation instead of all these range.setValue() .
Change all the values in a global array (a pair of actually) and when you're done just write these arrays to their respective sheets.
The difference will be enormous ! believe me ;)
All this is pretty well explained in the documentation about best practices.
Here is a "translation" of your code, I'm not sure I didn't make any error in transposition but I have no way to check without knowing what is in your sheets.
Just remember that arrays are 0 indexed while ranges start at 1.
function updateAttendance(){
var itemSpreadsheetKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';
var openedSS = SpreadsheetApp.openById(itemSpreadsheetKey);
var sheetStudentNames = openedSS.getSheetByName("StudentNames");
var sheetDailyData = openedSS.getSheetByName("DailyData");
var app = UiApp.getActiveApplication();
var ss = SpreadsheetApp.openById(itemSpreadsheetKey);
var dailyDataSheet = ss.getSheetByName("DailyData");
var studentNameSheet = ss.getSheetByName("StudentNames");
var dailyData = dailyDataSheet.getDataRange();
var studentNames = studentNameSheet.getDataRange().getValues();
var dailyLastRow = dailyData.getLastRow();
var studentNamesLastRow = studentNames.getLastRow();
var studentNamesLastColumn = studentNames.getLastColumn();
var dailyDataNamesArray = sheetDailyData.getDataRange().getValues();
for (var i = 1 ; i < dailyDataNamesArray.length; i++) {
if (i != ""){
var dailyTime = dailyDataNamesArray[i][4];
for (var j=1; j<studentNamesLastRow; j++) {
var today = dailyDataNamesArray[0][7];
if (dailyDataNamesArray[i][0] == studentNames[i][0]) {
studentNames[0][studentNamesLastColumn+1] = today;
studentNames[j][studentNamesLastColumn+1] = dailyTime;
}
}
}
}
studentNameSheet.getRange(1,1,studentNames.length,studentNames[0].length).setValues(studentNames):
dailyDataSheet.getRange(1,1,dailyDataNamesArray.length,dailyDataNamesArray[0].length).setValues(dailyDataNamesArray):
return app;
}
Replace the code after the var dailyDataNamesArray line with the following. It's a bit of a guess, so I hope for you that it works:
var todayCell1 = studentNames.getCell(1, studentNamesLastColumn).offset(0, 1);
for (var i=1; i<=dailyDataNamesArray.length; i++) {
if (i != ""){
var dailyTime = dailyData.getCell(i, 5).getValue();
var dailyVar2 = dailyData.getCell(i, 1).getValue();
for (var j=2; j<=studentNamesLastRow; j++) {
var today = dailyData.getCell(1, 8).getValue();
if ( dailyVar2 == studentNames.getCell(j, 1).getValue()) {
todayCell1.setValue(today);
studentNames.getCell(j, studentNamesLastColumn).offset(0, 1).setValue(dailyTime);
}
}
}
}