Link dynamic and manual data i Google sheets using QUERY - google-apps-script

I have a Google spreadsheet named "Words" with a number of words which are divided into categories.
2)
In Google spreadsheet named "UNIQUE + MANUALLY" I make a unique list in (UNIQUE category) from category in "Words".
To the unique list I would like to have attached a manual word.
How do I get column (MANUALLY Category groups) to follow (UNIQUE category) so the list does not change when new words and categories are added?

Answer:
You can use a script on button click to run the query and statically add the text into the desired cells.
The Idea:
The idea is very similar to how the formula currently works:
Get a list of all words
Remove duplicates and blank cells
Alphabetise them
Insert them into the correct column
Code Example:
Assuming that your column is 'UNIQUE + MANUALLY'!B2:B and the words are all in 'words'!A2:A:
function getUniqueWords() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const wordsSheet = ss.getSheetByName("words")
const destSheet = ss.getSheetByName("UNIQUE + MANUALLY")
const wordsToSort = wordsSheet.getRange("B2:B").getValues()
.flat().filter(function (el) {
return el != ""
}).filter(function (v, i, s) {
return s.indexOf(v) === i
}).sort().map(x => [x])
destSheet.getRange("A2:A").clear()
destSheet.getRange(2, 1, wordsToSort.length, 1).setValues(wordsToSort)
}
You can add this script to your Sheet by following the Tools > Script editor menu item, pasting this function into the editor, and saving the script. Make sure to press Run at least once to authorise the script so that it can run on your behalf.
If you want to add this to a button click in the Sheet itself, you can create a Drawing or add an image into a Sheet from the Insert menu item, and then with the image loaded into the sheet, you can click it, select the vertical ellipsis menu (⋮) which appears in the top-right of the image, select Assign script and in the dialog box enter the function name (in this case, getUniqueWords, without the succeeding ()).

Related

Script to download several columns of a Google Sheets Tab into separate text files

I would like to create a script, to be executed in a Google Sheets environment, that grabs all the contents of several columns within a specific tab, stacks the contents of each columns into a specific text file, and names the file after the header of each column.
For instance:
The working tab would be"Text_Files".
It has several columns, for instance, 3, but there could be more: A:A, B:B and C:C.
The value of the header for column A:A (cell A1) is "1". (Same as the column number)
The value of the header for column B:B is "2".
The value of the header for column C:C is "3".
Then, the script should grab the contents of cells A2:A, stack them into a text file, name the file "1.jsx", do the same for range B2:B, name this file "2.jsx" and for range C2:C name the file "3.jsx". (If there were more columns in the tab, the script should run until the very last column).
After having gathered all the data, it should pop up the dialog box asking the folder where to save all the .jsx files, in a similar ways as when we use the Pdf download option in he menu.
That's it.
Thanks so much.
It can be done this way:
function save_columns_into_files() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var folder = DriveApp.getFolderById('###');
for (var column in data[0]) {
var file_name = data[0][column];
var file_body = data.slice(1).map(x => x[column]).join('\n')
var txt_file = DriveApp.createFile(file_name + '.jsx', file_body, MimeType.PLAIN_TEXT);
var pdf_file = DriveApp.createFile(file_name + '.pdf', file_body, MimeType.PDF);
txt_file.moveTo(folder);
pdf_file.moveTo(folder);
SpreadsheetApp.getUi().alert('Files saved in folder ' + folder.getName());
}
}
No dialog box, though. Folder ID is wired in the script.
Add a proper dialog to select folders is a rather tricky task. Here is the official example: https://developers.google.com/apps-script/guides/dialogs#dialog.html
As a simpler variant it can be just a prompt dialog with text input area where you should type a name of desired output folder every time you run the script (keep in mind, Drive can have many folders with the same name, so there can be collisions). Let me know if you really need it.

Google App Script to find a value in particular column only

