Data Validation between workbooks in Google sheets - google-sheets-query

I've been having some trouble moving data from one source Spreadsheet to another, and having my formulas work. An overview of what I'm trying to do is have Spreadsheet 2 (the active document) pull information from Spreadsheet 1 (the source document). The code I made and was using before looked into a data validated dropdown list and then auto populated a new dropdown list. I want to automate the 1st data validated column and then have the same code run. I've put the code I'm having trouble with below. I am pretty new to this so any help would be much appreciated.
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var datass = SpreadsheetApp.openById("1APLcwkIE2EqVSS6Zongy799yg4z2tAN9J7h3jlJoBgQ").getSheetByName("Master List");
var activeCell = ss.getActiveCell();
var makes = datass.getRange(1, 1, 1, datass.getLastColumn()).getValues();
var makeIndex = makes[0].indexOf(activeCell.getValue()) + 1;
if(activeCell.getColumn() == 1 && activeCell.getRow() > 1) {
activeCell.offset(0, 1).clearContent().clearDataValidations();
if(makeIndex != 0) {
var validationRange = datass.getRange(2, makeIndex, datass.getLastRow());
var validationRule = SpreadsheetApp.newDataValidation().requireValueInRange(validationRange).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
} }

So, I didn't find any script very easily but I found an add on that helped so much with this! Use SheetGo for anyone who has a similar issue, if your looking for an easy answer!

Related

Dependent Dropdowns: 1 Independent, multiple dependent

