Adding a row and copying the information from the original row for every day in a date range in Google Sheets #2 - date

I have a Google Sheet where information from a Google Form is dumped. Two of the columns create a date range (columns C and G) and I would like for the sheet to automatically create a new row of information for every date of the range and copy all the other information from the original row for every row that is created. In the end, every date in the range has it's own row regardless of it being 2 days or 25 and all the the information gathered through the form be present for each day. If there is not a date in column G, it is only a one day trip and there is no need for additional rows. To make things more difficult when someone submits a form, the information is entered into the row directly beneath the last one that it filled, so these new rows filled by the date range will need to be down the sheet, possibly beginning at row 2000 or more as this sheet will have a lot of information in a few months. As you may see in the sample, there is another sheet in the workbook that performs all the sorting. Thanks for any help.
Sample Document

You will need to create a form submit event and attach the following code to it. Also you'll need to create a sheet name 'ResponseReview'.
function formSubmitEvent1(e)
{
var ss=SpreadsheetApp.openById('SpreadsheetID');
var sht=ss.getSheetByName('ResponseReview');
sht.appendRow(e.values);
}
The above code will need the SpreadsheetId in the openById Method. This code will append any new rows to the end of the ResponseReview sheet.
The code below will expand any entrees that have a date in column 3 and 7 and it will also remove the end date in column 7 from that first row. I use the fact that if column 3 is not empty and column 7 is not and column 7 is no equal to column 3 then that's a row that needs to be expanded. So I have to remove the end date so that it won't continue to get expanded when it's run again in the future. We could figure something else out if you need to keep than end date. We could add a don't expand column at the end.
function convertRangetoRows()
{
var ss=SpreadsheetApp.getActive();
var sht=ss.getSheetByName('ResponseReview');
var rng=sht.getDataRange();
var rngA=rng.getValues();
var rngB=[];
var day=86400000;
rngB.push(rngA[0]);
for(var i=1;i<rngA.length;i++)
{
rngB.push(rngA[i]);
if(rngA[i][2] && rngA[i][6] && rngA[i][2]!=rngA[i][6])
{
var row=rngA[i].slice();//returns a new copy of the array by value
rngA[i][6]='';//deletes the end date by reference so it also deletes the one thats already been pushed into rngB
var dt0=new Date(row[2]);
var dt1=new Date(row[6]);
var days=(dt1.valueOf()-dt0.valueOf())/day;
var dt=dt0.valueOf();
for(j=0;j<days;j++)
{
dt+=day;
row[2]=Utilities.formatDate(new Date(dt), Session.getScriptTimeZone(), "MM/dd/yyyy");//original array unchanged
row[6]='';//original array unchanged
rngB.push(row.slice());//push in a copy
}
}
var intermediate='nothing';
}
var outrng=sht.getRange(1,1,rngB.length,rngB[0].length);
outrng.setValues(rngB);
var end='the end is near';
}
This is what my spreadsheet looks like before running the expansion function:
And After:
And now you can leave the sheet linked to the form alone and let it be an archive for submitted data.

Related

Remove formula from column with python