I found below script from one of the Stackoverflow posts.. it is almost match my requirement but I need few changes... like.. I don't want to replace, I only want it to find my value in a particular column and also want it to go to that cell when it finds the value. Can someone help me out?
also.. I want a shortcut key to run the macro... instead of the sheet's Ctrl+F.. I want it to display the search prompt when I give Ctrl+F... is it possible??
function findingReplacing()
{
var s = SpreadsheetApp.getUi().prompt("Search String", "Please enter desired search string", SpreadsheetApp.getUi().ButtonSet.OK).getResponseText();
var rng = SpreadsheetApp.getActiveSheet().getRange('D:D');
var rngA = rng.getValues();
for(var i=1;i<rngA.length;i++)
{
if(rngA[i][0]==s)
{
rngA
As mentioned by #Marios, the easiest way is to use TextFinder in your selected range.
Here is a sample code:
function findingAndSelect()
{
var s = SpreadsheetApp.getUi().prompt("Search String", "Please enter desired search string", SpreadsheetApp.getUi().ButtonSet.OK).getResponseText();
var rng = SpreadsheetApp.getActiveSheet().getActiveRange();
Logger.log(s);
// Creates a text finder for the range.
var textFinder = rng.createTextFinder(s);
textFinder.matchEntireCell(true);
textFinder.matchCase(false);
// Returns the first occurrence of the string.
var result = textFinder.findAll();
if (result.length == 0){
/* string not found */
SpreadsheetApp.getUi().alert("Search String", "String not found",SpreadsheetApp.getUi().ButtonSet.OK);
}else{
result.forEach((range) => { range.setBackground('#d5f5df');});
}
}
How to use?
Select the entire column where you want to do the search.
Enter the string to be search.
Click OK.
What it does?
Ask for a string to be search.
Get active range/ selected range where to look for the string (in your case the whole column should be selected).
Create a text finder and look for the input string.
Check if the string was found. Then change the background color of all ranges where the string was found
Additional Information:
You can also specify the search preference you want in your text finder. Please check TextFinder to see available methods.
If you want to match the string to the entire cell, You can use matchEntireCell() and set to true.
// Match the entire content of a cell.
textFinder.matchEntireCell(true);
If you want to match the string based on its case, you can use matchCase() and set to true.
// Match the search text's case exactly
textFinder.matchCase(true);
Output:
Importing functions as macros
In the Google Sheets UI, select Tools > Macros > Import.
Select a function form the list presented and then click Add function.
Select clear to close the dialog.
Select Tools > Macros > Manage macros.
Locate the function you just imported in the list. Assign a unique keyboard shortcut to the macro. You can also change the macro name here; the name defaults to the name of the function.
Click Update to save the macro configuration.
Note: You can link a macro to a keyboard shortcut in the form Ctrl+Alt+Shift+Number

Google Sheets looking for a google script like VLOOKUP but combines the found values and joins them into a specific cell

I have a spreadsheet where I'm trying to add an automatic search function whenever a cell on the Sheet "List" Column 1 gets selected.
It's sort of like using a VLOOKUP function of the sheets but I've been unsuccessful trying to come up with an effective code for it.
Test Spreadsheet link
I made a simple test spreadsheet hopefully for people to easily understand how the sheet should work.
In the 'Database' sheet, there's a list of people with the fruits they like or dislike.
In the 'List' sheet, the list is reversed where the fruits are now the main list but here, when a person clicks on the cells with the fruits, the top cells should automatically update with the combined names of people who like or dislike that certain fruit.
The function should go like this:
If I click a cell on column 1 of the 'List' sheet,
A1 cell updates it's value with the active cell value
B1 cell updates it's value with the combined values based on who likes it from the 'Database' sheet Column 2.
B2 cell updates it's value similar as above but from Dislikes in Column 3
I've attached the code I currently have but I'm not able to get the last 2 steps working.
There is also a guide in the sheets on what the correct answers should look like for each fruit.
I got stuck looking for a way to make the steps 2 and 3 work. I was able to find a code here but it stops after finding one match. stackoverflow.com/questions/10838294/… My current problem is: Since the cells [B2:B] to filter from on the Database sheet has multiple values, is it possible to find all cells with at least a partial match, get the values of the cells on the left of that then list them into the B1 cell on the "List" sheet?
Test Spreadsheet link
Code.gs
function onSelectionChange(e){
var currentsheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var currentcell = currentsheet.getActiveCell();
var activerow = currentcell.getRow();
var activecol = currentcell.getColumn();
var sname = currentsheet.getName();
// Check if current sheet name is correct
if (
sname == 'List'
)
{
// Check if this on first column
if (activecol == 1)
{
// ACTION
var name = currentcell.getValue(); //Get current cell for searching
var prefsheet = SpreadsheetApp.getActive().getSheetByName("Database");
var last = prefsheet.getLastRow();
var data = prefsheet.getRange(1,1,last,2).getValues(); // create an array of data from columns A and B
for(nn=0;nn<data.length;++nn){
if (data[nn][1]==name){break} ;
SpreadsheetApp.getActiveSheet().getRange('A1').setValue('Fruit: ' + name);
SpreadsheetApp.getActiveSheet().getRange('B1').setValue('Like: ' + data[nn][0]);
}
}
};
};
I was able to find a workaround for this and it turns out I didn't have to use a Google Script code to keep updating the formula on List!B1.
I'm new with scripting and sheets but I'll be sharing this formula here in case someone needs something like this in the future.
This is what I used on List!B1
=JOIN(", ",query(filter(Database!A2:B,REGEXMATCH(Database!B2:B,A1)),"Select Col1"))
Regexmatch does the search for partial value and returns as "TRUE"
Filter will then list these rows and query "Select Col1" will only keep the first column of the results and remove the second column. Lastly, Join formula will concatenate them into one cell and add separators.
Which is working very nicely for my purpose. If anyone has any suggestions I'd love to hear about it too.

Make a selection from a dropdown list on google spreadsheet import range from a seperate google spreadsheet

So basically I know nothing about creating scripts and I am trying to organize data on my google spreadsheet, What I want to do is to take a column for this example "column A" and have cell A1 be a dropdown list using range(sheet2!,A1:H1). On sheet 2 would be all the information matching each column eg.. sheet2:A1=Cars,A2:$A=Names of cars, sheet2:B1=Planes,B2:$B=names of planes.
Ok so back to sheet 1 I want to be able to select one of the options from the dropdown list eg. Cars and for the information already stored on sheet 2 to populate A2:A$ since A1 already has the dropdown list in it.
You posted this quite a while ago, but never got any comments or answers - assuming you haven't figured it out, I've posted some sample code below for you. You should take a look through the Google Apps Script Documentation though to get some more help.
function myFunction(e)
{
var entry = e.value; //Did the user enter Cars, Trucks, Planes, etc
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); //The sheet where we will put the data validation
switch(entry)
{
case("Cars"): //If they put in cars
var dv = SpreadsheetApp.newDataValidation();
var options = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getRange("A2:A20").getValues(); //Grab the options for cars
dv.setAllowInvalid(false); //Don't allow incorrect values
//dv.setHelpText("Some help text here");
dv.requireValueInList(options, true); //Require the options
sheet.getRange("A2").setDataValidation(dv.build()); //Make the dropdown list on A1 for "Some Sheet Here" the list of car names
break; //We're done
}
}

A script for google spreadsheet to provide multiple hyperlink choice for one cell

I have a google spreadsheet. In some cells, it has multiple names(strings) that I would like to associate with individual hyperlinks.
E.g. if I have a cell such as "Charles Darwin", it's easy for me to create a hyperlink out of this name by doing something like
=Hyperlink(VLOOKUP("Charles Darwin", People!$A$1:$B$738, 2, false), "Charles Darwin")
(note that I have a "People" sheet from which I grab the hyperlink)
But if I happen to have multiple entries in that cell, say ";" or newline separated, e.g., "Charles Darwin; George Washington", I can't do that. I'd like to give the user an ability to click on the cell, have the contents of the cell be sent (as argument) to some kind of script, and for that script to find the hyperlinks in my "People" sheet for those strings, and then to present the user with a little "pop-up" right next to that cell, where the desired hyperlink could be clicked on.
I tried to find something along those lines on this site, but nothing similar seemed to come up. Might someone have a link or two for me (or basic example code) that I could start with to try to solve this? (I am assuming this is possible).
It's not possible to have two hyperlinks on the same cell.
It is possible to write scripts to Google Spreadsheets, but I'm not sure it's going to suit your use case well. The solution I see would be like this:
The user click on the desired cell, selecting it.
Then he clicks on a custom menu and picks an entry there, e.g. show links
A popup will show up (not besides the cell, but centered on the screen) with the links.
Do you think this is fine? The code would look like this (open the menu Tools > Script Editor)
function onOpen() {
SpreadsheetApp.getActive().
addMenu("Test", [{name: 'Show Links', functionName:'showLinks'}]);
}
function showLinks() {
var values = SpreadsheetApp.getActiveRange().getValue().split(';');
var app = UiApp.createApplication().setTitle('Links');
var grid = app.createGrid(values.length, 2);
for( var i = 0; i < values.length; ++i ) {
var url = findLink(values[i]);
grid.setWidget(
i, 0, app.createLabel(values[i])).setWidget(
i, 1, url ? app.createAnchor(url, url) : app.createLabel('Not Found'));
}
app.add(grid);
SpreadsheetApp.getActive().show(app);
}
var mapName2Url = null;
function findLink(name) {
if( mapName2Url == null ) { //lazy load
mapName2Url = {};
var data = SpreadsheetApp.getActive().getSheetByName('People').getDataRange().getValues();
for( var i = 1; i < data.length; ++i ) //skipping the header
mapName2Url[data[i][0]] = data[i][1];
}
return mapName2Url[name];
}
After you paste it on the script editor, run the onOpen function twice to authorize it and have the menu created for you. Next time you open the spreadsheet, the menu should be created automatically.
By the way, I have not tested this code, so it might contain dumb mistakes.