insertListItem(index, text) Wrong Index - google-apps-script

I am trying to use Google Apps Script to replace text into a Docs template and save it as a .pdf. I am mostly successful, but I am having one problem. I'd like for the script to search for a text in the template, replace the text with provided text, using bullets. It will ignore any extra \n that may have been placed into the text. Here is an example text:
Today was a good day.
Tomorrow will be a good day.
Yesterday was a decent day.
In my document, I would like the text to replace _text_ in a line: Comments: _text_. Ultimately, what should print out is the following:
Comments:
- Today was a good day.
- Tomorrow will be a good day.
- Yesteday was a decent day.
This is the code that I have so far, but it is not working too well. If anyone could offer any help, it would be greatly appreciated.
var listr = "";
var trunc = text.split("\n"); \\ where text is to be placed into the template
var index = b.findText("_text_").getStartOffset(); \\ var b is getBody()
for (var j = (trunc.length - 1); j >= 0; j--)
if(!trunc[j].equals("")) b.insertListItem(index, trunc[j]);
b.replaceText("_text_", "");
Any help would be much appreciated. I am having the hardest time understanding the concept of the indexes in Google Docs. Thank you.
Hello. Just wanted to let you know how I have ended up implementing this:
var trunc = text.split("\n"); \\where text is to be placed into the template
var index = b.getChildIndex(b.findText("foo").getElement().getParent()) + 1;
for (var j = (trunc.length - 1); j >= 0; j--)
if (trunc[j] != "") b.insertListItem(index, trunc[j]);
Hope that helps. It pushes the elements back on to each other backwards.

Ok well this crude code seems to insert at the beginning of the PARAGRAPH containing the TEXT, which appears to be a separate child element. Probably this particular code will only work if the text is not inside a sub-table, sub-list, etc... but maybe it will help.
var element = DocumentApp.create('newDoc').getBody()
.appendListItem('testing').copy();
var index = b.getChildIndex(
b.findText('_text_').getElement().getParent().asParagraph() );
b.insertListItem(index, element);
I've had a long day maybe I can improve it later, mostly what I think was missing was the getChildIndex() function. Also using the newDoc the insertListItem() had some weird "Element must be detached." message until I used .copy() so mental note there.

Related

Microsoft edge multi element copy

Does anyone know a fast way to copy multiple elements from an inspect page?
What I mean by that is I have a number of elements with same qualities i.e. same class and I want to copy all of them to my clipboard. Is there a way within inspect tool to do such a "trick" ? :)
Thank you in advance!
There's no specific simple way to do this, you can only using code to extract the elements you want.
For example if you want to get elements with the same class name, you can use the following code:
var outputText = "";
var targets = document.getElementsByClassName('classname');
for( var i = 0; i < targets.length; i++ ) {
outputText += targets[i].outerHTML;
}
console.log(outputText);
Then you can copy the output in the console.

How can I put every sentence of a text in a row of a table next to its translation in a Google Document?

I want to put a text to be translated in a Google Doc so that every sentence is in its own row of a table. In each row of the next column is the corresponding, machine-translated sentence. Finally, there is a third blank column where I will write my own translation for each sentence.
Like so
What would some command line code look like for accessing the specific Google Doc, inserting a table, splitting the text on each sentence, and then writing each sentence to a row of the table?
I am aware of Google API, but I have struggled with authentication problems so far. If someone can sketch out a general outline of what my script should look like, hopefully I can fill in the details.
I am trying my best to meet Stack Overflow's post guidelines, so if the question is not a good one, I'm happy to reformulate it. My question is multi-part, so I prefer to ask the broader version first, before breaking it into smaller aspects.
Try this:
function translate() {
var doc = DocumentApp.openById('documentID');
var body = doc.getBody();
var str = "An elephant is the biggest living animal on land. It is quite huge in size. It is usually black or grey in colour. Elephants have four legs, a long trunk and two white tusks near their trunk. Apart from this, they have two big ears and a short tail. Elephants are vegetarian. They eat all kinds of plants especially bananas. They are quite social, intelligent and useful animals. They are used to carry logs of wood from one place to another. They are good swimmers.";
//Split paragraph into sentences.
var result = str.match( /[^\.!\?]+[\.!\?]+/g ).map(str => str.trim());;
var translated = [];
result.forEach(res => {
translated.push(LanguageApp.translate(res, 'en', 'es'));
})
var table = body.appendTable();
for(var i = 0; i <= result.length; i++){
var tr = table.appendTableRow();
if(i == 0){
tr.appendTableCell("Origin");
tr.appendTableCell("Translated");
tr.appendTableCell("");
}else{
tr.appendTableCell(result[i-1]);
tr.appendTableCell(translated[i-1]);
tr.appendTableCell("");
}
}
}
Output:
References:
translate(text, sourceLanguage, targetLanguage)
appendTableRow()
appendTableCell()

