Problem, merging cell in a table document, google apps script [duplicate] - google-apps-script

I've writen this function (thanks, #Mogsdad) to merge cells in a table in a text google document, like this:
function onOpen() {
// Add a menu with some items, some separators, and a sub-menu.
DocumentApp.getUi().createMenu('Sample')
.addItem('merge cells of a table', 'mergeCells')
.addToUi();
}
function mergeCells() {
var body = DocumentApp.getActiveDocument().getBody();
for (var p= 0; p< body.getNumChildren(); p++) {
var child = body.getChild(p);
if (child.getType() == DocumentApp.ElementType.TABLE){
// Assume we've already located our table
var table = child;
var tableRow = table.getChild(2); // gets third row
var tableCell = tableRow.getChild(1); // gets second cell in row
tableCell.merge(); // Merges seconde cell with first cell.
}
}
}
But when I run the code, I got this weird result (very different of the expected, with the merged cell with the same dimensions of the table):
Is there a way to fix it? (merged cell with the same dimensions)

[edit to address updates in Google Docs]
This currently not possible. You can know if a cell is merged by looking calling getColSpan and getRowSpan but there are no setter methods.
Please star the following issue to be notified by updates regarding this.
The merge function you found is not specific to table cells, it is there to merge any element with a previous sibling of the same type, joining their content.
[original answer]
If you were expecting to have a merged cell that, like what you can do in a spreadsheet, that is not possible. Simply because that's not possible in Google Documents (at least not yet). Therefore the API cannot do this (it can only do things that are also possible manually).
This merge function is not specific to table cells as you probably imagined. It is working as designed.

You can do this by a workaround. Add a drawing and add a table in this drawing document. In this document te option 'merge cell's' is a possibility if you select 2 cells and press the right mouse button. See this youtube video for a tutorial

Use the Advanced Documents Service, batchUpdate and mergeTableCells.
function mergeCells() {
const documentId = 'DOCUMENT_ID';
const resource = {
requests: [
{
"mergeTableCells": {
"tableRange": {
"tableCellLocation": {
"tableStartLocation": {
"index": 2
},
"rowIndex": 0,
"columnIndex": 0
},
"rowSpan": 1,
"columnSpan": 2
}
}
}
]
}
Docs.Documents.batchUpdate(resource, documentId);
}
Resources
https://developers.google.com/apps-script/guides/services/advanced#enabling_advanced_services
MergeTableCellsRequest

One workaround is to embed tables within tables instead of merging cells. That way you can still programmatically add or remove cells/rows without ruining the tables. If you set the cell padding to 0, any stray paragraphs to 1pt font and remove any cell borders and you can achieve almost the same effect without any merged cells.
For example, I've got a cell with 4 columns, where I want the last column to be merged as as a single cell. I also want to be able to add or remove rows with Apps Script.
Table embedded within a table:
This way I can add or remove rows from the embedded table on the left and the right cell will remain "merged". You will have trouble getting the cell borders to line up, but if you can do without them you can still get it looking nice, like this:
And without borders:

Here is how to solve the merged cell in tables of a MS document when converting to a Google document: The idea is to go back to the MS word document and remove the merged cells and then copy and paste it or convert MS word to Google document. In this way we can get easy conversion of tables in MS documents to Google documents. But, within Google documents the cell can't be merged.

Related

Show and hide selected columns with single macro in google sheets

