How to insert a row when cell value changes in a column - google-apps-script

How to insert a row with value equal value of first row when cell value is different above cell in column H:H

I believe your goal as follows.
You want to insert a new row and put the header row to the inserted row using Google Apps Script.
In your question, you want to insert the new row when the value of column "F" is changed. But when I saw your sample image, the column is "H" instead of "F".
Unfortunately, I cannot understand about your actual goal. So in this answer, I would like to propose 2 patterns.
From your following replying,
The script is perfect. Can you modify the Text Color is RED and Fill Color is Yellow like a sample.
You want to put the values with the red font color and the yellow background color.
Sample script:
Before you use this script, please set the sheet name. And, in this sample script, the values of column "F" are checked. When you want to check the values of column "H", please modify "F2:F" to "H2:H".
function myFunction() {
const sheetName = "Sheet1"; // Please set the sheetname.
// 1. Retrieve values from the column "F".
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
let [temp, ...values] = sheet.getRange("F2:F" + sheet.getLastRow()).getValues();
// 2. Create an array including the row numbers for inserting new rows.
const insertRows = values.reduce((ar, [v], i) => {
if (v != temp) {
ar.push(i + 3);
temp = v;
}
return ar;
}, []);
// 3. Retrieve header row.
const header = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues();
// 4. Insert new rows and put the header row to the inserted row.
insertRows.reverse().forEach(i => {
sheet.insertRows(i);
sheet.getRange(i, 1, 1, header[0].length).setValues(header).setBackground("yellow").setFontColor("red"); // Modified
});
}
Note:
This sample script is used for your question and the sample image. So when you changed the structure of your Spreadsheet, the script might not be able to be used. Please be careful this.
Reference:
insertRows(rowIndex)

Related

Google Script: Find first empty cell in row, then add value

I want to create a macro that finds the leftmost empty cell in a row, then adds today's date to that row (as in setFormulaR1C1('=TODAY()') )
I have been able to get the last empty row or column from a sheet but not, specifically, the last empty cell from the row I'm standing on.
From I want to create a macro that finds the leftmost empty cell in a row, then adds today's date to that row (as in setFormulaR1C1('=TODAY()') ), I believe your goal is as follows.
You want to find the most left empty cell in the active row and want to put a formula of =TODAY() to the cell.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and save the script.
function myFunction() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getActiveRange();
const row = range.getRow();
const values = sheet.getRange(row, 1, 1, sheet.getLastColumn()).getDisplayValues()[0];
const column = values.findIndex(c => !c);
if (column == -1) return;
sheet.getRange(row, column + 1).setFormula("=TODAY()");
}
When this script is run, please select a cell in the sheet and run the script. By this, a formula of =TODAY() is put into the most left empty cell of the selected row.
When the empty cell is not found, the script is stopped.
If you want to fix the value of =TODAY() as the constant value, please modify it as follows.
From
sheet.getRange(row, column + 1).setFormula("=TODAY()");
To
const today = new Date();
today.setHours(0, 0, 0, 0);
sheet.getRange(row, column + 1).setValue(today);
References:
getActiveRange()
findIndex()

Google Sheet Macro - how do I return a column number based on dynamic cell contents?

I have the following code as a starting point. I want to select the entire column where row 3 contains a specific date value (it will be the date of the previous Monday; I have a formula returning this date in cell E1).
function selectDate() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss.getRange(3,?,1,ss.getMaxColumns()).activate();
}
Basically, the getRange column value would be interpreted as something like: "Find the column number where the value in row 3 is equal to the value in cell E1".
Any ideas would be very helpful, even if it's using a totally different method to achieve the same thing. Thank you so much!
In your situation, how about the following sample script?
Sample script:
function selectDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var searchValue = sheet.getRange("E1").getDisplayValue();
var res = sheet.getRange(3, 1, 1, sheet.getLastColumn()).createTextFinder(searchValue).matchEntireCell(true).findNext();
if (!res) return;
var column = res.getColumn();
sheet.getRange(1, column, sheet.getLastRow()).activate(); // Here, the found column is activated.
Browser.msgBox("Found column number is " + column); // Here, the found column number is shown in a dialog.
}
From your situation, I thought that getRange(3,?,1,ss.getMaxColumns()) in your script might be getRange(3, 1, 1, sheet.getLastColumn()).
When this script is run, row 3 is searched using the value of cell "E1". When the value is found, as a sample, the found column is activated and the column number is shown in a dialog. This is a sample. Please modify this for your actual situation.
Note:
If no column is selected, it is considered that the value of cell "E1" is not found in row 3. At that time, can you provide the detail of your Spreadsheet? By this, I would like to modify it.
Reference:
createTextFinder(findText) of Class Range

