Google sheets API append method (last on top) - google-sheets

When using google sheets api append method (in any language), the values to be appended to the sheet are added after the last non null row.
So new values appear at the bottom of the sheet, as explained here:
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append#InsertDataOption
How can I append values in a way that the new values appear at the top of the sheet?

You want to append values by inserting new rows. If my understanding is correct, how about this method? It seems that sheets.spreadsheets.values.append appends values to the last row. So I would like to propose to usesheets.spreadsheets.batchUpdate. The endpoint and request body are as follows. When you use this, please modify ### spreadsheet ID ###, "sheetId": 1234567890 and the parameters for range and values.
Endpoint :
POST https://sheets.googleapis.com/v4/spreadsheets/### spreadsheet ID ###:batchUpdate
Request body :
{
"requests": [
{
"insertRange": {
"range": {
"sheetId": 1234567890,
"startRowIndex": 0,
"endRowIndex": 1
},
"shiftDimension": "ROWS"
}
},
{
"pasteData": {
"data": "sample1, sample2, sample3",
"type": "PASTE_NORMAL",
"delimiter": ",",
"coordinate": {
"sheetId": 1234567890,
"rowIndex": 0,
}
}
}
]
}
Flow of this request :
Insert new row to row 1 using "insertRange".
Import values of "sample1, sample2, sample3" using "pasteData".
When the order of "insertRange" and "pasteData" is changed, at first, the value of "A1:A3" is overwritten. After this, the new row is inserted to the row 1. So it seems that the elements of "requests" which is an array run in the order.
Reference :
sheets.spreadsheets.batchUpdate
If I misunderstand your question, I'm sorry.

Related

How can I append or add rows below the last row. (in worksheet)

It is possible to append a row in a table using the method below:
POST /workbook/worksheets/{id|name}/tables/{id|name}/rows/add
How can I do the same but in a worksheet?
Now it's only possible to Update with a specific range:
PATCH /workbook/worksheets/{id|name}/range(address='<address>')
I can't type in the address like "range(address='A(lastRow):C(lastRow)')"
First, get the last row number using an Excel function(Match) before appending the row.
POST /me/drive/root:/demo.xlsx:/workbook/functions/match
BODY
{
"lookupvalue": "",
"lookuparray": {
"Address": "sheet1!A:A"
},
"matchtype": -1
}
Specify the last row number as the range and update the value.

How to add content to table cell via google-docs-api request?

I want to add a content to a table cell in google doc, but the way described in the documentation doesn't work.
What is wrong with my request? When I provide 1 for index parameter of insertText request it just pastes text before table. When I provide 2 as value of index parameter I get an error: "Invalid requests[1].insertText: The insertion index must be inside the bounds of an existing paragraph. You can still create new paragraphs by inserting newlines."
{
"requests": [
{
"insertTable": {
"endOfSegmentLocation": {
"segmentId": ""
},
"columns": 1,
"rows": 1
}
},
{
"insertText": {
"location": {
"index": 1
},
"text": "Cell content"
}
}
]
}
I expect that text must be inserted into the only cell of the table.
You want to append a table (1 x 1) to the last body.
You want to insert a text to the 1st cell.
From your request body, I could understand like above. If my understanding is correct, how about this flow? I think that there might be several solutions. So please think of this as just one of them.
In the case that new table is appended to the last body ("segmentId": "" means that the table is appended to the last body.), at first, the start index of the table is required to be known. So how about the following flows?
Flow 1:
In this flow, it supposes that the index of last body is not known.
Append a table using the following request body.
{
"requests": [
{
"insertTable": {
"endOfSegmentLocation": {
"segmentId": ""
},
"columns": 1,
"rows": 1
}
}
]
}
Retrieve the start index of table using the following endpoint. At that time, you can also retrieve the start index of the cell.
GET https://docs.googleapis.com/v1/documents/{fileId}?fields=body(content(startIndex%2Ctable))
Insert the text to the cell. In this case, it supposes that the retrieved start index of the appended table is 10. The start index of the 1st cell is 14 (I think that the start index of the 1st cell can be retrieved by start index of table + 4.). In this case, the request body for inserting the text to the cell is as follows.
{
"requests": [
{
"insertText":
{
"location":
{
"index": 14
},
"text": "Cell content"
}
}
]
}
Flow 2:
In this flow, it supposes that the index of last body is known. For example, when the table is appended to the new Document, you can create the table with the text using the following request body. In this case, the start index of the table and the cell are 1 and 5, respectively.
{
"requests": [
{
"insertTable":
{
"endOfSegmentLocation":
{
"segmentId": ""
},
"columns": 1,
"rows": 1
}
},
{
"insertText":
{
"location":
{
"index": 5
},
"text": "Cell content"
}
}
]
}
References:
Inserting or deleting table rows
Thread: Insert table in Google Docs API Python
If I misunderstood your question and this was not the direction you want, I apologize.
This is a follow up to the answers posted already. #ANewb hinted the the flow ends after the 5th cell. Ensure the values/entries in the payload aren't empty strings. For anyone encountering the same challenge, you can try using tenary conditions - for php $value == "" ? "N/A : $value;, for js let value = checkValue == "" ? "N?A": checkValue;

