Number table rows in Google Doc using Apps Script - javascript

I'm working on a script which takes text and places each paragraph in a numbered table cell. I'm running into a problem where each line break is counted as a paragraph by the script, which means my table either has empty cells or is numbered incorrectly.
Here's the working script (minus row numbering):
function formatArticle() {
var doc = DocumentApp.getActiveDocument()
var body = doc.getBody();
// Get the paragraphs
var paras = body.getParagraphs();
// Add a table to fill in with copied content
var addTable = body.appendTable();
for (var i=0;i<paras.length;++i) {
// If the paragraph is text, add a table row and insert the content.
if(i % 2 == 0) {
var tr = addTable.appendTableRow();
var text = paras[i].getText();
// Number the table rows as they're added in a cell to the left.
for(var j=0;j<2;j++) {
if(j == 0) {
var td = tr.appendTableCell(i);
} else {
var td = tr.appendTableCell(text);
}
}
}
// Shrink left column.
addTable.setColumnWidth(0, 65);
// Delete the original text from the document.
paras[i].removeFromParent();
}
}
Here's a demo Google Doc so you can see how text formats without setting a new one up yourself if that helps.

Logic
What you should do is to iterate each paragraph and check if that paragraph contains text. If yes, then add a row and put the text in it, else skip that paragraph and jump to the next one.
Implementation
function formatArticle(){
var doc = DocumentApp.getActiveDocument()
var body = doc.getBody();
// Get the paragraphs
var paras = body.getParagraphs();
var addTable = body.appendTable();
//paragraph index
var pIndex = 0;
for(var i = 0 ; i < paras.length ; i++){
var para = paras[i];
var paraStr = para.editAsText().getText();
// if there is string content in paragraph
if(paraStr.length){
var tr = addTable.appendTableRow();
var td1 = tr.appendTableCell(pIndex);
var td2 = tr.appendTableCell(paraStr);
pIndex ++;
}
para.removeFromParent();
}
// Shrink left column.
addTable.setColumnWidth(0, 65);
}
Here You get the string from paragraph var paraStr = para.editAsText().getText(); and check if the content exists if(paraStr.length) If yes then create a row, insert paragraph index and paragraph's text in it.

Try this: tr.appendTableCell(i/2 +1)
// Number the table rows as they're added in a cell to the left.
for(var j=0;j<2;j++) {
if(j == 0) {
var td = tr.appendTableCell(i/2 +1);
} else {
var td = tr.appendTableCell(text);
}
}
}

Related

JS Adding/Removing image from cell (toggle button)

I am looking for a way to add and remove an image in a cell.
I have the button assigned to this function but I can't seem to add it to the dynamic range. If I hardcode the column and row for testing it adds the image fine but then I can't figure out how to delete it.
function test() {
var sheet = SpreadsheetApp.getActiveSheet();
var selection = sheet.getSelection();
var ranges = selection.getActiveRangeList().getRanges();
for (var i in ranges) {
var data = ranges[i].getValues();
for (var row in data) for (var col in data[row]) {
var cell = data[row][col];
if (cell == '') continue; // if empty --> go to next cell
IF CELL CONTAINS IMAGE REMOVE IT
continue; // --> go to next cell
} else {
sheet.insertImage("URL", [col], [row], 125, 2); //Add image at col/row
}
}
ranges[i].setValues(data);
}
}
Before button click
After button click
Select new cells
After button click
I believe your goal is as follows.
When the script is run after the cells are selected, you want to put the image on the cell.
When the image is not put on the cell, you want to put the image on the cell.
When the image has already been put on the cell, you want to remove the image.
When the cell value is empty, you don't want to do anything.
In this case, how about the following modified script?
Modified script:
function test() {
const url = "###"; // Please set your URL.
const sheet = SpreadsheetApp.getActiveSheet();
const ranges = sheet.getActiveRangeList().getRanges();
let images = sheet.getImages();
ranges.forEach(r => {
const row = r.getRow();
const col = r.getColumn();
const numRows = r.getNumRows();
const numCols = r.getNumColumns();
for (let i = 0; i < numRows; i++) {
for (let j = 0; j < numCols; j++) {
if (sheet.getRange(row + i, col + j).isBlank()) continue;
const image = images.filter(e => {
const anchor = e.getAnchorCell();
return anchor.getRow() == row + i && anchor.getColumn() == col + j;
});
if (image.length > 0) {
image.forEach(e => e.remove());
images = sheet.getImages();
} else {
sheet.insertImage(url, col + j, row + i, 125, 2);
}
}
}
});
}
At first, please set your URL.
When you use this script, please select the cells and run the script.
When you run this script for the selected cells, the images are put on the cells which have no images, and the images are removed from the cells which have the images.
In this case, the image on the cells can be checked using the method of getAnchorCell() of Class OverGridImage.
References:
getImages() of Class Sheet
getAnchorCell() of Class OverGridImage