Script to move email addresses from one sheet to another

I have problems figuring out how to script the following:
1. I have a sheet tab_A:
Col_A, Col_B
URL_1, Email_1
URL_2, Email_2
URL_3, Email_3
1. I have a sheet tab_B:
Col_A, ..., Col_F
URL_3, empty
URL_1, empty
URL_2, empty
"..." means several columns with data.
I need a script that takes row for row in tab_A, copy the email address, find the correct row in tab_B (the same URL) and paste the email in Col F.
Any help is appreciated.
I believe your goal as follows.
You want to copy the values of the column "B" of "tab_A" to the column "F" of "tab_B" by checking the column "A" of "tab_A" and "tab_B" on the Spreadsheet.
For example, when the row 1 has URL_1, Email_1 on "tab_A" and the row 2 has URL_1 on "tab_B", you want to copy the value of Email_1 to the column "F" of "tab_B" with the same row.
In order to achieve your goal, I would like to propose the following flow.
Retrieve values from "tab_A" and create an object for searching the value of the column "A".
Create an array for putting values to "tab_B".
Put the values to "tab_B".
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and run myFunction. By this, the values are put to "tab_B". Before you use this, please set the sheet names for your actual situation.
function myFunction() {
// 1. Retrieve values from "tab_A" and create an object for searching the value of the column "A".
const ss = SpreadsheetApp.getActiveSpreadsheet();
const tabA = ss.getSheetByName("tab_A");
const sourceValues = tabA.getDataRange().getValues();
const obj = sourceValues.reduce((o, [a, b]) => Object.assign(o, {[a]: b}), {});
// 2. Create an array for putting values to "tab_B".
const tabB = ss.getSheetByName("tab_B");
const outputValues = tabB.getDataRange().getValues().map(r => [obj[r[0]] || ""]);
// 3. Put the values to "tab_B".
tabB.getRange(1, 6, outputValues.length, 1).setValues(outputValues);
}
Note:
When you want to use above script as the custom function, you can also use the following script. In this case, please put a custom formula of =SAMPLE(tab_A!A1:B, tab_B!A1:A) to the cell "F1" of "tab_B".
function SAMPLE(valuesOfTabA, valuesOfTabB) {
const obj = valuesOfTabA.reduce((o, [a, b]) => Object.assign(o, {[a]: b}), {});
return valuesOfTabB.map(r => [obj[r[0]] || ""]);
}
References:
getValues()
setValues(values)
Custom Functions in Google Sheets
reduce()
map()

Google sheets script that add a row

