Set column value via script in google sheets - google-sheets

I am trying to index my google sheet, based on an if condition. So, if the 3 column data is not empty, I want the first column of the sheet to get indexed. In the code below, the if statement is working fine, but I am unable to set the value of index in the first column.
var sheetFrom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("production");
var data = sheetFrom.getDataRange().getValues();
var count = 0;
var farmerCount = 0;
for(n=3;n<data.length;++n){ // iterate in the array, row by row
if (data[n][2]!=""){
farmerCount++;
data[n][0].setValue(farmerCount);
//sheetFrom.getRange(n, 0).setValue(farmerCount);
}
Thanks in advance.

Range indexing in Google Apps Script is 1 based so you want to use
sheetFrom.getRange(n, 1).setValue(farmerCount);
Possibly n+1 depending on how many header rows you have.

Related

Can I update Google Form questions with a spreadsheet?

I have tons of Google Forms for a project and each one has the same sections and questions, just different choices. Every time I want to update a question, I have to change each form individually which takes a lot of time. I was wondering if there's a way to link a Form to a Sheet so I can change the question in the spreadsheet and it'll update in every single form connected.
One option I could suggest is to create a container-bound script in your Google Sheets to update the questions for multiple Google Forms using Apps Script.
Example Sheet:
We have a Google Sheet with 2 Sheets named "Questions" and "Forms" respectively.
Sheet:Questions contains the list of questions available in your Google Forms. To Update column can be used as a flag to determine which questions you want to update in the Google Forms.
Sheet:Forms contains the list of Google Forms Ids' where you want the questions to be updated.
Example Apps Script Code:
function updateFormsQuestions() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formsSheet = ss.getSheetByName("Forms");
var questionsSheet = ss.getSheetByName("Questions");
//Get the list of forms to update
var formsList = formsSheet.getRange(2,1,formsSheet.getLastRow()-1).getValues();
Logger.log(formsList);
//Get the list of questions to update
var questionIndex = [];
var qCheckbox = questionsSheet.getRange(2,2,questionsSheet.getLastRow()-1,1).getValues();
Logger.log(qCheckbox);
qCheckbox.forEach(function(currentValue, index){
if(currentValue[0] == true)questionIndex.push(index);
});
Logger.log(questionIndex);
//Open Form and get all items
for( var i = 0; i < formsList.length; i++){
var forms = FormApp.openById(formsList[i][0]);
var items = forms.getItems();
//Update question
questionIndex.forEach(function(index){
Logger.log(index);
Logger.log(questionsSheet.getRange(index + 2, 1).getValue());
items[index].setTitle(questionsSheet.getRange(index + 2, 1).getValue());
});
}
}
What it Does?
Get the list of Google Forms Ids' under Sheet:Forms
Get all checkbox values under Sheet:Questions starting from Cell B2.
Check each checkbox values if set to true, then push the current index to the questionIndex array. (Note that in javascript array index starts from zero).
Open each forms listed in step 1, one-by-one using for-loop using FormApp.openById(). Then get all items of the current forms using .getItems(). It will give you an array of items available in your form (this may represent your questions in your form).
Forms items can be accessed as an array. Hence it should start from zero. (Question 1 = index 0, Question 2 = index 1 ... so on)
Update the questions in the current item using .setTitle(). The new title will be based on the cell value under Sheet:Questions column A. You can get the value of the cell using .getValue() assuming you already selected the correct cell range using .getRange().
Notice that we increment the row index by 2 when getting the cell value questionsSheet.getRange(index + 2, 1).getValue(). Cell rows and columns starts from 1 in sheets, if we want to access Cell A3, row = 3; col = 1. The index that we saved earlier in Step 3 starts from zero (since we used an array). If you are curious why we increment 2 instead of 1. The reason is because we also adjusted the indexing when we start getting the checkbox values from row 2 instead of row 1 in Step 2.
Sheet:Questions Column C will show you the indexing of the qCheckbox array, while Column D will show you the indexing of sheets when accessing rows.
Output:
BEFORE:
AFTER:
Additional References:
Forms Service - allows scripts to create, access and modify Google Forms
Spreadsheet Service - allows scripts to create, access, modify Google Sheets

How to get list of row that has value from a range of data based on column header as the criteria?

I have a range of data populated from a google form in sheet "Data".
I need to make a report (in sheet "Report") that shows the students attendance, based on name (from drop down list). The data that is blank is excluded in that report, as seen in column i to column k
desired result
I have shared the sheet here
I have tried to use filter
=filter(Data!B1:I20,Data!E1:E20<>"")
but still I cant find the way to change the "condition" in this formula to refer to the sheet Report A1.
what is the correct formula to achieve this?
Thanks you for your help.
Using Apps Script you will have to use the function getSheetByName(name).
Example:
// The code below logs the index of a sheet named "Expenses"
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Expenses");
if (sheet != null) {
Logger.log(sheet.getIndex());
}
Then to find from column E the rows that have value you would have to use the getRange(a1Notation) method:
// Get a range A1:D4 on sheet titled "Invoices"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("Invoices!A1:D4");
// Get cell A1 on the first sheet
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("A1");
Then you would have to iterate over that rows and get the rows where the E column has something.
Once you have that you can get the Report sheet and set the values there with setValues(values)
For more information on how the function you may need to use you have the reference of SpreadsheetApp and the overview on Extending Google Sheets