Generate Table with only one Column

Hello i try to generate a table with only one column. So my Links get displayed in only one column.
Here is my function:
function createTableForPdfFiles() {
//To Create The Table
var table = document.createElement("table");
table.setAttribute('id', 'pdfTable');
table.setAttribute('class', 'AANTable');
// insert Title Row
var TitleRow = table.insertRow();
var cell = TitleRow.insertCell();
cell.setAttribute('class', 'AANTitleRow');
cell.setAttribute('colSpan', pdfFiles.length + 1);
cell.appendChild(document.createTextNode("Datenblätter"));
//Insert Table Rows
var pdfRow = table.insertRow();
var cell = pdfRow.insertCell(); //Where the PDF´s are displayed
cell.setAttribute('class', 'AANPdfRow');
for (var i = 0; i < pdfFiles.length; i++) {
var cell = pdfRow.insertCell();
var link = document.createElement("a");
link.setAttribute("href", "www.test.at" + pdfFiles[i].Link);
var linktext = document.createTextNode(pdfFiles[i].Link);
link.appendChild(linktext);
cell.appendChild(link);
cell.setAttribute('class', 'AANPdfCell');
}
$("#divTable").append(table);
}
Right now it looks like:
But i want it to look like:
So how i can i make that possibe? I tried to add another Row to the table but the debugger says not supported...... Any help would be really great.
thanks for your Time.
You have to create anew row foer each pdf.
Hae to put this
var pdfRow = table.insertRow();
var cell = pdfRow.insertCell(); //Where the PDF´s are displayed
cell.setAttribute('class', 'AANPdfRow');
Inside the for
take a look at this -> fiddle

Create a bookmarklet that can retrieve all max length of text box and then print the id and max length in a table