I am trying to remove the formula from a column in a existing sheet with python.
I tryed to set my formula to None using the column object (column.formula = None)
It does not work and my column object remains unchanged. Anyone have inputs to solve this issue ? Thank you !
This took me a bit to figure out, but seems like I've found a solution. Turns out that this is a 2-step process:
Update the column object to remove the formula (by setting column.formula to an empty string).
For each row in the sheet, update the cell within that column to remove the formula (set cell.value to an empty string and cell.formula to None).
Completing the STEP 1 will remove the formula from the column object -- but that cell in each row will still contain the formula. That's why STEP 2 is needed -- STEP 2 will remove the formula from the individual cell in each row.
Here's some example code in Python that does what I've described. (Be sure to update the id values to correspond to your sheet.)
STEP 1: Remove formula from the Column
column_spec = smartsheet.models.Column({
'formula': ''
})
# Update column
sheetId = 3932034054809476
columnId = 4793116511233924
result = smartsheet_client.Sheets.update_column(sheetId, columnId, column_spec)
STEP 2: Remove the formula from that cell in each row
Note: This sample code updates only one specific row -- in your case, you'll need to update every row in the sheet. Just build a row object for each row in the sheet (like shown below), then call smartsheet_client.Sheets.update_rows once, passing in the array of row objects that you've built corresponding to all rows in the sheet. By doing things this way, you're only calling the API once, which is the most efficient way of doing things.
# Build new cell value
new_cell = smartsheet.models.Cell()
new_cell.column_id = 4793116511233924
new_cell.value = ''
new_cell.formula = None
# Build the row to update
row_to_update = smartsheet.models.Row()
row_to_update.id = 5225480965908356
row_to_update.cells.append(new_cell)
# Update row
sheetId = 3932034054809476
result = smartsheet_client.Sheets.update_rows(sheetId, [row_to_update])

Problem with understanding date formats in googleScripts

I made a few functions with GoogleSheets using AppsScripts for simple task a few times in previous years. I always had problems when taking dates from cells/ranges and processing them, but somehow alwaays found a workaround, so that I did not have to deal with it. Well, this time I can not find a workaround, so I will try to explain my problems with the following code:
function getDates(){
var s = SpreadsheetApp.getActiveSpreadsheet();
var sht = s.getSheetByName('Dates');
var date = sht.getRange(2,1).getValues();
Logger.log(date[0][0]); //output is Tue Jun 08 18:00:00 GMT-04:00 2021
var datumFilter= Utilities.formatDate(date[0][0], "GMT+1", "dd/mm/yy");
Logger.log(datumFilter); //output is 08/00/21
var outrng = sht.getRange(25,1);
outrng.setValue(date);
}
The first targeted cell ('var date') has a value of "9.6.21" in the spreadsheet. The cell is formatted as a date and it opens a calendar when double-clicked. When I set the new cells values (with 'outrng.setValue(date);'), the result is OK, with the same date as in the original cell.
But I do not need to simply transfer the values, I want to implement them in some loops and I have no idea how to simply get the date in the same format or at least the same date in the script as it is in the cell. As you can see from the logger, the values there are different. A simple d/m/yy format would be sufficient.
My spreadsheet settings are set to my local time (Slovenia, GMT+1).
I am guessing that I am missing some basics here. I have spent many hours trying to understand it, so any help is highly appreciated!
Cooper already answered all your questions in the comment. I'd like to add on and show you an example on what it would like and add some modifications.
Code:
function getDates() {
var s = SpreadsheetApp.getActiveSpreadsheet();
var sht = s.getSheetByName('Dates');
// get last row of the sheet
var lastRow = sht.getLastRow();
// get your sheet's timezone
var timezone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var output = [];
// getValues is mostly used for multiple cells returning a 2D array
// use getValue for single cells to return its actual value
// but since function name is getDates, I assume column A is all dates
// so we fetch the whole column (A2:A[lastRow]) except the header
var dates = sht.getRange("A2:A" + lastRow).getValues();
// for each date on that column, we format the date to d/M/yy
// m/mm = minute
// M/MM = month
dates.forEach(function ([date]){
Logger.log(date);
var datumFilter= Utilities.formatDate(new Date(date), timezone, "d/M/yy");
Logger.log(datumFilter);
// collect all dates in an array
output.push([datumFilter]);
});
// assign all the dates in the array onto range B2:B
sht.getRange(2, 2, output.length, 1).setValues(output);
}
Sample data:
Logs:
Output:
Note:
The output on sheets is not equal to logs due to the formatting of my sheet.

Copy data from one sheet, add current date to each new row, and paste

