how to insert an image from base64 string - google-apps-script

The code below should insert an image blob made from the base64 string img_3k, but somehow it doesn't. What am I doing wrong?
var img_3k = "iVBORw0KGg..."
function searchAndReplace() {
var body = DocumentApp.getActiveDocument().getBody();
var blobImg = Utilities.newBlob(Utilities.base64Decode(img_3k), MimeType.PNG);
body.insertImage(0, blobImg);
}

Well, I have no problem with your code.
I guess your problem is that you use a global variable, but you can not use global variables in Google Apps Script.
function searchAndReplace() {
var img= getImage();
var body = DocumentApp.getActiveDocument().getBody();
var blobImg = Utilities.newBlob(Utilities.base64Decode(img), MimeType.PNG);
body.insertImage(0, blobImg);
}
function getImage() {
return "iVBORw0KGgoAAA...SUVORK5CYII=";
}

just remove the "var" before your global var declaration:
img_3k = "iVBORw0KGg...";
Variables declared with var in global scope won't be visible in functions.
You could capitalize the variable as well (IMG_3K) so you know immediately that it is a static global one

The code was actually correct, but didn't get executed because I didn't call it from the right place. Put in the onInstall method and then it worked.

Related

How to make a closed search in Google Docs?

I have a document where I need to find a text or word, each time i run a function the selection has to go to next if a word or text is found. If it is at the end it should take me to top in a circular way just like find option in notepad.
Is there a way to do it?
I know about findText(searchPattern, from) but I do not understand how to use it.
There are several wrappers and classes in the DocumentApp. They help to work with the contents of the file.
Class Range
Class RangeElement
Class RangeBuilder
It is necessary to understand carefully what they are responsible. In your case the code below should be work fine:
function myFunctionDoc() {
// sets the search pattern
var searchPattern = '29';
// works with current document
var document = DocumentApp.getActiveDocument();
// detects selection
var selection = document.getSelection();
if (!selection) {
if (!document.getCursor()) return;
selection = document.setSelection(document.newRange().addElement(document.getCursor().getElement()).build()).getSelection();
}
selection = selection.getRangeElements()[0];
// searches
var currentDocument = findNext(document, searchPattern, selection, function(rangeElement) {
// This is the callback body
var doc = this;
var rangeBuilder = doc.newRange();
if (rangeElement) {
rangeBuilder.addElement(rangeElement.getElement());
} else {
rangeBuilder.addElement(doc.getBody().asText(), 0, 0);
}
return doc.setSelection(rangeBuilder.build());
}.bind(document));
}
// the search engine is implemented on body.findText
function findNext(document, searchPattern, from, callback) {
var body = document.getBody();
var rangeElement = body.findText(searchPattern, from);
return callback(rangeElement);
}
It looks for the pattern. If body.findText returns undefined then it sets on top of the document.
I have a gist about the subject https://gist.github.com/oshliaer/d468759b3587cfb424348fa722765187

simplifying variable.handler = function {}

I'm brushing up on my JS, and I don't know how to ask this, exactly.
I have this:
text_area.onkeyup = function() {
var text_length = this.value.length;
var text_remaining = text_max - text_length;
feed_back.innerHTML = "<strong>" + text_remaining + "</strong> charactres remaining";
}
It works. However, should I be able to take the function and pull it out to something like this?
function countDown() {
var text_length = this.value.length;
var text_remaining = text_max - text_length;
feed_back.innerHTML = "<strong>" + text_remaining + "</strong> charactres remaining";
}
and just call the function by its name?
text_area.onkeyup = countDown();
This has never worked for me, across multiple projects.
Should it? Why doesn't it?
You'll have to use:
text_area.onkeyup = countDown;
Without the parenthesis.
countDown is a reference to the actual function object countDown. It's simply a reference, and the function won't be called or executed.
countDown() actually calls the function, and evaluates to whatever it returns.
It doesn't work because () actually calls the function -- effectively setting text_area.onkeyup to the return value of countDown rather than the function itself.
Try this instead:
text_area.onkeyup = countDown;
The problem is that you're executing the function during the assignment, so the return value from the function becomes attached to the event. Instead you should attach a reference:
text_area.onkeyup = countDown
Or if countdown has parameters you want to pass with it then you can use a function to make sure they don't get lost. Something like this:
text_area.onkeyup = function(){ countDown(paremeter1, paremeter2); }
It shouldn't because you're assigning the result of a function call instead of a function reference. Should be:
text_area.onkeyup = countDown;

Passing state/data to Google Apps Script ServerHandler

I am trying to work out how I can pass some arbitrary state to a ServerHandler in Google Apps Script. The following code illustrates the question - can anybody help?
Thanks.
function myFunc(e) {
// want to get my data object back out here..?
}
function setUp()
{
var data = getMyDataArray();
// ... set up UI...
var h = app.createServerHandler('myFunc');
// How do I passs my data object to the myFunc handler?
flow.add(app.createButton().setText("OK").addClickHandler(h));
app.add(flow);
s.show(app);
}
You can use Hidden elements to store arbitrary data and send it along with a server handler invocation. The issue is that the the element can only store a string. But you can solve this using JSON.
function myFunc(e) {
var yourObj = Utilities.jsonParse(e.parameter.yourObject);
//do what you need
}
function setUp()
{
var data = getMyDataArray();
// ... set up UI...
var hidden = app.createHidden("yourObject", Utilities.jsonStringify(data));
var h = app.createServerHandler('myFunc').addCallbackElement(hidden);
flow.add(app.createButton().setText("OK").addClickHandler(h));
app.add(flow);
s.show(app);
}

Google Apps Script, HTML addClickHandler ServerHandler does NOT work

Can anyone confirm that HTML widgets accept ClickHandlers on the Server side ? I can't get my below code to work.
I create a serverHandler (and for good measure I have even added a useless callback element). Subsequently, I add it to a HTML.addClickHander (for good measure I have even added it to .addMouseUpHandler as well). The function is NOT executed.
var mouseclick = app.createServerHandler("handleTrainingClick_").addCallbackElement(lstFilter);
var params = [ "fromOrg", "trainingTitle", "dueDate", "medical", "status" ];
var resultSet = blSelectActiveTrainings_();
while (resultSet.hasNext()) {
var training = resultSet.next();
var html = TRAINING_ROW;
for (var pI in params) {
html = html.replace("$"+params[pI], training[params[pI]]);
}
pnlList.add(app.createHTML(html).setId(training.id).addClickHandler(mouseclick).addMouseUpHandler(mouseclick)
.addMouseMoveHandler(mousemove).addMouseOutHandler(mouseout).addMouseOverHandler(mouseover));
}
function handleTrainingClick_(e) {
Logger.log(e.source);
var app = UiApp.getActiveApplication();
return app;
}
HTML widgets server side handlers work just fine. It was an incorrect reference in my code. Thanks all.

Is there a work around for an object oriented front-end in Google Script

I'm having some problems with an event handler in the object below. I can't remember the error message but it basically said that it could not find the function. The code below is an example of what I'm trying to do.
var anObject = function () {
var n = 0;
var HandleClick(e) {
n ++;
};
return {
Init: function () {
var app = UiApp.getActiveApplication();
var handler = app.createServerHandler("HandleClick");
var com = UiApp.LoadComponent("MyGui", {prefix: "a"});
com.getElementById("button").addClickHandler(handler);
}
}
}
Would really appreciate a work-around if possible, if that is not possible then please tell me what you would suggest because I'm not sure how best to get around this.
Thanks guys.
All handler functions must be top level functions on your script. It's not possible to have it inside an object like this.