Time Driven Conditional Updates on Google Spreadsheets - google-apps-script

I would like to update the given date [reset day] on weekly periods.
During this update if weekly attendance will also reset to 0 and if its value is less than 2 Attendance points will decrease by 8 points.
Example Initial Sheet
Name | Attendance Point | Weekly Attendance | Reset Day
--------------------------------------------------------------
Jack | 12 | 0 | 13/09/2018
Jacob | 23 | 0 |
Emily | 12 | 1 |
Rick | 11 | 2 |
Rob | 21 | 3 |
Desired Update
Name | Attendance Point | Weekly Attendance | Reset Day
--------------------------------------------------------------
Jack | 4 | 0 | 20/09/2018
Jacob | 15 | 0 |
Emily | 4 | 0 |
Rick | 11 | 0 |
Rob | 21 | 0 |
Sample base sheet
https://docs.google.com/spreadsheets/d/1khPC5r2p0b1srsEGka3fl-GAl6nHACaVR0Cf31cqA1o/edit?usp=sharing
Thanks in advance
function resetCells() {
var ss = SpreadsheetApp.getActive().getSheetByName('Sheet');
var range = ss.getDataRange().offset(1, 0, ss.getLastRow() - 1);
var values = range.getValues().map(function(e) {
return e[0] ? [false, e[1], e[2], e[3], e[4] + 1, e[5]] : e;
});
range.setValues(values);
}
Update Function
function weekDays() {
var ss = SpreadsheetApp.getActive().getSheetByName('Sheet').getRange('F2').setValue(new Date())
}

I solved the problem with this snippet of script
function weekDays() {
var sd = SpreadsheetApp.getActive().getSheetByName('Sheet').getRange('F2').setValue(new Date())
var ss = SpreadsheetApp.getActive().getSheetByName('Sheet');
var range = ss.getDataRange().offset(1, 0, ss.getLastRow() - 1);
var values = range.getValues().map(function(e) {
if (Number(e[4]) < 2 && Number(e[2] >= 8) ) {
return e[1] ? [e[0], e[1], Number(e[2]) - 8, e[3], 0, e[5]] : e;
} else if (Number(e[4]) < 2 && Number(e[2]) < 8) {
return e[1] ? [e[0], e[1], 0, e[3], 0, e[5]] : e;
} else {
return e[1] ? [e[0], e[1], e[2], e[3], 0, e[5]] : e;
}
});
range.setValues(values);
}

Related

Add blank rows or header between unique values in Sort

I am pulling data from tabs in a sheet and putting them into a single tab using "compilation.sort(6,true);"
It pulls the data in, but it would be fantastic if there was a way to add rows during the sort, instead of afterwards. Is there a way to insert rows, or even a header, between unique values of the sort?
I have tried: "compilation.sort(6,true).insertRowAfter(i,1);" without success.
What I Have:
Row 1 | Row 2 | Row 3
--------- ------- -------
Pasta | Sauce | 3
Pasta | Sauce | 4
Pasta | Sauce | 5
Pizza | Sauce | 10
Pizza | Sauce | 11
Pizza | Sauce | 12
Spaghetti | Sauce | 9
What I am looking for:
Row 1 | Row 2 | Row 3
--------- ------- -------
Pasta | Sauce | 3
Pasta | Sauce | 4
Pasta | Sauce | 5
Pizza | Sauce | 8
Pizza | Sauce | 11
Pizza | Sauce | 12
Spaghetti | Sauce | 9
For the active sheet you can use
function runSample2() {
/**
* #type {conditionCallback}
*/
var cb;
cb = function(row, i, values) {
// Returns true if it's not the first row,
// the first cell of a row does not equal one of previous row
// and there is no an empty row before
return (
values[i - 1] &&
values[i - 1][0] !== row[0] &&
values[i - 1].join('') !== ''
);
};
var sheet = SpreadsheetApp.getActiveSheet();
insertRowBeforeByCondition_(sheet, cb);
}
function insertRowBeforeByCondition_(sheet, condition) {
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var i = values.length;
while (i-- > 0)
if (condition(values[i], i, values)) sheet.insertRowBefore(i + 1);
return sheet;
}
Based on the snippet.

Google script Multiple criteria in same row and validation of value in previous row

