Checkbox to Paste by last row in Column D - google-apps-script

Is it possible to:
have a checkbox (J2) copy a result (J3) and paste contentsOnly into another cell
(D13)
to then have the same checkbox copy a different result (shown in J3) and paste contentsOnly into the cell below the previous (D14).
lastly, loop step 2
.
Some of the searching and tried modifications:
var Col="A"; //Column that will find the last row not empty, can be assigned as parameter
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet2');
var yourRange = sheet.getRange(Col + 1).offset(sheet.getLastRow()-1, 0); //+1 spare 1 row after last row
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 4);
Also looking at this link to try and Determining the last row in a single column and continue.
.
Please find editable sheet below:
Trial - Checkbox to Paste by last row in Column D

Modification points:
In your situation, how about using this sample script? Ref When this sample script is used, the last row of the specific column can be retrieved. By reflecting this script in your script, I thought that your goal might be able to be achieved.
And, about your script, I thought that when the event object is used, the process cost can be reduced. Ref
When these points are reflected in your script, how about the following modification?
Modified script:
function onEdit(e) {
// Ref: https://stackoverflow.com/a/44563639
Object.prototype.get1stNonEmptyRowFromBottom = function (columnNumber, offsetRow = 1) {
const search = this.getRange(offsetRow, columnNumber, this.getMaxRows()).createTextFinder(".").useRegularExpression(true).findPrevious();
return search ? search.getRow() : offsetRow;
};
var {range} = e;
var sheet = range.getSheet();
if (sheet.getSheetName() != "Trail - Copy & Paste" || range.getA1Notation() != "J2" || !range.isChecked()) return;
var lastRowOfColumnD = sheet.get1stNonEmptyRowFromBottom(4);
lastRowOfColumnD = lastRowOfColumnD > 12 ? lastRowOfColumnD : 12;lastRowOfColumnD = lastRowOfColumnD > 12 ? lastRowOfColumnD : 12;
sheet.getRange("J3").copyTo(sheet.getRange(lastRowOfColumnD + 1, 4), { contentsOnly: true });
}
In this modification, when the checkbox of "J2" of "Trail - Copy & Paste" sheet is checked, the script works. And, the value of "J3" is copied to the next row of the last row of column "D".
From your reply of however, once all the data in cell D13:D are cleared, having a hard time doing the first copy and paste into D13. Do you know of any workaround for this?, I understood that you wanted to set the initial row number of 13. So, I modified abve script.

Related

Moving one row to bottom of a sheet after date has passed

I am looking for a macro that can help move a row of a sheet to the bottom of it once it passes a certain date. Basically this will be used for a meeting tracker and I'm trying to find a way to automatically move meetings to a "Completed" section once the date (located on Column F) passes.
I've created macros before to move things between sheets, but I'm unfamiliar with how to move things on the same sheet. Would anyone be able to help?
Here's the sheet: https://docs.google.com/spreadsheets/d/1EPueop9bdky_J8VgpFdSUzzsMRieRUreeCRIy18ScTY/edit#gid=0
I would like to move rows based on the date in Column F. Once it passes I would like it to move to the "Completed" section of the sheet. This is an active spreadsheet so the row "Completed" it's on could change as meetings are being added.
function moveActiveRowToBottom() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const r = sh.getActiveRange().getRow();
const vs = sh.getRange(r,1,1,sh.getLastColumn()).getValues();
sh.getRange(sh.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);
sh.deleteRow(r);
}
I believe your goal is as follows.
You want to check the date of column "F" of the sheet. When the date of column "F" is smaller than today, you want to move the row to the last row.
You want to achieve this in the same sheet in a Google Spreadsheet. And, the sheet has a row of "Completed" in column "A", you want to check the date of the above rows of the "Completed" row.
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. When you use this script, please run the function of myFunction().
function myFunction() {
const sheet = SpreadsheetApp.getActiveSheet(); // or const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
const row = sheet.getRange("A4:A" + sheet.getLastRow()).createTextFinder("Completed").findNext().getRow();
const now = new Date().getTime();
const moves = sheet.getRange("F4:F" + (row - 1)).getValues().reduce((ar, [f], i) => {
if (f && f.getTime() < now) {
const r = i + 4;
ar.push(sheet.getRange(`A${r}:F${r}`));
}
return ar;
}, []).reverse();
const len = moves.length;
if (len == 0) return;
const lastRow = sheet.getLastRow();
moves.forEach((r, i) => sheet.moveRows(r, lastRow - i + len - 1));
}
When this script is run, the column "F" of the rows from 4 to the "Completed" row is checked. And, when there are moving rows, the rows are moved to the last row of the sheet.
Note:
This sample script was tested using your provided Spreadsheet. When you change the Spreadsheet and/or your actual Spreadsheet is different from your provided Spreadsheet, this script might not be able to be used. Please be careful about this.
When I saw your sample Spreadsheet, it seems that the sheet name is Sheet 1. If you want to use the sheet using the sheet name, please be careful about this.
References:
reduce()
forEach()
moveRows(rowSpec, destinationIndex)

