Google Apps Scripts - MSWord to String - google-apps-script

When I attempt to run the following code (Output will be XML):
function doGet(e){
return getFilesHtml();
}
function getFilesHtml() {
//Create second to top level XML parent
var xml = XmlService.createElement('response');
try{
var files = DriveApp.getFilesByName('ANNOUNCEMENTS.doc');
//Iterate through files and push to an array
var filesarray = new Array();
while(files.hasNext()) {
filesarray.push(files.next());
}
var file = getNewestFile(filesarray);
//Create necessary XML elements and information
var file_content = XmlService.createElement('content').setText(file.getBlob().getDataAsString('UTF-8'));
xml.addContent(file_content);
}catch(error){
var stat_child = XmlService.createElement('status').setText('failure');
var message_child = XmlService.createElement('message').setText(error.message);
xml.addContent(stat_child);
xml.addContent(message_child);
}
//Prepare and respond with XML
var document = XmlService.createDocument(xml);
var xml2 = XmlService.getPrettyFormat().format(document);
//Return the XML
return ContentService.createTextOutput(xml2).setMimeType(ContentService.MimeType.XML);
}
function getNewestFile(array){
array.sort(function(a,b){
return new Date(b.getDateCreated()) - new Date(a.getDateCreated());
});
return array[0];
}
I get the following failure response:
<response>
<status>failure</status>
<message>
We're sorry, a server error occurred. Please wait a bit and try again.
</message>
</response>
My ultimate goal is to get the contents of this file. I've tried .getAs('application/pdf'), but that works not, like this. Is there any other method or a method to correct this issue?

The error message "We're sorry, a server error occurred. Please wait a bit and try again." indicates that something went wrong deep within Apps Script. You'll have to troubleshoot the problem further before you can get help, and the Apps Script troubleshooting guide should help you do that.

Related

'Invalid Argument' error with un-gzipping Blob in Apps script

I have a script that receives a gzipped blob from 3rd party API. I'm trying to un-gzip it using Utilities.ungzip() but getting an Invalid Argument error. Here's a sample code:
var liveReportResponse = UrlFetchApp.fetch(url)
var unzipped = Utilities.ungzip(liveReportResponse.getBlob()) // Fails with Invalid Argument error
An odd thing is that I can extract the content using the Drive File as intermediate storage:
var image = liveReportResponse.getBlob()
var file = {
title: 'some_file_.gzip'
};
file = Drive.Files.insert(file, image);
var file = DriveApp.getFileById(file.id)
var blob = file.getBlob()
var someBytes = Utilities.ungzip(blob) // It works
var data = someBytes.getDataAsString()
Would appreciate any help for fixing that.
Eventually, managed to fix that with:
liveReportResponse.getBlob().setContentType('application/x-gzip')
application/x-gzip seems not to be documented anywhere, but I've got it from blob.getContentType()

IMPORTJSON in Google Sheet sometimes not getting data