Google Apps Script for Multiple Find and Replace in ONE COLUMN in Google Sheets

Referencing: Google Apps Script for Multiple Find and Replace in Google Sheets
I'd like to use this same code for my purposes but only within 1 column... Any advice on how to limit this script to only one column? The reason is that when I run this to change Department Names in Column J, it works perfectly, except it also changes the 'Data Type' in my Date (Columns L and M) to include timezones, and that messes up other Sheets referencing those dates... Thanks!
I ended up switching out
function replaceInSheet(sheet, to_replace, replace_with) {
//get the current data range values as an array
var values = sheet.getDataRange().getValues();
with
function replaceInSheet(sheet, to_replace, replace_with) {
//get the current data range values as an array
var values = sheet.getRange('J:J').getValues();

Remove rows based on duplicates in a single column in Google Sheets

I have spreadsheet similar to this:
I'd like to remove all duplicates of row based on the first column data.
So from this screenshot row, 1 and 2 would be kept, and row 2 would be removed. Any help would be greatly appreciated.
P.S. In my case I have columns from A to AU and rows from 2 to 9500.
Thank you.
Maya's answer and the solution AJPerez linked both work.
You can also use Filter View, which doesn't require deleting rows or creating new rows/sheets.
First create a helper column, say to the left of all your data. If your data starts on row 1, then create a blank row above all your data; if not, you are fine. Afterwards, on the first row where you have data, say row 2, write in the formula
=iserror(match(B2,B$1:B1,0))
Replace "2" with the row number of the first row of your data and "1" with that number minus 1. Also populate the rest of the column with the formula. (Unfortunately, arrayformula doesn't work here.) The formula outputs TRUE when the entry in B# has not occurred in cells above.
Note that this assumes your data now starts with column B and column B is where you want the filter to base. If that's not the case, just edit the column index too accordingly.
Select this new helper column. Go to Data -> Filter Views... -> Create a new Filter. Select filter by value and check TRUE only.
Caveat: this filter can only work if there are actually rows with TRUE value. This will always be the case as some entries are always unique.
If you want to avoid the caveat in your future applications, you can use filter by conditions with custom formula. The formula b2 should work.
But to begin with, even without the helper column, the above formula should work. Why doesn't it? That would be a good question for Google Support should it exist.
You can also use a google apps script to do this. To open the script editor from google sheets:
Choose the menu Tools > Script Editor.
Copy and paste the following script:
function removeDuplicates() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var newData = [];
var ids = [];
for (var i in data) {
var row = data[i];
var duplicate = false;
if (ids.indexOf(row[0]) > -1) {
duplicate = true;
} else {
duplicate = false;
ids.push(row[0]);
}
if (!duplicate) {
newData.push(row);
}
}
sheet.clearContents();
sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData);
}
This assumes that you want to dedupe based on the contents of the first row of you sheet. If not you can adjust the row references from the 0 index to any other index you wish.
I would...
Create a new sheet
For column A, do =Unique(Sheet1!A:A)
Simply use VLOOKUP to populate the other columns. This will deliver the first value associated with the duplicates.

Creating a Macro in google spreadsheet to search and then write text

What I am trying to accomplish is I would like to search for a term in one cell, if that cell has the term write text to another cell. My specific example would be I would like to search for the term 'DSF' in column 4. If I find 'DSF' it would then write 'w' in column 5 & write '1.2' in column 3. This is searched per row.
I do understand the the .setvalue will write the needed text, but I do not understand how to create a search function. Some help would be greatly appreciated.
EDIT
Here is the code I am working with at the moment. I am modifying it from something I found.
function Recalls()
{
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues(); // read all data in the sheet
for(n=0;n<data.length;++n){ // iterate row by row and examine data in column D
if(data[n][3].toString().match('dsf')=='dsf'){ data[n][4] = 'w'}{ data[n][2] = '1.2'};// if column D contains 'dsf' then set value in index [4](E)[2](C)
}
//Logger.log(data)
//sh.getRange(1,1,data.length,data[3].length).setValues(data); // write back to the sheet
}
With the Logger.log(data) not using the // It works properly but it overwrites the sheet, which will not work since I have formulas placed in a lot of the cells. Also, Maybe I did not realize this but Is there a way to do a live update, as in once I enter text into a cell it will research the sheet? Otherwise having to 'run' the macro with not save me much time in the long run.
Try this. It runs when the sheet is edited. It only captures columns C,D,&E into the array and only writes back those columns. That should solve overwriting your formulas. It looks for 'DSF' or 'dsf' in column D (or contains dsf with other text in the same cell either case). Give it a try and let me know if I didn't understand your issue.
function onEdit(){
var sh = SpreadsheetApp.getActiveSheet();
var lr = sh.getLastRow()// get the last row number with data
var data = sh.getRange(2,3,lr,3).getValues(); // get only columns C.D,& E. Starting at row 2 thur the last row
//var data = sh.getDataRange().getValues();// read all data in the sheet
for(n=0;n<data.length-1;++n){ // iterate row by row and examine data in column D
// if(data[n][0].toString().match('dsf')=='dsf'){
if(data[n][1].match(/dfs/i)){ //changed to find either upper or lower case dfs or with other text in string.
data[n][2] = 'w';
data[n][0] = '1.2'};
}
sh.getRange(2,3,data.length,data[3].length).setValues(data); // write back to the sheet only Col C,D,& E
}

Resources