Googlesheet dropdown list to show/hide rows

I want to have various cells that have a dropdownlist to show/hide certain rows
I have the following table
If I select A2 (dropdownlist with AMERICAS_a and AMERICAS_s), with the _s option, I want to hide only rows 3 to 6
If I select A7 (dropdownlist with EUROPE_a and EUROPE_s), with the _s option, I want to hide only rows 8 to 12
I am using an Appscript which works only for 1 of the continent. I want to make it work for any of the Watchcell
function onEdit(a) {
var watchSheet = "Sheet1";
var watchCell = "A2";
var sheet = a.range.getSheet();
if (sheet.getName() !== watchSheet ||
a.range.getA1Notation() !== watchCell) {
return;
}
sheet.hideRows(2, 5);
switch (a.value) {
case "AMERICAS_a":
sheet.showRows(2, 5);
break;
case "AMERICAS_s":
sheet.showRows(2, 1);
break;
default:
}
}
But I am unsure how to add A7 as another watchcell. I have repeated the function onEdit(e) but only the last onEdit function works.
I believe your goal is as follows.
Your Spreadsheet has the data validation rules for several cells in the column "A".
When the value of the dropdown list is changed, you want to run the script.
For example, when the suffix letters of the value of the dropdown list are _s, you want to hide rows until the next dropdown list.
For example, when the suffix letters of the value of the dropdown list are _a, you want to show rows until the next dropdown list.
Modification points:
In your showing script, in the case of both values of AMERICAS_a and AMERICAS_s, the rows are shown.
From your question, I thought that when the position of data validation rules is retrieved, the script might become simple.
When these points are reflected in a sample script, it becomes as follows.
Modified script:
function onEdit(e) {
const sheetName = "Sheet1"; // Please set the sheet name.
const { range, value } = e;
const sheet = range.getSheet();
const row = range.rowStart;
const datavalidations = sheet.getRange("A1:A" + sheet.getLastRow()).getDataValidations();
if (sheet.getSheetName() != sheetName || !datavalidations[row - 1][0]) return;
datavalidations.splice(0, row);
const n = datavalidations.findIndex(([a]) => a);
sheet[value.slice(-2) == "_s" ? "hideRows" : "showRows"](row + 1, n > -1 ? n : datavalidations.length);
}
Testing:
When this script is used, the following result is obtained.
Note:
This sample script is for your sample showing Spreadsheet. So, when you change the structure of the Spreadsheet, this script might not be able to be used. Please be careful about this.
When this script is directly run with the script editor, an error like TypeError: Cannot destructure property 'range' of 'e' as it is undefined. occurs. Please be careful about this. Please change the dropdown list of the column "A".
References:
Simple Triggers
hideRows(rowIndex, numRows)
showRows(rowIndex, numRows)

Automatically populate cell in Google Sheets when another cell in same row is manually filled