Starting out like all others. I am new to macros and I know what I'm trying to do is easy, but I can't get it working.
So I'm making buttons on a spreadsheet to show and hide columns, if the column is hidden then show, if the column is shown then hide. So a toggle button between show and hide basically.
I will continue to research while this is here as I'm sure the answer is simple. Just an If, then, else but I'm a noob.
Any help would be appreciated. Here's one of the 'show' ones I have if it's easier to edit that.
Thanks
function ShowCA() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getActiveSheet().showColumns(6);
};
I believe your goal is as follows.
About the column "F", when the column is showing, you want to hide the column. When the column is hiding, you want to show the column.
You want to achieve this using a function of Google Apps Script.
In this case, I thought that isColumnHiddenByUser can be used. So, how about the following sample script?
Sample script:
function ShowCA() {
var column = 6; // This is column "F".
var sheet = SpreadsheetApp.getActive().getActiveSheet();
if (sheet.isColumnHiddenByUser(column)) {
sheet.showColumns(column);
} else {
sheet.hideColumns(column);
}
}
When this script is run, when the column "F" is showing, the column is hidden. When the column "F" is hiding, the column is shown.
References:
isColumnHiddenByUser(columnPosition)
showColumns(columnIndex)
hideColumns(columnIndex)

How to apply the same conditional formatting rule to multiple columns in Google sheets using apps script?

I have multiple columns - G, L, Q, V, AA, AF - to which I want to apply a conditional format rule in Google sheets. Starting in row 2 - so that I don't include the header row - I want any given cell in the specified column to .setBackgroundColor ("orange") if any text or data is found to the right of that cell. For example, I want cell G2 to be orange if cell H2 has anything entered inside of it, and L17 to be orange if S17 has data, and AA5 to be orange if AD5 is not blank.
My experience with apps script is very primative. I can only successfully write very few lines of code, so my dilemma is past my ability. I understand it is possible to apply conditional formatting using sheets' built in conditional formatting tab, but it will not work for my project seeing as I am gathering data with a Google form, and with every response I receive from the form, the sheet creates a new line for the submission that retains none of the formatting from the rest of the sheet. My plan would be to add a form submission trigger to the code so that the conditional formatting in the columns updates regularly with the sheet.
I have been looking around for some time online and have not found a solution to my problem. Any help would be greatly appreciated! Thank you!
The following example shows the process of creating a new conditional format rule, applying it to the sheet. Then copying and pasting the format of a range to a target range. You can find the references for the methods used in the references section at the end of this answer.
Example:
function myFunction() {
// The range where the formatting will be applied.
var range = 'G2:G'
// Get the array containing the conditional formatting rules for the sheet
var spreadsheet = SpreadsheetApp.getActive();
var conditionalFormatRules = spreadsheet.getActiveSheet().getConditionalFormatRules();
// Build the new conditional formatting rule and push it to the array
conditionalFormatRules.push(SpreadsheetApp.newConditionalFormatRule()
.setRanges([spreadsheet.getRange(range)]) // The range to apply to
.whenFormulaSatisfied('=H2<>""') // The formula to check
.setBackground('orange') // The format to apply
.build());
// Set the conditional format rules for the sheet with the updated array
spreadsheet.getActiveSheet().setConditionalFormatRules(conditionalFormatRules);
// Paste the format of the range into the next desired range
spreadsheet.getRange(range).copyTo(spreadsheet.getRange('L2:L'), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
/* repeat the previous instructions for all your target ranges replacing "L2:L" with the target range */
};
References:
-getConditionalFormatRules()
-newConditionalFormatRule()
-setConditionalFormatRules()
-copyTo(destination, copyPasteType, transposed)

How to copy and paste specific information in a same doc using Google App Script?

I'm very new using GAS what I'm trying to do is to copy some information that is already on the bottom of my doc to anywhere I want in my docs, this should work just by copying the information and paste it at the place I desire, but I want it to be done with Google App Script because it's a daily task and it's easier to do it with a function, instead of copying and pasting manually. Searching on how to do this, I found a lot of information about how to do it on Spreadsheets, but I needed it to be done on Google Docs. How can I do that?
If someone can guide me or send me a link to another similar question that would be very helpful, I don't know where to start.
This is what I have until now, I get all the data of the current doc and set it again to the page, the code gives me problems because it deletes my other information, also it selects all the doc's information. I want to select a piece of specific information and don't copy the content style.
function copyPasteInfo() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var notesText = body.getText();
body.appendPageBreak();
body.setText(notesText);
}
Link to the doc document
https://docs.google.com/document/d/1s2TCspXbjvHVurwhIWSdwJ_hMcZIoLTKj4FAB82nmhM/edit
Video example of how what i want to do
https://www.screencast.com/t/UmEon8Fm0lPe
Picture of the information i'm trying to copy and paste to the bottom of my doc
If I correctly understood your question, this code will help you to achieve your goal.
let body = DocumentApp.getActiveDocument().getBody();
function moveTable() {
// Get the last table and the previous table found in your Doc
const [previousTable, bottomTable] = getDesireTables();
// Make a copy of your last table
const bottomTableCopy = bottomTable.copy();
// Get the previous table's index
const previousTableIndex = body.getChildIndex(previousTable);
// Insert the last table's copy under the previous table in your Doc
body.insertTable(previousTableIndex + 1, bottomTableCopy);
// Remove the original last table
body.removeChild(bottomTable);
}
function getDesireTables(){
const tablesArr = body.getTables().slice(-3);
// Get the parent element type to check if it's a cell
const parentELementType = tablesArr[tablesArr.length - 1].getParent().getType();
if(parentELementType === DocumentApp.ElementType.TABLE_CELL){
// If there's a table inside a table, return this
return tablesArr.slice(0, 2);
}
else{
return tablesArr.slice(-2);
}
}
What I did was to get the last two tables in the Doc, then I made a copy of the last one and with the index of the previous one, I inserted it under the previous one.
Edit
I noticed you had a table inside a table. therefore I added the getDesireTables function. Which it will check if your bottom table has a table inside.
Docs
These are the docs I used to help you:
getTables().
copy().
insertTable(childIndex, table).