I want to create a bookmarklet by using javascript, which can retrieve max length of all text box in the page, and then print a table below the page with all id and max length indicated.
Here is my code, however it did not print anything.
javascript: (function() {
var body =document.getElementsByTagName('body')[0];
var tbl = document.createElement('table');
var tbdy = document.createElement('tbody');
var D = document,
i, f, j, e;
for (i = 0; f = D.forms[i]; ++i)
for (j = 0; e = f[j]; ++j)
if (e.type == "text") S(e);
function S(e) {
var l= document.getElementById(e.id);
var x = document.getElementById(e.maxlength);
var tr=document.createElement('tr');
var td1=document.createElement('td');
var td2=document.createElement('td');
td1.appendChild(document.createTextNode(l));
td2.appendChild(document.createTextNode(x));
tr.appendChild(td1);
tr.appendChild(td2);
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
body.appendChild(tbl);
})
This can actually be done much simpler than you have it.
Working jsfiddle: https://jsfiddle.net/cecu3daf/
You want to grab all of the inputs and run a loop over them. From this you can dynamically create a table and append it to the end of the document.body
var inputs = document.getElementsByTagName("input"); //get all inputs
var appTable = document.createElement("table"); //create a table
var header = appTable.createTHead(); //create the thead for appending rows
for (var i=0; i<inputs.length; i++) { //run a loop over the input elements
var row = header.insertRow(0); //insert a row to the table
var cell = row.insertCell(0); //insert a cell into the row
cell.innerHTML = inputs[i].maxLength; //input data into the cell
var cell = row.insertCell(0);
cell.innerHTML = inputs[i].id;
}
document.body.appendChild(appTable); //append the table to the document
To make it a bookmark, simply place the javascript: before hand. There is no need to encase it in a function. You can if you'd like to.

JavaScript : Delete dynamically created table

I am new to web development and struggling with deleting a dynamically created table.
Below is the JavaScript function to create the table when user clicks a button.
function DrawTable(data){
var oTHead = myTable.createTHead();
var oTFoot = myTable.createTFoot();
var oCaption = myTable.createCaption();
var oRow, oCell;
var i, j;
var heading = new Array();
heading[0] = "AAA";
heading[1] = "BBB";
heading[2] = "CCC";
heading[3] = "DDD";
var tableData = data.split(':');
// Insert a row into the header.
oRow = oTHead.insertRow(-1);
oTHead.setAttribute("bgColor","lightskyblue");
// Insert cells into the header row.
for (i=0; i < heading.length; i++)
{
oCell = oRow.insertCell(-1);
oCell.align = "center";
oCell.style.fontWeight = "bold";
oCell.innerHTML = heading[i];
}
// Insert rows and cells into bodies.
for (i=0; i < tableData.length; i++)
{
var oBody = oTBody0;
oRow = oBody.insertRow(-1);
var splitData = tableData[i].split(',');
for (j=0; j < splitData.length; j++)
{
oCell = oRow.insertCell(-1);
oCell.innerHTML = splitData[j];
}
}
}
The above code works perfectly and draws the table when user clicks on the button.
If user clicks on the button again it will draw the table again.
i.e., it will draw another header and all the rows all over again.
At this point I want to delete the existing header and rows and draw it all new.
I tried many things to delete the existing table, but nothing works.
Is there a way I can make sure that the table is not duplicated again?
UPDATE
The HTML part is:
<table id="myTable">
<tbody ID="oTBody0"></tbody>
</table>
ANOTHER UPDATE
I tried below and it worked.
oTHead.innerHTML = "";
oTBody0.innerHTML = "";
jQuery offers a .empty() function that you can use
$("#myTable").empty();
Or with javascript you can just set the innerHTML to empty
document.getElementById("myTable").innerHTML = "";
Just execute this function before you start trying to add new content to the table.
//$("#myTable").empty();
document.getElementById("myTable").innerHTML = "";
// Insert a row into the header.
oRow = oTHead.insertRow(-1);
oTHead.setAttribute("bgColor","lightskyblue");
// Insert cells into the header row.
for (i=0; i < heading.length; i++) {
oCell = oRow.insertCell(-1);
oCell.align = "center";
oCell.style.fontWeight = "bold";
oCell.innerHTML = heading[i];
}
Since you're using jQuery, just do this: $('#containerIdThatYourTableSitsIn').html('');
That will clear the html of whatever element your table sits in. Then just reload it.
Edit
As the comments have mentioned, .empty() is another option.

Javascript - Automatically switch/create to another row if a row is filled with 4 cells in a table

I think that the title is self-explanatory. I am retrieving data using XMLHttpRequest and the data is getting appended into columns of a table. I decided to only allow a row to have only 4 columns inside it and if another item exists then it should be appended into another row. This is what I have done:
//...
//unneccessary
//...
var album_photos = JSON.parse(xhr2.responseText);
for(var i = 0; i < album_photos.length; i++) {
if(!isInArray(album_photos[i].Image_ID, image_ids)) {
var tr = document.getElementById("tiare");
if(i % 4 == 0) {
tr = document.createElement("tr");
document.getElementById("images").appendChild(tr);
}
//...
//creating elements to be append
//...
tr.appendChild(td);
td.appendChild(imagewrap);
imagewrap.appendChild(imagemenu);
imagemenu.appendChild(imagemenuimg1);
imagemenu.appendChild(imagemenuimg2);
imagewrap.appendChild(imagewrapimg);
image_ids.push(album_photos[i].Image_ID);
//...![enter image description here][1]
//unneccessary
//...
And this is the markup:
<table width="80%" id="images">
<tr id="tiare">
</tr>
</table>
See how it's not getting splitted correctly:
How can I achieve this, my logic is not working at all! What should I do?
P.S: No jQuery solution allowed. :)
Any help would be appreciated. Thanks in advance. :)
UPDATE: I changed my code into this:
function getAlbumImages() {
var xhr2 = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xhr2.open('GET', 'admin/images_data.php');
xhr2.onreadystatechange = function(e) {
if(xhr2.readyState == 4 && xhr2.status == 200) {
var oldtable = document.getElementById("images");
var newtable = oldtable.cloneNode();
var tr = document.createElement("tr");
var album_photos = JSON.parse(xhr2.responseText);
for(var i = 0; i < album_photos.length; i++) {
if(!isInArray(album_photos[i].Image_ID, image_ids)) {
if(i%4 == 0 && i != 0){
newtable.appendChild(tr);
tr = document.createElement('tr');
}
var td = document.createElement('td');
var imagewrap = document.createElement('div');
imagewrap.className = "image-wrap";
var imagemenu = document.createElement('div');
imagemenu.className = "image-menu";
var imagemenuimg1 = document.createElement('img');
imagemenuimg1.src = "img/edit_img.png";
var imagemenuimg2 = document.createElement('img');
imagemenuimg2.src = "img/close.png";
var imagewrapimg = document.createElement('img');
imagewrapimg.className = "thumbnail";
imagewrapimg.src = "admin/album_photos/" + album_photos[i].Image_Path;
imagewrapimg.onclick = function() { showBigImage(this); };
tr.appendChild(td);
td.appendChild(imagewrap);
imagewrap.appendChild(imagemenu);
imagemenu.appendChild(imagemenuimg1);
imagemenu.appendChild(imagemenuimg2);
imagewrap.appendChild(imagewrapimg);
image_ids.push(album_photos[i].Image_ID);
} else {
continue;
}
}
newtable.appendChild(tr);
oldtable.parentNode.replaceChild(newtable, oldtable);
}
}
xhr2.send(null);
}
This function is called inside an setInterval with 5000 milliseconds break.
The problem coming now is that it disappears after 5 seconds. How can I resolve that?
The first problem I see is that i and i % 4 is not the images in your table, it's the images in the returned data. The two will differ as soon as you encounter an image already in your array. You need to use an index for the i % 4 that is the actual number of images in the table. You could use a separate count of how many images are in the table that you intialize with:
var imageCnt = document.getElementById("images").getElementsByTagName("td").length
And, the increment that any time you add an image to the table and then check %imageCnt % 4 to decide when to add a new row.
Then, don't you want to be adding images to the LAST row in the table, not the first row in the table because that's where the extra slots will be and where the new empty row goes. You will be adding images to the last row when you've just created a new row, but not when your last row is partially filled when you start. In that case, you'll be adding images to the first row. You can start with the last row
var table = document.getElementById("images");
var lastRow = table.rows[table.rows.length - 1];
Applying these to your first example of code would work like this:
//...
//unneccessary
//...
var album_photos = JSON.parse(xhr2.responseText);
var table = document.getElementById("images");
var tableBody = table.getElementsByTagName("tbody")[0];
var lastRow = table.rows[table.rows.length - 1];
// initialize cell count
var cellCount = table.getElementsByTagName("td").length;
for(var i = 0; i < album_photos.length; i++) {
if(!isInArray(album_photos[i].Image_ID, image_ids)) {
if (cellCount % 4 == 0 && cellCount !== 0) {
// make new row and append it to the table body
lastRow = document.createElement("tr");
tableBody.appendChild(lastRow);
}
//...
//creating elements to be append
//...
td.appendChild(imagewrap);
imagewrap.appendChild(imagemenu);
imagemenu.appendChild(imagemenuimg1);
imagemenu.appendChild(imagemenuimg2);
imagewrap.appendChild(imagewrapimg);
// best to append the new cell when it's fully formed
lastRow.appendChild(td);
++cellCount;
image_ids.push(album_photos[i].Image_ID);
//...![enter image description here][1]
//unneccessary

Categories

Resources