In Google Sheets, I want to create a macro that will automatically populate a column in each row when another column in that row is manually filled. The autofilled cell will use a formula that takes a chunk of the information (date) that's been entered manually and use a formula to concatenate it with a random number in order to create a unique ID. After inserting and executing the formula, the macro needs to copy and then paste "values only" the result of that formula. The point is to automatically create a stable ID in response to a triggering event (entry of date in row).
In pseudocode, here's the process I'd like the macro to execute:
when (date in yyyy-mm-dd format entered into A[i]) {
fill B[i] with =CONCATENATE(SUBSTITUTE(LEFT(A[i], 7), "-", ""),RANDBETWEEN(0,1000000000));
copy B[i];
PASTE_VALUES B[i] in B[i];
}
Apologies if I've overlooked a previous answer that solves this problem. I'm not new to coding, but I am new to coding in Google Sheets and am not sure what terms or phrases to use to describe what I'm after.
I believe your goal is as follows.
For example, when a value with the format of yyyy-mm-dd is put to the cell "A1", you want to put the formula of =CONCATENATE(SUBSTITUTE(LEFT(A1, 7), "-", ""),RANDBETWEEN(0,1000000000)) to the cell "B1".
You want to fix the value of the formula as the value.
You want to achieve this using OnEdit trigger.
Added: You want to put the value to the column "B", when the column "B" is empty.
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. And, please set the sheet name you want to use. When you use this script, please put the value with the format of yyyy-mm-dd to the column "A", by this, the script is run.
function onEdit(e) {
const sheetName = "Sheet1"; // Please set the sheet name.
const range = e.range;
const sheet = range.getSheet();
const [a, b] = range.offset(0, 0, 1, 2).getDisplayValues()[0];
if (sheet.getSheetName() != sheetName || range.columnStart != 1 || !/\d{4}-\d{2}-\d{2}/.test(a) || b) return;
const dstRange = range.offset(0, 1);
dstRange.setFormula(`=CONCATENATE(SUBSTITUTE(LEFT(${range.getA1Notation()}, 7), "-", ""),RANDBETWEEN(0,1000000000))`);
SpreadsheetApp.flush();
dstRange.copyTo(dstRange, { contentsOnly: true });
}
Reference:
Simple Triggers
This is the script I came up with:
/** #OnlyCurrentDoc */
function onEdit(e) { //Runs every time the sheet is edited
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1'); //Change this to whatever your sheet is named
var inputCol = sheet.getRange('A1'); //Change this to whatever column the date is going to be entered
//This is the range that will be checked. Slightly redundant, but makes it easier to reuse this script without needing to retype every variable
var myRange = inputCol;
//Get the row & column indexes of the active cell
var row = e.range.getRow();
var col = e.range.getColumn();
//Check that your edited cell is within the correct column
if (col == myRange.getColumn()) { //This runs only if a value is entered into the column defined in 'inputCol'
if(sheet.getRange(e.range.getA1Notation()).getValue() == '') {return}; //If the edited cell is empty (ie the date is deleted, nothing happens)
if(row == 1) {return} //If the header is changed, nothing happens
let codeCell = sheet.getRange('B'+row); //Change to the column that will store the generated code value
codeCell.setValue('=CONCATENATE(SUBSTITUTE(LEFT(A'+row+', 7), "-", ""),RANDBETWEEN(0,1000000000))');
let hardValue = codeCell.getValue(); //Gets the value from the formula you just entered
codeCell.setValue(hardValue); //Replaces the formula with just the resulting value
};
}
Comments are included to explain everything that is happening. Linked below is the spreadsheet I used to test this. It is set to allow editing, so feel free to use it to test the script yourself.
https://docs.google.com/spreadsheets/d/1UONgRPBEbxn8CQeiRSPS4eFKHjh4ae8hXGYn6ImHxeI/edit?usp=sharing
Hope this helps!

Copy & Delete Function on Sheets w/ Apps Script

