Update spreadsheets cell value by Using Google > Sheets API - google-sheets

Overview
I have inserted order data into a spreadsheet through spureadsheets api.
After that, I need to update the order data once inserted in the spreadsheet so that the customer can transfer the fee and the administration can process the shipment.
I would like to get the cell range where the updated order data exists and update the values in the corresponding cell range.
Can someone please help me with this?
The problem that is happening
Here I want to insert the following data into the range A5 to G5 on my spreadsheet. => (Wednesday, 12004, paid, 2021-11-05, jolly, 0145)
However, I want to get the cell range A5-G5, which is the cell position where the updated order data exists, but I don't know how to get the cell range using the API.
Processing test that I did
I was not able to get the cell location where the updated order data was located, so I tried to test by passing the range I wanted to update directly to the $range variable. However, it did not update correctly in the cell position A5-G5 where the updated order data was located.
1.$range = $sheet_ym.'!A1:""'; //I specified column A1 and an empty string, but got an error message.
2. $range = $sheet_ym.''; //No column and only an empty string forced the top row to be overwritten instead of the row with the updated order.
3. $range = $sheet_ym.'; !A1:A1000 //I got an error message when I specified column A1 + row A1000 => "Requested writing within range ['202112'!A1:A1000], but tried writing to column [B]" ["domain"]=> string(6) "global" ["reason"]=> string(10) "badRequest' }
4. $range = $sheet_ym.'!A1:O1000'; //Specifying A1 and O1000 forced the top row to be overwritten instead of the row where the updated order exists.
What I need support for.
Can you please tell me how to get the position of the cell where the updated order data exists, or how to specify a value for $range and automatically update the data in the appropriate cell range according to the updated order data
Every time I confirm a payment or complete a dispatch on the application side, the function insertif in the source code is triggered and the order data is inserted into the spreadsheet.
If I find duplicate values in the order_id, I want to overwrite the cell data in the row where the duplicate data exists. (I am unable to implement this correctly.)
In the sample you can see what happens when the data in the row with an order_id of 12004 (in the range A5 - G5) is updated.
When the payment is confirmed, the values C5 and D5 are updated.
When the payment is confirmed and the shipment is completed, the value of E5 is updated.
If no duplicate values are found in the order_id, then the data will be added to the last row in the spreadsheet. (I've already implemented this and it works fine.)
The state of the spreadsheet before the payment confirmation on the application side
sheet name = 202111
(order_id = 12004)
A
B
C
D
E
F
G
1
week
order_id
is_paid
paid_day
send
name
account_id
2
Monday
12001
mercy
0123
3
Monday
12002
paid
2021-11-02
send
kate
0153
4
Tuesday
12003
paid
2021-11-5
tarkey
0097
5
Wednesday
12004
jolly
0145
6
Thursday
12005
paid
2021-11-06
send
rashford
0083
The state of the spreadsheet when the payment has been confirmed on the application side, but the shipment has not been processed
sheet name = 202111
(order_id = 12004)
A
B
C
D
E
F
G
1
week
order_id
is_paid
paid_day
send
name
account_id
2
Monday
12001
mercy
0123
3
Monday
12002
paid
2021-11-02
send
kate
0153
4
Tuesday
12003
paid
2021-11-5
tarkey
0097
5
Wednesday
12004
paid
2021-11-6
jolly
0145
6
Thursday
12005
paid
2021-11-06
send
rashford
0083
The state of the spreadsheet when both payment confirmation and dispatch processing are done on the application side
sheet name = 202111
(order_id = 12004)
A
B
C
D
E
F
G
1
week
order_id
is_paid
paid_day
send
name
account_id
2
Monday
12001
mercy
0123
3
Monday
12002
paid
2021-11-02
send
kate
0153
4
Tuesday
12003
paid
2021-11-5
tarkey
0097
5
Wednesday
12004
paid
2021-11-6
send
jolly
0145
6
Thursday
12005
paid
2021-11-06
send
rashford
0083
SourceCode
function api_insertif($sheet_name=NULL,$current_date=NULL,$where=NULL,$input_data=array()){
$sheet_name=isset($sheet_name)?$sheet_name:'monthly';
$current_date=isset($current_date)?$current_date:date('Y-m-d');
$where=isset($where)?$where:'';
//The $input_data contains the customer order information.
$input_data=isset($input_data)?$input_data:array();
//A flag to separate insert and update operations on the spreadsheet
$insert=false;
//Set the new insertion flag to true
$insert = true;
//Sheet name (taken from the current year, e.g. 202110,202111)
$sheet_ym=isset($sheet_ym)?$sheet_ym:date('Ym');
//Receipt number of the order customer is trying to confirm
$duplicate_check_id = $input_data[0]['orderid'];
//Extracting order information from the worksheet
$worksheet_order_val = $worksheet['values'];
//Check that there are no duplicate orderids in the worksheet.¥¥
foreach($worksheet_order_val as $sheet_val){
 if($sheet_val[2] == $duplicate_check_id){
var_dump('There is a duplicate order ID.');
   $insert = false;
 }
}
var_dump('The insertion or update process has been checked.');
//If it is a new order and not an update of the order data
if($insert){
//The $inputdata contains the data of the order when the order is actually placed or when the management confirms the payment.
foreach($input_data as $row_data){
//Exception handling starts
try{
$client = $this->google_client;
$service = new Google_Service_Sheets($client);
$spreadsheetId = 'myspreadsheetid';
//202109, 202110, 202111, etc. The year and month are used as the sheet name.
$sheet_ym=isset($sheet_ym)?$sheet_ym:date('Ym');
$range = $sheet_ym.'!$A1';
$option = [
'valueInputOption' => 'USER_ENTERED'
];
$requestBody = new Google_Service_Sheets_ValueRange([
'values' => [
[  
$row_data['week'],
$row_data['order_id'],
$row_data['is_paid'],
$row_data['paid_day'],
$row_data['send'],
$row_data['name'],
$row_data['account_id']
]
],
//Inserting new order data into a spreadsheet
$service->spreadsheets_values->append($spreadsheetId, $range, $requestBody,$option);
var_dump('Order number has been successfully completed and inserted');
}catch(Exception $e){
//Handling data insertion failures
var_dump('function api_insertif() : Failed to insert some data');
var_dump($e);
return false;
}
}
//===============================================================================
//From here on down is not an insertion, but a process to update the spreadsheets
//===============================================================================
}else{
foreach($input_data as $row_data){
       //Exception handling starts
       try{
         var_dump('The same order number as the current order exists in the spreadsheet, so update it.')
         
         $client = $this->google_client; 
           
          $service = new Google_Service_Sheets($client);
          $spreadsheetId = 'myspreadsheetid';
$option_1 = [
                   'valueInputOption' => 'USER_ENTERED'
];
$option_2 = 'USER_ENTERED';
//Define the RequestBody
$updateBody = new Google_Service_Sheets_ValueRange([
'values' => [
[
$row_data['week'],
$row_data['order_id'],
$row_data['is_paid'],
$row_data['paid_day'],
$row_data['send'],
$row_data['name'],
$row_data['account_id']
]
],
]);
//Update process
$service->spreadsheets_values->update($spreadsheetId, $range, $updateBody, $option_1);
var_dump('The insertif update process is now complete.');
}catch(Exception $e){
var_dump('The update process of insertif could not be performed.');
var_dump($e);
exit;
return false;
}
}
}
Libraries and external services used
google-api-php-client--PHP5.6 v2.11.0
https://github.com/googleapis/google-api-php-client/releases
Google Cloud Platform
https://console.cloud.google.com/
The page I am referring to
php google api client
https://github.com/googleapis/google-api-php-client
Migrate from Sheets API from v3 https://developers.google.com/sheets/api/guides/migration#v4-api_5
PHP QuickStart
https://developers.google.com/sheets/api/quickstart/php

Related

how can I query sum across columns, but avoid duplicated submissions / rows from unique users?

I have a Google form accepting data from different users, which goes to a sheet and is used to SUM the values across columns at the end of the day. The problem is that users can re-submit forms to update the data totals if there is a change at the end of the day:
NAME K L M
ALF 4 0 1
BILL 1 0 0
SALLY 1 0 1
DENNIS 1 1 1
RICK 0 0 1
SALLY 2 1 1 <--- SALLY RESUBMITTED HER FORM AGAIN WITH UPDATED VALUES
In my current Query, I SUM() the columns after filtering by the date like this:
SELECT SUM(K), SUM(M), SUM(N) WHERE C = date '"&TEXT($B$1,"yyyy-mm-dd")&
$B$1 is a cell with a datepicker and col C is the user submitted form date. Col A has the unique form generated submission timestamps
As you can see, the SUM for each column will be off by the extra submission from Sally. I need to include only the most recent submissions from any of the users, and ignore any prior ones for this date. I'm not sure how to filter in this manner and sum just the most recent instance from each unique user.
** EDIT **
I should note the original form data is on another sheet and the cells are referenced via a query to this range. The form is also submitted daily, so the query must be able to specify the date in question for summation of entries.
Give a try on following formula-
=QUERY(INDEX(REDUCE({0,0,0,0},UNIQUE(J2:J7),LAMBDA(a,b,{a;SORTN(FILTER(J2:M7,J2:J7=b,C2:C7=date(2023,2,17)),1)})))," select sum(Col2), sum(Col3), sum(Col4)")
If you actually want most recent response to sum then use-
=QUERY(INDEX(REDUCE(SEQUENCE(1,COLUMNS(A2:M7),0,0),UNIQUE(J2:J7),LAMBDA(a,b,{a;QUERY(SORT(FILTER(A2:M7,J2:J7=b),1,0),"limit 1")}))),"select sum(Col11), sum(Col12), sum(Col13)")
Here you have another option, creating an auxiliary column that returns 1 if it corresponds to the date and is the last timestamp
=QUERY({K:M,
MAP(A:A,C:C,J:J,LAMBDA(ts,date,n,IF(date<>B1,0,IF(ts=MAX(FILTER(A:A,J:J=n,C:C=date)),1,0))))},
"SELECT SUM(Col1),SUM(Col2),SUM(Col3) where Col4=1")

Google Sheet Formula with complex query and multiple criteria

I need help to fix a query formula. I am trying to pull specific columns with a criteria. Tried my very best to come up with a formula but I keep on having errors.
Here are the criteria needed for each column:
data headers = txn headers
Contact* = full_name
email* = email but will only shows a unique value
Product name* = relevant_item_name where it only contains "Not Your Average Membership" or "The Not So Average Membership"
Billing amt = total where the event is charge
Status = event either contains charge or rebill based on last order_date
Last billed* = order_date but only the last date of that email* (especially if it has multiple order dates)
Cycle = relevant_item_pricing_option when it contains monthly should show "monthly" or One-time payment should show "annual"
Charges* = the order_id usually shows orderidnumber-chargenumber so only the -x
This is the sample file:
https://docs.google.com/spreadsheets/d/1gJn6hHRRKxrvWhRu5WZ-OOXO_EBpMo3_gpFkPlckreQ/edit?usp=sharing
Is it possible to pull in one query? Do I just assume that it's possible but if not can you suggest the best approach on how I can show the required data.
use:
=SORTN(QUERY(txn!A2:AR,
"select D,S,AO,AB,AM,X
where AO = 'Not Your Average Membership'
and AM matches 'charge|rebill'
order by X desc", ), 9^9, 2, 2, 1)
stuff like S = UNIQUE(S) and X = MAX(X) are not supported in QUERY
| - or logic
9^9 - return all rows
2 - group by unique mode of sortn
2 - unique for 2nd column outputted by query
1 - in ascending order
added formula to your sheet here:
=SORTN(LAMBDA(z,FILTER(z,REGEXMATCH(INDEX(z,,3),"Average"),REGEXMATCH(INDEX(z,,5),"charge|rebill")))(SORT({txn!D2:D15,txn!S2:S15,txn!AO2:AO15,txn!AB2:AB15,txn!AM2:AM15,txn!X2:X15,IFS(REGEXMATCH(txn!AR2:AR15,"Monthly"),"Monthly",REGEXMATCH(txn!AR2:AR15,"One"),"Annual",TRUE,"N/A"),IFNA(--REGEXEXTRACT(txn!W2:W15&"","-(\d+)"),0)+1},txn!X2:X15,0)),2^99,2,2,1)

manipulate data from multiple rows in a sheet, combine the new totals together, and post to a different sheet

I have two google sheets. One is more of a summary and the other one tracks all of the data. I need to get the price from the row on the 2nd page that is marked as entry, with a corresponding trade id to the first page, and then, if it was a long trade(Determined by the Long/Short(L/S) column on page 1, subtract the entry price from each exit price and then add those values together. If short trade it would be each entry price minus the exit entry price. Most trades will have 1 entry and 2 exits.
Basic example: Buy 3 contracts long at $10. Exit at $15 for 2 contracts and $20 for 1 contract.
So it will be (exit1 - entry) + (exit1 - entry) + (exit2 - entry). This
will give me the total points for each section of the trade. That data
then needs to get displayed on the overview tab
Example google sheet: https://docs.google.com/spreadsheets/d/1Y8QHrARyYjJKfOwq0g3waDfkVyWbWc2uSIzBiqsIal0/edit?usp=sharing
Edit: adjusted match to properly represent the outcome.
Try this one.
Formula:
=sum(query('Trades Taken'!A:D, "select D where A = "&A2&" and B = 'Exit'")) - (rows(filter('Trades Taken'!A:D, 'Trades Taken'!A:A = A2, 'Trades Taken'!B:B = "Exit")) * filter('Trades Taken'!D:D, 'Trades Taken'!A:A = A2, 'Trades Taken'!B:B = "Entry"))
I have simplified the formula so it would be easier to interpret.
Output:

Google Form Data Validation - Attendance Records using Google Forms and Google Sheets

I'm homeschooling 5 children this year (how am I that old?!). I have tried to streamline the process of attendance for a l.o.n.g. time.
I thought, "I'll use a Google Form that they will simply select their name and the date. (They can't cheat me on attendance because it should match the timestamp. Shhh.)
Here is the form: Google Form for Attendance & Google Form for Attendance drop down
The information from the form presents in my Google sheet as: Google Form Data
I have several students that have attendance sheets: Several Student Records
My student record looks like this: Student Record
What I need help with:
I need a P to be placed in the Student Record in the correct date as it is validated according to the information in the Google Form Data.
I need this to repeat for all of my student records. To search the data from Google Form Data and put the P in the correct places.
I think I may be making it more difficult than it needs to be, or I need to set up my sheets a bit differently.
You can use Form Submit Installable trigger in Sheets, so that whenever a form was submitted, the script function will be triggered to update the student record and place "P" on the date submitted.
Sample Code (Inbound script in your Google Sheets):
function UpdateStudentRecord(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formValues = e.values;
var name = formValues[1];
var date = new Date(formValues[2]);
var sheet = ss.getSheetByName(name);
//Get Month Year String and the day
var timeZone = Session.getScriptTimeZone();
var dateStr = Utilities.formatDate(date,timeZone, "MMMMM yyyy");
var day = date.getDate().toString();
//Find the row index of the submitted date
var colAValues = sheet.getRange('A1:A').getDisplayValues().flat();
var rowIndex = colAValues.indexOf(dateStr);
//Find the column index of the submitted day
var row3Values = sheet.getRange("A3:3").getDisplayValues().flat();
var colIndex = row3Values.indexOf(day);
//Write P in the cell
//Note that array index is in zero-based while sheet index is in one-based
sheet.getRange(rowIndex+1, colIndex+1).setValue("P");
}
Pre-requisite (Create a form submit trigger):
What it does?
Every time a form was submitted, UpdateStudentRecord() will be executed
Get the submitted form values in the event object e.values
Get the name of the student and the submitted date
Get the submitted date string in "Month Year" format using Utilities.formatDate(date, timeZone, format). And get the day using getDate()
Get all columnA values, use Array.flat() to change 2-d array to 1-d array. Search for the date string obtained in step 4 using Array.indexOf()
Get all Row3 values, use Array.flat() to change 2-d array to 1-d array. Search for the day obtained in step 4 using [Array.indexOf()]
Write "P" on the row and column index obtained in step 5 & 6 using setValue(value)
Note:
In this sample code, the sheet name should match the student name in form's drop-down list.
Output:

Google Sheets Select X where (max(y)<=z)

my title is potentially not that enticing. But I am trying to create a semi-dynamic formula in order to find a "stock on hand" up to a particular date in time. There is a set number of locations ids 1-10, and two product types 3 & 4.
It is not guaranteed that each location will have a stock count at the date in question. I want to use query to find THE MOST RECENT stock count where location and product type and <= date
here is the basic formula
=QUERY(Sheet1!A160:E3530,"SELECT D WHERE ((B = "&$H$1&")) AND (E <= date '"&TEXT(MAX($M$3),"yyyy-mm-dd")&"') AND ((A = "&G2&"))", true)
But I need to figure out how to use MAX to find the most recent date within the date range specified.
Any help appreciated!
EDIT 23/06/2021
You will note this is a fraction of the data I have in my set (in the example sheet), so most numbers show as zero, but the formula
=MAXIFS($C$3:$C$6040,$A$3:$A$6040,I3,$B$3:$B$6040,$J$2,$E$3:$E$6040,(MAX(QUERY($A$3:$E$6040,"SELECT E WHERE (E <= date '"&TEXT($R$2,"yyyy-mm-dd")&"') AND ((A = "&I3&")) AND ((B = "&$J$2&"))", true))))
works on my full data. So this finds the most recent record of equipment type 3 or 4, up to the specified date and from a specified yard. Further filtering is done based on a change type of "converted, removed,dead,added,etc". What I want to do now is do a monthly or fortnightly line chart over time, eg the 14th and 29th of each month, or the 20th of each month and plot the the sum of each column J:Q. To start I hoped to use the date in U:U and populate the V:AC accordingly.
I have played with the onEvent script but I am struggling to make progess here

Resources