Pasting Bold text into a doc after being taken form Spreadsheet

So I've been working through a problem of pulling structured data from a spreadsheet and them using App Script to insert it into a Template Google Doc.
I have it working simply as concatenated strings, but I'm trying to do it with the BODY class so if I want to put the end product into Gmail it could be easier. Or if I want to retain table structure....
So, everything is fine and dandy, except for this one bit of code. I'm struggling with setBold. It's a weird syntax in that it's a boolean operation, right?
So here is what I have and it's pretty easy to grok I think:
for(var i = 0; i < num; i++) {
var songName = String(dataArray[i][1]);
var sWs = String(dataArray[i][2]);
var pub = String(dataArray[i][3]);
newText.editAsText().appendText('SONG NAME:'+ nLi).setBold(true);
newText.editAsText().appendText(songName + brk).setBold(false);
newText.editAsText().appendText('SONGWRITER(S):' + nLi);
But it's coming out as:
SONG NAME:
I have also tried this code:
newText.editAsText().setBold(true);
newText.editAsText().appendText('SONG NAME:'+ nLi);
newText.editAsText().setBold(true);
newText.editAsText().appendText(songName + brk);
newText.editAsText().appendText('SONGWRITER(S):' + nLi);
Thinking of the setBold as setting then unsetting a flag.
Neither worked.
I prefer using styles:
function addboldtext() {
const doc=DocumentApp.getActiveDocument();
const body=doc.getBody();
const style1={};
style1[DocumentApp.Attribute.BOLD]=true;
style1[DocumentApp.Attribute.FOREGROUND_COLOR]='#000000';//you can add all of the attributes that you wish
body.appendParagraph("This is text").setAttributes(style1)
}

Can you help me make more OOP abstraction with this code?

This code is not java code, and I'm not getting any answer from ActionScript developers. So I tagged it with java, but Action Script is similar to java and this an OOP question.
I'm using Grid Data and I want to accomplish this following task:
Method 1: I want to multiply each row Row1num1 * Row1num2 and so on,
var Row1num1:String;
var Row2num2:String;
var Row2num1:String;
var Row2num2:String;
var Row3num1:String;
var Row3num2:String;
var event1:Object={num1:Row1num1,num2:Row1num2};
var event2:Object={num1:Row2num1,num2:Row2num2};
var event3:Object={num1:Row3num1,num2:Row3num2};
then add them to a dataGrid
dataGrid.columns =["num1","num2"];
dataGrid.addItem(event1);
dataGrid.addItem(event2);
dataGrid.addItem(event3);
but by using this method, if I have 20 rows, I will have a lot of variables, obviously it's bad.
method 2: In this method creating Grid Data rows at runtime and multiply them.
//button to add rowGrid
dd.addEventListener(MouseEvent.CLICK,ddd);
var numm:String="34";
function ddd(evt:MouseEvent):void
{
var event4:Object={num1:Rownum1,num2:Rownum2};
dataGrid.addItem(event4);
}
but when I use this method, I have a hard time accessing each row data and multiply them.
This example because I'm creating GPA calculator and I want to take each row credit Hours and multiply them with the scale value at the same row, first method is bad because there's not abstraction .
The second method what I'm hoping to work ,because I want user to add row depend on their number of courses.
I hope my English is not bad.
I hope my question don't get vote down, and by reading this question can you determine what I'm missing so I can learn it .
And is there any tutorial I can use to solve my problem?
I'm just addressing your first method for now, but it almost seems at though you want an array of some sort.
Here's a link on how to use Actionscript arrays.
If you need more dimensions, you can make an array of arrays. This will help you cut down on the number of variables.
I hope I correctly understood your question. I'll give it a go either way...
So, one of the best things about actionscript in comparison to most other strongly-typed Object-Oriented languages is how easy reflection is (probably thanks to its javascript origins).
That being said, what you can do is simply create an array using a "for" loop. What I am assuming is that the variables row1Num1 row2Num2 and so on already exist in your class. Otherwise, obviously it would be much more efficient to store them in an array and simply read from it into a new array. Anyhow, the code should look something like this:
method 1:
var eventsArr:Array = [];
for(var i:int = 1; this["row" + i + "Num1"] != undefined /*or i<=length*/; i++){
eventsArr.push({num1:this["row" + i + "Num1"], num2:this["row" + i + "Num2"]});
}
for(var j:int = 0; j < eventsArr.length; j++){
dataGrid.addItem(eventsArr[j]);
}
method 2:
dd.addEventListener(MouseEvent.CLICK,ddd);
var numm:String="34"; //I am assuming this refers to the row number you wanted to add.
function ddd(evt:MouseEvent):void
{
var event4:Object={num1:this["row" + numm + "Num1"],num2:this["row" + numm + "Num2"]};
eventsArr.push(event4);
dataGrid.addItem(event4);
}
Hope that helps.

JSFL: convert text from a textfield to a HTML-format string

I've got a deceptively simple question: how can I get the text from a text field AND include the formatting? Going through the usual docs I found out it is possible to get the text only. It is also possible to get the text formatting, but this only works if the entire text field uses only one kind of formatting. I need the precise formatting so that I convert it to a string with html-tags.
Personally I need this so I can pass it to a custom-made text field component that uses HTML for formatting. But it could also be used to simply export the contents of any text field to any other format. This could be of interest to others out there, too.
Looking for a solution elsewhere I found this:
http://labs.thesedays.com/blog/2010/03/18/jsfl-rich-text/
Which seems to do the reverse of what I need, convert HTML to Flash Text. My own attempts to reverse this have not been successful thus far. Maybe someone else sees an easy way to reverse this that I’m missing? There might also be other solutions. One might be to get the EXACT data of the text field, which should include formatting tags of some kind(XML, when looking into the contents of the stored FLA file). Then remove/convert those tags. But I have no idea how to do this, if at all possible. Another option is to cycle through every character using start- and endIndex, and storing each formatting kind in an array. Then I could apply the formatting to each character. But this will result in excess tags. Especially for hyperlinks! So can anybody help me with this?
A bit late to the party but the following function takes a JSFL static text element as input and returns a HTML string (using the Flash-friendly <font> tag) based on the styles found it its TextRuns array. It's doing a bit of basic regex to clear up some tags and double spaces etc. and convert /r and /n to <br/> tags. It's probably not perfect but hopefully you can see what's going on easy enough to change or fix it.
function tfToHTML(p_tf)
{
var textRuns = p_tf.textRuns;
var html = "";
for ( var i=0; i<textRuns.length; i++ )
{
var textRun = textRuns[i];
var chars = textRun.characters;
chars = chars.replace(/\n/g,"<br/>");
chars = chars.replace(/\r/g,"<br/>");
chars = chars.replace(/ /g," ");
chars = chars.replace(/. <br\/>/g,".<br/>");
var attrs = textRun.textAttrs;
var font = attrs.face;
var size = attrs.size;
var bold = attrs.bold;
var italic = attrs.italic;
var colour = attrs.fillColor;
if ( bold )
{
chars = "<b>"+chars+"</b>";
}
if ( italic )
{
chars = "<i>"+chars+"</i>";
}
chars = "<font size=\""+size+"\" face=\""+font+"\" color=\""+colour+"\">"+chars+"</font>";
html += chars;
}
return html;
}