I have a range that assigns shifts to a set of employees, in which the row labels are dates (ie, the Y axis is a chronological set of dates), and the column headers are locations (Building1, Building2, etc). Each row, then, contains employees assigned to each location for that day. Or, alternatively, each column will contain a chrono list of who will be assigned to the location specified in that column's header.
I am attempting to match a name, say "John Doe" for each instance he appears throughout the range, and return a 2 column list of dates and locations for which he is assigned. John Doe will be listed many times over the dates in question and various locations (in multiple columns).
I've reached the limit of my expertise both with AppsScript and Filter functions and greatly appreciate any help. I believe a loop is necessary, but perhaps there is a better way. For what its worth, my goal is to take this list and put every assignment on the user's calendar (I've solved for this already). TIA everyone!
Sample input and output situation
From your provided Spreadsheet, I believe your goal is as follows.
You want to achieve the following situation using Google Apps Script.
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 put a custom function of =SAMPLE(Data!A3:F20,"John Doe") to a cell. By this, the result values are returned.
const SAMPLE = ([h, ...v], searchName) =>
[["Data", "Location"], ...v.flatMap(([hh, ...vv]) => {
const i = vv.indexOf(searchName);
return i != -1 ? [[hh, h[i + 1]]] : [];
})];
If you don't want to include the header row, you can also use the following script.
const SAMPLE = ([h, ...v], searchName) =>
v.flatMap(([hh, ...vv]) => {
const i = vv.indexOf(searchName);
return i != -1 ? [[hh, h[i + 1]]] : [];
});
Testing:
When this sample script is used for your sample input values, the following situation is obtained.
In the case of "John Doe", from your expected output, "Building4" of "8/8/2022" is not included as shown in the red background cell. But, I'm worried that you might have miscopied. So, I proposed the above sample script. If you want to except for the value of the specific date, please tell me. This can be also achieved.
Reference:
Custom Functions in Google Sheets
The result that you are looking for could be achieved by using Google Sheets built-in functions in a formula:
=ARRAYFORMULA(QUERY(SPLIT(FLATTEN(Data!A4:A20&"💣"&Data!B3:F3&"💣"&Data!B4:F20),"💣"),"SELECT Col1,Col2 WHERE Col3 = 'John Doe'")
Briefly, the above formula uses FLATTEN and Google Sheets array handling feature to "unpivot" your double entry table, then uses QUERY to filter and limit the data to be returned.
Related
How do you create a "reverse pivot" in Google Sheets?
Background:
I have a sheet that many people edit. I have spent more time than I care to admit user-proofing it. (There is a list of things I have tried at the bottom of this post if you are curious). The solution that has worked the best is letting my users "see" if a cell has a formula in it. I have an apps script that when combined with conditional formatting highlights the cell, alerting them to please not type over it. Still, this hasn't quite solved the problem. (Especially when they insert rows.)
Issue:
I recently revised these sheets, replacing thousands of formulas with a handful of arrayformulas. That has fixed more problems than it's causing, but now my users get a little freaked out when they type in a cell in an arrayformula column and the whole column of data disappears. I was hoping that there was some way to modify the isFormula app script I am using to highlight the cells that it applies to. My thinking is this: figure out if the formula in the cell is an arrayformula. If true, highlight the cells that are populated by the formula.
The script I am hoping can be altered: isFormula():
/**
* Used to conditionally format cells having formulas
*
* #param {number,number} input The column number and
column row to start evaluating this formual and starting
* #return if getFormula() returns any value, false otherwise
* #customfunction
*/
function isFormula(startcol, startrow) {
// prepare string
var str = String.fromCharCode(64 + startcol) + startrow;
// retrieve formula
var fCell = SpreadsheetApp.getActiveSpreadsheet()
.getRange(str).getFormula();
// return false if empty else true
return fCell ? true : false;
}
The conditional formatting rule:
=isformula(A1)
Workarounds I tried:
User Education: I did try getting them to notice if there was a
formula, and not type over it, but that approach failed. My users
would type over the formulas, or insert rows, or accidentally move
cells and I would be back here again.
Applying Permissions: I tried limiting permissions to cells with formulas, but that caused problems with sorting and filtering. There are hundreds of rows... they do need to be able to sort.
A shout out to the helpers:
Thanks for helping! You are wonderful and amazing!
-s.
I have added the very basic example script "Double" via the instructions given in the Google Apps Scripts guide. Simple stuff, but the function does not show up in my Google Sheet when I type in a cell "=doub..."
I get no errors in the script editor. I can run the default functions within Google Sheets, yet I can't get any new functions to appear.
The assumption is that you are trying to create a custom function and have it show up as an autocomplete item when you are typing formulas in cells.
Custom functions will appear in this list if their script includes a JsDoc #customfunction tag, as in the DOUBLE() example below.
/**
* Multiplies the input value by 2.
*
* #param {number} input The value to multiply.
* #return The input multiplied by 2.
* #customfunction
*/
function DOUBLE(input) {
return input * 2;
}
usually the commented portion of JavaScript is not too important but in this case it is. The comment must be properly structured to get the function to render as an autocomplete item when typing formulas in cells
https://developers.google.com/apps-script/guides/sheets/functions#autocomplete
Is there a way to get the identification (i.e. A1 notation) of a selected cell or range in Google Sheets?
Something like:
=SELECTION(['Sheet1']) -> "D6"
This custom function will get the selection at the time you update the cell with the function. But it will not update as the selection changes.
Henrique provides a good explanation of why custom functions like this don't update in Google Apps - script to summarise data not updating.
/**
* A function that gets the current selection, in A1Notation.
*
* #customfunction
*/
function SELECTED_RANGE() {
return SpreadsheetApp.getActive().getActiveRange().getA1Notation();
}
I am sorry cause I do not know any scripting language I am posting my concerns here. I am in need of script having the below functionality. I have created https://sites.google.com/site/iitmamritwater website.
I am in need a web service for a HTTP GET request like : https://sites.google.com/site/iitmamritwater?id=xxxxxxxxxx that would validate id as submitted in query param. Currently I have only 2 valid ID values each of 10 digits length. The web service response should state id validity with its balance - something like below:
If xxxxxxxxxx is one of the two possible correct values then response should be as below:
https://sites.google.com/site/iitmamritwater?id=xxxxxxxxxx
V;10.50;
If xxxxxxxxxy is not one of the two values then response should be as below:
https://sites.google.com/site/iitmamritwater?id=xxxxxxxxxy
N;00.00;
Its a very simple script but cause I do not know scripting I am stuck implementing the concept. I don't know even how to begin with - can some one please post the code for same - it would be highly helpful for me? It will save my project development time period.
See this answer for an example of serving multiple html pages using HtmlService. The basic idea is to write doGet() to accept a query parameter that it will use to select which html page to serve.
In your case, instead of serving HTML pages, you should use the ContentService to output the appropriate response, based on the evaluation of the received parameters.
function doGet(e) {
if (!e.parameter.id) {
// No id provided...
return ContentService.createTextOutput('Error - no id');
}
// else, get response for given id
var response = validateId( e.parameter.id );
// ...and serve it as text output
return ContentService.createTextOutput( response );
}
/**
* Get a response string for the given id
*
* #param {string} id 10 digit id
* #returns {string} Result of validation & lookup
*/
function validateId( id ) {
return "Under construction";
}