How to convert duration to seconds in Google Sheets which uses IMPORTRANGE - firebase

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.

Related

How do I solve the 0 element problem in Google Earth Engine?

I used the .combine command to convert two image collections into a two-band image collection (in the last line) to use in a function in the next step. This command is executed but writes 0 elements in the console. Where does this problem come from?
code link: https://code.earthengine.google.com/ed0992093ff830d926c7dd14403477c6
Code:
var ndvi = function(img){
var bands = img.select(['B2','B3','B4','B8']).multiply(0.0001)
.clip(geometry);
var index = bands.normalizedDifference(['B8','B4']).rename('NDVI_S2');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
var S2 = ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
//.filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE',20))
.map(ndvi);
print(S2);
var START = '2018-10-24';
var END = '2019-06-30';
var DATES = [ '2018-12-19', '2018-12-29', '2019-01-23', '2019-02-12', '2019-03-04',
'2019-03-19', '2019-04-08', '2019-04-13', '2019-05-13', '2019-05-18', '2019-05-23',
'2019-05-28', '2019-06-02', '2019-06-07', '2019-06-12', '2019-06-17', '2019-06-22',
'2019-06-27'];
var addTime = function(x) {
return x.set('Date', ee.Date(x.get('system:time_start')).format("YYYY-MM-dd"))};
var Sentinel = ee.ImageCollection(S2)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print(Sentinel);
var PMODIS =
ee.Image('MODIS/006/MCD43A4/2018_12_19').select('Nadir_Reflectance_Band4');
var MODProjection = PMODIS.projection();
print('MODIS projection:', MODProjection);
var Viz = {min: 0, max: 1, palette: ['be6c44','ca3a3a','e4ae0c','565c04','819536']};
var S2_resampled = Sentinel.map(function(img){
var S2Mean = img
// Force the next reprojection to aggregate instead of resampling.
.reduceResolution({
reducer: ee.Reducer.mean(),
maxPixels: 2146
})
// Request the data at the scale and projection of the Sentinel image.
.reproject({
crs: MODProjection
});
return S2Mean
.copyProperties(img,['system:time_start','system:time_end','system:index']);
});
Map.addLayer(S2_resampled)
var M_ndvi = function(img){
var bands =
img.select(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5']).multiply(0.0001)
.clip(geometry);
var index=bands
.normalizedDifference(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5'])
.rename(
'NDVI_MOD');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
var MOD = ee.ImageCollection('MODIS/006/MCD43A4')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
.map(M_ndvi);
var MODIS = ee.ImageCollection(MOD)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print(MODIS);
var S2_and_MOD = S2_resampled.combine(MODIS, false);
print(S2_and_MOD);
var Diff = S2_and_MOD.map(function(img){
var clip = img.clip(geometry);
var Diffe = clip.expression('NDVI_S2 - NDVI_MOD',
{'NDVI_S2':clip.select('NDVI_S2') ,
'NDVI_MOD':clip.select('NDVI_MOD')}).rename('Diff');
return Diffe
.copyProperties(img,['system:time_start','system:time_end']); });
print(Diff);
ee.Image.combine() uses the system:ID property to join the 2 images. See the documentation here. Since your images do not match, the resulting collection has no images.
A solution that should fit your needs utilizes the ee.Join.inner() to take advantage of the Date property that you have created to join the 2 image collections. A similar question was answered here.
Using inner join, I was able to accomplish what appeared to be your goal of finding the difference in NDVI between the S2 and MODIS collections. The full working script can be found here: https://code.earthengine.google.com/dc45df1b7cf83723d53e9f7917975e2d
Code:
// Function - Calculate S2 NDVI
var ndvi = function(img){
var bands = img.select(['B2','B3','B4','B8']).multiply(0.0001)
.clip(geometry);
var index = bands.normalizedDifference(['B8','B4']).rename('NDVI_S2');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
// Get S2 NDVI images
var S2 = ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
//.filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE',20))
.map(ndvi);
print('S2 NDVI ImageCollection',S2);
// Set Date Parameters
var START = '2018-10-24';
var END = '2019-06-30';
// Create Date List
var DATES = [ '2018-12-19', '2018-12-29', '2019-01-23', '2019-02-12', '2019-03-04',
'2019-03-19', '2019-04-08', '2019-04-13', '2019-05-13', '2019-05-18', '2019-05-23',
'2019-05-28', '2019-06-02', '2019-06-07', '2019-06-12', '2019-06-17', '2019-06-22',
'2019-06-27'];
// Function - Add 'Date' field to image
var addTime = function(x) {
return x.set('Date', ee.Date(x.get('system:time_start')).format("YYYY-MM-dd"))};
// Run addTime on S2 ImageCollection
var Sentinel = ee.ImageCollection(S2)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print('Date Added S2', Sentinel);
// Get MODIS Projection
var PMODIS = ee.Image('MODIS/006/MCD43A4/2018_12_19').select('Nadir_Reflectance_Band4');
var MODProjection = PMODIS.projection();
print('MODIS projection:', MODProjection);
// Set Visualization Parameters
var Viz = {min: 0, max: 1, palette: ['be6c44','ca3a3a','e4ae0c','565c04','819536']};
// Reproject S2 images to MODIS projection
var S2_resampled = Sentinel.map(function(img){
var S2Mean = img
// Force the next reprojection to aggregate instead of resampling.
.reduceResolution({
reducer: ee.Reducer.mean(),
maxPixels: 2146
})
// Request the data at the scale and projection of the Sentinel image.
.reproject({
crs: MODProjection
});
return S2Mean
.copyProperties(img,['system:time_start','system:time_end','system:index']);
});
print('S2_resampled',S2_resampled);
Map.addLayer(S2_resampled);
// Function - Calculate MODIS NDVI
var M_ndvi = function(img){
var bands = img.select(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5']).multiply(0.0001)
.clip(geometry);
var index = bands.normalizedDifference(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5']).rename('NDVI_MOD');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
// Get MODIS NDVI Images
var MOD = ee.ImageCollection('MODIS/006/MCD43A4')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
.map(M_ndvi);
// Run addTime on MODIS ImageCollection
var MODIS = ee.ImageCollection(MOD)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print('MODIS',MODIS);
// Combine MODIS and S2 Image Collections using Date
// Specify the join type
var join_type = ee.Join.inner();
// Set the join parameter
var filter = ee.Filter.equals({
leftField: 'Date',
rightField: 'Date'
});
// Execute the join
var inner_join = ee.ImageCollection(join_type.apply(MODIS,S2_resampled,filter));
// Flatten joined images into a single image with 2 bands
var S2_and_MOD = inner_join.map(function(feature) {
return ee.Image.cat(feature.get('primary'), feature.get('secondary'));
});
print('Combined S2 and MODIS Collection:',S2_and_MOD);
// Calculate the difference between S2 and MODIS NDVI values
var Diff = S2_and_MOD.map(function(img){
var clip = img.clip(geometry);
var Diffe = clip.expression('NDVI_S2 - NDVI_MOD',
{'NDVI_S2':clip.select('NDVI_S2') , 'NDVI_MOD':clip.select('NDVI_MOD')}).rename('Diff');
return Diffe
.copyProperties(img,['system:time_start','system:time_end']); });
print('NDVI Difference Collection',Diff);

Write to Spreadsheet in Google sheet from ASP.NET

I have a code, it should write in the Spreadsheet of google sheet. When I run the function, I receive this error:
Message[Requested writing within range ['6/12/2019-20:37'!A1], but
tried writing to column [B]] Location[ - ] Reason[badRequest]
Domain[global]
That its my code:
private void SheetPattern(Item webinar)
{
var valueRange = new ValueRange();
var range = $"{sheet}!A:D";
DateTime dateTime=(DateTime)webinar.webInfo.times[0].startTime;
var date = dateTime.Day+"-"+dateTime.Month+"-"+dateTime.Year;
var hour = dateTime.Hour + ":" + dateTime.Minute;
var webName = webinar.webInfo.subject;
var webDescription = webinar.webInfo.description;
var oblist = new List<object>() { date, hour, webName, webDescription};
valueRange.Values = new List<IList<object>> { oblist };
var appendRequest = service.Spreadsheets.Values.Append(valueRange, SpreadsheetId, range);
Console.WriteLine(appendRequest);
appendRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum.USERENTERED;
var appendReponse = appendRequest.Execute();
}
I found the problem its a Syntax problem, here:
var hour = dateTime.Hour + ":" + dateTime.Minute;
when I make a new sheet with a new name, google sheet doesn't permit the char : in the sheet name. So I change this code for that code:
var hour = dateTime.Hour + "-" + dateTime.Minute;

Extract Index vegetation by points over collection in GEE

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))

Relate calculated data model to Cloud SQL model

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.

Why the "if" gets ignored in this Google apps script?

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);
}
}

Resources