After someone submits a Google Form response, their responses go to the DropRequests sheet (although the form is not currently linked for reasons).
What we want to do is after someone submits their form, and their responses go to the DropRequests sheet, that if the value in column C matches that of column F in the StudentMatches sheet, it is moved to the OldMatches sheet. We have started on the code below but it does not yet work. Any ideas on how to make this functional and fix the issue with the range in the last line?
function moveMatch(){
var oldmatches = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("OldMatches");
var droprequest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DropRequests");
var currentmatches = SpreadsheetApp.openById('1dd9UhD2LpshCFVYizpf3OwI1XzPrq3AfqhMAO1iJ6Ns')
value1 = currentmatches.getRange("F:F").getDisplayValues();
value2 = droprequest.getRange("C:C").getDisplayValues();
for(var i in value1)
if(value2[0,i]=value1){
currentmatches.getDataRange.getRow(0,i).moveTo(oldmatches.getLastRow())
}
}
Thank you again.
I believe your goal is as follows.
There are 3 sheets DropRequests, StudentMatches, OldMatches in your Spreadsheet.
You want to retrieve the values of column "C" from DropRequests sheet, and want to compare these values with the values of column "F" of StudentMatches sheets.
When the values are matched, you want to move the row from the StudentMatches sheet to the 1st empty row of OldMatches sheet.
When moveTo is used, the moved row becomes the empty row. In your goal, you want this situation.
In this case, how about the following sample script?
Sample script:
function moveMatch() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet1 = ss.getSheetByName("DropRequests");
var srcSheet2 = ss.getSheetByName("StudentMatches");
var dstSheet = ss.getSheetByName("OldMatches");
var srcValues1 = srcSheet1.getRange("C2:C" + srcSheet1.getLastRow()).getValues().map(([c]) => c);
var [,...srcValues2] = srcSheet2.getDataRange().getValues();
var values = srcValues2.flatMap((r, i) => srcValues1.includes(r[5]) ? i + 2 : []);
if (values.length == 0) return;
var lastCol = srcSheet2.getLastColumn();
var lastRow = dstSheet.getLastRow();
values.forEach((r, i) => srcSheet2.getRange(r, 1, 1, lastCol).moveTo(dstSheet.getRange(lastRow + 1 + i, 1)));
}
In this modification, the values are retrieved from the column "C" of "DropRequests" and "StudentMatches". And, the values of the column "C" of "DropRequests" are compared with the column "F" of "StudentMatches" sheet. When the values are matched, the row is moved from "StudentMatches" to "OldMatches".
Note:
First, please check the sheet names, again.
This sample script is for your question. So, when the Spreadsheet is changed, this script might not be able to be used. Please be careful this.
References:
forEach()
moveTo(target)

How can I make the following code move information into two columns instead of one in google sheets?

function setCalculate(){
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1M/edit#gid=0");
var srcSheet = ss.getSheetByName("AutoQuoteDataBase");
var lastRow = srcSheet.getLastRow();
var values = srcSheet.getRange("A2:BY" + lastRow).getValues();
var res = values.flatMap(r => r[76] == 1 ? [r[1]] : []);
if (res.length == 0) return;
srcSheet.getRange("BW2").setValue(res[0]);
}
This code works perfectly for its original purpose which was to copy IDs from Column B, say B2 is 'w131' and B3 is 'z1122', etc.
I needed Cell BW2 to be filled with one of these IDs if I put a '1' in column BY,
and it has to be the corresponding ID so putting a '1' in BY2 fills BW2 with 'w131' and putting a '1' in BY3 fills BW2 with 'z1122' etc.
What I need is for the same row to be moved from column BZ into CB2 when the code is triggered.
I believe your goal is as follows.
You want to copy the cell "B" to "BW" when the cell "BY" is edited to 1.
You want to run the script by a trigger.
In this case, how about the following modification?
Modified script:
Please copy and paste the following script to the script editor and save the script. When you use this script, please put 1 to the column "BY" of "AutoQuoteDataBase" sheet. By this, the script is run.
function onEdit(e) {
var range = e.range;
var sheet = range.getSheet();
if (sheet.getSheetName() != "AutoQuoteDataBase" || range.columnStart != 77 || range.getValue() != 1) return;
sheet.getRange("B" + range.rowStart).copyTo(sheet.getRange("BW" + range.rowStart), {contentsOnly: true});
Note:
This script is run by a simple trigger of onEdit. So when you directly run this script, an error like TypeError: Cannot read property 'range' of undefined occurs. Please be careful about this.
For example, when you want to copy the column "B" to the column "BW" by checking the column "BY" without using onEdit, you can also use the following script. In this case, you can directly run this function with the script editor.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = ss.getSheetByName("AutoQuoteDataBase");
var lastRow = srcSheet.getLastRow();
var values = srcSheet.getRange("A2:BY" + lastRow).getValues();
var res = values.map(r => [r[76] == 1 ? r[1] : null]);
if (res.length == 0) return;
srcSheet.getRange("BW2:BW" + (res.length + 1)).setValues(res);
}
Reference:
Simple Triggers