How to merge the two cells of a table in a Google text Document without this weird result?

I've writen this function (thanks, #Mogsdad) to merge cells in a table in a text google document, like this:
function onOpen() {
// Add a menu with some items, some separators, and a sub-menu.
DocumentApp.getUi().createMenu('Sample')
.addItem('merge cells of a table', 'mergeCells')
.addToUi();
}
function mergeCells() {
var body = DocumentApp.getActiveDocument().getBody();
for (var p= 0; p< body.getNumChildren(); p++) {
var child = body.getChild(p);
if (child.getType() == DocumentApp.ElementType.TABLE){
// Assume we've already located our table
var table = child;
var tableRow = table.getChild(2); // gets third row
var tableCell = tableRow.getChild(1); // gets second cell in row
tableCell.merge(); // Merges seconde cell with first cell.
}
}
}
But when I run the code, I got this weird result (very different of the expected, with the merged cell with the same dimensions of the table):
Is there a way to fix it? (merged cell with the same dimensions)
[edit to address updates in Google Docs]
This currently not possible. You can know if a cell is merged by looking calling getColSpan and getRowSpan but there are no setter methods.
Please star the following issue to be notified by updates regarding this.
The merge function you found is not specific to table cells, it is there to merge any element with a previous sibling of the same type, joining their content.
[original answer]
If you were expecting to have a merged cell that, like what you can do in a spreadsheet, that is not possible. Simply because that's not possible in Google Documents (at least not yet). Therefore the API cannot do this (it can only do things that are also possible manually).
This merge function is not specific to table cells as you probably imagined. It is working as designed.
You can do this by a workaround. Add a drawing and add a table in this drawing document. In this document te option 'merge cell's' is a possibility if you select 2 cells and press the right mouse button. See this youtube video for a tutorial
Use the Advanced Documents Service, batchUpdate and mergeTableCells.
function mergeCells() {
const documentId = 'DOCUMENT_ID';
const resource = {
requests: [
{
"mergeTableCells": {
"tableRange": {
"tableCellLocation": {
"tableStartLocation": {
"index": 2
},
"rowIndex": 0,
"columnIndex": 0
},
"rowSpan": 1,
"columnSpan": 2
}
}
}
]
}
Docs.Documents.batchUpdate(resource, documentId);
}
Resources
https://developers.google.com/apps-script/guides/services/advanced#enabling_advanced_services
MergeTableCellsRequest
One workaround is to embed tables within tables instead of merging cells. That way you can still programmatically add or remove cells/rows without ruining the tables. If you set the cell padding to 0, any stray paragraphs to 1pt font and remove any cell borders and you can achieve almost the same effect without any merged cells.
For example, I've got a cell with 4 columns, where I want the last column to be merged as as a single cell. I also want to be able to add or remove rows with Apps Script.
Table embedded within a table:
This way I can add or remove rows from the embedded table on the left and the right cell will remain "merged". You will have trouble getting the cell borders to line up, but if you can do without them you can still get it looking nice, like this:
And without borders:
Here is how to solve the merged cell in tables of a MS document when converting to a Google document: The idea is to go back to the MS word document and remove the merged cells and then copy and paste it or convert MS word to Google document. In this way we can get easy conversion of tables in MS documents to Google documents. But, within Google documents the cell can't be merged.

