I have a Typescript and Node project in which I am trying to insert the information I get from the database into the spreadsheet using the Google API V4
https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}:batchUpdate
This is the JSON object that I get from the database:
let sheetData = [
{
"country":null,
"age":25,
"fileName":"testName1"
},
{
"country":"Spain",
"age":null,
"fileName":"testName2"
}
]
I transform it with papaparse:
const papa = require("papaparse")
let result = papa.unparse(sheetData, {
header: false,
delimiter: ';',
encoding: 'UTF-8',
})
console.log(result)
This is what I get:
;25;testName1
Spain;;testName2
This is the xml that I use from the API to add the information:
{
"requests": [
{
"pasteData": {
"coordinate": {
"sheetId": 123,
"rowIndex": 2,
"columnIndex": 1
},
"delimiter": ";",
"type": "PASTE_VALUES",
"data": ";25;testName1Spain;;testName2"
}
}
]
}
I attach a screenshot with the result of the sheet:
My problem: All the information is put in the same row, how do I have to modify the array to include line breaks and be identified by the API?
This is the JSON that works from the API by adding \n:
{
"requests": [
{
"pasteData": {
"coordinate": {
"sheetId": 123,
"rowIndex": 2,
"columnIndex": 1
},
"delimiter": ";",
"type": "PASTE_VALUES",
"data": ";25;testName1\nSpain;;testName2"
}
}
]
}
This is the result I want to achieve, but I don't know how to treat the JSON with the information I get:
I thought that in your script, how about the following sample script?
Sample script:
const sheets = google.sheets({ version: "v4", auth }); // Please use your authorization script.
let sheetData = [
{
country: null,
age: 25,
fileName: "testName1",
},
{
country: "Spain",
age: null,
fileName: "testName2",
},
];
let result = papa.unparse(sheetData, {
header: false,
delimiter: ";",
encoding: "UTF-8",
});
console.log(result);
const requests = {
requests: [
{
pasteData: {
coordinate: {
sheetId: 123, // Please set your sheet ID.
rowIndex: 2,
columnIndex: 1,
},
delimiter: ";",
type: "PASTE_VALUES",
data: result,
},
},
],
};
sheets.spreadsheets.batchUpdate(
{
spreadsheetId: "###", // Please set your Spreadsheet ID.
resource: requests,
},
(err, result) => {
if (err) {
console.log(err);
return;
}
console.log(result.data);
}
);
In this modification, your value of result is used as the data of pasteData request.
When I tested this script, I confirmed that your expected result can be obtained.
Related
i'm using the node.js client library of google transcoder api. I'm able to retrive a paginated list of some jobs, but i'm not able to order elements by start date. Here my codes:
const { TranscoderServiceClient } = require('#google-cloud/video-transcoder').v1;
class TranscoderApiController {
constructor() {
this.projectId = process.env.GOOGLE_CLOUD_PROJECT;
this.location = process.env.TASK_LOCATION;
}
async getEntries(req, res, next) {
const params = {
pageSize: req.query.pageSize ? parseInt(req.query.pageSize) : 10,
pageToken: req.query.pageToken,
filter: req.query.filter,
orderBy: req.query.orderBy
}
const client = new TranscoderServiceClient();
const result = await client.listJobs({
parent: client.locationPath(this.projectId, this.location),
pageSize: params.pageSize,
orderBy: 'createTime.seconds'
}, {
autoPaginate: false
});
if (result.length == 3 && result[2] != undefined) {
return result[2];
} else {
return result[1];
}
}
}
module.exports = new TranscoderApiController();
When i call the getEntries method i receive the following error:
"3 INVALID_ARGUMENT: The request was invalid: sort order \"createTime.seconds\" is unsupported"
If i remove the orderBy: 'createTime.seconds' line then the api works but is not ordered as i want. The result is something like that (i abbreviate the json):
{
"jobs": [
{
"labels": {},
"name": "projects/<id>/locations/europe-west1/jobs/<uuid>",
"inputUri": "",
"outputUri": "",
"state": "SUCCEEDED",
"createTime": {
"seconds": "1656602896",
"nanos": 386772728
},
"startTime": {
"seconds": "1656602900",
"nanos": 755000000
},
"endTime": {
"seconds": "1656603062",
"nanos": 428000000
},
"ttlAfterCompletionDays": 30,
"error": null,
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://<url>/render_md.mp4",
"preprocessingConfig": null
}
],
"editList": [...],
"elementaryStreams": [...],
"muxStreams": [...],
"manifests": [],
"adBreaks": [],
"spriteSheets": [],
"overlays": [],
"output": {
"uri": "gs://<url>/md.mp4/"
},
"pubsubDestination": {
"topic": "projects/<id>/topics/transcoder_api"
}
},
"jobConfig": "config"
},
...
],
"unreachable": [],
"nextPageToken": "Co8BCjgKDGV1cm9wZS13ZXN0MRIZdHJhbnNjb2Rlci5nb29nbGVhcGlzLmNvbRgBII..."
}
As you can see each job have the startTime.seconds property. I follow the syntax described here:
https://google.aip.dev/132#ordering
Any support to solve the ordered issue is appreciated.
I am using the googleapis module in a Node application. I was using version 21 but have just updated to version 52 due to a security vulnerability in the older version.
There are several breaking changes. I have overcome most except for formatting a date/time string. Is the following payload correct for formatting a date/time value in cell A11?
const formatDate = (next) => {
sheets.spreadsheets.batchUpdate({
auth: authClient,
spreadsheetId: sheetId,
requestBody: {
requests: [{
"repeatCell": {
range: { sheetId: 0, startRowIndex: 10, endRowIndex: 11, startColumnIndex: 0, endColumnIndex: 1},
cell: { userEnteredFormat: { numberFormat: { "type": "DATE_TIME", "pattern": "ddd yyyy-mm-dd hh:mm" } } },
fields: "userEnteredFormat.numberFormat"
}
}]
}
}, (err, response) => {
// ...
next();
}
);
}
No errors were returned with the above payload, but the formatting is not taking place. Is the key requestBody? Previously I was using resource.
I used async to perform authentication before formatting the date:
const authClient = new google.auth.JWT(client_email, null, private_key, SCOPES, null);
const sheetId = "1vgiEnV8fU_MrnIy31fbPAzhHz.......";
function authenticate(next) {
authClient.authorize((err) => {
next(err);
}
}
const tasks = [ authenticate, insertRow, formatdate ];
require("async").series(tasks);
Code for insertRow is not included here, but that works without problem.
I think that your script is correct. The cell format of "A11" is modified with the request body. And in this case, the request body can be used for both requestBody and resource.
But please confirm the following points, again.
sheetId of spreadsheetId: sheetId, is required to be the Spreadsheet ID.
In this case, when =now() is put to the cell "A11" and run the script, you can see the modified cell format.
By the following modification, you can check the returned values from Sheets API.
sheets.spreadsheets.batchUpdate(
{
auth: authClient,
spreadsheetId: "spreadsheetId", // <--- Please check this.
requestBody: {
requests: [
{
repeatCell: {
range: {
sheetId: 0,
startRowIndex: 10,
endRowIndex: 11,
startColumnIndex: 0,
endColumnIndex: 1,
},
cell: {
userEnteredFormat: {
numberFormat: {
type: "DATE_TIME",
pattern: "ddd yyyy-mm-dd hh:mm",
},
},
},
fields: "userEnteredFormat.numberFormat",
},
},
],
},
},
(err, res) => {
if (err) {
console.log(err);
return;
}
console.log(res.data);
}
);
Note:
In my environment, I tested your script with googleapis#52.1.0, and I could confirm the script worked.
This modified script supposes that your authorization process for using Sheets API has already been done.
References:
googleapis for Node.js
Method: spreadsheets.batchUpdate
RepeatCellRequest
Added:
Sample script for testing:
const client_email = "###"; // Please set here.
const private_key = "###"; // Please set here.
const spreadsheetId = "###"; // Please set here.
const { google } = require("googleapis");
let jwtClient = new google.auth.JWT(
client_email,
null,
private_key,
["https://www.googleapis.com/auth/spreadsheets"]
);
jwtClient.authorize((err) => {
if (err) console.log(err);
});
const sheets = google.sheets({ version: "v4", auth: jwtClient });
sheets.spreadsheets.batchUpdate(
{
spreadsheetId: spreadsheetId,
requestBody: {
requests: [
{
repeatCell: {
range: {
sheetId: 0,
startRowIndex: 10,
endRowIndex: 11,
startColumnIndex: 0,
endColumnIndex: 1,
},
cell: {
userEnteredFormat: {
numberFormat: {
type: "DATE_TIME",
pattern: "ddd yyyy-mm-dd hh:mm",
},
},
},
fields: "userEnteredFormat.numberFormat",
},
},
],
},
},
(err, res) => {
if (err) {
console.log(err);
return;
}
console.log(res.data);
}
);
Input Data
[{
"_index": "abc",
"_type": "_doc",
"_id": "QAE",
"_score": 6.514091,
"_source": {
"category": "fruits",
"action": "eating",
"metainfo": {
"hash": "nzUZ1ONm0e167p"
},
"createddate": "2019-10-03T12:37:45.297Z"
}},
{
"_index": "abc",
"_type": "_doc",
"_id": "PQR",
"_score": 6.514091,
"_source": {
"category": "Vegetables",
"action": "eating",
"metainfo": {
"hash": "nzUZ1ONm0e167p"
},
"createddate": "2019-10-03T12:37:45.297Z"
}
}-----------------
----------------]
I have around 30,000 records as input data. How to insert this data in a single query. I tried by
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: '********',
log: 'trace'
});
client.index({
index: "abc",
body: ****input data*****
}).then((res) => {
console.log(res);
}, (err) => {
console.log("err", err);
});
In this code, send input data in the body. but it returns an error. Please suggest to me.
This seems like what are you looking for:
'use strict'
require('array.prototype.flatmap').shim()
const { Client } = require('#elastic/elasticsearch')
const client = new Client({
node: 'http://localhost:9200'
})
async function run () {
await client.indices.create({
index: 'tweets',
body: {
mappings: {
properties: {
id: { type: 'integer' },
text: { type: 'text' },
user: { type: 'keyword' },
time: { type: 'date' }
}
}
}
}, { ignore: [400] })
const dataset = [{
id: 1,
text: 'If I fall, don\'t bring me back.',
user: 'jon',
date: new Date()
}, {
id: 2,
text: 'Winter is coming',
user: 'ned',
date: new Date()
}, {
id: 3,
text: 'A Lannister always pays his debts.',
user: 'tyrion',
date: new Date()
}, {
id: 4,
text: 'I am the blood of the dragon.',
user: 'daenerys',
date: new Date()
}, {
id: 5, // change this value to a string to see the bulk response with errors
text: 'A girl is Arya Stark of Winterfell. And I\'m going home.',
user: 'arya',
date: new Date()
}]
// The major part is below:
const body = dataset.flatMap(doc => [{ index: { _index: 'tweets' } }, doc])
const { body: bulkResponse } = await client.bulk({ refresh: true, body })
//
if (bulkResponse.errors) {
const erroredDocuments = []
// The items array has the same order of the dataset we just indexed.
// The presence of the `error` key indicates that the operation
// that we did for the document has failed.
bulkResponse.items.forEach((action, i) => {
const operation = Object.keys(action)[0]
if (action[operation].error) {
erroredDocuments.push({
// If the status is 429 it means that you can retry the document,
// otherwise it's very likely a mapping error, and you should
// fix the document before to try it again.
status: action[operation].status,
error: action[operation].error,
operation: body[i * 2],
document: body[i * 2 + 1]
})
}
})
console.log(erroredDocuments)
}
const { body: count } = await client.count({ index: 'tweets' })
console.log(count)
}
run().catch(console.log)
Reference link: https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/bulk_examples.html
I need to extract the text value of productid from order but unfortunately i haven't been able to traverse the JSON. Any ideas about how to traverse the nodes in Node JS the simplest way possible ?
{
"order": {
"PRD_SHIRT_048": {
"price": "40.99",
"productId": "PRD_SHIRT_048",
"quantity": "1"
},
"PRD_TOP_047": {
"price": "40.99",
"productId": "PRD_TOP_047",
"quantity": "1"
}
}
}
First of all, you need to decide where you want to extract the data from.
If it is from a file you need to import the file with for example the npm package 'fs'.
Example code:
const fs = require("fs");
const content = fs.readFileSync("content.json");
console.log("Output: \n" + content);
You can use axios to get the json data from a specific url. For example:
axios.get('yoururl')
.then((response) => {
// handle success
console.log(response);
})
.catch((error) => {
// handle error
console.log(error);
});
Then you have extracted the data successfully.
After that you can parse the json content with JSON.parse and that will return an object with all its content.
For example for your code:
const json = `{"order": {
"PRD_SHIRT_048": {
"price": "40.99",
"productId": "PRD_SHIRT_048",
"quantity": "1"
},
"PRD_TOP_047": {
"price": "40.99",
"productId": "PRD_TOP_047",
"quantity": "1"
}
}}`;
const obj = JSON.parse(json);
console.log(obj.order.PRD_SHIRT_048.productId);
If you want, you can iterate over the objects from the order object and get the product id from that.
If I understand your question correctly, you are looking to extract the productIds?
Here is a solution using vanilla javascript
const data = { order: { PRD_SHIRT_048: { price: '40.99', productId: 'PRD_SHIRT_048', quantity: '1' }, PRD_TOP_047: { price: '40.99', productId: 'PRD_TOP_047', quantity: '1' } } };
console.log(Object.keys(data.order));
// => [ 'PRD_SHIRT_048', 'PRD_TOP_047' ]
console.log(Object.values(data.order).map(({ productId }) => productId));
// => [ 'PRD_SHIRT_048', 'PRD_TOP_047' ]
.as-console-wrapper {max-height: 100% !important; top: 0}
Or if you need a more flexible solution (i.e. multiple different paths for the productId, nested productIds etc), you could consider using a library
// const objectScan = require('object-scan');
const data = { order: { PRD_SHIRT_048: { price: '40.99', productId: 'PRD_SHIRT_048', quantity: '1' }, PRD_TOP_047: { price: '40.99', productId: 'PRD_TOP_047', quantity: '1' } } };
console.log(objectScan(['order.*.productId'], { rtn: 'value' })(data));
// => [ 'PRD_TOP_047', 'PRD_SHIRT_048' ]
console.log(objectScan(['order.*'], { rtn: 'property' })(data));
// => [ 'PRD_TOP_047', 'PRD_SHIRT_048' ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan
const json = `{"order": {
"PRD_SHIRT_048": [
"price",
"productId",
"quantity"
],
"PRD_TOP_047": [
"price",
"productId",
"quantity"
]
}}`;
const obj = JSON.parse(json);
console.log(obj.order.PRD_SHIRT_048.productId);
I am trying to insert bolded text into Google Spreadsheet. I have the following NodeJS code that inserts the text successfully.
var body = {
data: [{
range: 'M2:M3',
values: [["value1"],["value2"]]
}],
valueInputOption: 'USER_ENTERED',
};
var sheets = google.sheets('v4');
sheets.spreadsheets.values.batchUpdate({
auth: auth,
spreadsheetId: SPREADSHEET_ID,
resource: body
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
});
I looked up and found that in order to change the text format to bold, the following code needs to be used.
requests: [
{
"format": {
"textFormat": {
"bold": true
}
}
}
]
However, I cannot understand where this code should go. Tried putting requests as well as format separately inside data and batchUpdate but it did not work.
How about this sample script? If you want to update cell values and cell format, simultaneously, you can use spreadsheets.batchUpdate. The detail information is here.
The following sample imports [["value1"],["value2"]] to 'M2:M3' as shown in your script. As a sample, Sheet id is 0. The range is required to be inputted the GridRange.
Sample script :
var sheets = google.sheets('v4');
var request = {
spreadsheetId: SPREADSHEET_ID,
resource: {
"requests": [
{
"updateCells": {
"rows": [
{
"values": [
{
"userEnteredValue": {
"stringValue": "value1"
},
"userEnteredFormat": {
"textFormat": {
"bold": true
}
}
}
]
},
{
"values": [
{
"userEnteredValue": {
"stringValue": "value2"
},
"userEnteredFormat": {
"textFormat": {
"bold": true
}
}
}
]
}
],
"range": {
"sheetId": 0, // Sheet id
"startColumnIndex": 12,
"endColumnIndex": 13,
"startRowIndex": 1,
"endRowIndex": 3
},
"fields": "*"
}
}
]
},
auth: auth,
};
sheets.spreadsheets.batchUpdate(request, function(err, response) {
if (err) {
console.error(err);
return;
}
console.log(JSON.stringify(response, null, 2));
});
If I misunderstand your question, I'm sorry.