So, this goal seemed simple at first, but I can't seem to wrap my head around how to accomplish it.
I have these independent dropdowns, with between 3 to 4 dependent dropdowns associated with each independent. I would like to be able to apply the associated dependent dropdowns when the independent dropdown is selected.
Example: Dropdowns in Column A have 3-4 variables associated with them (https://docs.google.com/spreadsheets/d/1ErRBqfEeRqTNLIH0N11IjViP-_ej1LMdrOXNvDOcsx8/edit?usp=sharing)
In the following code, I can apply 1 independent, and 1 dependent, but I can't figure out how to scale it to my needs:
function onEdit(){
var tabLists = "Lists";
var spreadsheet = SpreadsheetApp;
var activeSheet = spreadsheet.getActiveSpreadsheet().getActiveSheet();
var data = spreadsheet.getActiveSpreadsheet().getSheetByName(tabLists);
var activeCell = activeSheet.getActiveCell();
if(activeCell.getColumn() == 1 && activeCell.getRow() > 1 && activeSheet.getSheetName().includes("Programming")){
activeCell.offset(0, 1).clearDataValidations(); //Clears data validation 1 column over
var exerciseCat = data.getRange(1, 1, 1, data.getLastColumn()).getValues();
var catIndex = exerciseCat[0].indexOf(activeCell.getValue()) + 1;
if(catIndex != 0){
var validationRange = data.getRange(3, catIndex, data.getLastRow());
var validationRule = spreadsheet.newDataValidation().requireValueInRange(validationRange).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
}
}
I thought that maybe my answer existed within making a 4-level dependent dropdown, but that didn't work either.
All help is greatly appreciated, as I am still quite new to any form of coding.
From your showing script, I guessed that you might have wanted to directly run the script with the script editor. So, in this modification, I didn't use the event object. By this, you can run the script with the OnEdit trigger and also directly run this modified script with the script editor.
And, in your script, only the data validation of column "B" of "Programming" sheet is set. In order to set other columns, I prepared an object for retrieving the values for setting the data validation rules.
So, how about the following modification?
Sample script:
function onEdit() {
var tabLists = "Lists";
var spreadsheet = SpreadsheetApp;
var activeSheet = spreadsheet.getActiveSpreadsheet().getActiveSheet();
var data = spreadsheet.getActiveSpreadsheet().getSheetByName(tabLists);
var activeCell = activeSheet.getActiveCell();
// I modified below script.
var row = activeCell.getRow();
if (activeCell.getColumn() == 1 && row > 1 && activeSheet.getSheetName().includes("Programming")) {
var obj = { "Top Sets": [1, 2, 3], "Top Set/Percentage": [4, 5, 6, 7] };
var v = activeCell.getValue();
if (!obj[v]) return;
activeCell.offset(0, 1, 1, activeSheet.getLastColumn() - 1).clearContent().clearDataValidations();
var lastRow = data.getLastRow();
var rules = obj[v].map(r => {
var r = data.getRange(3, r, lastRow - 2, 1);
return SpreadsheetApp.newDataValidation().requireValueInRange(r).build();
});
activeCell.offset(0, 1, 1, rules.length).clearContent().setDataValidations([rules]);
}
}
When the column "A" of "Programming" sheet is edited, this script is run. And, by the value of column "A", the data validation rules of other columns are put.
Note:
This modified script can be tested using your provided Spreadsheet. So, when you change the Spreadsheet, this script might not be able to be used. Please be careful about this.

Copying & pasting drop down lists clears cells

So I'm quite new to script, and I've got some working dynamic dependent drop down lists. When I clear a cell in column A, it clears the cell directly to the right of it, which is great.
However, when I copy and paste a row, it clears the cell to the right of column A. My question is: Is there a way to make a row "copy & paste-able", so it doesn't clear column B when pasting?
Here are some images of what I'm describing:
[1]: https://i.stack.imgur.com/F0xOg.png
[2]: https://i.stack.imgur.com/geHuu.png
Lastly, here's the script that I'm using:
function onEdit(){
var tabLists = "Exercise Index";
var spreadsheet = SpreadsheetApp;
var activeSheet = spreadsheet.getActiveSpreadsheet().getActiveSheet();
var data = spreadsheet.getActiveSpreadsheet().getSheetByName(tabLists);
var activeCell = activeSheet.getActiveCell();
if(activeCell.getColumn() == 1 && activeCell.getRow() > 3 && activeSheet.getSheetName().includes("Week")){
activeCell.offset(0, 1).clearContent().clearDataValidations();
var makes = data.getRange(1, 1, 1, data.getLastColumn()).getValues();
var makeIndex = makes[0].indexOf(activeCell.getValue()) + 1;
if(makeIndex != 0){
var validationRange = data.getRange(2, makeIndex, data.getLastRow());
var validationRule = spreadsheet.newDataValidation().requireValueInRange(validationRange).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
}
}
Copy of the google sheet: https://docs.google.com/spreadsheets/d/1OrDTJiAlVJRU5tKCA55CoVgnT83_k8n_yz9BkWYpZ_0/edit?usp=sharing
Thanks in advance!
From your replying, I thought that the reason for your current issue is due to activeCell.offset(0, 1).clearContent().clearDataValidations(). When your script is run, the right side cell of the active cell is cleared. So, in your script, how about the following modification?
From:
activeCell.offset(0, 1).clearContent().clearDataValidations();
To:
activeCell.offset(0, 1).clearDataValidations();
Or, remove activeCell.offset(0, 1).clearContent().clearDataValidations();.

getSheetByName seems to get ANY active sheet

I would like for the following function to only run on my "Estimate" tab, but it runs on all tabs. I thought calling the sheet by name would resolve this, but it doesn't. I'm very new to GAS and have minimal coding experience, so I'm obviously just doing something wrong.
Here is a link to my sheet
function onEdit(){
//https://www.youtube.com/watch?v=8aOn0VMgG1w
//var ss = SpreadsheetApp.getActiveSpreadsheet();
//var estss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Estimate');
//commented out to try the var below...
//same result
var estss = SpreadsheetApp.getActive().getSheetByName('Estimate');
//var catss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Categories');
//commented out to try the var below...
//same result
var catss = SpreadsheetApp.getActive().getSheetByName('Categories');
var activeCell = estss.getActiveCell();
if(activeCell.getColumn() == 1 && activeCell.getRow() > 1){
activeCell.offset(0, 1).clearContent().clearDataValidations();
var cat = catss.getRange(1,2,1,catss.getLastColumn()).getValues();
var catIndex = cat[0].indexOf(activeCell.getValue()) + 2;
if(catIndex != 0){
var validationRange = catss.getRange(2, catIndex,catss.getLastRow());
var validationRule = SpreadsheetApp.newDataValidation().requireValueInRange(validationRange).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
}
}
When selecting a category in column A on the "Estimate" tab, the following column (B) should set a data validation with all of the sub-categories (rows below the corresponding category), from the "Categories" tab. It basically works, but it also works on every other tab. I would like for it to work on the "Estimate" tab only.
Instead of the active methods, use the Event object
If your event object is e -> function onEdit(e){}
e.range returns the edited range, then you could use
e.range.getSheet().getName() to get the name of the active sheet
then you could use an if statement like
if(e.range.getSheet().getName() !== 'Sheet 1') return;
to stop the execution of the script when the active sheet's name isn't Sheet 1

How to change the column the code is calling for in Google Sheet App script?

I'm using a app script code from: https://www.chicagocomputerclasses.com/google-sheets-apps-script-dynamic-dependent-dropdown-data-validation-lists/
to use dependent drop down data validation lists on a google sheet document.
The code is working but now I need to make it work on our office google sheet document. The code is made to work from the first column, but I need it to work on the E column of our document.
I've tried changing :
if(activeCell.getColumn() == 1 && activeCell.getRow() >1){
to : if(activeCell.getColumn() == 5 && activeCell.getRow() >1){
but it doesn't work, the code was working only on first column
and now it doesn't work at all, since I've been trying some things, even if it seems to me that I didn't change anything really beside the number of the column...
Here's my test google sheet: https://docs.google.com/spreadsheets/d/1p_bc6FsxiE8a0J8XElv6SyjnXXtwc0qjoJ_MuSkHcUg/edit#gid=1591147038
And here's the code :
function onEdit(){
var tablists = "Listes"
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var datass = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("tabLists");
var activeCell = ss.getActiveCell();
if(activeCell.getColumn() == 5 && activeCell.getRow() >1){
activeCell.offset(0, 1).clearContent().clearDataValidations();
var projets = datass.getRange(1, 1, 1, datass.getLastColumn()).getValues();
var projetsIndex = projets[0].indexOf(activeCell.getValue())+1;
if(projetsIndex ! = 0) {
var validationRange = datass.getRange(3, projetsIndex, datass.getLastRow());
var validationRule = SpreadsheetApp.newDataValidation().requireValueInRange(validationRange).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
}
}
If you have any idea on what I'm missing !
Thanks a lot !!!
I think I just found out !
It was missing a semicolon on the second row of the code :
var tablists = "Listes"
Now it works !

Review of personal code

I found this code and implemented it into my spreadsheet. My problem is that the code overwrites some data validation I had in my empty list. I wish to keep that drop down menu since I want the users to have it as easy as possible. I thought I could add the lines below (see text between **)
function onEdit(event) {
// assumes source data in sheet named Masterlist
// target sheet of move to named Actionlist
// test column with yes/no is col 13 or M;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Masterliste"
&& r.getColumn() == 13 && r.getValue() == "Ja") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Actionlist");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
// **
var cellrange = SpreadsheetApp.getActive().getRange(target);
var range = SpreadsheetApp.getSheetByName("Dropdown").getRange('A16:B18'); //This is the range for the dropdown I want to hand over.
var rule = SpreadsheetApp.newDataValidation().requireValueInRange(range).build();
cell.setDataValidation(rule); //Include a data validation menu in each line automatically
// **
s.getRange(row, 1, 1, numColumns).copyTo(target); //This executes the copy order with the data provided before
}
}
I know this might be easy for some of you but I have just started with google 4 months ago and it's driving me crazy. I am familiar to excel and VBA, but not to Java at all.
Yes I did already do the codeacademy courses. They really didn't help me a lot. Sorry for my tone I am getting really annoyed by this. Thanks for your help. Enjoy the weekend!
You need to add an option to copyTo. Here is what that looks like:
s.getRange(row, 1, 1, numColumns).copyTo(target, {contentsOnly:true});
Alternatively you could use: copyValuesToRange(sheet, column, columnEnd, row, rowEnd)
https://developers.google.com/apps-script/reference/spreadsheet/range#copyTo(Range,Object)