I'm starting with a script that someone here graciously helped with and need to build onto it and do not know where to start. Here is the current script:
function yourFunction(){
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet1');
var rg=sh.getDataRange();//columns are fruit,status and then cost.
var vA=rg.getValues();
for(var i=1;i<vA.length;i++){
if(vA[i][0].toString()=='Apple' && vA[i][1].toString()=='Ripe' && vA[i][2].toString=='Large' && vA[i][4].toString=''){
vA[i][4]=5.5;
}
}
rg.setValues(vA);//This writes all of the data at one time.
}
What I would like to add to this is a second set of criteria that looks at another column value = Lot Number(Column D). Assuming that the current Lot Number is the same as the previous row's and where all the above match, each additional rows will be a set value 3. But if the value of the Lot Number before the current row is not the same, then the value is 5. In what I've read, there may need to be some looping condition in this so the calculations don't keep going on and on. Any help here would be much appreciated. Thanks!
Here is a link to a basic format of the spreadsheet Test Script
Here's an updated function that demonstrates the general approach for what I believe you're describing.
var COLUMNS = {
FRUIT: 0,
STATUS: 1,
SIZE: 2,
LOT_NUMBERr: 3,
COST: 4,
NEW_VALUE: 5,
}
function updateValues() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet3');
var range = sheet.getDataRange();
var values = range.getValues();
var previousLotNumber = -1;
for(var i = 1; i < values.length; i++){
if (values[i][COLUMNS.FRUIT] == 'Apple'
&& values[i][COLUMNS.STATUS] == 'Ripe') {
values[i][COLUMNS.COST] = 5.5;
}
if (previousLotNumber == values[i][COLUMNS.LOT_NUMBER]) {
values[i][COLUMNS.NEW_VALUE] = 3;
} else {
values[i][COLUMNS.NEW_VALUE] = 5;
}
previousLotNumber = values[i][COLUMNS.LOT_NUMBER];
}
range.setValues(values);
}
After running this function, this sheet looks like the following:
+--------+-----------+--------+------------+------+-----------+
| Fruit | Status | Size | Lot Number | Cost | New Value |
+--------+-----------+--------+------------+------+-----------+
| Apple | Ripe | Large | 101 | 5.5 | 5 |
| Apple | Ripe | Medium | 101 | 5.5 | 3 |
| Apple | Ripe | Large | 103 | 5.5 | 5 |
| Apple | Not Ready | Large | 102 | | 5 |
| Apple | Not Ready | Medium | 101 | | 5 |
| Banana | Ripe | Large | 201 | | 5 |
| Orange | Ripe | Large | 301 | | 5 |
| Orange | Not Ready | Medium | 301 | | 3 |
| Pear | Ripe | Large | 401 | | 5 |
+--------+-----------+--------+------------+------+-----------+
A few notes:
use descriptive variable names
use a set of constants to provide descriptive names for the columns
for your ask, all you need to do is use a variable to store the previous rows lot number, no additional looping complexity required

Create new row for each not empty column

I'm trying to convert an Excel macro to Google Apps Script. I would like to create a new row on a specific sheet for each not empty column in Google Spreadsheets.
My Inputsheet looks like the following:
ID | Inrellevant Column | Givenmoney | Takenmoney | Othermoney
1 | Data1 | 100 | 200 | 300
2 | Data2 | 400 | | 500
I want to create a new row in another sheet for each not empty cell, so the desired Outputsheet would be:
ID | Inrellevant Column | Moneycode | Amount
1 | Data1 | Givenmoney | 100
1 | Data1 | Takenmoney | 200
1 | Data1 | Othermoney | 300
2 | Data2 | Givenmoney | 400
2 | Data2 | Othermoney | 500
I tried the following:
Outputsheet.getRange('A2').offset(0, 0, Inputsheet.length).setValues(Inputsheet);
However I can't see to create a loop to create new rows for each not empty column.
Hoi Fred, assuming you want the output to appear from the top left cell onwards in the sheet 'Outputsheet', try this code:
function myFunction() {
var ss = SpreadsheetApp.getActive(),
source = ss.getSheetByName('Inputsheet'),
target = ss.getSheetByName('Outputsheet'),
arr = [
["ID", "Header 2nd col", "Moneycode", "Amount"]
],
data = source.getDataRange().getValues(),
headers = data[0];
data.splice(1)
.forEach(function (r) {
r.forEach(function (c, i) {
if (!isNaN(parseFloat(c)) && isFinite(c) && i > 1) {
arr.push([r[0], r[1], headers[i], c])
}
})
})
target.getRange(1, 1, arr.length, arr[0].length).setValues(arr);
}
See this example sheet where you can run the above script from the menu 'My Menu'....

How to increment field value count using MySQL [duplicate]