Bold conditional formatting script for Google Spreadsheets

What I want to do is essentially what this user wanted to do here:
I need a script that formats the cells in column A bold, but only the cells that contain the word 'Hello'.
However I have no knowledge of Google Apps scripts at all, and I need an answer put in much simpler terms than what I could find there or anywhere else. Any help is appreciated; thank you!
To start, from your spreadsheet, open "Tools / Script Editor...". When the dialog opens, choose to "Create Script For... Spreadsheet". You will end up with a sample script - we're going to edit it to do what you want.
Change the readRows() function as shown here. The change is that instead of logging the content of every row, we will use an if statement to check if the cell contains a string with 'Hello' in it. Then, if it does, we'll bold the cell text.
function readRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
// Arrays start at 0, Google Sheets start at 1 - must remember that.
// We will loop starting at 1, because we want to skip the header in
// Row 1, aka Array index 0
for (var i = 1; i <= numRows - 1; i++) {
var colA = values[i][0];
if (colA.toString().indexOf('Hello') >= 0) {
sheet.getRange(i+1,1).setFontWeight("bold");
}
}
};
Now, how to run that? The sample already has an onOpen() function that will set up a custom menu... let's just change the text it displays in the User Interface, as shown here. The only change is in the 'name' property of the menu entries.
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Bold Hello",
functionName : "readRows"
}];
sheet.addMenu("Script Center Menu", entries);
};
Save your script. Go back to your spreadsheet, and reload it (to get it to run the onOpen trigger function). When your menu shows up, you're all set.
Next - start with the "First Script" tutorial here. The Google Apps Script documentation covers all the services provided by Apps Script, but the basic language structure and objects are javascript, so you should get familiar with that. Just try googling "learn javascript", and you'll find tons of tutorials, books, and other resources.
I can't make this simpler.
In the now not so new 'New' Sheets this can be achieved without a script:
Clear formatting, select ColumnA and Format, Conditional formatting..., Format cells if... Text contains and:
hello
Then for Formatting style click the B and Done.
This way is not case sensitive and will embolden contents such as OTHELLO.
If you aren't trying to set too many conditional formatting rules, there's an easier way to set colors, though not bold. In Google Drive Spreadsheet, click the "Format" menu. The bottom menu item should be "Conditional formatting..."; click that. That should produce a dialog box that defaults to something like this (to the extent that I can draw it with text):
x
Conditional formatting
[Text contains ◊ ] [ ] []Text: [ ] []Background: [ ] x
e.g. "done" or "Jonathan"
_______________________________________________________________________________
+ Add another rule
[ Save rules ] [ Cancel ]
In your example, you're looking for cells that contain "Hello", so the default of "Text contains" would do the job. Put "Hello" into the text box, and set a format in the "Text":" and "Background:" boxes. That doesn't give you bold, but it does allow colors.
I see that your question dates back half a year, so it's probably too late for you (and if you strictly need bold, it doesn't solve the problem anyway), but it may help others.