Is there a way to filter using count of a nested array item when using OData Query?

I am using Microsoft Graph List CalendarView to get calendar events from outlook. I would like to filter out items where count of attendees is 0. (Logically meaning time blocked for self).
I understand there is a $count parameter that will return the count of items. However, in the List CalendarView response i am not after the count of calendar items, but rather the count of attendees within each calendar item. And infact to use a not equal (ne) filter based on it.
{
"value": [
{
"originalStartTimeZone": "originalStartTimeZone-value",
"originalEndTimeZone": "originalEndTimeZone-value",
"iCalUId": "iCalUId-value",
"reminderMinutesBeforeStart": 99,
"isReminderOn": true,
"attendees":[
{
"type":"required",
"status":{
"response":"none",
"time":"0001-01-01T00:00:00Z"
},
"emailAddress":{
"name":"Samantha Booth",
"address":"samanthab#a830edad905084922E17020313.onmicrosoft.com"
}
},
{
"type":"required",
"status":{
"response":"none",
"time":"0001-01-01T00:00:00Z"
},
"emailAddress":{
"name":"Dana Swope",
"address":"danas#a830edad905084922E17020313.onmicrosoft.com"
}
}
]
}
]
}
I want to specifically filter out any event items where the array size of "attendees" is 0.
Is this feasible using OData query params?
It appears filtering against attendees property is not supported, see for example, this thread for a details. But the following approach could be considered:
a) introduce an extended property for event resource which will expose summary info (flag whether event contains attendees or the count of attendees) about attendees.
Update all the existing events:
PATCH https://graph.microsoft.com/v1.0/me/events/{event-id}
Content-Type: application/json
{
"singleValueExtendedProperties": [
{
"id":"String {66f5a359-4659-4830-9070-00047ec6ac6e} Name ContainsAttendes",
"value":"1"
}
]
}
b) now events could be filtered like this:
https://graph.microsoft.com/beta/me/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq 'String {66f5a359-4659-4830-9070-00047ec6ac6e} Name ContainsAttendes' and ep/value eq '1')
where it is assumed ContainsAttendes=1 corresponds to events which have one or more attendees

iOS Swit 3 - filter array inside filter

I would like to filter array inside a filter. First I have a big array of Staff object (self.bookingSettings.staffs). Inside this array I have multiple object like this :
"staffs": [
{
"id": 1,
"name": "Brian",
"services": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4
}
],
"pos": 1
},...
I would like to filter this array in order to have only services with id = 3.
I succeed to have if first object is equal to 3 with this code :
self.bookingSettings.staffs.filter({ $0.services.first?.id == self.bookingService.id })
but that takes only the first item.
I think I have to filter inside my filter function, something like this to loop over all object inside services :
self.bookingSettings.staffs.filter({ $0.services.filter({ $0.id == self.bookingService.id }) })
but I've the following error: Cannot convert value of type [BookingService] to closure result type Bool.
Is this a good idea ? How can I achieve this ?
You could use filter, which would look something like this:
self.bookingSettings.staffs.filter {
!$0.services.filter{ $0.id == self.bookingService.id }.isEmpty
}
This code is constructing an entire array of filtered results, only to check if its empty and immediately discard it. Since filter returns all items that match the predicate from the list, it won't stop after it finds a match (which is really what you're looking for). So even if the first element out of a list of a million elements matches, it'll still go on to check 999,999 more elements. If the other 999,999 elements also match, then they will all be copied into filter's result. That's silly, and can use way more CPU and RAM than necessary in this case.
You just need contains(where:):
self.bookingSettings.staffs.filter {
$0.services.contains(where: { $0.id == self.bookingService.id })
}
contains(where:) short-circuits, meaning that it won't keep checking elements after a match is found. It stops and returns true as soon as find a match. It also doesn't both copying matching elements into a new list.

Swagger query parameter template

I have on query parameter which is little bit complex and i have my own syntax to make that value. Its has more then one variable to make one complete string value.
Let suppose name of parameter is index which has row and column like to make this value 20:30
index = { row: 20, col:30 }
index2 = { row: 20, col:30, chr: 15 }
Now i wanted to make it as
example.com?index=20:30
example.com?index2=20:30:15
Can someone tell me how can i define this in swagger ?
Thank you.
Make your swagger parameter a string and in your code behind handle the splitting into multiple variables...
I do exactly that here:
http://turoapi.azurewebsites.net/swagger/ui/index#/Echo/Echo_Get
"parameters": [
{
"name": "location",
"in": "query",
"description": "SoFL= 26.16,-80.20",
"required": true,
"type": "string"
},
That location is (Latitude,Longitude) and I split it with a C# TypeConverter
...and the request looks like:
http://turoapi.azurewebsites.net/api/Echo?location=26.16,-80.20
The code for that WebApi is here:
https://github.com/heldersepu/TuroApi

Resources