Google Apps Scripts - Copy Inline Drawing from One Document to Another - google-apps-script

I am trying to copy an entire document from one to another.
I am simply trying to copy an INLINE_DRAWING from one google doc to another but I keep getting this error. If I remove the attempt to append the drawing then there is no errors, but then in my finished document there are no drawings. How do you properly copy inline drawings from one doc to another?
// fromFile & toFile are objects after calling .getBody()
function copyFileContentsFromTo(fromFile,toFile){
for(var i=0; i<fromFile.getNumChildren();i++){ //run through the elements of the template doc's Body.
var child = fromFile.getChild(i);
switch (fromFile.getChild(i).getType()) { //Deal with the various types of Elements we will encounter and append.
case DocumentApp.ElementType.PARAGRAPH:
// Look for child elements within the paragraph. Inline Drawings are children.
if(child.asParagraph().getNumChildren() !=0 && child.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_DRAWING) {
console.log("Found an Inline Drawing");
var drawing = child.asParagraph();
toFile.append(drawing.copy()); // This causes the error!
}else{
toFile.appendParagraph(child.copy());
}
break;
case DocumentApp.ElementType.TABLE:
toFile.appendTable(child.copy());
break;
default:
console.log("Whoops. Did not handle this Element Type when Copy Data from Template to Main: " + fromFile.getChild(i).getType());
break;
}
}
}
I have already search all over and cant find any resources, this is the closest but still yields the error in my screenshot: Google script InlineDrawing class

In your script, it is required to modify as follows.
From:
toFile.append(drawing.copy());
To:
toFile.appendParagraph(drawing.copy());
IMPORTANT:
In the current stage, when the paragraph including the inline drawings is copied, please disable V8 runtime. When the above-modified script is used with V8 runtime, an error like Exception: Action not allowed occurs. So please be careful about this. This has already been reported at Google issue tracker. Ref I would ilke to believe this bug can be removed in the future update.
Reference:
appendParagraph(paragraph)

Related

Adding formatted text to a Google Doc

I have a Google Sheet with form responses. I created some code so that each time a form is completed, the results populate a Google Doc. This works fine.
However, I want to add text to my Google Doc as well, which I accomplish using:
function myFunction(e) {
var doc = DocumentApp.create('File');
var text = 'insert text here';
body.appendParagraph(text);
doc.saveAndClose();
}
This text only is added as plain text, however, and I'd like to format this text. Specifically, I'd like to add the text so that it's bolded, underlined, and center-aligned in the document body.
How do I do this?
After some internet searching and SO searching, I tried adding html (e.g., <b> </b>) and I tried text.setBold(true). These approaches did not work.
I'll admit that I know very little about coding in Google Script editor, so I'm not at all sure how to go about this. I'm lucky enough that I got all my form responses to populate a named Google Doc file!
Here's a fragment of a document that I created recently:
var nameStyle={};
nameStyle[DocumentApp.Attribute.FONT_SIZE]=8;
nameStyle[DocumentApp.Attribute.BOLD]=true;
nameStyle[DocumentApp.Attribute.FOREGROUND_COLOR]='#000000';
var valStyle={};
valStyle[DocumentApp.Attribute.FONT_SIZE]=12;
valStyle[DocumentApp.Attribute.BOLD]=false;
valStyle[DocumentApp.Attribute.FOREGROUND_COLOR]='#cc0000';
body.appendParagraph('Basic Project Data').setAttributes(hdg1Style);
var p1=body.appendParagraph(Utilities.formatString('%s: ','PID')).setAttributes(nameStyle);
var p2=body.appendParagraph(Utilities.formatString('%s',selObj.pid)).setAttributes(valStyle);
p2.merge();
for(var i=0;i<basicDataA.length;i++){
var par1=body.appendParagraph(Utilities.formatString('%s: ',basicDataA[i][0])).setAttributes(nameStyle);
var par2=body.appendParagraph(Utilities.formatString('%s',basicDataA[i][1])).setAttributes(valStyle);
par2.merge();
}
Note, the appendParagraph first and then setAttributes.
The above response got me on the right path (Thanks!). Google hasn't documented this feature very well, and some of the features that should work do not. I had found the info on formatting using offsets but that is incredibly tedious and verbose. Here's the full example method that works to insert pre-formatted text into a Google Doc. Hope it helps someone else. Obviously the 2D array can instead be wired up to be fetched from a form, but this will at least show how the rest of the formatting works.
// Open a document by ID.
var body = DocumentApp.openById('YourDocId').getBody();
var authorAffils = [['Tony Tiger',1],['Micky Mouse',2],['Daffy Duck',3],['Elmo Orange',4]];
var nameStyle={};
nameStyle[DocumentApp.Attribute.FONT_SIZE]=11;
// nameStyle[DocumentApp.TextAlignment.Normal]; // This seems to do nothing
nameStyle[DocumentApp.Attribute.FOREGROUND_COLOR]='#000000';
var affilStyle={};
affilStyle[DocumentApp.Attribute.FONT_SIZE]=11;
// affilStyle[DocumentApp.TextAlignment.SUPERSCRIPT]; // This seems to do nothing
affilStyle[DocumentApp.Attribute.FOREGROUND_COLOR]='#cc0000';
for(var i=0;i<authorAffils.length;i++){
var par1=body.appendParagraph(Utilities.formatString(' %s,',authorAffils[i][0])).setAttributes(nameStyle);
var par2=body.appendParagraph(Utilities.formatString('%s',authorAffils[i][1])).setAttributes(affilStyle);
// I am not entirely clear why alignment only works this way whereas font size and color work the other way.
par1.setTextAlignment(DocumentApp.TextAlignment.NORMAL).merge();
par2.setTextAlignment(DocumentApp.TextAlignment.SUPERSCRIPT).merge();
}

