In google sheets, how do I copy (Not Move) entire row to another sheet based on a word (Not single value) in a cell - google-sheets

I would like to copy (Not move) the entire row to another sheet when there is a specific word in a cell.
I have a sheet named "List" with 7 columns, in the the 7th column I put notes for each row. Every time I write the word "Lead" in that column, I would like that entire row to be copied to another sheet named "Opportunity". Please note that the word "Lead" will be followed by other words in that cell, example: "Lead, wants tree removed and landscaping service". So its not a single value.
Thank you very much for the help.

You can create your custom function for this.
Steps:
Tools-> Script editor.
For example write:
function myFunction(input) {
return input;
}
Go to Resources -> Triggers of current project -> Add trigger
Choose your function name (myFunction), from table, changes then save
In Google sheet cell write for example
=myFunction(A1)
and change A1 cell. You will get changes.
Code of working function that copy cells value if they have word "Lead" :
function myFunction(input) {
var array = [''];
if(typeof input != 'object') {
return array;
} else {
for (var name in input) {
for (var name2 in input[name]) {
if(input[name][name2].toString().indexOf('Lead') != -1) {
array.push(input[name]);
}
}
}
}
if(array.length > 1) {
array.splice(0, 1);
}
return array;
}
Usage. In second sheet (Opportunity) past in any cell:
=myFunction('List'!A1:G50)
Here is link with working formula.

This should be possible with QUERY(). Assuming the source sheet is 'Sheet1', in sheet 'Opportunity' enter in A1:
=QUERY('Sheet1!A1:G', "where G contains 'Lead'", 1)
Change sheet name and ranges to suit.

Related

Force Dropdowns to Display in B2:B When Adjacent Cell in A2:A Has Data

In this sample Google Sheet that you can edit, I'm trying to configure the data validation dropdown menus in B2:B to only display when the adjacent cells in A2:A have data in them. As you can see in my spreadsheet, I have the data validation configured alright, but it inserts dropdown menus all the way down column B, even if there's no data next to it in Column A, and I don't want that.
How can I configure this to where Data Validation dropdown menus only display when there is data in adjacent cells in column A?
Thanks for your help!
You need a script
function onEdit(event){
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (r.getColumn() == 1 && s.getName() == 'Dropdowns'){
r.offset(0,1).clearContent()
if (r.getValue() == ''){
r.offset(0,1).clearDataValidations();
}
else{
var lists = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Colors');
r.offset(0,1).setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(true)
.requireValueInRange(lists.getRange('A2:A'+lists.getLastRow()), true)
.build());
}
}
}

Sorting data in a sheet with added information Google Sheets

My work has a Google Form where different information is inputted. All this information is then automatically put into a Google Sheet. We will call it "All data sheet".
"All data sheet" has multiple sheets in it, one with all of the data and then one for each type of data which needs to be given to different people. One of those is called 'Caretaker'.
I then have a second Google Sheet (example called 'Sorting') that pulls everything from the 'Caretaker' sheet onto 'Import_range'.
This allows the caretaker to see everything that needs fixing with the oldest thing at the top and the newest at the bottom.
The caretaker would like the newest at the top.
I can easily make another sheet (see 'Sorted') that uses the sort function to put the newest at the top.
However, he would also like another column where he can either check a box to show it's done or write an x.
When new data appears, the checked box does not move down.
Is there any way to sort the data but also have an input column which stays with the sorted data?
Link to example.
You have to use Google Apps Script.
Try this:
To start, go to Tools and click Script editor.
Delete the code in Code.gs
Paste the code provided below and save
Refresh your Spreadsheet and Custom Menu will pop up in the Menu
Go To Custom Menu and Click Update Sorted Sheet
First execution will require user's authorization. Once you authorized the script, make sure to rerun the Custom Menu.
The code below will create a Custom Menu in your Spreadsheet. Clicking the custom menu will execute a function that will update the Sorted Sheet and retain its checkbox values.
I also added comments to explain the function of each line in the code.
Code:
function updateSorted() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Import_range");
var sortedSh = ss.getSheetByName("Sorted");
/* Use this if the Import_range is from different spreadsheet
var iSS = SpreadsheetApp.openById("Insert Sheet ID here");
var sh = iSS.getSheetByName("Insert Sheet name here");
and comment the var sh = ss.getSheetByName("Import_range"); above*/
/*
Check if the Sorted Sheet has data.
If true, compare Sorted Sheet and Import_range data
else, copy Import_range data to Sorted Sheet.
*/
if(sortedSh.getLastRow() > 1){
var sData = sortedSh.getRange(2, 1, sortedSh.getLastRow()-1, 5).getValues(); //remove unnecessary data
var sDataFiltered = sData.filter(e => e[4]); //get Date column of Sorted sheet
var sDates = sortedSh.getRange(2, 5, sortedSh.getLastRow()-1, 1).getValues().flat();
var sDatesFiltered = sDates.filter((a) => a); //remove unnecessary data
var importDates = sh.getRange(2, 4, sh.getLastRow()-1, 1).getValues().flat(); //get Date column of Import_range
//convert dates to String format
var arr1 = sDatesFiltered.map( dateString => String(dateString))
var arr2 = importDates.map( dateString => String(dateString))
var difference = arr2.filter(x => !arr1.includes(x)); //get the difference between arr1 and arr2
difference.forEach(dates => {
var index = arr2.indexOf(dates); //get new entry position in Import_range
var newEntry = sh.getRange(index+2, 1, 1, 4).getValues().flat(); //get row data of new entry from Import_range
newEntry.unshift(false); //append false in the beggining of the array
sDataFiltered.push(newEntry); //append new entry to sDataFiltered array
})
var range = sortedSh.getRange(2, 1, sDataFiltered.length, 5);
range.setValues(sDataFiltered); //set the values of Sorted sheet using the sDataFiltered array as data
sortedSh.getRange(2, 1, sDataFiltered.length, 1).insertCheckboxes(); //get the checkbox range and insert checkbox
range.sort({column: 5, ascending: false}); //sort the data by Date column
}else{
var range = sh.getRange(2, 1, sh.getLastRow()-1, 4);
var data = range.getValues();
data.forEach(row => {
row.unshift(false)
})
var sortedRange = sortedSh.getRange(2, 1, data.length, 5);
sortedRange.setValues(data);
sortedSh.getRange(2, 1, data.length, 1).insertCheckboxes();
sortedRange.sort({column: 5, ascending: false});
}
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Custom Menu')
.addItem('Update Sorted Sheet', 'updateSorted')
.addToUi();
}
Examples:
Populating Empty Sorted Sheet:
Updating Import_range sheet, clicking checkboxes and updating Sorted Sheet:
Implementing Time Driven Triggers:
Open your Apps Script project.
At the left, click Triggers alarm.
At the bottom right, click Add Trigger.
Select and configure the type of trigger you want to create.
Click Save.
For time driven, your trigger setup should somehow look like this:
The example trigger above will update the sheet every minute. The down side of using time driven trigger is the quota limit. Gmail accounts are limited to 90 minutes of total runtime. Exceeding quotas will result to errors. See Quotas for Google Services.
Using Buttons: Alternative to Custom Menu
To create a user friendly button in your Sheet
Go to Insert -> Drawing
Draw the desired button shape and style.
Click Save and Close
Move the button to your desired position
Right click, click the 3 vertical dots and select Assign script
Type updateSorted and click OK
Click the button to run
Note: If you decided to use buttons and want to remove the Custom Menu in your sheet, just remove the onOpen function in your Apps Script.
References:
Google Apps Script on Sheets
Custom Menu
Simple Triggers
Class Sheet
Class Range
Class Spreadsheet
Installable Trigger

