I am creating a site where clients can construct a price quote.
I have used Tabulator to show the data in a table.
The Tabulator data is in its own .JS file "buildTabulator.js", while the Quote scripts are in another .JS file "quote.js".
I am able to extract the data and get it mostly doing what I want so far.
But, when I try to create an IF ELSE statement in the quote.js file to determine which price should be displayed based on the unit of measure (UOM) of the item, it will not work correctly. It always shows the EACH or EA price of the item which is in the IF part of the IF ELSE statement.
More specifically, if the user adds an item to the quote that is sold by the EACH it should show one price, but if they choose an item that is sold by the CASE it should display a different price.
Please see the attached screenshots and code below and advise if you can...
I am hoping this is something simple that a noob like me has missed by mistake.
First screenshot is showing the code in VSC.
Second screenshot is showing an example in the console log of the browser. This example is using an item that is sold by the CASE and should show the case price of the item but instead shows a "-" because the EACH price of this item is a dash since its not sold by the each.
In the log it shows CS for CASE which is correct but the "-" should actually be 0.2937 which is shown in the table above the console.
Please let me know if there is any more information I can provide or any questions you may have.
Thank you so much in advance!!
CODE FROM "buildTabulator.js"
cellClick: function (e, cell) {
globalThis.itemImage =
"imgsQuote/" + cell.getRow().getData().IMAGE + ".png";
globalThis.itemCode = cell.getRow().getData().CODE;
globalThis.itemDescription = cell.getRow().getData().DESCRIPTION;
globalThis.itemBx = cell.getRow().getData().BX;
globalThis.itemCs = cell.getRow().getData().CS;
globalThis.itemUom = cell.getRow().getData().UOM;
globalThis.itemCost = cell.getRow().getData().COST;
globalThis.itemBox = cell.getRow().getData().BOX;
globalThis.itemHalf = cell.getRow().getData().HALF;
globalThis.itemLess = cell.getRow().getData().LESS;
globalThis.itemCase = cell.getRow().getData().CASE;
globalThis.itemBxWt = cell.getRow().getData().BXWT;
globalThis.itemCsWt = cell.getRow().getData().CSWT;
// globalToLocal();
setItemPrice();
},
CODE FROM "quote.js"
function setItemPrice() {
console.log(globalThis.itemUom);
var itemPrice;
if ((globalThis.itemUom = "EA")) {
itemPrice = globalThis.itemBox;
} else {
itemPrice = globalThis.itemCase;
}
console.log(itemPrice);
}
after another 3 hours or so of searching I found an answer that works:
setting variable with ternary expression
Related
Goal: I have a bunch of keywords I'd like to categorise automatically based on topic parameters I set. Categories that match must be in the same column so the keyword data can be filtered.
e.g. If I have "Puppies" as a first topic, it shouldn't appear as a secondary or third topic otherwise the data cannot be filtered as needed.
Example Data: https://docs.google.com/spreadsheets/d/1TWYepApOtWDlwoTP8zkaflD7AoxD_LZ4PxssSpFlrWQ/edit?usp=sharing
Video: https://drive.google.com/file/d/11T5hhyestKRY4GpuwC7RF6tx-xQudNok/view?usp=sharing
Parameters Tab: I will add words in columns D-F that change based on the keyword data set and there will often be hundreds, if not thousands, of options for larger data sets.
Categories Tab: I'd like to have a formula or script that goes down the columns D-F in Parameters and fills in a corresponding value (in Categories! columns D-F respectively) based on partial match with column B or C (makes no difference to me if there's a delimiter like a space or not. Final data sheet should only have one of these columns though).
Things I've Tried:
I've tried a bunch of things. Nested IF formula with regexmatch works but seems clunky.
e.g. this formula in Categories! column D
=IF(REGEXMATCH($B2,LOWER(Parameters!$D$3)),Parameters!$D$3,IF(REGEXMATCH($B2,LOWER(Parameters!$D$4)),Parameters!$D$4,""))
I nested more statements changing out to the next cell in Parameters!D column (as in , manually adding $D$5, $D$6 etc) but this seems inefficient for a list thousands of words long. e.g. third topic will get very long once all dog breed types are added.
Any tips?
Functionality I haven't worked out:
if a string in Categories B or C contains more than one topic in the parameters I set out, is there a way I can have the first 2 to show instead of just the first one?
e.g. Cell A14 in Categories, how can I get a formula/automation to add both "Akita" & "German Shepherd" into the third topic? Concatenation with a CHAR(10) to add to new line is ideal format here. There will be other keywords that won't have both in there in which case these values will just show up individually.
Since this data set has a bunch of mixed breeds and all breeds are added as a third topic, it would be great to differentiate interest in mixes vs pure breeds without confusion.
Any ideas will be greatly appreciated! Also, I'm open to variations in layout and functionality of the spreadsheet in case you have a more creative solution. I just care about efficiently automating a tedious task!!
Try using custom function:
To create custom function:
1.Create or open a spreadsheet in Google Sheets.
2.Select the menu item Tools > Script editor.
3.Delete any code in the script editor and copy and paste the code below into the script editor.
4.At the top, click Save save.
To use custom function:
1.Click the cell where you want to use the function.
2.Type an equals sign (=) followed by the function name and any input value — for example, =DOUBLE(A1) — and press Enter.
3.The cell will momentarily display Loading..., then return the result.
Code:
function matchTopic(p, str) {
var params = p.flat(); //Convert 2d array into 1d
var buildRegex = params.map(i => '(' + i + ')').join('|'); //convert array into series of capturing groups. Example (Dog)|(Puppies)
var regex = new RegExp(buildRegex,"gi");
var results = str.match(regex);
if(results){
// The for loops below will convert the first character of each word to Uppercase
for(var i = 0 ; i < results.length ; i++){
var words = results[i].split(" ");
for (let j = 0; j < words.length; j++) {
words[j] = words[j][0].toUpperCase() + words[j].substr(1);
}
results[i] = words.join(" ");
}
return results.join(","); //return with comma separator
}else{
return ""; //return blank if result is null
}
}
Example Usage:
Parameters:
First Topic:
Second Topic:
Third Topic:
Reference:
Custom Functions
I've added a new sheet ("Erik Help") with separate formulas (highlighted in green currently) for each of your keyword columns. They are each essentially the same except for specific column references, so I'll include only the "First Topic" formula here:
=ArrayFormula({"First Topic";IF(A2:A="",,IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))) & IFERROR(CHAR(10)®EXEXTRACT(REGEXREPLACE(LOWER(B2:B&C2:C),IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))),""),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))))})
This formula first creates the header (which can be changed within the formula itself as you like).
The opening IF condition leaves any row in the results column blank if the corresponding cell in Column A of that row is also blank.
JOIN is used to form a concatenated string of all keywords separated by the pipe symbol, which REGEXEXTRACT interprets as OR.
IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))) will attempt to extract any of the keywords from each concatenated string in Columns B and C. If none is found, IFERROR will return null.
Then a second-round attempt is made:
& IFERROR(CHAR(10)®EXEXTRACT(REGEXREPLACE(LOWER(B2:B&C2:C),IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))),""),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>"")))))
Only this time, REGEXREPLACE is used to replace the results of the first round with null, thus eliminating them from being found in round two. This will cause any second listing from the JOIN clause to be found, if one exists. Otherwise, IFERROR again returns null for round two.
CHAR(10) is the new-line character.
I've written each of the three formulas to return up to two results for each keyword column. If that is not your intention for "First Topic" and "Second Topic" (i.e., if you only wanted a maximum of one result for each of those columns), just select and delete the entire round-two portion of the formula shown above from the formula in each of those columns.
I'm trying to create a custom variable in Google Tag Manager. I need it to show a 0 value when...
A customer purchases using a discount code which contains the words 'Gift Voucher'
AND
It generates negative revenue.
Else it should just appear standard revenue (there are times when negative revenue is needed, hence why it should only appear as 0 when a gift voucher is used)
Ive tried the following
function () { if ({{Discount Code Used}} = str.includes("Gift Voucher") && {{Revenue}}<0 ) {return 0; } else { return {{Revenue}}; }}
But this is returning a undefined value
Is anyone able to help?
The first half of your if condition is a bit off:
{{Discount Code Used}} = str.includes('Gift Voucher')
The right way to use the .includes() method of a string is like this:
{{Discount Code Used}}.includes('Gift Voucher')
I would recommend using .indexOf() instead of .includes(), since it is supported by more browsers.
{{Discount Code Used}}.indexOf('Gift Voucher') !== -1
If it is still returning undefined, double check that Discount Code Used and Revenue are set to the correct values.
I've created a script editor for a google sheet that has multiple tabs. One if statement I can't seem to get working is - If sheet "Employee Evolution" column 8 EQUALS "Disqualified" AND column 13 is NOT EQUAL to "NO DATA", move the row to sheet "Disqualified" I've tried so many different ways to rearrange and can't get it to work.
**function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Employee Evolution" && r.getColumn() == 8 && r.getValue() == "Disqualified" && r.offset.getValue(0,5) != "NO DATA") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Disqualified");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1,numColumns).moveTo(target);
s.deleteRow(row);**
I have no coding experience, so I'm having a difficult time understanding javascript documents that explain this stuff. Please help!
Below is the link to my spreadsheet
https://docs.google.com/spreadsheets/d/1vp46hMbmB5968cRW2BGhS66qqNhl91Llk8xeknlRuQc/edit#gid=0
Right now I only have the first if statement and else if statement set up with multiple conditions, but that is not working. When I populate the 8th column (H) with Disqualified and populate the 13th column (M) with anything at all, nothing happens. And, if I populate column H with Qualified and populate column M with Paid Search, nothing happens.
Basically I want the row to move to either the PPC tab or the Disqualified tab. However, I don't want the row to move until both columns H and M are populated with specific text. If column H says "Qualified" AND column M says "Paid Search" the row should move to the PPC tab. If column H says "Disqualified" AND column M says anything other than NO DATA (even Paid Search), the row should move to the Disqualified tab.
The problem I can't get past is that I need to have each if statement look at both columns before executing true.
I hope this makes sense and thank you for your help.
It's not possible to define if that if should be working or not based just on the code as we don't have that spreadsheet you're using.
But I do notice some things that maybe are wrong on yout assumptiong, for this break that if into :
s.getName() == "Employee Evolution" => Checks if the current sheet that you have active is called "Employee Evolution"
r.getColumn() == 8 => checks if the current column that you have active is column number 8 (column h)
r.getValue() == "Disqualified" => checks if the current cell that you have active is equal to Disqualified (must matcha case as well)
r.offset.getValue(0,5) != "NO DATA") => Checks if column offset by 5 (will be equal column 13 indeed) is different then "NO DATA" (also must match case)
And of course as this function is onEdit, so this code will only run when you change something on the spreadsheet.
So I suppose by reading that code is that whenever someone changes column 8 to "Disqualified" (must match the capital letters as well) and all the other criterias match, it should be moved to "Disqualified" sheet. Pay attention to all the case sensitive scenarios you have.
I think overall the code seems fine. Share the spreadsheet so we can check what might be going wrong.
PS: by something being active I mean that your cursor is clicked/selected that thing
guys!
I'm new to this website and also not good with coding. So I would really appreciate some help.
Right now I'm in need of a specific code to make a google sheet work perfectly.
To further explain:
I have a google sheet that a few information will be input by other co-workers. What I need is a code that will register the date in a specific cell and by whom the input was made on another cell.
So far this is what I have:
function onEdit(event) {
var sheet = event.source.getSheetByName("Input");
// Note: actRng = return the last cell of the row modified
var actRng = event.source.getActiveRange();
var index = actRng.getRowIndex();
var cindex = actRng.getColumnIndex();
// Note: date = return date
// Note: user = return the user email
var userCell = sheet.getRange(index,14);
var dateCell = sheet.getRange(index,2);
var inputdate = Utilities.formatDate(new Date(), "GMT+0200", "yyyy-MM-dd");
// Note(with hour): var inputdate = Utilities.formatDate(new Date(), "GMT+0200", "yy-MM-dd HH:mm");
//var user = event.user; // Note: event.user will not give you collaborator's Id
var user = Session.getEffectiveUser();
// Note: setValue = Insert in the cell the date when this row was modified
if (userCell.Value == null) {
userCell.setValue(user);
dateCell.setValue(inputdate)
}
}
My main problems/questions are:
I don't exactly need the last modifier, but the person who first input info on the cells. Therefore I tried that last IF (If the cell that is supposed to have the last modifier e-mail is blank, it means that nobody changed that row before, so the code should add the user on the userCell), although it is not working since every change I make it ignores the verification.
I also want to add that the event will only happen if you add values, if you delete them, nothing happens. (so far even when I delete cells, it counts as modification)
Most of the sheet is protected to avoid that people by accident erase some of the formulas, so the cells that this code changes are also protected. Is there a way to make the code bypass cell protection?
Please, help me identify what I'm doing wrong and hopefully I'll get this working perfectly! Thanks for the help !
If you want to prevent the script from firing when a cell is deleted, try:
var editedCell = SpreadsheetApp.getActiveSheet().getRange(e.range.getRow(), e.range.getColumn());
if (editedCell == "") {
return;
}
I would change Session.getEffectiveUser() to session.getActiveUser().
The last if statement is unnecessary. You want whoever most recently edited the field to be identified, along with the date.
I performed my first query with a grouping function using the following code:
let dc = new TypedDataContext()
open MathNet.Numerics.Statistics
let newData = query { for x in dc.MyData do
where (x.ID = "number of type string")
groupBy x.Code into g
let average = query { for x in g do
averageBy x.Billed_Amt }
select (g, average) }
|> Seq.toList
System.Console.WriteLine(newData)
I am now wanting to calculate the standard deviation of the billed amounts in each group. However, when I try to reference the column, 'Billed_Amt,' like so
let sd = newData.Billed_Amt.StandardDeviation()
I receive the following error: "constructor or member 'Billed_Amt' is not defined."
I also tried newData.g.Billed_Amt.StandardDeviation(), in case I needed to reference the groups first, but I got the same error message referring to 'g'.
How do I overcome this?
I will say that I notice that the 'list' I created with the query claims to have 63 items. These would be the different group keys, not the rows of data themselves.
I feel like the research I have done online to solve this problem has just sent me in circles. Most of the resources online do not dumb it down enough for newbies like me. Any help would be appreciated.
Thank you!