TinyMCE - automatically insert additional attributes when copying/pasting content?

Is there a way to configure TinyMCE to automatically insert additional attribues when copying and pasting content into a textarea?
In my case, I have a textarea that I copy/paste content with text and images. When images are inserted, I would like to automatically mark the img tags as having a specific CSS class (for ensuring they are fluid).
I'm using Django TinyMCE is that makes any difference. Has anyone succeeded in achieving this sort of behavior?
The TinyMCE Paste plugin has the ability for you to pre or post process the content during the paste process.
I would recommend using the postprocess API as this allows the Paste plugin to do its cleanup first.
https://www.tinymce.com/docs/plugins/paste/#paste_postprocess
For example you could do something like this in your TinyMCE init (not that this is what you want to do I just had this example handy from a project):
paste_postprocess: function(editor, fragment) {
var allElements = fragment.node.getElementsByTagName("td");
for (i = 0; i < allElements.length; ++i) {
console.log('initial font family: ', allElements[i].style.fontFamily);
var st = allElements[i].style;
stCleaned = st.fontFamily.replace("sans-serif", "").replace("Calibri", "Arial");
st.fontFamily = stCleaned; // Indirectly
}
}
...then each time the Paste plugin gets run your code will get run after it and you can manipulate the pasted content as you see fit.

Google script InlineDrawing class

I'm trying to insert InlineDrawing into table cell.
According to documentation you can add InlineDrawing to Paragraph.
so
tr = table.appendTableRow();
var tc1 = tr.appendTableCell();
var tc1.appendParagraph( how to fit new InlineDrawing here? );
How to get new instance of inlineDrawing ? How to work with this object ?
I can't find any online reference about this.
Thank you for your help.
Here you go: (credit: https://gist.github.com/bennettscience/cd51762de17c860d6930)
// Don't forget your global variables up top.
// Search through the page elements. Paragraphs are top-level, which is why I start with those.
if( type == DocumentApp.ElementType.PARAGRAPH ){
// Look for child elements within the paragraph. Inline Drawings are children.
if(element.asParagraph().getNumChildren() !=0 && element.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_DRAWING) {
// For whatever reason, drawings don't have their own methods in the InlineDrawing class. This bit copies and adds it to the bottom of the doc.
var drawing = element.asParagraph().copy();
body.appendParagraph(drawing);
}
}
Yes, I've also noticed Google's documentation is lacking in many areas. You have to use the copy() method to get a copy of it. See an example code snippet here: How do I export InlineDrawing as an image in Document?. In that, he uses child.getParent().copy() to get the paragraph with the InlineDrawing. There's only one other reference I found (http://googlestyle.client.jp/document_services/class_inlinedrawing.html). See the removeFromParent section, where he uses getImages to get a list of handles to images in the document.

Multiple JS Lines in Chrome.Tabs.ExecuteScript()

I have a Chrome Extension that performs some actions based on the button toggle (state 0/1).
The problem is that right now, it changes the color Red/Blue, but there are some other actions that need to happen. I can't find a way to refer to a separate multi-line script or file in Chrome.Tabs.ExecuteScript. Every example I've found on the Web only has a single command, which is useless for me! Splitting across lines doesn't work. There will be FOR-loops, IF-statements, and other complexity I want to inject.
Actions needed:
(State=0) Red background, make all IMG tag invisible, etc.
(State=1) Blue background, make all IMG tags visible, etc.
background.js
var state = 0;
function activate()
{
if (state == 0)
{
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="red"'
});
state = 1;
}
else
{
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="blue"'
});
state = 0;
}
}
chrome.browserAction.onClicked.addListener(activate);
Make a separate file with your commands, and execute it with
chrome.tabs.executeScript({
file: 'content1.js'
});
If you need to pass parameters along, see this question.
Alternative solution is to have a single content script and pass commands to it using Messaging.
If your approach registers listeners, make sure to execute addListener only once.

Changing text attributes (font, size, etc) at the cursor level in a google doc using Google apps script

I would like know if and how it is possible to change text attributes such as font, size, etc. in Google Apps script at the cursor's level. The script is bound to a Google doc file. For example, after running the script, the text font will change for anything written after that point while leaving the text written before unchanged. This is to mimic the way built-in styles or font menus behave in Google docs.
Here is what I came up with so far. It seems to change the text font globally in the document instead of applying the changes only to the text written after running the code. Any suggestions?
var cursor = DocumentApp.getActiveDocument().getCursor();
if(cursor){
var element4 = cursor.getElement()
var body = DocumentApp.getActiveDocument().getBody()
if (element4.editAsText) {
body.editAsText().setFontFamily(DocumentApp.FontFamily.CALIBRI);
}
}
The code below changes the FontFamily for the paragraph in which you select a text... it keeps the same style for all what is coming after and preserves everything before.
If you want to go deeper in precision you'll have to play with offsets and work at text level inside the paragraph but I thought this version could be sufficient.
function setStyle() {
var selection = DocumentApp.getActiveDocument().getSelection();
if (!selection) {
DocumentApp.getUi().alert('Cannot find a selection in the document.');
return;
}
var selectedElements = selection.getSelectedElements();
var element = selectedElements[0].getElement().getParent();
element.setFontFamily(DocumentApp.FontFamily.CONSOLAS);
}
The DocumentApp.FontFamily enumeration is now deprecated. You should use string names, like "Consolas" (case sensitive!), instead.
You can visit the setAttributes section of the DocumentApp Reference found here