Multiple data validations in google sheets problem

I have a dropdown menu in A1 but I want it to reject input if B1 says "Closed". It won't let me keep the dropdown box as soon as I create the data validation for rejecting input. How do I fix this?
It is not possible to add 2 different data validation criteria in the selected range.
One workaround that you could do is to use data validation to have a drop-down menu and create an onEdit() function in Apps Script that will reject the inputs.
Sample Code:
function onEdit(e){
var cell = e.range;
var col = e.range.getColumn();
var ui = SpreadsheetApp.getUi();
//Check if current edited cell is in column 1 and if the cell besides the current cell is Closed
if(col == 1 && cell.offset(0,1).getValue() == "Closed"){
//Display warning message
ui.alert(
'Warning',
'You cannot modify cells that are closed, returning the original value of the cell',
ui.ButtonSet.OK
)
//return cell to its original value
cell.setValue(e.oldValue);
}
}
What it does?
Check if the modified cell is in column 1 and verify if the adjacent cell on its right has the value "Closed"
If true, display a warning message and return the cell to its original value
Output:
I used Range.offset(rowOffset, columnOffset) to get the value of the cell on the right side of the current cell by using +1 as column offset.
Additional Reference:
Container-bound Scripts
Google Sheets events

Trying to create a script editor code for sheet3 only

I'm trying to make a Y/N popup box appear when you open the sheet3 on a Googlesheet file. So far I have this code:
function onOpen() {
var ui = SpreadsheetApp.getUi();
var result = ui.alert(
'Please confirm',
'Have you sorted the Calculations Page?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
ui.alert('Thank you, you may continue.');
} else {
// User clicked "No" or X in the title bar.
ui.alert('Please sort the Order Number column.');
}
}
But with this code, it applies when I open the document, and only when I open the document. I'd like it so the box appears when I open the sheet3 tab. Extra points if there is a way to take me to sheet2 if you click 'No' on the box!

Vaadin grid - change component column in one row only

I have a grid with several columns. For three columns i used the column renderer. Each of the columns contains one button.
If i click one of those buttons, i want to replace the three buttons in that specific row with two other buttons. All the other rows should not be affected. Is this possible in a Vaadin grid?
Components in different columns don't know each other, as they are all defined in a separate scope (in the componentRenderer of their own column. You cannot define the Button outside of the componentRenderer as you found out in another question today). So the "obvious" solution won't work, where you add a clickListener on the Button to directly change the other buttons.
If you had one column with 3 Buttons inside then this would be much easier.
There is a way, but I see this more as a hack than as a solution. Because you need some extra implementation in the item class for this to work.
In the ComponentRenderer, you can add an if-statement where you look at some value of the item. In one case, you'll render button 1, in the other case you'll render the other button. And in the click listeners of the button you change that value in the item and refresh the dataprovider, so the componentRenderer is invoked again. It will now see the value on the item has changed, therefore displaying some other Button.
Here is some code to show what I mean:
// grid item class
public class Foo {
private boolean buttonPressed = false;
public Foo(){
}
public isButtonPressed(){
return buttonPressed;
}
public setButtonPressed(boolean buttonPressed){
this.buttonPressed = buttonPressed;
}
}
// adding of button columns
// do this 3 times for a test of your scenario.
grid.addComponentColumn(item -> {
if(!item.isButtonPressed()){
return new Button("Before Button was Pressed", click -> {
item.setButtonPressed(true);
grid.getDataProvider().refresh(item);
});
} else {
return new Button("Button was Pressed", click -> {
item.setButtonPressed(false);
grid.getDataProvider().refresh(item);
})
}
})

Resources