I am needing to create a single table that displays values from a Cloud SQL data model and Calculated data model side by side as if the data models were related.
Costs Table
I have a calculated data model named 'Costs' that is populated from a spreadsheet. The data in this table looks like this:
PROJECT_ID, ACCRUED_COSTS, REMAINING_COSTS
0001 , 10000 , 25000
0002 , 25000 , 2000
0003 , 15000 , 5000
The code I'm using to generate the calculated model is here:
return getSSData();
function getSSData(){
var values = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("SHEET_NAME").getRange("RANGE").getValues();
var ssData = [];
for (var i = 0; i<values.length; i++){
var newRecord = app.models.costsTable.newRecord();
// add all fields to the new record
newRecord.project = values[i][0].toString();
newRecord.projectID = values[i][1].toString();
newRecord.actual = values[i][2];
newRecord.estimate = values[i][3];
ssData.push(newRecord);
}
// return the array of the model.newRecord objects that would be consumed by the Model query.
return ssData;
}
Projects Table
I also have a Cloud SQL data model named 'Projects'. The data in this table looks like this:
PROJECT_ID, PROJECT_NAME , PROJECT_BUDGET
0001 , project_alpha , 50000
0002 , project_beta , 30000
0003 , project_charlie, 19000
Combined Table
I need to create a page containing a table widget that displays all columns of data from both tables side by side like this:
PROJECT_ID, PROJECT_NAME , PROJECT_BUDGET, ACCRUED_COSTS, REMAINING_COSTS
0001 , project_alpha , 50000 , 10000 , 25000
0002 , project_beta , 30000 , 25000 , 2000
0003 , project_charlie, 19000 , 15000 , 5000
The Problem
This would be easy if the tables could be related to each other but unfortunately calculated models do not support relating.
Per earlier comment you have two options to get this accomplished. Either way add the additional fields like ‘Project_Name’ and ‘Project_Budget’ to your calculated model.
Option 1 (fetch all records with index function):
function getSSData(){
var values = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("SHEET_NAME").getRange("RANGE").getValues();
var projects = app.models.Projects.newQuery().run();
var ids = projects.map(function(p){return p.PROJECT_ID;});
var ssData = [];
for (var i = 0; i<values.length; i++){
var newRecord = app.models.costsTable.newRecord();
// add all fields to the new record
newRecord.project = values[i][0].toString();
newRecord.projectID = values[i][1].toString();
newRecord.actual = values[i][2];
newRecord.estimate = values[i][3];
var index = ids.indexOf(values[i][1].toString());
if(index !== -1) {
var project = projects[index];
newRecord.Project_Name = project.PROJECT_NAME;
newRecord.Project_Budget = project.PROJECT_Budget;
}
ssData.push(newRecord);
}
// return the array of the model.newRecord objects that would be consumed by the Model query.
return ssData;
}
Option 2 (run line item query):
function getSSData(){
var values = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("SHEET_NAME").getRange("RANGE").getValues();
var ssData = [];
for (var i = 0; i<values.length; i++){
var newRecord = app.models.costsTable.newRecord();
var query = app.models.Projects.newQuery();
query.filters.PROJECT_ID._equals() = values[i][1].toString();
var results = query.run();
// add all fields to the new record
newRecord.project = values[i][0].toString();
newRecord.projectID = values[i][1].toString();
newRecord.actual = values[i][2];
newRecord.estimate = values[i][3];
if(results.length > 0) {
var project = results[0];
newRecord.Project_Name = project.PROJECT_NAME;
newRecord.Project_Budget = project.PROJECT_BUDGET;
}
ssData.push(newRecord);
}
// return the array of the model.newRecord objects that would be consumed by the Model query.
return ssData;
}
I would encourage you to try both. Create a variable for startdate = new Date() at the beginning and then before you return the data do console.log(new Date() - startdate), which will give you the time difference in milliseconds of your total script execution. That way you can also figure out for yourself which process is faster.
Related
I have copied the data from Googlesheet1 to Googlesheet2 using the below query
=IMPORTRANGE("url","!A2:H")
Which has copied the data from Googlesheet1 to Googlesheet2.
In that sheet, I am having a duration column like the below image
When i used the app script to copy the data to the firestore instead of saving the duration it saves the data in DateTime format like below.
Is there any way to convert the given duration to seconds in Google sheet.
I have tried using =value(G2*24*3600) but it didn't work in the Googlesheet2 since that sheet is a clone of Googlesheet1
App script Logic:
function firestore() {
// Firestore setup
const email = "//client-email";
const key = "//client-key";
const projectId = "timesheet-aog";
var firestore = FirestoreApp.getFirestore (email, key, projectId);
// get document data from ther spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetname = "timesheet";
var sheet = ss.getSheetByName(sheetname);
// get the last row and column in order to define range
var sheetLR = sheet.getLastRow(); // get the last row
var sheetLC = sheet.getLastColumn(); // get the last column
var dataSR = 2; // the first row of data
// define the data range
var sourceRange = sheet.getRange(2,1,sheetLR-dataSR+1,sheetLC);
// get the data
var sourceData = sourceRange.getValues();
// get the number of length of the object in order to establish a loop value
var sourceLen = sourceData.length;
console.log('sourceLen is', sourceLen);
// Loop through the rows
for (var i=0;i<sourceLen;i++){
var data = {};
console.log('data is', sourceData);
data.date = sourceData[i][0];
data.name = sourceData[i][1];
data.workFrom = sourceData[i][2];
data.project = sourceData[i][3];
data.phase = sourceData[i][4];
data.task = sourceData[i][5];
data.totalHrs = sourceData[i][6];
data.comments = sourceData[i][7];
firestore.createDocument("timesheet",data);
}
}
Here is the formula for A1 cell of the second sheet:
={
IMPORTRANGE("url","!A2:F"),
ARRAYFORMULA(
IF(
IMPORTRANGE("url","!G2:G") = "",
"",
N(IMPORTRANGE("url","!G2:G")) * 24 * 3600
)
),
IMPORTRANGE("url","!H2:H")
}
Try using named ranges for columns (A2:F, G2:G, H2:H) in the original sheet, and import them by those names so you won't need to adjust the formula where exact column names are used.
I just attach my woocommerce through webhook in google sheet and get some code from internet for getting orders data on it every things looks fine but there is only one product name available even if the order contain more than one products.You can check the webhook data here when order is created. here is my google sheet script code
//this is a function that fires when the webapp receives a GET request
function doGet(e) {
return HtmlService.createHtmlOutput("request received");
}
//this is a function that fires when the webapp receives a POST request
function doPost(e) {
var myData = JSON.parse([e.postData.contents]);
var order_created = myData.date_created;
var product_name = myData.line_items[0].name;
var itemName = myData.line_items[0].name;
var quantity = myData.line_items[0].quantity;
var product_items = quantity + " x " + itemName + "\n";
var product_qty = myData.line_items[0].quantity;
var order_total = myData.total;
var billing_email = myData.billing.email;
var billing_first_name = myData.billing.first_name;
var billing_phone = myData.billing.phone;
var shipping_address = myData.shipping.address_1;
var timestamp = new Date();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([timestamp,order_created,billing_first_name,billing_phone,shipping_address,product_name,product_qty,order_total,billing_email,product_items]);
}
You are trying to loop through sone JSON transaction data that includes multiple line items.
There are two flaws in your code:
1 - the script does not loop through the product items:
var product_name = myData.line_items[0].name;
var itemName = myData.line_items[0].name;
var quantity = myData.line_items[0].quantity;
var product_items = quantity + " x " + itemName + "\n";
var product_qty = myData.line_items[0].quantity;
You are getting line_items[0], but if there are multiple line items in the transaction then you are only ever returning the first line item.
2 - The variables being appended in sheet.appendRow() need to be re-considered.
Your code specifies ten variables, including product name and product quantity. However there are no unique values for these two variables since they are form part of the line items and vary with each line item in the transaction.
Your variable product_items is an attempt to recognise this by concatenating the details for each line item; however the variable fails because it depends on looping through the line_items AND progressively concatenating line item values.
The following code is an example of how you might achieve your outcome:
function doPost(e) {
var myData = JSON.parse([e.postData.contents]);
var timestamp = new Date();
var order_created = myData.date_created;
var billing_first_name = myData.billing.first_name;
var billing_phone = myData.billing.phone;
var billing_email = myData.billing.email;
var shipping_address = myData.shipping.address_1;
var order_total = myData.total;
var lineitems=""
for (i in myData.line_items)
{
var product_name = myData.line_items[i].name;
var itemName = myData.line_items[i].name;
var quantity = myData.line_items[i].quantity;
var linetotal = myData.line_items[i].total;
var product_items = quantity + " x " + itemName + ":$"+linetotal +"\n";
var lineitems =lineitems+product_items;
}
Logger.log("Timestamp: "+timestamp);
Logger.log("Order created: "+order_created);
Logger.log("Billing first name: "+billing_first_name+", Phone: "+billing_phone+", Email: "+billing_email);
Logger.log("Shipping Address: "+shipping_address)
Logger.log("Line items = "+lineitems);
Logger.log("Order Total: "+order_total)
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([timestamp,order_created,billing_first_name,billing_phone,shipping_address,order_total,billing_email,lineitems]);
}
How I can extract index vegetation points over collections by adapting this beautiful code by #Rodrigo E. Principe:
Extract pixel values by points and convert to a table in Google Earth Engine
I try extract all values mas GEE is crashing, so only NDVI or EVI can works fine.
I did it with this tutorial https://developers.google.com/earth-engine/tutorial_api_06
// Dataset do sensor LS8
var dataset = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2018-04-01', '2019-03-31')
.select('B5', 'B4')
.filterBounds(aoi6010)
.filter(ee.Filter.lt('CLOUD_COVER', 20));
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
return image.addBands(ndvi);
};
var withNDVI = dataset.map(addNDVI);
print(withNDVI);
// Empty Collection to fill
var ft = ee.FeatureCollection(ee.List([]))
var fill = function(img, ini) {
// type cast
var inift = ee.FeatureCollection(ini)
// gets the values for the points in the current img
var ft2 = img.reduceRegions(p601018, ee.Reducer.first(),30)
// gets the date of the img
var date = img.date().format()
// writes the date in each feature
var ft3 = ft2.map(function(f){return f.set("date", date)})
// merges the FeatureCollections
return inift.merge(ft3)
}
// Iterates over the ImageCollection
var newft = ee.FeatureCollection(withNDVI.iterate(fill, ft))
I am trying to get a spreadsheet to update a calendar on my Google account, but I am struggling to get the if condition on the code below to work. When I run inseritoNelCal the debug says that it is unspecified even though the spreadsheet has actually data in each row/column.
var IN_CAL = new String('INSERITO');
function dallaTabellaAlCalendario() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var title = row[0]; // First column
var startTime = new Date(row[1]); // 2nd column
var endTime = new Date(row[02]); // 3rd column
var description = row[3]; // 4th column
var location = row[4]; // 5th column
var guests = row[5]; // 6th column
var inseritoNelCal = row[6]; // 7th column
}
if (inseritoNelCal != IN_CAL){
var calendar CalendarApp.getCalendarById("mycalendarID").createEvent(title, startTime, endTime, {Descrizione: description, Luogo: location, Allievi: guests, Inserito: inseritoNelCal });
sheet.getRange(startRow, 7).setValue(IN_CAL);
}
}
I have a TABLE in SQL Database there is a columns in
TABLE ID,Subject,Body,Status,TimeDate in the 400 row data and each i have take a Id as a P_Key and Identity Specification is Yes.
Here is Id = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 etc..
I want to select greater Id from table based on saved old id like i have saved ID 12 in im getting same id like this with Linq Query below:
public static int CheckId()
{
DataClassesDataContext con = new DataClassesDataContext(Globals.con);
var q = from v in con.TABLE
where v.Id== 12 & v.Status == Active
select v.Id;
foreach (var val in q)
{
return Convert.ToInt32(val);
}
return 0;
}
the i can return a greater id then 12. and there is also one issue. if there is greater ID is Missing from DB example Id 13 is missing then i will get Id 14 in that case. please let me know how can i get id like this i want from db using linq query.
Use Min
return con.<TABLE>
.Where(v=>v.ID > 12)
.Select(v=>v.ID)
.DefaultIfEmpty()
.Min();
I made a sample for you
List<Int32> test = new List<Int32>{1,2,3,4,5,6,7,8,9,10,11,12,14,13,15,16};
var min = test.Where(x=>x>12).Min();
Gives result 13 only, even when 14 is the first bigger
In Your case
//get a table object
Table table = new Table() //if you want whole row.
table = con.Table.Where(x=>x.id>12).MIN();
Based on the code you already have:
DataClassesDataContext con = new DataClassesDataContext(Globals.con);
var q = from v in con.TABLE
where v.Id > 12 & v.Status == Active
orderby v.Id
select v.Id;
return q.Take(1); // to return the whole row
// or
return q.Take(1).Id; // to return only the Id
This would return the first row meeting the criterias (id > 12, status = active). Add error handling code as needed.