I have created a sheet to keep my crypto holdings. I use this importJSON function I found on youtube : (I have changed the help text for myself)
/**
* Imports JSON data to your spreadsheet Ex: IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1/?convert=EUR","data/quotes/EUR/price")
* #param url URL of your JSON data as string
* #param xpath simplified xpath as string
* #customfunction
*/
function IMPORTJSON(url,xpath){
try{
// /rates/EUR
var res = UrlFetchApp.fetch(url);
var content = res.getContentText();
var json = JSON.parse(content);
var patharray = xpath.split("/");
//Logger.log(patharray);
for(var i=0;i<patharray.length;i++){
json = json[patharray[i]];
}
//Logger.log(typeof(json));
if(typeof(json) === "undefined"){
return "Node Not Available";
} else if(typeof(json) === "object"){
var tempArr = [];
for(var obj in json){
tempArr.push([obj,json[obj]]);
}
return tempArr;
} else if(typeof(json) !== "object") {
return json;
}
}
catch(err){
return "Error getting data";
}
}
I use this function to readout an API :
This is a piece of my script :
var btc_eur = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1/?convert=EUR","data/quotes/EUR/price");
var btc_btc = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1/?convert=BTC","data/quotes/BTC/price");
ss.getRange("B2").setValue([btc_eur]);
ss.getRange("H2").setValue([btc_btc]);
var bhc_eur = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1831/?convert=EUR","data/quotes/EUR/price");
var bhc_btc = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1831/?convert=BTC","data/quotes/BTC/price");
ss.getRange("B3").setValue([bhc_eur]);
ss.getRange("H3").setValue([bhc_btc]);
The last few days I get "Error getting data" errors. When I start manualy the script it works.
I than tried this code I found here :
ImportJson
function IMPORTJSON(url,xpath){
var res = UrlFetchApp.fetch(url);
var content = res.getContentText();
var json = JSON.parse(content);
var patharray = xpath.split("/");
var res = [];
for (var i in json[patharray[0]]) {
res.push(json[patharray[0]][i][patharray[1]]);
}
return res;
}
But this gives an error about : TypeError: Cannot read property "quotes" from null. What am I doing wrong ?
The big problem is your script call API at least 4 times. When few users do it too, the Google server call API too much times.
The API of Coinmarketcap has limited bandwidth. When any client reach this limit, the API return HTTP error 429. Google Scripts is on shared Google servers, that means lot of users looks as one client for Coinmarketcap API.
When API decline your request, your script fails – the error message corresponds to the assumed error (xpath cant find quotes component in empty varible).
This is ruthless behavior. Please, don't ruin API via mass calls.
You can load data from API at once and re-use it angain for each finding in data.
I have similar Spreadsheet automatically filled from Coinmarketcap API, you can copy it for your:
Coins spreadsheet
Google Script on GitHub.
This my script is strictly ask API only once for whole runtime and reusing one response for all queries.
Change of your script
Also you can make few changes in your Code for saving resources:
Change IMPORTJSON function from this:
function IMPORTJSON(url,xpath){
var res = UrlFetchApp.fetch(url);
var content = res.getContentText();
var json = JSON.parse(content);
...
to this:
function IMPORTJSON(json, xpath) {
...
and rutime section of code you can change like this:
var res = UrlFetchApp.fetch("https://api.coinmarketcap.com/v2/ticker/1/?convert=EUR");
var content = res.getContentText();
var json = JSON.parse(content);
var btc_eur = IMPORTJSON(json,"data/quotes/EUR/price");
var btc_btc = IMPORTJSON(json,"data/quotes/BTC/price");
ss.getRange("B2").setValue([btc_eur]);
ss.getRange("H2").setValue([btc_btc]);
...
Main benefit is: the UrlFetchApp.fetch is called only once.
Yes, I know, this code is not works 1:1 like your. That because that receive prices only for EUR and not for BTC. Naturally fetching comparation between BTC and BTC is unnecessary because it is always 1 and other values you can count matematically from EUR response – please don't abuse an api for such queries.
As Jakub said, the main issue is that all requests are counted as coming from the same Google server.
One solution which I consider easier is to put a proxy server in the middle, this can be done by either purchasing a server and setting it up (which is quite complex) or using a service like Proxycrawl which includes some free requests and after that, unless you run thousands of queries per month, it should cost you less than 1 USD per month.
To do that you just need to edit one line of the script:
var res = UrlFetchApp.fetch(url);
This line, becomes this:
var res = UrlFetchApp.fetch(`https://api.proxycrawl.com/?token=YOUR_TOKEN&url=${encodeURIComponent(url)}`);
Make sure to replace YOUR_TOKEN with your actual service token
Just this simple change will make the requests never fail as each request will be sent from a different IP instead of all coming from Google.

File.makeCopy error

I am using the following code to make a copy of a file:
var backupFolder = DriveApp.getFolderById('1vOnO5aSOSFNWtOLHuAz4Lv2lsRgBwBpS');
var file = DriveApp.getFileById('1TJ_5Khw7wcqlIfbZ_-KLOQ-DsU02FsoRFYR1A3B4qAs');
file.makeCopy(file.getName(), backupFolder);
Most of the time that works without any issue.
Some times I get the following error:
We're sorry, a server error occurred. Please wait a bit and try again
Does anyone know how I can get a more meaningful error message to understand what is the issue?
To build on Anton's and Nancy's answers one useful approach I have found for error logging and catching important issues, is to append the error to a google sheet for reference with a timestamp and to send me a warning email with the failure reason. This gives me an instance notice something is not right, and helps me to keep track of issues.
function someImportantProcess(){
var ss = SpreadsheetApp.getActiveSpreadSheet();
var sheet = ss.getSpreadsheetByName('Sheet1');
try {
someImportant function(){
Logger.log('important stuff')
}
} catch(e){
sheet.appendRow([timestamp, e])
sendEmail(e)
}
}
sendEmail(e){
var subject = '[Important a script failed]';
var body = e;
sendEmail(myemail#google.com, subject, body);
}

DriveApp.createFile causes a server error

I got the following error when I tried to download a picture from a URL using Google Apps Script.
We're sorry, a server error occurred. Please wait a bit and try again.
Here is the code.
function TT() {
var response = UrlFetchApp.fetch('https://www.dropbox.com/s/g9jtm390l67uqkb/128.png?dl=1');
var blob = response.getBlob();
Logger.log(blob.getContentType());
var file = DriveApp.createFile(response);
}
Well, should try to create a file from its blob, not from the response it self.
function TT() {
var response = UrlFetchApp.fetch('https://www.dropbox.com/s/g9jtm390l67uqkb/128.png?dl=1');
var blob = response.getBlob();
Logger.log(blob.getContentType());
var file = DriveApp.createFile(blob);
}
I'v runned a test and it works perfectly.

Error uploading .xls file and converting to Google Spreadsheet via GAS

Prior Research
Please do not close this question as a duplicate because my question deals with how to resolve the specific error message I am receiving and not the general question of whether my objective is achievable or not — as some other related questions, yielded by my research and below detailed, have asked.
Related questions and why they do not apply here
This question, asked 7/27/2012, does not apply because it: (1) is too old (after 10 months, new solutions/methods might exist) and (2) does not deal with the specific error message I am experiencing.
This question, asked 10/12/2012, fails to apply for similar reasons.
My below code was copied from here which was forked from here. These are presumably, working solutions because they have been referenced as such from other question/answer exchanges here on Stack Overflow.
Objective
Programmatically, I am trying to:
Search my email inbox.
Find Excel (.xls) file attachments.
Upload those .xls file attachments to Google Drive.
While uploading, convert the .xls files into a Google Spreadsheet file format.
Problem
When I execute processInbox() (code shown at the bottom of this question), it fails and I get the error message shown below.
Error Message
Request failed for returned code 403.
Server response:
{
"error":{
"errors":[
{
"domain":"usageLimits",
"reason":"accessNotConfigured",
"message":"AccessNotConfigured"
}
],
"code":403,
"message":"AccessNotConfigured"
}
}
(line 13, file "DriveUpload")
Question
What am I doing wrong? And how can I fix it?
For example, do I need to do something special in my API console relative to setting up my project to, say, access Google Drive or something? What am I missing?
Note: I have not yet successfully implemented oAuth in any of my applications, yet.
Error Source
Line 13
(This is the code line referenced by the error message.)
var uploadRequest = UrlFetchApp.fetch("https://www.googleapis.com/upload/drive/v2/files/?uploadType=media&convert=true&key="+key, params); // convert=true convert xls to google spreadsheet
Code
The complete body of code I am working with is shown below for your reference. I extracted the error-triggering, “line 13,” and highlighted it above to help us focus on the proximate cause of the problem.
DriveUpload.js
function uploadXls(file) {
authorize();
var key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // <-- developer key
var metadata = { title: file.getName() }
var params = {method:"post",
oAuthServiceName: "drive",
oAuthUseToken: "always",
contentType: "application/vnd.ms-excel",
contentLength: file.getBytes().length,
payload: file.getBytes()
};
// convert=true convert xls to google spreadsheet
var uploadRequest = UrlFetchApp.fetch("https://www.googleapis.com/upload/drive/v2/files/?uploadType=media&convert=true&key="+key, params);
var uploadResponse = Utilities.jsonParse(uploadRequest.getContentText());
var params = {method:"put",
oAuthServiceName: "drive",
oAuthUseToken: "always",
contentType: "application/json",
payload: Utilities.jsonStringify(metadata)
};
var metaRequest = UrlFetchApp.fetch("https://www.googleapis.com/drive/v2/files/"+uploadResponse.id+"?key="+key, params)
return DocsList.getFileById(uploadResponse.id);
}
function authorize() {
var oauthConfig = UrlFetchApp.addOAuthService("drive");
var scope = "https://www.googleapis.com/auth/drive";
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");
}
function processInbox() {
// get all threads in inbox
var threads = GmailApp.getInboxThreads();
for (var i = 0; i < threads.length; i++) {
// get all messages in a given thread
var messages = threads[i].getMessages();
// iterate over each message
for (var j = 0; j < messages.length; j++) {
// log message subject
var subject = messages[j].getSubject()
//Logger.log(subject);
if ( subject == "with xls attach" ){
Logger.log(messages[j].getSubject());
var attach = messages[j].getAttachments()[0];
var name = attach.getName();
var type = attach.getContentType();
//var data = attach.getDataAsString();
Logger.log( name + " " + type + " " );
var file = uploadXls(attach);
SpreadsheetApp.open(file);
}
}
}
};
Drive API is already built in GAS: https://developers.google.com/apps-script/reference/drive/
Use DriveApp and your problems go away ;-)
This maybe a temp solution
Step 1: Use a Google Form to Collect Data to a Google spreadsheet
Step 2: Add the Zoho Sheet App to your Google Drive
In a Zoho Sheet
Goto
Data Menu
»Link External Data
Select either
CSV
RSS/Atom Feed
or HTML Page
You can schedule it to update at specific time intervals
What I like is the VBA and Macros in Zoho
You can also do Pivot Charts and Tables
You can copy and paste Excel VBA into Zoho !
I have an Unpivot VBA that I will run on my Tabular dataset
before I can do a PivotChart
It is hard to beat all the functionality of Excel and I often fall back on familiar tools !
If I hear of anything I will post it
Good luck