I have a sheet below in which I would like to display the symbol of currency according to region selected in column C. If we select America, the symbol of dollar must appear before the cost in B column, like when we select Europe, the symbol of euro must appear before the cost in column B.
https://docs.google.com/spreadsheets/d/1dlfXRcSDy7XhQmRuVa3dEmx6zjHukOlOoRp5V-Em1c0/edit#gid=0
You can use VLOOKUP or CONCATENATE whatever you want, the symbol must appear before the price.
Thanks in advance
I created a onEdit script for you. Try it our for yourself. I added some comment if you want to change the sheetname / column to check. Hope that this fits your needs.
Go to tools -> Script editor
Choose setNumberFormat from the dropdown and run it with the little play button. Give premission.
(maybee repeate 2 with the onEdit from the dropdown.)
Close. And now you should have a working script.
The Script for others
function onEdit(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
//Change sheet name to check
const sheet = "Purchase Sheet";
const activeSheet = ss.getActiveSheet().getName();
const cell = ss.getActiveSheet().getActiveCell();
// 3 = column c. So change this to you needs
if (activeSheet == sheet && cell.getColumn() == 27){
console.log("True");
setNumberFormat();
}
}
function setNumberFormat() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const cell = ss.getActiveSheet().getActiveCell();
let numberFormat = "";
//With this as example, you can extend to your needs.
switch (cell.getValue()) {
case "AMERICA":
numberFormat = "$#,##0.00";
break;
case "EUROPE":
numberFormat = "€#,##0.00";
break;
}
cell.offset(0, -21).setNumberFormat(numberFormat);
}
Related
I'm looking for a code I can use in google sheets.
I need to get a notification when a cell changes in a specific column and get it through email or Slack.
Can someone please help me?
I'm currently using
function onSpeEdit(e) {
var sh = e.source.getActiveSheet();
var rng = e.source.getActiveRange();
var col = 1
if (sh.getName() == 'mySheet' && rng.getColumn() == col) {
MailApp.sendEmail(
'yourEmail#gmail.com',
`Change Notification`,
`Change in ${rng.getA1Notation()} old value "${e.oldValue}" new value "${e.value}" `);
}
}
Try
function onSpeEdit(e) {
var sh = e.source.getActiveSheet();
var rng = e.source.getActiveRange();
var col = 1
if (rng.getColumn() == col) {
MailApp.sendEmail(
'yourEmail#gmail.com',
`Change Notification`,
`Change in ${rng.getA1Notation()} of ${sh.getName()} old value "${e.oldValue}" new value "${e.value}" `);
}
}
change name of sheet, column and email address
you will need to define an installable trigger in order to use services that requires authorization.
Installable Triggers
edit : il you want to add another information, i.e. from column B, try to replace the sentence by
`Hey, the title ${sh.getRange('B'+rng.getRow()).getValue()} from sheet ${sh.getName()} changed. Before it has the number ${e.oldValue} now is ${e.value}.`
I'm trying to write an inputted date from the adjacent cell.
i.e. date entered in A1, B1 = A1 but in word form (in Spanish).
I'm close to a solution but I'm sure making things more complicated than they need to be.
The date column(A) is currently being separated into 3;
day(B), month(D), year(F), using; =LEFT($A1;2), =MID($A1;4;2), =RIGHT($A1;4) accordingly.
In Columns C,E,G I'm using
=INDEX(IMPORTXML("https://www.buscapalabra.com/numeros-a-letras.html?cifra="&B1;"//li[1]//strong");1)
where B1 changes to E1, F1 depending on the column
finally in column H where the date will be written I use:
=trim(LOwer($C2&"de "&TEXT($D2;"mmmm")&" de "&$F2))&If(Value(Right($E2;1))=1;If(Value(MID($E2;4;1))<>1;"o";"");"")
For some reason the text value returned from the site has a space on the end and also does not properly word numbers ending in 1. Hence the use of TRIM() & the nested IF()
It works for now, I haven't tested it exhaustedly but I'd love to hear what people think, I'm new to Sheets but there has to be a cleaner way to do this.
Use custom functions:
You could do this with an Apps Script Custom Function.
First, open a bound script by selecting Tools > Script editor, and copy the following functions to the script (check inline comments for more information):
function DATE_IN_WORDS(date) {
const day = date.getDate(); // Day of the month in numbers
const year = date.getFullYear(); // Year in numbers
const options = { month: 'long'};
const month = new Intl.DateTimeFormat('es-ES', options).format(date); // Month in words
const dayAndYear = [day, year].map(number => { // Retrieve word for day and year
const url = "https://www.buscapalabra.com/numeros-a-letras.html?cifra=" + number
const resp = UrlFetchApp.fetch(url).getContentText();
const first = "<em>Como sustantivo:</em> El <strong>";
const cut = resp.substring(resp.indexOf(first), resp.length);
let word = cut.substring(first.length, cut.indexOf("</strong>")); // Get desired section of HTML
if (number.toString().slice(-1) == "1" && number.toString().slice(-2) != "11") {
word = word.trim() + "o"; // Replace "un" with "uno"
let arrayWord = word.split(" ");
let lastWord = arrayWord.pop();
if (lastWord === "veintiúno") { // If 21, replace "ú" with "u"
lastWord = lastWord.replace("ú", "u");
arrayWord.push(lastWord);
word = arrayWord.join(" ");
}
return word;
} else return word;
});
return dayAndYear.join("de " + month + " de "); // Join day, month and year
}
This function uses:
Intl.DateTimeFormat to retrieve the month in Spanish.
UrlFetchApp to fetch information from https://www.buscapalabra.com/numeros-a-letras.html.
Once it is defined, you can use the function DATE_IN_WORDS the same you would any sheets built-in function. This function would accept the cell with the Date as a parameter.
Example:
Reference:
Custom Functions in Google Sheets
I am running the following script as its own .gs file
/**
* TITLE:
* Hide a row if a value is inputted.
*/
//**GLOBALS**
// Sheet the data is on.
var SHEET = "Norm Adam";
// The value that will cause the row to hide.
var VALUE = "Yes";
// The column we will be using
var COLUMN_NUMBER = 11
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
//Ensure on correct sheet.
if(SHEET == activeSheet.getName()){
var cell = ss.getActiveCell()
var cellValue = cell.getValue();
//Ensure we are looking at the correct column.
if(cell.getColumn() == COLUMN_NUMBER){
//If the cell matched the value we require,hide the row.
if(cellValue == VALUE){
activeSheet.hideRow(cell);
};
};
};
}
It works fine on a computer browser but on iOS device it doesn't work through the google sheets app and I actually can't even get the editable through safari. I read that only the onEdit function will work on a mobile device so I figured this should work. Is there another piece to this puzzle?
Thanks
Mike
(credit for script creation goes to: https://yagisanatode.com/2018/05/26/how-to-hide-a-row-based-on-a-cell-value-in-google-sheets-with-filter-or-google-apps-script/ )
Script V2:
I commented below on this still not working in iOS. I figured the simpler it was the more likely to work?
function onEdit(e) {
if (e.range.getColumn() == 11 && e.value == 'Yes') {
e.range.getSheet().hideRows(e.range.getRow());
}
}
getActive calls, especially ss.getActiveCell() should be avoided on mobile apps. Consider alternatives like e.range to get the edited range from event objects.
==================================
UPDATE 11 December 2019
My Question is more about Macro Script
The GOAL (in illustration)
to change below raw sheet:
to more readable format:
Basically what i'm doing is split the campaign name with the separator and parse it.
I don't have the problem if the function on only process single cell,for example:
on "Report" Sheet the CELL B2 , is taking data from "Data" B2 ONLY
i got problem when the return data require conditional operator that involve specific condition. So while processing cell B2, it require content from E2, D2, etc
=====================================
i'm taking data from Google Ads/Analytics API to Google Sheet on specific worksheet (i call it 'Raw Data').
Now i'm using pattern for the campaign, so i can easily split/break with separator in order for me to get specific data.
For Example:
With this, by using underscore as separator, i can split campaign name, into various data:
Campaign Objective: Sales
Campaign Title: TBMB
Network: SEM
Branch: All
Targeting: Keywords
..etc
Then i create new sheet called Called CReport which consist the same data from Raw Data sheet, but in much better visualization for marketing people.
Now, after searching on Google, i found the solution for self reference cell.
The script goes like this:
function getSegment(data,index){
temp=data.split("_");
return temp[index-1];
}
function dataParse(input,dataSegment){
return Array.isArray(input) ? input.map(function(e){
return e.map(function(f){
if(f!=""){
return getSegment(f,dataSegment);
}
}
)}
) : "false usage";
}
So if i want to have a column with Network Name, i can place this formula on row 2 (because row 1 is for table header) something like this:
=ArrayFormula(dataParse('RAW DATA'!B2:B;2))
Now my question:
This works for self-reference cell, means if the data taken from B2 in RAW DATA sheet, it will be the only data referenced to cell in Campaign Report sheet.
If the pointer is in B2 on CReport Sheet require data not only from B2 in RAW DATA but also D2 Cell.
What script i need to add in my function ?
i'm expecting the chunk of code will something like this
function dataParse(input,dataSegment){
return Array.isArray(input) ? input.map(function(e){
return e.map(function(f){
if(f!=""){
segmentData=getSegment(f,dataSegment);
if(segmentData=="google"){
returnData=get reference from column D //<---
}else{
returnData=get reference from column E //<---
}
return returnData
}
}
)}
) : "false usage";
}
Hope its clear enough.
Thanks in Advance !
I modified your function in this way:
// range (String): It will be used to get the info in a range
function dataParse(input,dataSegment, range){
var val = "";
return Array.isArray(input) ? input.map(function(e, index){
return e.map(function(f){
if(f!=""){
// If col D has value google then take info from col B
if(f === "google") val = getDesiredRangeValue("B", range, index);
// else take info from col E
else val = getDesiredRangeValue("E", range, index);
// Take segment as needed
return getSegment(val,dataSegment);
}
}
)}
) : "false usage";
}
In order to make it work, I inserted an extra argument to the function. Now you will need to pass as an string the range in A1 notation in your ArrayFormula, this is because the input argument only gives you the values in the cells, and with that extra argument it will be possible to obtain extra info. To make it work fine, always use the same range as the next example shows:
=ArrayFormula(dataParse('RAW DATA'!D2:D5, 2,"D2:D5"))
or
=ArrayFormula(dataParse('RAW DATA'!D2:D, 2,"D2:D"))
Notice I also added a new function called getDesiredRangeValue, which will take the values from the column you need, depending if one of the cells from Col D has the value google. This is how the function looks:
/*
// A1 (String): The col from where you will want the info
// range (String): It will be used to get the info in a range
// index (Integer): It gives the index number from the main array gotten in the input arg
*/
function getDesiredRangeValue(A1, range, index){
var rowNumbers = range.match(/\d+/g);
// It checks if the range will has and end or it will prolong without specifying and end row
if(rowNumbers.length > 1){
var rangeCol = ss.getRange(A1 + rowNumbers[0] + ":" + A1 + rowNumbers[1]).getValues();
} else {
var rangeCol = ss.getRange(A1 + rowNumbers[0] + ":" + A1).getValues();
}
// It returns the whole value from each cell in the specified col
return rangeCol[index][0];
}
Code
Now your whole code will look like this:
// Global var
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("RAW DATA");
function getSegment(data,index){
temp=data.split("_");
return temp[index-1];
}
/*
// A1 (String): The col from where you will want the info
// range (String): It will be used to get the info in a range
// index (Integer): It gives the index number from the main array gotten in the input arg
*/
function getDesiredRangeValue(A1, range, index){
var rowNumbers = range.match(/\d+/g);
// It checks if the range will has and end or it will prolong without specifying and end row
if(rowNumbers.length > 1){
var rangeCol = ss.getRange(A1 + rowNumbers[0] + ":" + A1 + rowNumbers[1]).getValues();
} else {
var rangeCol = ss.getRange(A1 + rowNumbers[0] + ":" + A1).getValues();
}
// It returns the whole value from each cell in the specified col
return rangeCol[index][0];
}
// range (String): It will be used to get the info in a range
function dataParse(input,dataSegment, range){
var val = "";
return Array.isArray(input) ? input.map(function(e, index){
return e.map(function(f){
if(f!=""){
// If col D has value google then take info from col B
if(f === "google") val = getDesiredRangeValue("B", range, index);
// else take info from col E
else val = getDesiredRangeValue("E", range, index);
// Take segment as needed
return getSegment(val,dataSegment);
}
}
)}
) : "false usage";
}
Docs
These are the docs I used to help you:
Class Sheet
Custom Functions
I have been searching for a while and trying to work together a script from various answered topics that will allow me to adjust an adjacent cells content based on the data entered. I cannot seem to get it to work properly and need some help steering the ship the right direction. Here is what I am trying to accomplish:
--If the value of cell A2:A is a six digit number AND the value of cell D2:D (same row) is "MATCH" then the value for cell B2:B should be set to "ANN"
--If the value of cell A2:A is a six digit number AND the value of cell D2:D (same row) is "NO MATCH" then the value for cell B2:B should be set to "ANN" and a drop-down data validation list of ['ANN','RNW'] populate WITH the default value of the list set to "ANN"
--If the value of cell A2:A has a length of seven or greater characters then a drop-down data validation list of ['1DY','RNW','NEW'] populate WITH the default value of the list set to "1DY"
Is it even possible to set the value of a data validation cell to a specific, default value? This is important as when the user is entering data they will more than likely accept the default value. If they don't want the default value then they can select a value from the drop-down list.
I built a test sheet which shows the what the sheet should look like when data is filled out in column A and the associated values in column B.
My test is here: https://docs.google.com/spreadsheets/d/1p8sq63S-vSU1FKFLjtr2ZypItN5viXotoZL0Ki2PoQM/edit?usp=sharing
Here is the cobbled together script I was attempting to build (I too find it funny). This is my first attempt to right a Google Script to run on a spreadsheet.
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var aSheet = ss.getActiveSheet();
var aCell = aSheet.getActiveCell();
var aColumn = aCell.getColumn();
var aRow = aCell.getRow();
//var licenseStatus = aSheet.getRange(aRow, aColumn+9).getValue();
// The row and column here are relative to the range
// getCell(1,1) in this code returns the cell at B2, B2
var licenseTypeCell = aSheet.getRange(aRow, aColumn+1);
if (aColumn == 1 && aSheet.getName() == 'Onsite') {
if (isnumber(aCell) && (len(aCell) <= 6)) {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['ANN','RNW']).build();
licenseTypeCell.setValue("ANN");
licenseTypeCell.setDataValidation(rule);
} else {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['1DY','RNW','NEW']).build();
licenseTypeCell.setValue("1DY");
licenseTypeCell.setDataValidation(rule);
}
}
}
Any help/guidance would be greatly appreciated.
You are on the right track, few minor changes. Below you will find some new function to be used in your code.
1) getValue() You get your cell using var aCell = aSheet.getActiveCell() i.e the cell that was edited. But to get the value of the cell you will need to do the following aValue = aCell.getValue()
2) isNaN() To check if the aValue (as determined above) is a number or not. You will use a function called isNaN(aValue). Google script uses javascript platform and hence we need to use functions from javascript. This is different from an inbuilt function you use in a google spreadsheet. It returns True if the value is Not A Number(NAN). Hence, we use a not operator(!) to flip the return value, like so
if(!isNaN(aValue))
3) Number of digits There is no len function in google scripts, hence to determine if the number is 6 digits long you can do the following
if(aValue < 1000000)
Your final code will look something like this:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var aSheet = ss.getActiveSheet();
var aCell = aSheet.getActiveCell();
var aColumn = aCell.getColumn();
var aRow = aCell.getRow();
//var licenseStatus = aSheet.getRange(aRow, aColumn+9).getValue();
// The row and column here are relative to the range
// getCell(1,1) in this code returns the cell at B2, B2
var licenseTypeCell = aSheet.getRange(aRow, aColumn+1);
var aValue = aCell.getValue()
if (aColumn == 1 && aSheet.getName() == 'Main') {
if (!isNaN(aValue) && aValue < 1000000) {
var matchCell = aSheet.getRange(aRow, aColumn+3).getValue()
//The above gets value of column D (MATCH or NO MATCH)
if(matchCell == "MATCH"){ //Check if Col D is MATCH
licenseTypeCell.setValue("ANN");
}
else{
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['ANN','RNW']).build();
licenseTypeCell.setValue("ANN");
licenseTypeCell.setDataValidation(rule);
}
} else {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['1DY','RNW','NEW']).build();
licenseTypeCell.setValue("1DY");
licenseTypeCell.setDataValidation(rule);
}
}
}
Also, note the addition of the following lines to check for col D Value
var matchCell = aSheet.getRange(aRow, aColumn+3).getValue()
//The above gets value of column D (MATCH or NO MATCH)
if(matchCell == "MATCH"){ //Check if Col D is MATCH
licenseTypeCell.setValue("ANN");
}