i want to add data from mysql to spreadsheet using google app script.
And the data has been successfully pulled and successfully displayed in the console log, but how do I enter it into the google sheet???
here's the script:
var server = 'xxx.xxx.xxx.xxx';
var port = 3306;
var dbName = 'xxx';
var username = 'xxx';
var password = 'xxxxx';
var url = 'jdbc:mysql://'+server+':'+port+'/'+dbName;
function readFromTable() {
try {
const conn = Jdbc.getConnection(url, username, password);
const start = new Date();
const stmt = conn.createStatement();
stmt.setMaxRows(1000);
const results = stmt.executeQuery('SELECT * FROM tickets');
const numCols = results.getMetaData().getColumnCount();
while (results.next()) {
let rowString = '';
for (let col = 0; col < numCols; col++) {
rowString += results.getString(col + 1) + '\t';
}
Logger.log(rowString);
**//here should be a script to input data into google sheet**
}
results.close();
stmt.close();
const end = new Date();
Logger.log('Time elapsed: %sms', end - start);
} catch {
// TODO(developer) - Handle exception from the API
Logger.log('Failed with an error %s', err.message);
}
}
Something like this:
function readFromTable() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
try {
const conn = Jdbc.getConnection(url, username, password);
const start = new Date();
const stmt = conn.createStatement();
stmt.setMaxRows(1000);
const results = stmt.executeQuery('SELECT * FROM tickets');
const numCols = results.getMetaData().getColumnCount();
let a = [];
while (results.next()) {
let row = [];
for (let col = 0; col < numCols; col++) {
row.push(results.getString(col + 1));
}
a.push(row);
}
sh.getRange(1,1,a.length,a[0].length).setValues(a);
results.close();
stmt.close();
const end = new Date();
Logger.log('Time elapsed: %sms', end - start);
} catch {
// TODO(developer) - Handle exception from the API
Logger.log('Failed with an error %s', err.message);
}
}
Related
I use apps script to connect to an SQL database and execute a query. It works as intended but writing the result to a docs sheet takes too long. The execution exceeds the timeout long before all rows are written. The query itself is executed relatively fast (<10s) but writing the lines (over 12000 results) happens very slowly. I use the following code:
var server = 'x.x.x.x';
var port = 3306;
var dbName = 'xxx';
var username = 'xxx';
var password = 'xxx';
var url = 'jdbc:mysql://'+server+':'+port+'/'+dbName;
function readData() {
var conn = Jdbc.getConnection(url, username, password);
var stmt = conn.createStatement();
var results = stmt.executeQuery('insertQueryHere');
var metaData=results.getMetaData();
var numCols = metaData.getColumnCount();
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('sheet123');
sheet.clearContents();
var arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(metaData.getColumnName(col + 1));
}
sheet.appendRow(arr);
while (results.next()) {
arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(results.getString(col + 1));
}
sheet.appendRow(arr);
}
results.close();
stmt.close();
sheet.autoResizeColumns(1, numCols+1);
}
Any idea on how to improve performance?
You are making repeated calls to the server with appendRow(). Instead collect all the new rows in an array and use setValues(). See Best Practices
function readData() {
var conn = Jdbc.getConnection(url, username, password);
var stmt = conn.createStatement();
var results = stmt.executeQuery('insertQueryHere');
var metaData=results.getMetaData();
var numCols = metaData.getColumnCount();
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('sheet123');
sheet.clearContents();
var arr=[];
var rows = [];
for (var col = 0; col < numCols; col++) {
arr.push(metaData.getColumnName(col + 1));
}
rows.push(arr);
while (results.next()) {
arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(results.getString(col + 1));
}
rows.push(arr);
}
sheet.getRange(sheet.getLastRow()+1,1,rows.length,numCols).setValues(rows);
SpreadsheetApp.flush(); // just to make sure the data is written
results.close();
stmt.close();
sheet.autoResizeColumns(1, numCols+1);
}
This question already has answers here:
Long processing time likely due to getValue and cell inserts
(2 answers)
Closed 1 year ago.
My Google Sheets Apps Script has been timing out - it does a simple read from a MySQL DB and loads the data in, it queries one single persisted table which hosts only 150 rows so there is no reason it should be timing out.
My Script looks like this:
var server = 'IP';
var port = PORT;
var dbName = 'DB';
var username = 'UN';
var password = 'PW';
var url = 'jdbc:mysql://'+server+':'+port+'/'+dbName;
function readData() {
var conn = Jdbc.getConnection(url, username, password);
var stmt = conn.createStatement();
var results = stmt.executeQuery('SELECT * FROM db.table');
var metaData=results.getMetaData();
var numCols = metaData.getColumnCount();
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('SheetName');
sheet.clearContents();
var arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(metaData.getColumnName(col + 1));
}
sheet.appendRow(arr);
while (results.next()) {
arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(results.getString(col + 1));
}
sheet.appendRow(arr);
}
results.close();
stmt.close();
/*sheet.autoResizeColumns(1, numCols+1);*/
}
/*ScriptApp.newTrigger('readData')
.timeBased()
.everyHours(2)
.create();*/
Is there anything that could be done to better handle the import to speed it up, as I said the data is persisted into a table on the DB, the table only has approx 150 rows and 10-15 columns so the data is small and queries instantly from a DB GUI
This provide a bit of a speed up all though a greater of performance is achievable if you can write code on both ends of the stream and access them via ssl.
var server = 'IP';
var port = PORT;
var dbName = 'DB';
var username = 'UN';
var password = 'PW';
var url = 'jdbc:mysql://' + server + ':' + port + '/' + dbName;
function readData() {
var conn = Jdbc.getConnection(url, username, password);
var stmt = conn.createStatement();
var results = stmt.executeQuery('SELECT * FROM db.table');
var metaData = results.getMetaData();
var numCols = metaData.getColumnCount();
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('SheetName');
sheet.clearContents();
var arr = [];//this is where you store all of the data
let row = [];
for (var col = 0; col < numCols; col++) {
row.push(metaData.getColumnName(col + 1));
}
arr.push(row);
while (results.next()) {
row = [];
for (var col = 0; col < numCols; col++) {
row.push(results.getString(col + 1));
}
arr.push(row)
}
sheet.getRange(1, 1, arr.length, arr[0].length).setValues(arr);//this is where you save all of your data into the spreadsheet thus saving you all of the individual writes to the rows.
results.close();
stmt.close();
}
Class Range setValues() Method
I have this code to auto insert/update data in Google Sheet from MySql database.
var server = 'server';
var port = 3306;
var dbName = 'db_name';
var username = 'db_username';
var password = 'db_pass';
var url = 'jdbc:mysql://'+server+':'+port+'/'+dbName;
function readData() {
var conn = Jdbc.getConnection(url, username, password);
var stmt = conn.createStatement();
var results = stmt.executeQuery('SELECT .... ');
var metaData=results.getMetaData();
var numCols = metaData.getColumnCount();
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('Sheet1');
sheet.clearContents();
var arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(metaData.getColumnName(col + 1));
}
sheet.appendRow(arr);
while (results.next()) {
arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(results.getString(col + 1));
}
sheet.appendRow(arr);
}
results.close();
stmt.close();
sheet.autoResizeColumns(1, numCols+1);
}
How can I set starting row and column for the data inserted? Now it starts from 'A1' and I'd like to start from 'D5'?
Tried to add var cell = sheet.getRange('A1'); after var sheet = with no result.
The basic idea would be to split the problem into 2:
Get the data from your your MySQL into a 2D array
Add the data to the spreadsheet.
function readData() {
// Get data
const conn = Jdbc.getConnection(url, username, password)
const stmt = conn.createStatement()
const results = stmt.executeQuery('SELECT .... ')
const columnNames = getColumnNames(results)
const data = getStringData(results)
results.close()
stmt.close()
// Set data to spreadsheet
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
const sheet = spreadsheet.getSheetByName('Sheet1')
sheet.clearContents()
addToRange(sheet.getRange('B5'), [
columnNames,
...data,
])
}
function getColumnNames(results) {
const result = []
const metaData = results.getMetaData()
const numCols = metaData.getColumnCount()
for (let col = 0; col < numCols; col++) {
result.push(metaData.getColumnName(col + 1))
}
return result;
}
function getStringData(results) {
const result = [];
while (results.next()) {
const row = [];
for (let col = 0; col < numCols; col++) {
row.push(results.getString(col + 1))
}
result.push(row)
}
return result
}
function addToRange(range, values) {
return range
.offset(0, 0, values.length, values[0].length)
.setValues(values)
}
Adding function also make the code more readable and help to split the problem.
Note that I'm adding the column headers to the row 5 (I join the data and the headers). You can set them separately in different ranges if you so desire.
References
Range.offset() (Apps Script reference)
Range.setValue() (Apps Script reference)
Spread syntax (...) (MDN JavaScript reference)
try below code:
var server = 'server';
var port = 3306;
var dbName = 'db_name';
var username = 'db_username';
var password = 'db_pass';
var url = 'jdbc:mysql://'+server+':'+port+'/'+dbName;
function readData() {
var conn = Jdbc.getConnection(url, username, password);
var stmt = conn.createStatement();
var results = stmt.executeQuery('SELECT .... ');
var metaData=results.getMetaData();
var numCols = metaData.getColumnCount();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('Sheet1');
sheet.clearContents();
var arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(metaData.getColumnName(col + 1));
}
sheet.appendRow(arr);
while (results.next()) {
arr=[];
for (var col = 0; col < numCols; col++) {
arr.push(results.getString(col + 1));
}
//sheet.appendRow(arr);
var range = sheet.getRange(5,4, arr.length, arr[0].length);
range.setValues(arr);
}
results.close();
stmt.close();
sheet.autoResizeColumns(1, numCols+1);
}
I want to dynamically send data to MySQL database from Google spreadsheet
I am using Google app scripts but this have not managed to accomplish the task
I can manage store records on the variable but unable to pass them and send to the database, below are the scripts I have;
The scripts below only add ,'" + data[i][0] + "' and 1,'" + data[i][] + "' to the database table instead of actual values
Please help me on this
function writeManyRecords() {
//var sheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1e4o3m5F2sWvNFlMk2MN8tHYtX_WYFmFJyOjW0_AHk/edit#gid=648128284");
var data = sheet.getDataRange().getValues();
//var stmt = conn.createStatement();
var conn = Jdbc.getConnection('jdbc:mysql://IP_address:3306/database_name','user','password');
conn.setAutoCommit(false);
var start = new Date();
var stmt = conn.prepareStatement('INSERT INTO _user_granted_authority' + '(_URI, _CREATOR_URI_USER) values (?, ?)');
for (var i = 0; i < 5; i++) {
stmt.setString(1,'" + data[i][0] + "');
stmt.setString(2,'" + data[i][1] + "');
stmt.addBatch();
}
var batch = stmt.executeBatch();
Logger.log(sheet.getDataRange().getValues());
conn.commit();
conn.close();
var end = new Date();
Logger.log('Time elapsed: %sms for %s rows.', end - start, batch.length);
}
}
Try the below where I have modified the setString part to use just the variables:
function writeManyRecords() {
//var sheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1e4o3m5F2sWvNFlMk2MN8tHYtX_WYscFmFJyOjW0_AHk/edit#gid=648128284");
var data = sheet.getDataRange().getValues();
//var stmt = conn.createStatement();
var conn = Jdbc.getConnection('jdbc:mysql://IP_address:3306/database_name','user','password');
conn.setAutoCommit(false);
var start = new Date();
var stmt = conn.prepareStatement('INSERT INTO _user_granted_authority' + '(_URI, _CREATOR_URI_USER) values (?, ?)');
for (var i = 0; i < 5; i++) {
stmt.setString(1, data[i][0]);
stmt.setString(2, data[i][1]);
stmt.addBatch();
}
var batch = stmt.executeBatch();
Logger.log(sheet.getDataRange().getValues());
conn.commit();
conn.close();
var end = new Date();
Logger.log('Time elapsed: %sms for %s rows.', end - start, batch.length);
}
I want to extract values from a mysql database into a google sheet. Here's what I have so far the script editor:
// Replace the variables in this block with real values.
var address = 'some.rds.amazonaws.com';
var user = 'abc';
var userPwd = '123';
var db = 'db';
var dbUrl = 'jdbc:mysql://' + address + '/' + db;
function readFromTable(member) {
var conn = Jdbc.getConnection(dbUrl, user, userPwd);
var start = new Date();
var stmt = conn.createStatement();
var results = stmt.executeQuery('SELECT fullname FROM member WHERE id_member = 12345; ' );
var numCols = results.getMetaData().getColumnCount();
while (results.next()) {
var rowString = '';
for (var col = 0; col < numCols; col++) {
rowString += results.getString(col + 1) + '\t';
}
Logger.log(rowString)
}
results.close();
stmt.close();
var end = new Date();
Logger.log('Time elapsed: %sms', end - start);
}
If I run it from the script editor the log gives
[15-06-11 14:04:01:870 BST] Bob Brett
[15-06-11 14:04:01:873 BST] Time elapsed: 121.0ms
However, in a sheet if I insert =readFromTable() gives a blank cell and no errors.
What am I missing?
Your method does not return anything. The cell will display the return value of the function, not the log. Add a return statement at the end of the function and try again.