I donĀ“t know how to code or write scripts.
I have a recording script/macro that order/sort a range according to 2 conditions and is working great for my needs.
I would like however to add a functionality but don't know how to do it, I would like the script would add a blank row between the 1 of the conditions (column 34).
The first condition of the below script is to order/sort according to 2 words in column 34 (or AH), is it possible between that "frontier" to automatically add a blank row?
This is the code I have:
/** #OnlyCurrentDoc */
function Navios() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('u3:Ak').activate()
.sort([{column: 34, ascending: true}, {column: 22, ascending: true}]);
};
This is a example sheet (pls ignore the conditional format). I want a blank row between words "A decorrer" and "Concluido" in column AH (or 34)
Can someone help?
Thanks.
I believe your goal as follows.
You want to insert new row between the value of A decorrer and the value of Concluido at the column "AH" after the sort script was run in your function Navios().
Modification points:
In this case, I would like to suggest the following flow.
Run your script for sorting in the function Navios().
Add a script for inserting new row in the function Navios().
Retrieve values of the column "AH".
Retrieve the boundary of the values A decorrer and Concluido.
Insert new row between the values.
When above points are reflected to your script, it becomes as follows.
Modified script:
function Navios() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var range = spreadsheet.getRange('u3:Ak'); // Modified
range.activate().sort([{column: 34, ascending: true}, {column: 22, ascending: true}]); // Modified
// I added below script.
var values = range.offset(0, 13, range.getNumRows(), 1).getValues();
for (var i = 0; i < values.length; i++) {
if (values[i][0] != values[0][0]) {
spreadsheet.insertRowAfter(i + 2);
// spreadsheet.deleteRow(spreadsheet.getMaxRows());
break;
}
}
}
In this modified script, when the script is run, a row is added to the sheet. By this, the number of rows are increased every run. When you want to keep the number of rows when the script is run, please use the line of // spreadsheet.deleteRow(spreadsheet.getMaxRows());. By this, when new row is inserted, the bottom row of the sheet is deleted. By this, the number of rows are kept. But I'm not sure about your actual situation. So I suggested it as the additional information.
Reference:
insertRowAfter(afterPosition)

Score calculation, considering negative marking

I'm trying to find if I can ask a script to calculate a grade where for each good answer it gives +1, and for each wrong answer it substracts -0,25. The calculation will be made in column C, as shown in the screenshot. In the example, the correct score is 6,25 instead of 7.
BTW, the score calculation refers to the key answers on the row 2.
I believe your goal as follows.
You want to calculate for the values of column "C" by checking the background colors of each cell using Google Apps Script.
When the background color of cell is #3ace9c (green), you want to add 1.
When the background color of cell is #ff9900 (orange), you want to reduce 0.25.
You want to calculate for the values of column "C" by comparing the columns "D" to "M" at the row 2 (the referring answer) and each row (after row 3) using Google Apps Script.
When the columns "D" to "M" at the row 2 are the same with each row, you want to add 1.
When the columns "D" to "M" at the row 2 are NOT the same with each row, you want to reduce 0.25.
For this, how about this answer?
Pattern 1:
In this pattern, the background colors are used. The flow of this sample script is as follows.
Prepare an object including the color codes for "good" and "wrong" answers.
Retrieve the background colors from the range of "D3:M" in the sheet.
Calculate the values using the object and the background colors.
Put the values to the column "C" in the sheet.
Sample script:
function myFunction() {
const sheetName = "Sheet1"; // Please set the sheet name.
// 1. Prepare an object including the color codes for "good" and "wrong" answers.
const obj = {"#3ace9c": 1, "#ff9900": -0.25}; // Please set the color codes, if you change the color.
// 2. Retrieve the background colors from the range of "D3:M" in the sheet.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const backgrounds = sheet.getRange("D3:M" + sheet.getLastRow()).getBackgrounds();
// 3. Calculate the values using the object and the background colors.
const result = backgrounds.map(r => [r.reduce((c, e) => c += obj[e], 0)]);
// 4. Put the values to the column "C" in the sheet.
sheet.getRange(3, 3, result.length, 1).setValues(result);
}
Pattern 2:
In this pattern, the referring answer of the row 2 is used. The flow of this sample script is as follows.
Retrieve values from the range of "A2:M" in the sheet.
Retrieve the referring answer.
Calculate the values of each values by comparing the referring answer, and create an array including the result values.
Put the values to the column "C" in the sheet.
Sample script:
function myFunction() {
const sheetName = "Sheet1"; // Please set the sheet name.
// 1. Retrieve values from the range of "A2:M" in the sheet.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const values = sheet.getRange("A2:M" + sheet.getLastRow()).getValues();
// 2. Retrieve the referring answer.
const answers = values.shift();
answers.splice(0, 3);
// 3. Calculate the values of each values by comparing the referring answer, and create an array including the result values.
const result = values.map(([,,c,...dm]) => [dm.reduce((c, e, i) => e == answers[i] ? c + 1 : c - 0.25, 0)]);
// 4. Put the values to the column "C" in the sheet.
sheet.getRange(3, 3, result.length, 1).setValues(result);
}
References:
map()
reduce()
getBackgrounds()
getValues()
setValues()