Google Apps Script Web App image workaround - dom

I'm using a set of workaround functions I got from another stack overflow post, but I can't seem to modify them to work for a background image:
This works:
google.script.run
.withSuccessHandler( function(bytes){ showImage(bytes) })
.loadImageBytes("1WH0TrUxzzzzzzzzzcqEYZnTD6zPM9");
function showImage(bytes){
document.getElementById("page1").src = "data:image/png;base64," + bytes;
}
but this does not:
google.script.run
.withSuccessHandler( function(bytes){ showImage(bytes) })
.loadImageBytes("1WH0TrUxzzzzzzzzzcqEYZnTD6zPM9");
function showImage(bytes){
document.getElementById("page1").style.backgroundImage= "data:image/png;base64," + bytes;
}
The server side code is:
function loadImageBytes(id){
console.log(id);
var bytes = DriveApp.getFileById(id);
console.log(bytes.getName());
try{
bytes= bytes.getBlob();
bytes= bytes.getBytes();
}
catch(e){console.log(e);}
return Utilities.base64Encode(bytes);
}

I think that in your script, the value for backgroundImage is required to be modified. So how about this modification?
From:
document.getElementById("page1").style.backgroundImage= "data:image/png;base64," + bytes;
To:
document.getElementById("page1").style.backgroundImage = "url(data:image/png;base64," + bytes + ")";
Reference:
background-image

Related

I get a corrupted PDF when I use Apps Script to convert a sheet to pdf and send in email

I am trying to use the following code to convert the current sheet in my spreadsheet to a pdf and send it via email:
function sendEmailPDF(pdfName, email, title, body) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var sheetId = sheet.getSheetId();
var url_base = ss.getUrl().replace(/edit$/,'');
var url_ext = 'exportFormat=pdf' //export as pdf
+ '&format=pdf' //export as pdf
+ '&size=letter' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false' //hide optional headers and footers
+ '&printtitle=false' //hide optional headers and footers
+ '&pagenumbers=false' //hide page numbers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid=' //the sheet's Id
var token = ScriptApp.getOAuthToken();
var params = {
headers: {
'Authorization': 'Bearer ' + token,
},
'muteHttpExceptions' : true
};
var response = UrlFetchApp.fetch(url_base + url_ext + sheetId, params)
var blob = response.getBlob().setName(pdfName + ".pdf");
var mailOptions = {attachments:blob, htmlBody:body};
if (MailApp.getRemainingDailyQuota() > 0){
MailApp.sendEmail(
email,
title,
"html content only",
mailOptions
);
}
}
Now the code executes without errors, and I receive an email with the pdf attached, but I can't open it because I get an error saying that it's corrupted and can't be opened.
When I remove the following code at line 24:
'muteHttpExceptions' : true
The code fails to execute, and I get the following error in my log:
Request failed for https://docs.google.com/spreadsheets/d/146PS13Dz2HOzljUsH-umTU1FUIlcL1UCFqANAqNRUP0/exportFormat=pdf&format=pdf&size=letter&portrait=true&fitw=true&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&fzr=false&gid=133193667 returned code 404. Truncated server response: <!DOCTYPE html><html lang="en"><head><meta name="description" content="Web word processing, presentations and spreadsheets"><meta name="viewport" c... (use muteHttpExceptions option to examine full response) at sendEmailPDF(sendEmailPDF:27) at submitNewProject(submitNewProject:264) at userOnEdit(On Edit:68) at userOnEdit(Code:2)
I have searched high and low and looked at different code samples of how to use Apps Script to send a pdf via email, but none of them seem to be working for me.
Any help is appreciated!
I think that there are 2 modification points in your script.
1. Query parameter
Please try to insert ? as follows.
From :
var url_base = ss.getUrl().replace(/edit$/,'');
To :
var url_base = ss.getUrl().replace(/edit$/,'') + "export?";
2. Advanced parameters of MailApp.sendMail()
attachments BlobSource[] an array of files to send with the email (see example)
The blob is an array. So please modify as follows.
From :
var mailOptions = {attachments:blob, htmlBody:body};
To :
var mailOptions = {attachments: [blob], htmlBody:body};
I think that when the blob is only one, attachments:blob works. If you want to send several blobs, please use an array.
Reference :
sendEmail(recipient, subject, body, options)
If this still didn't work, please tell me. I would like to modify it.
Answering to KingOfTheNerds...
I've had a similar issue that one day my code stopped working. The solution above didn't solve my problem.
But I've found out, that the problem was in the line code:
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
because my spreadsheet link was not ended with the word "edit".
My solution is to change mentioned line to:
var url_base = spreadsheet.getUrl().replace(/edit.+/,'');
I hope it will help somebody :)

Using Word.SearchOptions in an Office Add-In