I have a table student attendance.
Fields/data sample
id | studid | cls_id | smonth | syear | total_p | total_a
1 | 20 | 2 | 08 | 2015 | 2 | 1
2 | 21 | 2 | 08 | 2015 | 1 | 0
3 | 22 | 2 | 08 | 2015 | 2 | 1
I want, to check what is the total_p and total_a value of each students in last update and then increment 1.
If I am enter the both students are present = 1 so I want total_p value 20=3, 21=2, 22=3
How to get database field values and increment 1's.?
My controller
$present = Input::get($student->id);
if ($checkatt)
{
if ($present == 1)
{
DB::table($wys_total_attend_table)->where('studid', $student->id)
->where('smonth', $date_exploded[1])
->where('syear', $date_exploded[2])
->where('stotal_p', 1)
->update(array(
'stotal_p' => 1 + 1,
));
DB::table($wys_total_attend_table)->where('studid', $student->id)
->where('smonth', $date_exploded[1])
->where('syear', $date_exploded[2])
->where('stotal_p', 0)
->update(array(
'stotal_p' => 1,
'stotal_a' => 0,
));
} elseif ($present == 0)
{
DB::table($wys_total_attend_table)->where('studid', $student->id)
->where('smonth', $date_exploded[1])
->where('syear', $date_exploded[2])
->where('stotal_a', 1)
->update(array(
'stotal_a' => 1 + 1,
));
DB::table($wys_total_attend_table)->where('studid', $student->id)
->where('smonth', $date_exploded[1])
->where('syear', $date_exploded[2])
->where('stotal_a', 0)
->update(array(
'stotal_a' => 1,
));
DB::table($wys_total_attend_table)->where('studid', $student->id)
->where('smonth', $date_exploded[1])
->where('syear', $date_exploded[2])
->where('stotal_p', 1)
->where('stotal_a', 0)
->update(array(
'stotal_a' => 0 + 1,
));
}
}
I think u just want to update each record of total_p and total_a column just make it simple:
//get the id of student
$student_id = Input::get('student_id');
$present = Input::get('status'); //dropdown value 0,1
//You need a model for your table let say:
#Student.php
<?php
class Student extends Eloquent{
protected $table = 'students'; //table name
}
//Your Controller codes
public function findStudent($id, $status){
$query=Student::find($id);
if($query->count() && $status==1 ){ //status 1 = present
$query->total_p += 1; //plus one value in the total_p column in the tbl.
$query->save();
}else{
$query->total_a +=1;
$query->save();
}
}

Google sheets, sort function

I want to auto-sort through the script editor in Google Sheets. I have in my Google Sheets several columns:
+--------+------------+-------+--------+------------+
| Region | Mag | Comp | Region | Mag |
+--------+------------+-------+--------+------------+
| A | MIKA | TRUE | A | MIKA |
| B | KALO | FALSE | B | NOKA |
| C | MINA | FALSE | C | South-East |
| D | North | TRUE | D | North |
| B | NOKA | FALSE | B | KALO |
| C | South-East | FALSE | C | MINA |
+--------+------------+-------+--------+------------+
I would like to match the two columns (Region, Mag) on the left with the two columns (Region, Mag) on the right, so in the end I would have my comparison column (which has a formula like =exact(string1,string2)) with TRUEs only.
I want to have a kind of button so that my two columns (Region, Mag) on the right of Comp could sort themselves.
I had this script, thanks to #JPV
function onOpen() {
SpreadsheetApp.getUi().createMenu('Sort').addItem('Sort Col D and E', 'sort').addToUi();
}
function sort() {
var ss = SpreadsheetApp.getActiveSheet();
var srange = ss.getRange('A2:B7').getValues();
var trange = ss.getRange('D2:E7');
var trangeVal = trange.getValues();
var returnarr = [];
for (var i = 0, ilen = trangeVal.length; i < ilen; i++) {
for (var j = 0, jlen = srange.length; j < jlen; j++) {
if (trangeVal[i][0] == srange[j][0] && trangeVal[i][1] == srange[j][1]) {
returnarr[j] = trangeVal[i];
}
}
}
trange.setValues(returnarr);
}
But seems not working and throwing an error like "Cannot convert Array to Object[][]"
Any help please!
Again thanks to #JPV
Ok. Maybe this script will help you ?
function onOpen() {
SpreadsheetApp.getUi().createMenu('Sort').addItem('Sort Col D and E', 'sort').addToUi();
}
function sort() {
var ss = SpreadsheetApp.getActiveSheet();
var srange = ss.getRange('A2:B7').getValues();
var trange = ss.getRange('D2:E7');
var trangeVal = trange.getValues();
var returnarr = [];
for (var i = 0, ilen = trangeVal.length; i < ilen; i++) {
for (var j = 0, jlen = srange.length; j < jlen; j++) {
if (trangeVal[i][0] == srange[j][0] && trangeVal[i][1] == srange[j][1]) {
returnarr[j] = trangeVal[i];
}
}
}
trange.setValues(returnarr);
}
Note: this will only work if the values in D&E are somewhere to be found in A&B. Also be aware of the fact that his will overwrite the values in D&E.
Test sheet here