Google script InlineDrawing class - google-apps-script

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.

Related

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

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)

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();
}

JList does not clear

I have an issue with removing old elements from my lists. I tried using the methods clear() and removeAllElements() and removeAll() wherever I could but that does not seem to clear them.
To help you understand the situation a little bit better:
d1 is an ArrayList that contains all available devices in our program.
availList2 and availList3 are using the DefaultListModel.
We wanted to make it so that when the user loads the products from the proper text file, if he did that a second time the products already listed in our gui would be overwritten with the ones in the original text file. However we ended up having duplicates of the products, even though we used the clear() method in both the d1 (ArrayList) and the JList.
Any useful tips or possible causes would be appreciated. Thank you very much in advance.
if(ev.getSource() == load_availables) {
int returnVal = chooser.showOpenDialog(mainApp.this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
d1.returnDevices().removeAll(d1.returnDevices());
availList2.clear();
availList3.clear();
//availList2.removeAllElements();
//availList3.removeAllElements();
File file = chooser.getSelectedFile();
read.ReadDevices(file);
for(int i = 0; i < read.Size(); i++) {
d1.add_AvailableDevices(read.get(i));
}
}
}
If the list is not cleared then I would suggest you don't have the proper reference to the DefaultListModel that is being used by the JList when you invoke the clear() method.
Start by the reading the section from the Swing tutorial on How to Use Lists.
Download the ListDemo code and play with it. Change the "Fire" button to use the clear() method on the DefaultListModel to prove to yourself that is all you need to do.
Once you see the code working then you figure out how your code is different from the ListDemo working version.

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

Click path to show/hide div

I'm trying to create a fairly straightforward interface with Raphael, whereby if you click on a given path you'll get a corresponding div to appear. Since I'm likely going to be using irregular shapes I'll be creating the shapes in Illustrator and then converting to paths using readysetraphael.com, but if there's a better way to do it I'm open to that too.
I'm basically looking to capture the functionality you see here, but with raphael objects as the buttons.
http://jsfiddle.net/4xV7b/
Here's my current fiddle -- what I don't understand is what needs to happen during the mouseclick event to show/hide the corresponding divs.
el.click(function() {
//mysterious voodoo magic goes here
});
If you were using Raphael 2, you could use the data method to store arbitrary information with your elements -- as in this example.
Essentially, when you're creating each path, you simply call
el.data( 'div_id', 'greenthing' );
Then, when that element is clicked, you can retrieve the indicated div from the element using
el.click( function()
{
var div_id = this.data( 'div_id' );
// Display the div here. Josemando's approach is perfectly cool and will work universally.
} );
If you wanted to make sure that only one div at a time is displayed, you could do this (primitive but effective):
el.click( function()
{
rsr.forEach( function( subEl )
{
var divId = subEl.data('div_id' );
if ( divId && document.getElementById( divId ) )
document.getElementById( divId ).style.display = 'none';
} );
} );
There are, of course, other ways to skin that cat.
You may also find that your path construction code would be more manageable if you put all of the shape-specific data into a structured object and then render each path in a loop. The fiddle I've provided above demonstrates such a technique, which will pay off quickly once you have more than a handful of shapes.
You can use pure javascript to show a div:
document.getElementById("redthing").style.display = "block";
If you want animations, you can try using jQuery, or even manually creating them with css