I am developing an Office Add-In that processes the text of each paragraph of a Word document against data in JSON format and writes the result to a within the index.html file that is rendered in the Task Pane. This works fine. I am now trying to format the strings within the Word document that correspond to the hits for the keys in the JSON data.
I have a JS block in the head of the index.html file in which I call "Office.initialize" and define a variable based on the JSON data, and have utility functions related to the above functionality. After that comes a function in which I get the Word context and process the Word file paragraphs against the JSON data, and then try to search the Word paragraph itself in order to format the hits. In this last task I am trying to reproduce a snippet from Michael Mainer 1. But no formatting happens when I activate this function. Unfortunately I don't have access to a console since I am on a Mac, which makes it harder to debug.
I would be very appreciative of someone showing me where I'm going wrong.
`function tester() {
Word.run(function (context) {
// Create a proxy object for the document's paragraphs
var paragraphs = context.document.body.paragraphs;
// Load the paragraphs' text, which I run regexes on
context.load(paragraphs, 'text');
return context.sync().then(function () {
for (var i = 0; i < paragraphs.items.length; i++) {
var text = paragraphs.items[i].text;
// jquery to iterate over the "notes" objects from the JSON
$.each(notes, function(key, value) {
var regex = new RegExp("\\b" + key + "\\b", "g");
var res = regex.test(text);
// if the regex hits...
if (res == true) {
// This part works fine, using the JSON data to append to the <DIV> with ID = "notes"
document.getElementById('notes').innerHTML += "<button onclick=hide('" + value.seqNo + "')><b>" + key + "</b></button><p class='" + value.seqNo + "' id='" + i + "'>" + value.notes[0].note + "</p>";
// I now go on to searching for these hits within the current paragraph in the Word file
var thisPara = paragraphs.items[i];
// Set up the search options.
var options = Word.SearchOptions.newObject(context);
options.matchCase = false
// Queue the commmand to search the current paragraph for occurrences of the string "key" (coming from the JSON data)
var searchResults = paragraphs.items[i].search(key, options);
// Load 'text' and 'font' for searchResults.
context.load(searchResults, 'text, font');
// Synchronize the document state by executing the queued-up commands, and return a promise to indicate task completion.
return context.sync().then(function () {
// Queue a command to change the font for each found item.
for (var j = 0; j < searchResults.items.length; j++) {
searchResults.items[j].font.color = '#FF0000'
searchResults.items[j].font.highlightColor = '#FFFF00';
searchResults.items[j].font.bold = true;
}
// Synchronize the document state by executing the queued-up commands,
// and return a promise to indicate task completion.
return context.sync();
});
}
});
}
});
})
.catch(function (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
`
It looks like you just need access to the font property, have you tried just:
context.load(searchResults, 'font');
That was working for me?

Generate and download file from Word dialog

Is there a way to generate a file with some JSON content and prompt the user with a saveAs dialog.
This is from an open dialog in word.
The object could be like (will be quite a lot bigger in practice)
var obj = {a: 1, b: 2, c: 'qwerty'}
I tried to uri encode and using window.open without any luck.
content = JSON.stringify(obj);
uriContent = "data:application/octet-stream," + encodeURIComponent(content);
newWindow = window.open(uriContent, 'filename');
I did this for XML, but it requires some back-end and front-end work. On the backend, you need some ASPX like this:
string filename = "export.xml";
byte[] data = Convert.FromBase64String(Request.QueryString[0].Replace("\"", ""));
string decodedString = System.Text.Encoding.UTF8.GetString(data);
// set the http content type to "APPLICATION/OCTET-STREAM
Response.ContentType = "APPLICATION/OCTET-STREAM";
System.String disHeader = "Attachment; Filename=\"" + filename + "\"";
Response.AppendHeader("Content-Disposition", disHeader);
Response.Flush();
Response.Write(decodedString);
I called mine "download.aspx." Then on the front-end, you have to use AJAX. This created a form region on the page and the forces a submit of the form to start the download:
// Helper function to load a form and then send the post results to a
// new window so that we can get the download button
function ajax_download(url, data, input_name) {
try {
$('#form-div').append("<form method='GET' action='" +
url + "' target='_blank'>" +
"<input type=hidden name='" + input_name + "' value='" +
JSON.stringify(data) + "'/></form>");
$('#form-div').find('form').submit();
} catch (err) {
showNotification("error", err.description);
}
}
To call it, you simply make this this call from your JavaScript code where you want it:
xml = "<xml><data>12345</data></xml>";
ajax_download('./Download.aspx', btoa(xml), 'xml');
In this case, mine is targeting XML and always creates a file called "export.xml", but you can adjust it as needed.

Google maps downloadUrl does not return 200

