I have a sheet that shows Items Cost. What I want to do instead of showing numbers i want to use the following BLACKHORSE were B = 1, L = 2, A = 3,C=4,K=5,H=6,7=O,8=R,9=S and E=0. How do i put this in a script in Google Sheets to where say cell h9 the sum of the total cost of the items it puts the letters instead of numbers
There may be many ways to calculate the values that you want. Consider this as one approach.
function so5715442701() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetname = "57154427";
var sheet = ss.getSheetByName(sheetname);
// code to find the key for a given value in a javascript key:value array
Object.prototype.getKey = function(value){
for(var key in this){
if(this[key] == value){
return key;
}
}
return null;
};
// a key:value array for BLACKHORSE
var blackhorse = {
B : 1,
L : 2,
A : 3,
C : 4,
K : 5,
H : 6,
O : 7,
R : 8,
S : 9,
E : 0
};
// get the cost value from a cell
var costprice = sheet.getRange("C15").getValue();
// convert the number to a string
var cost = costprice.toString(); // convert to string
//Logger.log("DEBUG: cost = "+cost+", length = "+cost.length);
// set a variable to accumulate the results
var costtotal="";
// loop through the characters in the cost value
for (var i = 0; i < cost.length; i++) {
var letter = cost.charAt(i);
var costkey = blackhorse.getKey(letter);
var costtotal = costtotal+costkey
}
//Logger.log("DEBUG: cost = "+cost+", Blackhourse cost = "+costtotal);
sheet.getRange("D15").setValue(costtotal);
}
CREDIT
- How can I process each letter of text using Javascript?
- How to get a key in a JavaScript object by its value?
Related
I am using google spreadsheet and this is my code to import data and save my filter on it.
function importCSVFromWeb() {
// Provide the full URL of the CSV file.
var csvUrl = "https://covid19.who.int/WHO-COVID-19-global-table-data.csv";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var sheet = SpreadsheetApp.getActiveSheet();
// --- I added below script.
var filter = sheet.getFilter();
var range = filter.getRange();
var criteria = [];
var start = range.getColumn();
var end = start + range.getNumColumns() - 1;
for (var i = start; i <= end; i++) {
var criterion = filter.getColumnFilterCriteria(i);
if (criterion) criteria.push({col: i, c: criterion.copy()});
}
filter.remove();
// ---
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
// And, I added below script.
criteria.forEach(({col, c}) => range.createFilter().setColumnFilterCriteria(col, c));
}
My issue is: How can i share the spreadsheet with my filter applied on it to use it ?
In my case, I want to use another visualization tool on only filtered data
I manage a large email list for my gaming society. In column A, I have the e-mails, and in column B, I have the usernames. I populate column B with a formula that extracts the name of the user from their e-mail address, which is often in the firstname.lastname#email.com form. Column B therefore returns "Firstname" after I run the formula if the user's email is in the firstname.lastname#email.com format.
Sometimes, however, the emails have just the initial of the first name (f.lastname#email.com) and, in these case, I want to have Column B return the word 'Gamer' rather than, for example, the first letter of the user's email.
Here is the script I use at the moment, which current deletes all rows with four or more numbers:
function removeNumbers() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
if (row[0].toLowerCase().indexOf("robot") > -1) {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
On your shared spreadsheet, use this
function firstName() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var lr=sheet.getLastRow()
var val = sheet.getRange(2,1,lr-1,2).getValues();//get the col A email addrs
var newVal=[]//new array for before fitst period
for (var i = 0; i <= val.length-1; i++) {
var str=val[i][0].split(".")//split email at period
var len=str[0].length // determine lenght of number string of first split
if(val[i][1]=="inactive"){
newVal.push(["inactive"])
continue
}
if(len<=1){//if 1 or less
def="Gamer"
newVal.push([def]) //put Gamer in new array
}
else{
newVal.push([toTitleCase(str[0])]) //keep first name
}}
sheet.getRange(2, 2, newVal.length, 1).setValues(newVal)//set new values in col B
}
function toTitleCase(str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0)
.toUpperCase() + txt.substr(1)
.toLowerCase();
});
}
This well also run on the active sheet.
I have a large sheet with over 4000 rows and 30 columns.
I am trying to automaticly add new rows to the sheet if there are less than x "empty" rows. Empty rows are defined by just containing formulas but the data column A is empty.
To check if a row is empty or not I check column A, because you have to enter data in column A. After adding new rows the script should copy/paste the last row before over the new rows, so they contain the formulas as well.
Here is the script (PREVIOUS VERSION):
function addRowsItems() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('items');
var freeRows = 300; // Number of empty Rows after last Entry
var lRow = sh.getLastRow(), lCol = sh.getLastColumn(), range = sh.getRange(lRow,1,1,lCol);
var startRow = lRow-freeRows;
if(startRow < 0) {
startRow = 1; }
var values = sh.getRange("A" + startRow + ":A").getValues();
var maxIndex = values.reduce(function(maxIndex, row, index) {
return row[0] === "" ? maxIndex : index;
}, 0);
var maxIndex = maxIndex + startRow;
var space = lRow - maxIndex;
var addLines = freeRows - space;
if(space < freeRows) {
sh.insertRowsAfter(lRow, addLines);
range.copyTo(sh.getRange(lRow+1, 1, addLines, lCol), {contentsOnly:false});
}
}
This is working in a new sheet with less data.
But using it in the main sheet with over 4000 rows of data I get a time out. The script adds the new rows but it times out before it is able to copy/paste.
Why is it taking so much time? Is there an easier way to achieve that?
So this is the actual version. Cell B1 contains COUNBLANK of Range A:A.
function addRowsItems() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('items');
var freeRows = 307; // Number of empty Rows after last Entry
var lRow = sh.getMaxRows(), lCol = sh.getMaxColumns(), range = sh.getRange(lRow,1,1,lCol);
var space = sh.getRange("B1").getValues();
var addLines = freeRows - space;
if(space < freeRows) {
sh.insertRowsAfter(lRow, addLines);
range.copyTo(sh.getRange(lRow+1, 1, addLines, lCol), {contentsOnly:false});
}
}
Try the COUNTBLANK function returns a count of empty cells in a range. Cells that contain text, numbers, errors, etc. are not counted. Formulas that return empty text are counted.
I have a function that copies and pastes info from one sheet to two others, then sorts all three sheets differently. The first sheet is a simple alpha sort by column 1, the second sheet is an alpha sort by column 2, and the third sheet sorts by columns 3-8 in that order. When data is edited on "Student list details" the user clicks the "SORT" button to run this script and modify all three pages. However, the third page (AutoDocHeidiOnly2) is not sorting properly. There is no error given, it appears to run fine, but the sheet is not sorted.
function myFunction() {
//var copyFromRange = 'Student List Details!A3:H1000';
//var copyToRangeStart = 'AutoDocHeidiOnly!A3:H1000';
// copyValuesOnly(copyFromRange, copyToRangeStart);
var sld = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Student List Details");
var ado = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("AutoDocHeidiOnly");
var ado2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("AutoDocHeidiOnly2");
var sourceRange=sld.getRange("A3:H1000");
var sourceData = sourceRange.getValues();
ado.getRange(3,1,sourceData.length,sourceData[0].length).setValues(sourceData);
ado2.getRange(3,1,sourceData.length,sourceData[0].length).setValues(sourceData);
var lastRow = sld.getLastRow()
var range = sld.getRange(3,1,lastRow,9);
range.sort(1);
var lastRow = ado.getLastRow()
var range = ado.getRange(3,1,lastRow,8);
range.sort(2);
var lastRow = ado2.getLastRow()
var range = ado2.getRange(3,1,lastRow,8);
range.sort({Column: 3},{Column: 4},{Column: 5},{Column: 6},{Column: 7},{Column: 8});
// ado.getDataRange()
// var rowssld = sld.getDataRange().getValues();
// var ado2 = sheet.getSheets('AutoDocHeidiOnly2')
//var row = sld.getRange(88, 3, 1, 9).getValues();
// ado.appendRow(row[0]);
// var targetrange = ado.getRange(3, 1, sld.getLastRow(), 9);
//var rangeValues = sld.getRange(3, 1, sld.getLastRow(), 9).getValues();
//targetrange.setValues(rangeValues);
//for (var i = 3; i < rowssld.length; i++){
// for (var j = 1; j < 9; j++){
// var val=sld.getRange(i,j).getValue();
// ado.getRange(i,j).setValue(val);
// }
// }
Browser.msgBox("FINISHED") ;
}
function test()
{
var sld = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Student List Details");
var ado = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("AutoDocHeidiOnly");
var ado2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("AutoDocHeidiOnly2");
var sourceRange=sld.getRange("A3:H1000");
var sourceData = sourceRange.getValues();
ado.getRange(3,1,sourceData.length,sourceData[0].length).setValues(sourceData);
ado2.getRange(3,1,sourceData.length,sourceData[0].length).setValues(sourceData);
var lastRow = sld.getLastRow()
var range = sld.getRange(3,1,lastRow,9);
range.sort(1);
var lastRow = ado.getLastRow()
var range = ado.getRange(3,1,lastRow,8);
range.sort(2);
var lastRow = ado2.getLastRow()
var range = ado2.getRange(3,1,lastRow,8);
range.sort(3);
// ado.getDataRange()
// var rowssld = sld.getDataRange().getValues();
// var ado2 = sheet.getSheets('AutoDocHeidiOnly2')
//var row = sld.getRange(88, 3, 1, 9).getValues();
// ado.appendRow(row[0]);
// var targetrange = ado.getRange(3, 1, sld.getLastRow(), 9);
//var rangeValues = sld.getRange(3, 1, sld.getLastRow(), 9).getValues();
//targetrange.setValues(rangeValues);
//for (var i = 3; i < rowssld.length; i++){
// for (var j = 1; j < 9; j++){
// var val=sld.getRange(i,j).getValue();
// ado.getRange(i,j).setValue(val);
// }
// }
Browser.msgBox("FINISHED") ;
}
//function copyValuesOnly(copyFromRange, copyToRangeStart) {
// var ss = SpreadsheetApp.getActiveSpreadsheet();
//var source = ss.getRange(copyFromRange);
//source.copyTo(ss.getRange(copyToRangeStart), {contentsOnly: true});
Just taking a crack at this, but did you try specifying the ascending order for the columns on the 3rd sheet? For example:
range.sort({Column: 3},{Column: 4},{Column: 5},{Column: 6},{Column: 7},{Column: 8});
Try:
range.sort([{Column: 3, ascending: true},{Column: 4, ascending: true},{Column: 5, ascending: true},{Column: 6, ascending: true},{Column: 7, ascending: true},{Column: 8, ascending: true}]);
By no means am I one of the wizards on here, but I've ran into some funky issues myself, so just trying to be helpful! :)
I am facing a problem in the following script. I am not much into scripting at all and this is not my script also but here am getting the result which is grouping the values( For Example if i have a value A in three cells it should return the value as 3 instead it is returning AAA. Can someone help me out to count the values and return it
Thanks in Advance,
Here is the script :
function sumBackgroundColors(rangeString, color) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var sumRange = s.getRange(rangeString);
//var sum = 0;
var openCount = 0;
var sumRangeBackground = sumRange.getBackgroundColors();
var sumRangeValues = sumRange.getValues();
for(var row = 0; row < sumRangeBackground.length; row++ ) {
for(var col = 0; col < sumRangeBackground[0].length; col++ ) {
if( sumRangeValues[row][col]=="LG M"&& sumRangeBackground[row][col] == color ) {
openCount = openCount + sumRangeValues[row][col];
//if(sumRangeBackground[row][col] == color && sumRangeValues[row][col] == 1 ) {
// sum = sum + parseFloat(sumRangeValues[row][col]);
}
}
}
return openCount;
//return sum;
}
Here is a function which will take the value to be searched as argument. Rest of the things have been explained in comment lines.
function searchCount(value){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get the whole data from activesheet in a 2D array
var data = sheet.getDataRange().getValues();
//Initialize counter
var count = 0;
//Iterate through the array
for(var i in data){
for(var j in data[i]){
// if a match found, increament the counter
if(value.toString == data[i][j]){
count++;
}
}
}
// return the count value
return count;
}
your problem could be due to openCount = openCount + sumRangeValues[row][col];
According to your example sumRangeValues[row][col] isn't an int. int + not an int = ??? if you want to keep a count of things you probably want openCount++ to replace that line instead, which is just a shortcut to openCount = openCount + 1;
Even if sumRangeValues[row][col] was an int, that line still wouldn't be what you're looking for. If you're searching for all the 3s in your spreadsheet your code would find your first 3, and then that line would execute 0 = 0 + 3 congrats, you just found 3 threes. You would continue to add three every time you found a three.
Waqar's code is essentially your code (amazingly simplified, but it iterates the same way) except he doesn't check color and he uses ++ instead of that line.