I've done some reading but my limited knowledge on scripts is making things difficult. I want to:
Copy a variable number of rows data range, known colums, from one sheet titled 'Download'
Paste that data in a new sheet titled 'Trade History' from Column B
In the new sheet, add today's date formatted (DD/MM/YYYY) in a new column A for each record copied
The data in worksheet 'Download' uses IMPORTHTML
The data copied from Download to store a historical record needs a date in Column A
I've managed to get 1 and 2 working, but can't work out the 3rd. See current script below.
function recordHistory() {
var ss = SpreadsheetApp.getActive(),
sheet = ss.getSheetByName('Trade_History');
var source = sheet.getRange("a2:E2000");
ss.getSheetByName('Download').getRange('A2:E5000').copyTo(sheet.getRange(sheet.getLastRow()+1, 2))
}
You need to use Utilities.formatDate() to format today's date to DD/MM/YYYY.
Because you're copying one set of values, and then next to it (in column A), pasting another, I altered your code a bit as well.
function recordHistory() {
var ss = SpreadsheetApp.getActive(),
destinationSheet = ss.getSheetByName('Trade_History');
var sourceData = ss.getSheetByName('Download').getDataRange().getValues();
for (var i=0; i<sourceData.length; i++) {
var row = sourceData[i];
var today = Utilities.formatDate(new Date(), 'GMT+10', 'dd/MM/yyyy'); // AEST is GMT+10
row.unshift(today); // Places data at the beginning of the row array
}
destinationSheet.getRange(destinationSheet.getLastRow()+1, // Append to existing data
1, // Start at Column A
sourceData.length, // Number of new rows to be added (determined from source data)
sourceData[0].length // Number of new columns to be added (determined from source data)
).setValues(sourceData); // Printe the values
}
Start by getting the values of the source data. This returns an array that can be looped through to add today's date. Once the date has been added to all of the source data, determine the range boundaries for where it will be printed. Rather than simply selecting the start cell as could be done with the copyTo() method, the full dimensions now have to be defined. Finally, print the values to the defined range.

How to import range in google spreadsheet ignoring the Error "overwrite data"?

In above picture I have the following formula importrange("spreadsheet_id","Sheet!A2:P1010") in cell A2767
I have some data below now is there any way to ignore that error and let it fetch and overwrite?
Importrange needs blank cells to hold the size of the content you are importing. If the example you gave is in column A then "A67:P1077" need to be cleared. You can have data in the sheet after that for those rows and columns. You can force that to happen with
function onEdit(e)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("importtosheetname");// replace with your sheet name
var values = sheet.getRange("A68:P1077").getValues(); //note that the formula cell is not deleted assuned to be A67
if (values[0][0] == "#REF!")
sheet.getRange("A67:P1077").clearContent();
}

How to identify the current row in an Apex Tabular Form?

Friends,
I have written the following JavaScript to ascertain which row of an tabular form the user is currently on. i.e. they have clicked a select list on row 4. I need the row number to then get the correct value of a field on this same row which I can then perform some further processing on.
What this JavaScript does is get the id of the triggering item, e.g. f02_0004 This tells me that the select list in column 2 of row 4 has been selected. So my Javascript gets just the row information i.e. 0004 and then uses that to reference another field in this row and at the moment just output the value to show I have the correct value.
<script language="JavaScript" type="text/javascript">
function cascade(pThis){
var row = getTheCurrentRow(pThis.id);
var nameAndRow = "f03_" + row;
var costCentre = $x(nameAndRow).value;
alert("the cost centre id is " + costCentre);
}
// the triggerItem has the name fxx_yyyy where xx is the column number and
// yyyy is the row. This function just returns yyyyy
function getTheCurrentRow(triggerItem){
var theRow = triggerItem.slice(4);
return theRow;
}
Whilst this works I can't help feeling that I must be re-inventing the wheel and that
either, there are built-in's that I can use or if not there maybe a "better" way?
In case of need I'm using Apex 4.0
Thanks in advance for any you can provide.
Well, what you have described is exactly what I typically do myself!
An alternative in Apex 4.0 would be to use jQuery to navigate the DOM something like this:
var costCentre = $(pThis).parents('tr').find('input[name="f03"]')[0].value;
I have tested this and it works OK in my test form.