My code is based on the example of google code:
https://developers.google.com/maps/articles/phpsqlinfo_v3
and was working fine.
I need to change a former 'gid' (Integer) field to 'id' (String) to get saved to the database and used to display a new labeled symbol on the map.
The strange thing is, that the url, that is build in the code to call the addrow.php file is OK. When I capture this string with alert(url), and I manually use this string, the new data is added to the database.
In my script, the call seems to fail (responseCode == 200 && data.length <=1), since no data is written to the database and the alert from the 'else-clause' is displayed as short pop-up.
Here's the code I use in my project (to save data from a form):
//save new marker to Postgis-database and add new markerwithlabel on the fly
function saveData(){
var gender = escape(document.getElementById("gender").value);
var hoehe = InZahl(document.getElementById("hoehe").value);
var breite = InZahl(document.getElementById("breite").value);
var id = escape(document.getElementById("id").value);
var vital = document.getElementById("vital").value;
var typ = document.getElementById("typ").value;
var ein_mehr = document.getElementById("ein_mehr").value;
var st_durchm = document.getElementById("st_durchm").value;
var frucht = document.getElementById("frucht").value;
var anmerk = document.getElementById("anmerk").value;
var latlng = marker.getPosition();
var url = "./mapdata/addrow.php?gender=" + gender +
"&hoehe=" + hoehe + "&lat=" + latlng.lat() + "&lng=" + latlng.lng() +
"&breite=" + breite + "&id=" + id + "&typ=" + typ + "&ein_mehr=" +ein_mehr + "&st_durchm=" + st_durchm +
"&frucht=" + frucht +
"&vital=" + vital + "&anmerk=" + anmerk;
downloadUrl(url, function (data, responseCode) {
if (responseCode == 200 && data.length <=1) {
infowindow.close();
marker.setDraggable(false);
marker.setIcon('./images/mm_purple.png');
marker.labelContent = id;
marker.setMap(map);
downloadUrl("./mapdata/getxml_get_last.php", function (data1) {
var xml = parseXml(data1);
var ms = xml.documentElement.getElementsByTagName("m");
var gid = ms[0].getAttribute("gid");
var html_n = "<div id='InfoWindow'><p style='font-weight:bold;'>" + id + "</p> \n\<p>Höhe:" + hoehe + " Breite: "+ breite +
"<br />\n\Typ: "+typ+" Stämme: "+ein_mehr+" St-Durchm: "+ st_durchm + "<br />\n\Vitalität: "+vital+" Fruchtbehang: "+frucht+
"<p/>\n\<p style='text-align:right;'><a href='sm_juniperus.php?operation=ssearch&ResetFilter=0&SearchField=gid&FilterType=%3D&FilterText="+ gid +
"' target='_blank'> Daten editieren </a></p></div>";
infowindow.setContent(html_n);
bindInfoWindow(marker, map, infowindow, html_n);
(function(i, marker, gid) {
var origIcon = marker.getIcon();
new LongPress(marker, 1000);
google.maps.event.addListener(marker, 'longpress', function(e) {
marker.setDraggable(true);
marker.setIcon(mmcross);
});
google.maps.event.addListener(marker, 'dragend', function(){
updatePosition(marker, gid);
marker.setIcon(origIcon);
});
})(i,marker,gid);
//add new marker to markerCluster-Array and to markerArray
markerCluster.addMarker(marker,false);
markerArray.push(marker);
i++;
}); // End add new marker
}
else {
alert("Your data couldn't be saved!");
}
}); // End downloadUrl
}; // END saveData()
As I said, my code worked fine, but after 3 evenings passed to solve this, I thought it would be time to ask for help.
If anybody has an idea, where the mistake lies, I would apreciate any hint.
Just to confirm, you're aware that you by doing
if (responseCode == 200 && data.length <=1) {
you are saying 'if the request is successful and the data it returns is only one character or below in length'? I am unsure if this is intended or not, because this way the code inside the if statement is only ran if the response is successful but contains only 1 or 0 characters.

How to convert QScriptValue to QVariantList in Blackberry Qt C++

it is my code for conversion from QScriptValue to QVariantList .But i am getting error on the last line. please correct me if i am doing something wrong.
void ApplicationUI::onResult(QNetworkReply* reply)
{
if (reply->error() != QNetworkReply::NoError){
return; // ...only in a blog post
}
QString data = (QString) reply->readAll();
QScriptEngine engine;
QScriptValue result = engine.evaluate("(" + data + ")");
QScriptValue entries = result.property("result");
QVariantList *mainListd=entries.toVariant().toList();
}
I want to insert this mainListd in GroupDataModel.
QVariant::toList() returns a QList<QVariant>. You're trying to store it in a QVariantList*, which is in fact a QList<QVariant>*. You shouldn't be using a pointer here.