Google Apps Script: Save Spreadsheet as ODS for Local Backup - excel
I could use a hand. My company uses Google Sheets extensively, and we need a way to access files when we lose our Internet connection.
I could not get any of the examples found on this site to work for creating xls or ods from Google Sheets via script.
I did script a way to create csv backups, accessible from a local Google Drive folder. When used with an hourly trigger, this script creates csv files of every sheet of any spreadsheet modified in the last hour, puts them in a folder, and zips it inside a folder specifically for backups. From there I can move the zip to our local server.
function backUpMaker() {
var backupFolderId = '<Id of Backup Folder>';
var timeNow = new Date();
var newFolder = DocsList.createFolder(timeNow);
var newFolderId =newFolder.getId();
newFolder.addToFolder(DocsList.getFolderById(backupFolderId));
newFolder.removeFromFolder(DocsList.getRootFolder());
var sheets = DriveApp.getFilesByType(MimeType.GOOGLE_SHEETS);
while (sheets.hasNext()) {
var sheet = sheets.next();
var lastUpdate = sheet.getLastUpdated();
var timeHourAgo = new Date();
timeHourAgo = timeNow - 3600000;
if(lastUpdate >= timeHourAgo){
var sheetId = sheet.getId();
var csv = eachSheet(sheetId,newFolderId);
}
}
var backupFolder = DocsList.getFolderById(backupFolderId);
try{
backupFolder.createFile(Utilities.zip(newFolder.getFiles(), timeNow + '.zip'));
} catch(err) {
Logger.log(err);
}
newFolder.setTrashed(true);
}
function eachSheet(key,newFolderId) {
var ss = SpreadsheetApp.openById(key);
var ssId = ss.getId();
var ssName = ss.getName();
var howManySheets = ss.getNumSheets();
try{
for (var sheetIndex=0; sheetIndex < howManySheets; sheetIndex++) {
var activeSheet = ss.getSheets()[sheetIndex];
var activeName = activeSheet.getName();
if(activeName != 'Dropdowns'){ //Skip a hidden sheet used for validation on many of our spreadsheets
var activeId = activeSheet.getSheetId();
var time = new Date();
var fileName = time + " Backup: " + ssName + " " + activeName + ".csv";
var csv = contentCSV(ssId,activeId);
var folder = DocsList.getFolderById(newFolderId);
folder.createFile(fileName, csv, 'text/plain');
}
}
} catch(err) {
Logger.log(err)
}
}
function contentCSV(key,gid) {
var file = DocsList.getFileById(key);
var response = UrlFetchApp.fetch("https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + key +
"&gid=" + gid + "&exportFormat=csv", oAuth());
var fileText = response.getContentText();
return fileText;
}
function oAuth() {
var oauthConfig = UrlFetchApp.addOAuthService("spreadsheets");
var scope = "https://spreadsheets.google.com/feeds"
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://accounts.google.com/OAuthAuthorizeToken");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
var requestData = {
"oAuthServiceName": "spreadsheets",
"oAuthUseToken": "always",
};
return requestData;
}
How would I modify this to save as ods rather than csv? Or is there a better way to save backups? Thank you for your help!
Working code follows, thanks to input by #serge-insas :
Note: To make this work, enter your backup folder's id key, then choose ods or xlsx by commenting out the other choice. Then you need to set up a timed hourly trigger for backUpMaker(). Logs will catch errors for files that have been moved temporarily. Here goes:
function backUpMaker() {
var backupFolderId = '0B5--------------------1ZX1k';
//var exportFormat = 'ods';
var exportFormat = 'xlsx';
var timeNow = new Date();
var newFolder = DocsList.createFolder(timeNow);
var newFolderId =newFolder.getId();
newFolder.addToFolder(DocsList.getFolderById(backupFolderId));
newFolder.removeFromFolder(DocsList.getRootFolder());
var sheets = DriveApp.getFilesByType(MimeType.GOOGLE_SHEETS);
while (sheets.hasNext()) {
var sheet = sheets.next();
var lastUpdate = sheet.getLastUpdated();
var timeHourAgo = new Date();
timeHourAgo = timeNow - 3600000;
if(lastUpdate >= timeHourAgo){
try{
var key = sheet.getId();
var name = sheet.getName();
var fileName = timeNow + " Backup: " + name + "." + exportFormat;
var blob = contentBackup(key,exportFormat);
var folder = DocsList.getFolderById(newFolderId);
folder.createFile(blob).rename(fileName);
} catch(err){
Logger.log(err);
}
}
}
var backupFolder = DocsList.getFolderById(backupFolderId);
try{
backupFolder.createFile(Utilities.zip(newFolder.getFiles(), timeNow + '.zip'));
} catch(err) {
Logger.log(err);
}
newFolder.setTrashed(true);
}
function contentBackup(key,exportFormat) {
try{
if(exportFormat == 'xlsx'){
exportFormat = 'xls';
}
var file = DocsList.getFileById(key);
var response = UrlFetchApp.fetch("https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + key +
"&exportFormat=" + exportFormat, oAuth());
var fileBlob = response.getBlob();
return fileBlob;
} catch(err) {
Logger.log(err)
}
}
function oAuth() {
var oauthConfig = UrlFetchApp.addOAuthService("spreadsheets");
var scope = "https://spreadsheets.google.com/feeds"
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://accounts.google.com/OAuthAuthorizeToken");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
var requestData = {
"oAuthServiceName": "spreadsheets",
"oAuthUseToken": "always",
};
return requestData;
}
Your code needed very few changes to get ods files.
2 differences : the requested format in the urlFetch becomes "ods" and the returned object is not a string anymore but a blob.
Beside that, I kept all the sheet selection functions that you wrote and it seems to work fine as well. (nice job you did !).
Below is the full code I reproduced from yours and changed as described. My tests were working fine.
function backUpMaker() {
var backupFolderId = '0B3qS--------------TXdlY2M';
var timeNow = new Date();
var newFolder = DocsList.createFolder(timeNow);
var newFolderId =newFolder.getId();
newFolder.addToFolder(DocsList.getFolderById(backupFolderId));
newFolder.removeFromFolder(DocsList.getRootFolder());
var sheets = DriveApp.getFilesByType(MimeType.GOOGLE_SHEETS);
while (sheets.hasNext()) {
var sheet = sheets.next();
var lastUpdate = sheet.getLastUpdated();
var timeHourAgo = new Date();
timeHourAgo = timeNow - 3600000;
if(lastUpdate >= timeHourAgo){
var sheetId = sheet.getId();
var csv = eachSheet(sheetId,newFolderId);
}
}
var backupFolder = DocsList.getFolderById(backupFolderId);
try{
backupFolder.createFile(Utilities.zip(newFolder.getFiles(), timeNow + '.zip'));
} catch(err) {
Logger.log(err);
}
newFolder.setTrashed(true);
}
function eachSheet(key,newFolderId) {
var ss = SpreadsheetApp.openById(key);
var ssId = ss.getId();
var ssName = ss.getName();
var howManySheets = ss.getNumSheets();
try{
for (var sheetIndex=0; sheetIndex < howManySheets; sheetIndex++) {
var activeSheet = ss.getSheets()[sheetIndex];
var activeName = activeSheet.getName();
if(activeName != 'Dropdowns'){ //Skip a hidden sheet used for validation on many of our spreadsheets
var activeId = activeSheet.getSheetId();
var time = new Date();
var fileName = time + " Backup: " + ssName + " " + activeName + ".ods";
var blob = contentODS(ssId,activeId);
var folder = DocsList.getFolderById(newFolderId);
folder.createFile(blob).rename(fileName);
}
}
} catch(err) {
Logger.log(err)
}
}
function contentODS(key,gid) {
var file = DocsList.getFileById(key);
var response = UrlFetchApp.fetch("https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + key +
"&gid=" + gid + "&exportFormat=ods", oAuth());
var fileBlob = response.getBlob();
return fileBlob;
}
function oAuth() {
var oauthConfig = UrlFetchApp.addOAuthService("spreadsheets");
var scope = "https://spreadsheets.google.com/feeds"
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://accounts.google.com/OAuthAuthorizeToken");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
var requestData = {
"oAuthServiceName": "spreadsheets",
"oAuthUseToken": "always",
};
return requestData;
}
Related
Automatically unzipping files on google drive with google app script
I found and have made several codes to automatically unzip new files on my google drive with google app script, but none of them work. Can someone help me figure out how to get one code to work? The code is supposed to get a zip file from a given google drive folder and unzip it, so that the files within can be extracted and used in a different code. Here are the six codes that might work, but don't. I only need one to work so I don't mind which one :) Thank you in advance for your suggestions and help! function unZip() { var theFolderID = DriveApp.getFolderById(folderID); var theFile = theFolderID.getFilesByType(MimeType.ZIP); if (theFile.length > 0) { for (var i in theFile) { file = theFile[i]; var unZippedfile = Utilities.unzip(file); var newfile = DriveApp.createFile(unZippedfile); var fileId = SpreadsheetApp.create(newfile).getId(); var file = DriveApp.getFileById(fileId); folderName.addFile(newfile); root.removeFile(newfile); } } } function unZipItAll() { var theFolder = getFolder_(folderName); var theFile = theFolder.getFilesByType("application/zip"); if (theFile.length > 0) { for (var i in theFile) { file = theFile[i]; var unZippedfile = Utilities.unzip(file); var newfile = DriveApp.createFile(unZippedfile); var fileId = SpreadsheetApp.create(newfile).getId(); var file = DriveApp.getFileById(fileId); folderName.addFile(newfile); root.removeFile(newfile); } } } function unzip() { var theFolderID = DriveApp.getFolderById(folderID); var theFile = theFolderID.getFilesByType("application/zip"); while (theFile.hasNext()){ var fileBlob = theFile.next().getBlob(); fileBlob.setContentType("application/zip"); var unZippedfile = Utilities.unzip(fileBlob); var newfile = DriveApp.createFile(unZippedfile); var fileId = SpreadsheetApp.create(newfile).getId(); var file = DriveApp.getFileById(fileId); folderName.addFile(file); root.removeFile(newfile); } } function unZipIt() { var theFolder = DriveApp.getFolderById(folderID); var theFile = theFolder.getFilesByType("application/zip"); var fileBlob = theFile.next().getBlob(); fileBlob.setContentType("application/zip"); var unZippedfile = Utilities.unzip(fileBlob); var newDriveFile = DriveApp.createFile(unZippedfile[0]); Logger.log(newDriveFile.getId()) } function Unzip() { var SourceFolder = DriveApp.getFolderById(folderID) var DestinationFolder = DriveApp.getFolderById(folderID) var ZIPFiles = SourceFolder.getFilesByType(MimeType.ZIP) while (ZIPFiles.hasNext()){ var fileBlob = ZIPFiles.next().getBlob(); var unZippedfile = Utilities.unzip(fileBlob); var newDriveFile = DestinationFolder.createFile(unZippedfile[0]); } } function testzip(){ var theFolderID = DriveApp.getFolderById(folderID); var theFile = theFolderID.getFilesByType("application/zip"); if (theFile.length > 0) { for (var i in theFile) { file = theFile[i]; var unZippedfile = Utilities.unzip(file); var unzipstr = unZippedfile[0].getDataAsString(); var newfile = DriveApp.createFile(unzipstr); folderName.addFile(newfile); root.removeFile(newfile); } } }
Exporting a Google Sheet into an Excel using Google script
I am trying to automate a backup of a google sheet into an excel. After trying different scripts seen here and there on Stackoverflow, the one I have is now running but nothing is happening. Any ideas? Here is the code: function exportAsxlsx() { var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); var spreadsheetId = spreadsheet.getId() var file = DriveApp.getFileById(spreadsheetId) var url = 'https://docs.google.com/spreadsheets/d/'+spreadsheetId+'/export?format=xlsx'; var token = ScriptApp.getOAuthToken(); var response = UrlFetchApp.fetch(url, { headers: { 'Authorization': 'Bearer ' + token } }); var blobs = response.getBlob(); var folder = DriveApp.getFoldersByName('Exports'); if(folder.hasNext()) { var existingPlan1 = DriveApp.getFilesByName('newfile.xlsx'); if(existingPlan1.hasNext()){ var existingPlan2 = existingPlan1.next(); var existingPlanID = existingPlan2.getId(); Drive.Files.remove(existingPlanID); } } else { folder = DriveApp.createFolder('BackUp'); } folder = DriveApp.getFoldersByName('BackUp').next(); var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss"); var name = SpreadsheetApp.getActiveSpreadsheet().getName() + " Copy " + formattedDate; folder.createFile(blobs).setName(name + '.xlsx') }
So, here is a script that works: function exportAsxlsx() { var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); var spreadsheetId = spreadsheet.getId() var file = DriveApp.getFileById(spreadsheetId) var url = 'https://docs.google.com/spreadsheets/d/'+spreadsheetId+'/export?format=xlsx'; var token = ScriptApp.getOAuthToken(); var response = UrlFetchApp.fetch(url, { headers: { 'Authorization': 'Bearer ' + token } }); var blobs = response.getBlob(); var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss"); var name = SpreadsheetApp.getActiveSpreadsheet().getName() + " Copy " + formattedDate; var folder = DriveApp.getFolderById("your folder ID"); folder.createFile(blobs).setName(name + '.xlsx'); }
NodeJS Script Runs on Local Machine but Not in Firebase Cloud Functions?
My script written in NodeJS connects to Firebase, checks my Firebase Database and even successfully sends notifications when results from my database return true... However, it only works when I run it from my local machine. I deploy it to Firebase and it will not work. Could someone please advise? Thank you. I hate asking on here because I'm a newbie but I have spent hours tonight trying to find an answer... INDEX.JS // Firebase Functions const functions = require('firebase-functions'); var admin = require("firebase-admin"); // Default admin firebase configuration admin.initializeApp(functions.config().firebase); // var serviceAccount = require("xxxxxx-80xxxxd-firebase-adminsdk- xxxxxxx.json"); var moment = require('moment'); var FCM = require('fcm-push'); var dateTime = require('node-datetime'); var serverKey = 'xxxxxxxxxxxxxpSELZBjQYwpZgmxxxxxxxxxxx'; var fcm = new FCM(serverKey); //Initial function call: exports.CheckDates = functions.https.onRequest((req, response) => { // Get a database reference to our posts var db = admin.database(); var ref = db.ref("records"); var userToken = ''; var itemExpires = ''; var itemName = ''; var reminded = ''; var itemCount = 0; var counter = 1; var itemFoundCount = 0; var dt = dateTime.create(); var formatted = dt.format('m-d-Y'); ref.once("value", function (recordsSnapshot) { recordsSnapshot.forEach(function (recordsSnapshot) { var mainKey = recordsSnapshot.key; recordsSnapshot.forEach(function (child) { var key = child.key; var value = child.val(); if (key == 'Account') { userToken = value.userToken; } if (key == 'Items') { recordsSnapshot.child("Items").forEach(function (itemsSnapshot) { counter++; if (itemFoundCount === 0) { itemFoundCount = itemsSnapshot.numChildren(); } var itemsChildkey = itemsSnapshot.key; var itemsChildvalue = itemsSnapshot.val(); itemExpires = itemsChildvalue.itemExpires; itemName = itemsChildvalue.itemName; reminded = itemsChildvalue.reminded; moment().format('YYYY-MM-DD'); var currentDate = moment(); var otherTime = moment(reminded); if (typeof reminded !== 'undefined') { if (currentDate.diff(otherTime, 'days') >= 30) { if (currentDate.diff(itemExpires, 'days') <= 90) { itemCount++; console.log("Expire date is less than " + currentDate + " by 90 days = " + (currentDate.diff(otherTime, 'days') <= 90)); db.ref("records/" + mainKey + "/Items/" + itemsChildkey + '/reminded').set(formatted); } } } else { itemCount++; db.ref("records/" + mainKey + "/Items/" + itemsChildkey + `enter code here`'/reminded').set(formatted); } if (counter == itemFoundCount && itemCount > 0) { console.log(itemFoundCount); var message = { to: userToken, // required fill with device token or topics notification: { title: 'Item Expire Notification', body: itemCount + ' is about to expire.' } }; //callback style fcm.send(message, function (err, response) { if (err) { console.log("Something has gone wrong!"); } else { console.log("Successfully sent with response: ", response); } }); itemCount = 0; itemFoundCount = 0; counter = 1; } }); } }); }); }); response.send(200, "ok"); }) // END exports.CheckDates Obviously, I remove the Exports.CheckDates lines when I run it locally but it wasn't showing up at all without the exports on Firebase's console. It returns warnings locally and on Firebase console but it works on one and not the other.
Please disregard this question. The script adds the date that the last time a notification was sent to the item's "Reminded" key in the database... this prevents notifications from going out every day for the same thing.. It ran on my local machine, and did it's job but I couldn't figure out why it wouldn't run again... well, ha! At least we know that part works.
Synchronous Call : Call 2nd function after 1st function is executed completely
I recently stating coding in node.js and might be a very simple question. Trying to write a XML parser/validator to validate xml schema and values against values/ xpath stored in an excel sheet. Now once the validation function is complete I want to call a printResult function to print final result. However if I try to call the function immediately after the first function .. its printing variables initial values and if called within the first which is iterating though the number of xpaths present in excel sheet and printing result with increments. var mocha = require('mocha'); var assert = require('chai').assert; var fs = require('fs'); var parseString = require('xml2js').parseString; var xpath = require('xpath'); var dom = require('xmldom').DOMParser; var XLSX = require('xlsx'); var Excel = require("exceljs"); var should = require('chai').should(); var HashMap = require('hashmap'); var colors = require('colors'); require('/xmlValidator/dbConnect.js'); var map = new HashMap(); var elementMap = new HashMap(); var resultValue; //console.log('hello'.green); map.set("PASS", 0); map.set("FAIL", 0); map.set("INVALID_PATH", 0); function computeResult(elementPath, result) { var pass = map.get("PASS"); var fail = map.get("FAIL"); var invalidPath = map.get("INVALID_PATH"); elementMap.set(elementPath, result); if (result == "PASS") { pass++; map.set("PASS", pass); } else if (result == "FAIL") { fail++; map.set("FAIL", fail); } else { invalidPath++; map.set("INVALID_PATH", invalidPath) } printResult(); } function printResult() { var pass = map.get("PASS"); var fail = map.get("FAIL"); var invalidPath = map.get("INVALID_PATH"); console.log(("PASS Count :" + pass).green); console.log(("FAIL Count :" + fail).red); console.log(("Inavlid Path :" + invalidPath).yellow); elementMap.forEach(function(value, key) { if (value == "INVALID_PATH") console.log((key + ":" + value).yellow); else if (value == "FAIL") console.log((key + ":" + value).red); else console.log(key + ":" + value); }); } var workbook = new Excel.Workbook(); workbook.xlsx.readFile('utils/' + process.argv[2]) .then(function() { var worksheet = workbook.getWorksheet(1); worksheet.eachRow(function(row, rowNumber) { //console.log(rowNumber); var row = worksheet.getRow(rowNumber); var dataPath1 = row.getCell("A").value; var dataPath2 = row.getCell("B").value; var dataPath = dataPath1 + dataPath2; //console.log(dataPath); var dataValue = row.getCell("D").value; var flag = row.getCell("E").value; //console.log(flag) //console.log(dataValue); if (!flag) validate(dataPath, dataValue, rowNumber); //else console.log("NOT EXECUTED" + rowNumber) }); }) function validate(dataPath, dataValue, rowNumber) { var fail = 0; fs.readFile('utils/' + process.argv[3], 'utf8', function(err, data) { if (err) { console.log("ERROR ERROR ERROR ERROR "); return console.log(err); } var doc = new dom().parseFromString(data); var subId = String(xpath.select1(dataPath, doc)); if (subId == "undefined") { /*console.log('undefined caught'); console.log("row number :" + rowNumber);*/ var resultValue = "INVALID_PATH"; computeResult(dataPath, resultValue); } else { var subId = xpath.select1(dataPath, doc); var value = subId.lastChild.data; /*console.log("row number :" + rowNumber); console.log("actual value: " + value); console.log("expected value:" + dataValue );*/ if (dataValue == null) { assert.notEqual(value, dataValue, "value not found"); resultValue = "PASS"; computeResult(dataPath, resultValue); } else { if (value == dataValue) resultValue = "PASS"; else resultValue = "FAIL"; computeResult(dataPath, resultValue); } } }); } In the code above i want to call printResult() function after validate function is completely executed (workbook.xlsx.readFile) Can some one please help me out how to use done () function or make sync call ?
If fs.readFileAsync('utils/' + process.argv[3], 'utf8') can be executed once, then validate() will be completely synchronous and calling printResult() after the verification loop will be trivial. In the main routine, you can simply aggregate two promises ... var promise1 = workbook.xlsx.readFile(); var promise2 = fs.readFileAsync(); // requires `fs` to be promisified. ... before embarking on the verification loop. Promise.all([promise1, promise2]).spread(/* verify here */); Also a whole bunch of tidying can be considered, in particular : establishing "PASS", "FAIL" and "INVALID_PATH" as constants to avoid lots of repetitive string creation, using js plain objects in lieu of hashmap, building map from elementMap inside the print function. having validate() return its result and building elementMap in the main routine Here's the whole thing, about as tight as I can get it. I may have made a few assumptions but hopefully not too many bad ones ... var mocha = require('mocha'); var assert = require('chai').assert; var Promise = require("bluebird"); var fs = Promise.promisifyAll(require("fs")); // allow Bluebird to take the pain out of promisification. var parseString = require('xml2js').parseString; var xpath = require('xpath'); var dom = require('xmldom').DOMParser; var XLSX = require('xlsx'); var Excel = require("exceljs"); var should = require('chai').should(); // var HashMap = require('hashmap'); var colors = require('colors'); require('/xmlValidator/dbConnect.js'); const PASS = "PASS"; const FAIL = "FAIL"; const INVALID_PATH = "INVALID_PATH"; function printResult(elementMap) { var key, result, map = { PASS: 0, FAIL: 0, INVALID_PATH: 0 }, colorNames = { PASS: 'black', FAIL: 'red', INVALID_PATH: 'yellow' }; for(key in elementMap) { result = elementMap[key]; map[(result === PASS || result === FAIL) ? result : INVALID_PATH] += 1; console.log((key + ": " + result)[colorNames[result] || 'black']); // presumably colors can be applied with associative syntax? If so, then the code can be very concise. } console.log(("PASS Count: " + map.PASS)[colorNames.PASS]); console.log(("FAIL Count: " + map.FAIL)[colorNames.FAIL]); console.log(("Inavlid Path: " + map.INVALID_PATH)[colorNames.INVALID_PATH]); } function validate(doc, dataPath, dataValue) { var subId = xpath.select1(dataPath, doc), value = subId.lastChild.data, result; if (String(subId) == "undefined") { result = INVALID_PATH; } else { if (dataValue === null) { assert.notEqual(value, dataValue, "value not found"); // not too sure what this does result = PASS; } else { result = (value === dataValue) ? PASS : FAIL; } } return result; } //Main routine var workbook = new Excel.Workbook(); var promise1 = workbook.xlsx.readFile('utils/' + process.argv[2]); // from the question, workbook.xlsx.readFile() appears to return a promise. var promise2 = fs.readFileAsync('utils/' + process.argv[3], 'utf8'); Promise.all([promise1, promise2]).spread(function(data2, data3) { var worksheet = workbook.getWorksheet(1), doc = new dom().parseFromString(data3), elementMap = {}; worksheet.eachRow(function(row, rowNumber) { // var row = worksheet.getRow(rowNumber); // row is already a formal variable ??? var dataPath, dataValue; if (!row.getCell('E').value) dataPath = row.getCell('A').value + row.getCell('B').value; dataValue = row.getCell('D').value; elementMap[dataPath] = validate(doc, dataPath, dataValue); }); printResult(elementMap); }); Untested so may not run but at least you can raid the code for ideas.
gcloud nodejs copy table
I can't copy a table to a different dataset, but I can do it to the same one. Am I doing anything wrong? var project_id = "project" var dataset_id = "testDb"; var dataset_bk_id = "testDbBk" var table_id = "test"; var dataset = bigquery.dataset(dataset_id); var dataset_bk = bigquery.dataset(dataset_bk_id); var table = dataset.table(table_id); var table_bk = dataset_bk.table(table_id); var metadata = { createDisposition:"CREATE_IF_NEEDED", destinationTable: { //required if allowLargeResults = true projectId:project_id, datasetId:dataset_bk_id, tableId:table_id }, writeDisposition:"WRITE_TRUNCATE" }; table.copy(table_bk, metadata, function(err, job, apiResponse) { if (err){ reject(err.message); }else{ fulfill("Table " + table_id + " copied."); } }); Another thing that concerns me is the fact that I'm not getting any error in that bit of code.