The "stock/average" sheet calculates the average purchase price. F is Products and H is the purchase price.
I need to calculate and save profit/loss of each sale in the E column after every sale. Like: the purchase price of the first product is 14200 (First image # stock/average, column H, second product) so 2800 should be put here. I can do it using vlookup or query but the purchase price gets changed with each purchase so I need to do it using the script and preserve the result.
Link to Spreadsheet:
Please help.
The code in this answer is presented in two parts:
Section One - Add this to your IF statement.
var thissheet = range.getSheet();
var edditedCol = range.columnStart;
var edittedRow = range.rowStart;
var productdetails = sheet.getRange(edittedRow,1,1,5).getValues();
var product = productdetails[0][0];
var qty = productdetails[0][1];
var sellprice = productdetails[0][2];
// Logger.log("DEBUG: product = "+product+", qty:"+qty+", sellprice="+sellprice);
var avg = getcost(product);
var net = +sellprice-(+avg*qty);
var netprofit = Math.round(net * 100) / 100
sheet.getRange(edittedRow,5).setValue(netprofit);
// Logger.log("DEBUG: net profit = "+netprofit);
This identifies the edited row and column, and get the values for the appropriate
- Product
- Qty
- Total sales value
- calls a separate function to return the average cost for the relevant product,
- calculates the net profit,
- updates the value in the "Profit" Column on the sheet.
Section Two - a sub-routine gets the average cost from the "stock/average" Sheet.
function getcost(product){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetname = "stock/average";
var sheet = ss.getSheetByName(sheetname);
var Fvals = sheet.getRange("F5:F").getValues();
var Flast = Fvals.filter(String).length;
var sarange = sheet.getRange(5,6,Flast,7);
// Logger.log("DEBUG: sarange = "+sarange.getA1Notation());
var data = sarange.getValues();
// convert the 2D array to a 1D array for the "Product" column.
var colA = new Array()
for(i=0;i<data.length;++i){
colA.push(data[i][0]) ;// taking index 0 means I'll get column A of each row and put it in the new array
}
// find the posityion of the editted product on the "stack/average" sheet
var pos = colA.indexOf(product);
// get the average cost for this line.
var avgcost = data[pos][2];
// Logger.log("DEBUG: the average cost = "+avgcost);
return avgcost;
}
Related
I've wrote the following code- on the homepage there is a cell (merged at the moment) where we'd put in the date. The end goal is to have the script send emails out when the current date meets 14 days later from the date in the cell.
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Email addresses")
var hpsheet = ss.getSheetByName("Main Page-Control Plan")
var startRow = 2; // Start at second row because the first row contains the data labels
var numRows = 2; // Put in here the number of rows you want to process
// Fetch the range of cells A2:B4
// Column A = Email Address, Column B = First Name
var dataRange = sheet.getRange(startRow, 1, numRows, 2)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column of selected data
var personName = row[1]
var currentDate = new Date(hpsheet.getRange("F6:F9").getValue());
var fourteenDaysLater = new Date(currentDate.getTime() + 14 * 24 * 60 * 60 * 1000);
console.log(fourteenDaysLater)
var subject = 'Recovery schedule is due';
var message ='Hi, ' + personName + '\n\n' + 'Recovery schedule is due. Please notify other members in this email chain if this has been done. '
if (fourteenDaysLater < new Date()) {
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
I've put a daily trigger on it to run the script between 6-7am and put the date in the cell as 09/02/23, I've changed the number of days to 1 in the fourteenDaysLater variable so I could see if it worked today but I didn't get emails for some reason.
Is there something wrong with the code?
I think the problem is when you parse the string to Date(), where the parsed date shows Sat Sep 16 00:00:00 GMT+12:00 2023 in my timezone.
To make sure it parses the correct format and timezone, try the code below:
var timezone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var dateString = "09/02/23"; //replace with your cell value
var format = "dd/MM/yy"; //date format to parse
var currentDate = Utilities.parseDate(dateString,timezone,format);
var fourteenDaysLater = new Date(currentDate.getTime() + 14 * 24 * 60 * 60 * 1000);
I'm trying to organize a database by a rank in a certain order that I want. Normally, sort would work, but I want a couple of things to happen:
1. raw data so that filters can work for other data (i.e. by name, team, etc)
2. I don't want to always sort by rank
Ranks in order:
Captain, Officer, Chef, Crew, Recruit, Lost, Brig
Right now I'm forcing a filtered sort first alphabetically only when the rank filter is sorted, then when that is done, it sorts the list according to the above sort. The problem that I'm having is that it takes some time to execute the script. I'm thinking that this can be done much more efficiently, but I'm way rusty when it comes to this stuff. Here's my code below:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var members = ss.getSheetByName("Members");
var temp = ss.getSheetByName("sortRank");
var ranks = ["Captain", "Officer", "Chef", "Crew", "Recruit", "Lost", "Brig"];
var rankData = members.getRange(1,5,members.getLastRow(),1);
var search = null;
var query = null;
var x = null;
if(order != null) {
ranks = ranks.reverse();
}
for (var i=0; i < 7; i++) {
search = rankData.createTextFinder(ranks[i]);
x = search.findAll().length;
if(x != 0) {
query = search.findNext().getRow();
members.getRange(query,1,x,37).copyTo(temp.getRange(temp.getLastRow()+1,1));
}
}
}
Sort members by rank:
Assumes rank is in column 5 of members.
var members = ss.getSheetByName("Members");
var rankData = members.getRange(1,5,members.getLastRow(),1).getValues();
var ranks = ["Captain", "Officer", "Chef", "Crew", "Recruit", "Lost", "Brig"];
var rVal={};
ranks.forEach(function(e,i){rVal[e]=i+1;});
members.getDataRange().setValues(members.getDataRange().getValues().sort(function(a,b){return rVal[a[4]]-rVal[b[4]];}));
I'd like to make a script that compares the date within a row to today's date and delete that row if today's date is paste the date row.
This is my current script:
function deleteRow1() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 1; // First row of data to process
var numRows = sheet.getLastRow()-1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 2, numRows);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i=0;i<data.length;i++) {
var row = data[i];
var date = new Date();
var sheetDate = new Date(row);
var Sdate = Utilities.formatDate(date,'GMT+0200','yyyy:MM:dd')
var SsheetDate = Utilities.formatDate(sheetDate,'GMT+0200', 'yyyy:MM:dd')
if (Sdate > SsheetDate){
sheet.deleteRow(i+2) //don't delete header
}
}
}
The ultimate goal is to compare dates in column C with today's date and to delete that particular row if today's date is greater.
Right now when I run the script, it deletes some rows, but not specifically the rows that are earlier than today's date.
The beginnings of this script was based off another StackOverflow post
when you start iteration from top to bottom deleting row in iteration alter the offset (actual row number) of next rows
above problem can be solved using start the iteration from bottom to top.
for (i=data.length-1;i>=0;i--)
here is the working code
function deleteRow1()
{
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow()-1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 2, numRows);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i=data.length-1;i>=0;i--)
{
var row = data[i];
var date = new Date();
var sheetDate = new Date(row);
var Sdate = Utilities.formatDate(date,'GMT+0200','yyyy:MM:dd')
var SsheetDate = Utilities.formatDate(sheetDate,'GMT+0200', 'yyyy:MM:dd')
if (Sdate.valueOf() > SsheetDate.valueOf())
{
sheet.deleteRow(i+2) //don't delete header
}
}
}
I am trying to pre-populate a drop down list in a Google Form from a list generated by a range in a Google Sheet. I can pull the list into an array, but can't seem to create the choice in the form.
//Define sheet location (where vendor list range lives) and form location
var se = SpreadsheetApp.openById("sheet_ID_that_works");
var vendorList = se.getSheetByName("vendorList");
var vendorPullIn = sub.getRange("vendorListRange");
var form = FormApp.openById('form_ID_that_works');
var item = form.addListItem();
item.setTitle('Select Vendor')
var choiceList = vendorPullIn.getValues();
item.setChoiceValues(choiceList);
choices need to be in a single array...
.getValues() returns a 2d array...
one way to flatten values out...
var choiceList = [];
var values = vendorPullIn.getValues();
for ( var row in values )
for ( var col in values[row] )
if ( values[row][col] )
choiceList.push( values[row][col] );
I've written a script to collect data by global variables:
var row = sheet.getActiveSelection().getRowIndex();
var mfg = sheet.getRange("M" + row).getValue().toUpperCase()
var changeOrder = sheet.getRange("W" + row).getValue().toUpperCase()
var sku = sheet.getRange("H" + row).getValue()
var revision = sheet.getRange("AE" + row).getValue()
var productName = sheet.getRange("J" + row).getValue().toUpperCase()
var packSize = sheet.getRange("K" + row).getValue().toUpperCase()
var project = sheet.getRange("D" + row).getValue().toUpperCase()
var targetSS = SpreadsheetApp.openById('0Ai_j76HcGMnIdG1QNDgxQU1NWWVIQ2o2bkM5SjdtQ0E').getSheetByName('Tech Newsletter - Current');
var targetLastRow = targetSS.getLastRow(); // Get # rows currently in target
var targetNewRow = targetLastRow+1
var nlMfg = targetNewRow.getRange("C").setValue(mfg);
and I want to run a custom script, when the menu option is selected, it will take the global variables and add them in custom order (next available row) to a pre-defined worksheet or another google doc if possible.
The other worksheet is called "Newsletter" and
Column A = Timestamp, Column B = User, Column C = mfg, Column D = changeOrder, Column E = sku, Column F = productName + packSize, Column G = project
I am able to write a function to get a text box, but this doesn't help. The research I've done only leads me to copying an entire range based on criteria. Not helping. I have the menu option already, but need a function to tell the document where to put the data.
Thanks,
See spreadsheetApp.openById(yourid).appendRow
var targetSS = SpreadsheetApp.openById('0Ai_j76HcGMnIdFRUUFZIRTdsUmhXdjcxUmtmSlY3Mmc').getSheetByName('Newsletter Template');
var targetLastRow = targetSS.getLastRow(); // Get # rows currently in target
var targetNewRow = targetLastRow+1
targetSS.getRange("A"+targetNewRow).setValue(month + "/" + day + "/" + year);
targetSS.getRange("B"+targetNewRow).setValue(username)
targetSS.getRange("C"+targetNewRow).setValue(mfg);
targetSS.getRange("D"+targetNewRow).setValue(changeOrder);
targetSS.getRange("E"+targetNewRow).setValue(sku + " REV" + revision);