Copy link to clipboard
Copied
Hi all
I've written the following script:
function _table() {
if (app.selection.length > 0) {
var _selection = app.selection[0];
if (_selection.parent.constructor.name == "Table" || _selection.parent.parent.constructor.name == "Table") {
var _cells = _selection.columns[0].cells;
for (var i = 0; i < _cells.length - 1; i++) {
var i2 = i + 1;
if (_cells[i].contents === _cells[i2].contents) {
var _mergeValue = _cells[i].contents;
_cells[i].merge(_cells[i2]);
_cells[i].contents = _mergeValue;
if (_cells[i].contents === _cells[i2].contents) {
i--;
}
}
}
}
}
}
app.doScript(_table, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT);
Unfortunately it's not performing as expected. What it should do is loop through the selected cells and check if subsequent cells contain the same content and merge them if they do. And not only merge them but only keep one instance of the content, not both, as would be standard with InDesign.
In some cases, this works fine. In some, it behaves weirdly and in some cases it doesn't work at all.
In this case, it works on one of the columns. If I select the other one, the script doesn't do anything. It doesn't matter which column I start with.
In this case, it behaves completely unexpectedly. It merges some of the cells but not correctly. This is the result:
Any ideas why the script behaves like that? Any help is much appreciated!
Copy link to clipboard
Copied
Hi,
I have reworked your code a little to make it work with a 2 column table.
if (app.selection.length > 0) {
var _selection = app.selection[0];
// altered this just to make sure _selection, points at a table.
if ( _selection.parent.constructor.name === "Table"){
_selection = _selection.parent;
} else if ( _selection.parent.parent.constructor.name === "Table"){
_selection = _selection.parent.parent
} else {
_selection = null;
}
if (_selection != null ){
// altered this so we get all the cells in a single list
// note this is by column, not row
var _cells = _selection.columns.everyItem().cells.everyItem().getElements();
for (var i = 0; i < _cells.length/2; i++) {
// as it is by column, the cell next to it is half the size of the table
var i2 = i + _cells.length/2;
if (_cells[i].contents === _cells[i2].contents) {
var _mergeValue = _cells[i].contents;
_cells[i].merge(_cells[i2]);
_cells[i].contents = _mergeValue;
}
}
}
}
Hope this helps, if you have any further questions please don't hesitiate to respond.
Copy link to clipboard
Copied
First, when you change collection of objects - destroy them when iterating - you need to iterate from the end - otherwise, the next object in the collection may not be the one you would expect it to be.
Second, instead of setting ".contents" to a variable and then using it - first empty contents of the Cell you want to merge with, then merge with it - this way you'll preserve formatting - otherwise you are just transferring "raw" text contents.
I'm not JS guy so can't give you a working code but I hope it will help.
Copy link to clipboard
Copied
Or, if your selection is a whole Table or whole Rows - instead of iterating through Cells - iterate through Rows and then Cells in a Row.
This way, even if you merge / unmerge Cells in a Row - it won't affect other Rows.
Still, depends on the number of Columns in a Row you may need to iterate backward.
Copy link to clipboard
Copied
Hi,
I don't know if it is just a quirk of how InDesign handles its collections but when you do a merge withs cells in a collection, the collection does not change until you actually call it again, so you can work with all the elements, you do have to be careful, because if you rely on the change you have to refresh the collection. This can be seen in the debugger,
As can be seen above I have merged 8 cells into for, but the length of the _cells collection is still 8, so it has not updated.
It should also be noted that using this method you can't actually delete cells, you are not allowed to, the JS throughs an error.
Copy link to clipboard
Copied
But if you're merging cells in rows - why are you working on columns??
Copy link to clipboard
Copied
Hi,
I could have done it either way, I just used the columns as a way to get all the cells, the only change between the rows and columns would be how the cells are represented in the columns, so thinking back it would probably have made more send to use
var _cells =_selection.rows.everyItem().cells.everyItem().getElements();
This would change the maths section to something more simple.
Copy link to clipboard
Copied
That was my point - simpler math / navigation.
Copy link to clipboard
Copied
Hi,
Updated the code it has both options included so that the decision is up to you as to which you use. Just for curiosity and so people can see the code and what changes depending on if you use columns or rows.
var userRows = true; // change to false to use the columns
if (app.selection.length > 0) {
var _selection = getTableObjectFromSelection( app.selection[0]);
if (_selection != null ){
(userRows) ? mergeCellsUsingRows ( _selection) : mergeCellsUsingColumns ( _selection);
}
}
function mergeCellsUsingRows ( selectionObj){
var _cells = selectionObj.rows.everyItem().cells.everyItem().getElements();
for ( var i = 0; i < _cells.length - 1; i+2){
var i2 = i++;
mergeCellsCleanly ( _cells[i], _cells[i2]);
}
}
function mergeCellsUsingColumns ( selectionObj){
var _cells = selectionObj.columns.everyItem().cells.everyItem().getElements();
for (var i = 0; i < _cells.length/2; i++) {
// as it is by column, the cell next to it is half the size of the table
var i2 = i + _cells.length/2;
mergeCellsCleanly ( _cells[i], _cells[i2]);
}
}
function getTableObjectFromSelection ( selectionObj){
// altered this just to make sure _selection, points at a table.
if ( _selection.parent.constructor.name === "Table"){
_selection = _selection.parent;
} else if ( _selection.parent.parent.constructor.name === "Table"){
_selection = _selection.parent.parent
} else {
_selection = null;
}
return _selection;
}
function mergeCellsCleanly ( cell1, cell2){
if ( cell1.contents === cell2.contents){
cell1.contents = "";
cell1.merge(cell2);
}
}