Copy link to clipboard
Copied
Hello,
I have a document with many tables with the same Table Style.
All the tables have two columns.
I have managed to make a java script (jsx) that can change the width of the two columns and applied this automatically to all the tables in the document.
Now, I would like to swap the two columns in every table in the document, so that the leftmost column becomes the rightmost one.
If anyone has a few lines of code to accomplish this, it would be great.
With best regards from,
Geir Braathen
1 Correct answer
(eg. a word in italic) in the moved column it will be gone afterwards.
Hi Mark, I wouldn’t be surprised if other problems pop up but the text formatting might be solved with a simple copy and paste after the properties have been set. This seems to work:
/**
* Swaps the first two columns of a table
* @ param the table
* @ return void
*/
function swapColumns(t){
var nc = t.columns.add(LocationOptions.BEFORE, t.columns[0]);
var c = nc.cells;
var lc = t.columns[2].cells;
for
...
Copy link to clipboard
Copied
Hi @geirb9262873, I have previously written code to do this. See my answer here. Let me know if it works for you as the code is quite untested. (Also, sadly, it is more than just a few lines only!)
- Mark
Edit: If you try my function, you would use something like this:
// swap first and second columns
moveRowOrColumn(table.columns[1], LocationOptions.BEFORE, table.columns[0]);
Copy link to clipboard
Copied
Hi Mark,
Thank you for your reply.
I would love to try your code, but I get a bit lost in the long script you link to, so I am not sure how to apply the one-liner you give here. I tried a bit, but I get error messages.
I am new to scripting in InDesign, so I depend on some complete script that works without too much tweaking.
Cheers,
Geir
Copy link to clipboard
Copied
Ah I see. Not to worry. To use my code as it is (in the other post) delete these lines:
/*
example 1:
duplicate first row after itself
*/
var newRow = duplicateRowOrColumn(table.rows[0], LocationOptions.AFTER);
// then convert to body row
if (newRow != undefined && newRow.isValid)
newRow.rowType = RowTypes.BODY_ROW;
But which tables do you want it to work with? Just the first selected table? All tables in a story? All in a document? I'll need to adjust the way the script gets the table(s) depending on what you want.
- Mark
Copy link to clipboard
Copied
Hi again Mark,
Thank you for your quick reply.
I want to apply the swap to all the tables in the document.
All the tables are similar and of same Table Style. They all have two columns, but a varying number of rows.
I hope I have explained clearly. I will give it another try now with your last advice.
Cheers,
Geir
Copy link to clipboard
Copied
Hello again,
Quick feedback with good news!
It works on the first table, but not the rest of the tables.
I tried to put in some code to choose all tables, but I get an error.
If you find a way for this to work on all the tables, it would be fantastic.
Cheers,
Geir
Copy link to clipboard
Copied
Hi @geirb9262873, well done on giving it a go. Yes my script was only demonstrating on the first table. Here's what I'd like you to change to make it work for all tables:
1. remove all text between
function main() {
and this line
/**
* Duplicate a table Row or Column
and replace with this:
var doc = app.activeDocument,
tables = doc.stories.everyItem().tables.everyItem().getElements();
for (var i = 0; i < tables.length; i++) {
var table = tables[i];
if (table.isValid)
moveRowOrColumn(table.columns[1], LocationOptions.BEFORE, table.columns[0]);
}
and that should do it!
- Mark
Copy link to clipboard
Copied
Hi Geir, Does this work?
var table=app.activeDocument.selection[0].tables[0];
swapColumns(table);
/**
* Swaps the first two columns of a table
* @ param the table
* @ return void
*/
function swapColumns(t){
var nc = t.columns.add(LocationOptions.BEFORE, t.columns[0]);
var c = nc.cells
var lc = t.columns[2].cells
for (var i = 0; i < c.length; i++){
c[i].properties = lc[i].properties
};
t.columns[2].remove();
}
Copy link to clipboard
Copied
OMG @rob day! Using the "properties" property is brilliant! My script stupidly loops over them all! Nice one. 🙂
- Mark
Edit: I hope you don't mind, I edited my function to apply the properties the way you did, which is very convenient, but I also noticed that you then need to move the content in a more deliberate way, to ensure that text styles and graphics come with it correctly. (See my function.)
Copy link to clipboard
Copied
I hope you don't mind
No probelm.
Copy link to clipboard
Copied
Hi Rob,
Thank you for elegant little program.
However, I get an error message when I try to run it.
Maybe there is some additional code needed that I am not aware of.
I am quite new to scritping in InDesign.
I attach a screen capture of the error message.
Cheers,
Geir
Copy link to clipboard
Copied
Hi @geirb9262873, select a text frame with a table in it first and then run script.
- Mark
Copy link to clipboard
Copied
Hi Rob and Mark,
I got it.
One has to select a text frame. Then it works on the first table in that frame.
I would like to make it work on all the tables in the story (or the document, which has only one story).
What I will do now as a better than nothing solution is to do it page by page and select the text frame on that page.
I have expanded Rob's script with some additional lines like
var table=app.activeDocument.selection[0].tables[1];
swapColumns(table);
var table=app.activeDocument.selection[0].tables[2];
swapColumns(table);
var table=app.activeDocument.selection[0].tables[3];
swapColumns(table);
so then I get four tables in that frame fixed.
This is better than nothing.
Cheers,
Geir
Copy link to clipboard
Copied
Hi Geir, You can call my function from your table loop— you shouldn’t need to select anything.
This would loop over all the dcoument tables and call the swap function:
//all the document stories
var s = app.activeDocument.stories
for(var i=0; i < s.length; i++){
//the tables
var t = s[i].tables;
for(var j=0; j < t.length; j++){
//call the function
swapColumns(t[j])
}
}
/**
* Swaps the first two columns of a table
* @ param the table
* @ return void
*/
function swapColumns(t){
var nc = t.columns.add(LocationOptions.BEFORE, t.columns[0]);
var c = nc.cells
var lc = t.columns[2].cells
for (var i = 0; i < c.length; i++){
c[i].properties = lc[i].properties
};
t.columns[2].remove();
}
on each table
Copy link to clipboard
Copied
Hi Rob,
Thank you so much. It works like a dream now. The script runs through the whole docuement and does its job perfectly.
I am very happy about the quick and competent help I have received here.
Is there is a guide or a text book that explains how to make jsx scripts in InDesign.
I am thinking about using Python, as I have some experience with that language for visualisation of scientific data. I think there is some sort of interface so that InDesign will understand code written in Python.
I wish you a lovely day.
Thank to Mark also for his answers and efforts.
All the best from,
Geir
Copy link to clipboard
Copied
I am thinking about using Python, as I have some experience with that language for visualisation of scientific data
The other options are Applescript and Visual Basic—no Python
But the JavaScript (ExtendScript) variables, functions, and loops should be familiar, so I’m guessing you want to learn ExtendScript.
You can get a PDF of Adobe’s Scripting Guide here:
https://usermanual.wiki/adobe/InDesigncs6ScriptingJSEN.3768967468/view
And an HTML guide with sample scripts here:
https://developer.adobe.com/console/servicesandapis
And a searchable well organized API is here:
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#about.html
Copy link to clipboard
Copied
Glad it's solved! Just a caveat on Rob's script—being beautiful and brief—if you had multiple text styles (eg. a word in italic) in the moved column it will be gone afterwards.
I have heard of someone using python to script Adobe products but when I looked into it they were basically using python to deliver javascript commands... so no, not a good option, sadly.
- Mark
Copy link to clipboard
Copied
(eg. a word in italic) in the moved column it will be gone afterwards.
Hi Mark, I wouldn’t be surprised if other problems pop up but the text formatting might be solved with a simple copy and paste after the properties have been set. This seems to work:
/**
* Swaps the first two columns of a table
* @ param the table
* @ return void
*/
function swapColumns(t){
var nc = t.columns.add(LocationOptions.BEFORE, t.columns[0]);
var c = nc.cells;
var lc = t.columns[2].cells;
for (var i = 0; i < c.length; i++){
c[i].properties = lc[i].properties;
app.select(lc[i].texts[0])
app.copy()
app.select(c[i].texts[0])
app.paste()
};
t.columns[2].remove();
}
Copy link to clipboard
Copied
Yes exactly—that's a quick way to solve it, but... then the user's clipboard is changed.
Copy link to clipboard
Copied
Hi Mark,
you could use method duplicate() or move() on the source text.
Before you have to empty the target cell.
But be aware that there are perhaps graphic cells in your table!
Regards,
Uwe Laubender
( Adobe Community Professional )
Copy link to clipboard
Copied
Yes that's how I do it in my script. And graphic cells, too! There's always more to it when you set out to do a "quick script".
- Mark
Copy link to clipboard
Copied
This technique works well, unless you have just another table in any cell in the column to move. I personally would say that this is an InDesign bug that not any cell content is duplicated but only the "textual" one. You will end up with an empty new cell in this scenario.
What you in fact have to do in this case is - unfortunately - using the computer's clipboard function, using the copy/paste mechanism mentioned below.
Copy link to clipboard
Copied
Two more notable things regarding the t.columns.add(LocationOptions.XXX, t.columns[n]) command:
1. It remains completely unclear what exactly is added with which content if you use this command. Intuitively you would assume that the column is just duplicated just as if you would move a column manually in your layout - where really everything is duplicated. But this is NOT the case, and also here no documentation available at all, so that you need to endeavour for an arduous trial-error experience. It turns out that only mere textual content is duplicated; no tables in cells, no anchored objects.
2. If you try to copy the cell's content using select(...) and app.copy(), you will be confronted with error messages eg if the cell content consists only of an anchored graphic. Therefore, don't copy the cell's content, but copy the cell as such instead - i.e.: Don't use something like select(table.columns[x].cells[y].texts[0]) and copy this, but use select(table.columns[x].cells[y]) and copy/paste that. Which seems to transfer text, tables, anchored items. (Of course, also here no official documentation available.)
Copy link to clipboard
Copied
Oh, and, by the way, if you follow the recommendation 2. and copy cells instead of cell contents, you clearly copy all cell properties as well, inasmuch you won't need the step to transfer all cell properties.
What you definitely should do is to transfer all column properties using this neat technique.

