Copy link to clipboard
Copied
Hi,
I have a script that can move data from one unformatted table in one document to a formatted table in a second document. It works ok, but if I have a third document, then the script fails. I'm dealing with it with a clause that checks if there are 2 documents or not at the beginning of the script but I would like to be able to have a third document open for reference sometime so I want to modify the script. Don't laugh, it's an old script from Shane which I have adapted a bit.
--Table Data replace
--Use this script to replace data in a table already designed in ID CS4.
--You need two document opened, one with a table formatted and the other document with the table with the same number of columns and rows without formating. Select the part you want to replace in the first and the part you want to replace with in the other document and you're good to go.
--By Shane Stanley, from the ID Magazine issue 2.
--fixed number of rows and columns check that didn't work on 2013-03-25 by Jeff Lambert
tell application "Adobe InDesign CC 2019"
if number of document is not 2 then
beep
activate
display dialog "This script requires two documents open, with equivalent table areas selected." buttons {"OK"}
return
end if
set columnCount1 to count of columns of selection of document 1
set rowCount1 to count of rows of selection of document 1
set columnCount2 to count of columns of selection of document 2
set rowCount2 to count of rows of selection of document 2
if (rowCount1 is not equal to rowCount2) then
beep
activate
display dialog "The number of rows don't match." & return & " You have " & rowCount1 & " rows for the document in front vs " & return & rowCount2 & " rows for the document in back." buttons {"OK"}
return
else if (columnCount1 is not equal to columnCount2) then
beep
activate
display dialog "The number of columns don't match." & return & " You have " & columnCount1 & " columns for the document in front vs " & return & columnCount2 & " columns for the document in back." buttons {"OK"}
return
end if
display dialog "Which document contains the formatted table?" buttons {"Cancel", "Front", "Back"} default button 2
if button returned of result = "Back" then
set dataDocument to document 1
set formatDocument to document 2
else
set dataDocument to document 2
set formatDocument to document 1
end if
set ourData to contents of selection of dataDocument
set contents of selection of formatDocument to ourData
end tell
Here's the way I would like to work on this. Having 3 documents open, Document1 in window 1, Document 2 and 3 in a second window. Document 1 would be the active document, and document 3 would be in a hidden tab in window 2.
example of documents setup
I don't want to have a dialog that asks which document is the front and the back from a list, it would be too long since I have hundreds of tables to do this way. Having a dialog with two buttons is enough and it defaults to the front-most which is how I usually work, I just hit enter and I'm good to go.
So, how can I deal with the top document in each window? I could have 4 documents or more if possible but still be able to run the script and the only document the script has to work with would be the top ones from each window, not the other tabs which are hidden. If there are more then two windows, it could just throw an error, that would be fine.
Thanks for any help!
Copy link to clipboard
Copied
I’m not sure tabbing the windows will help. If your reference document is in front before you run the script (you click its title) you could send it to back, which would make the other 2 docs Document 1 and Document 2. So replace the if statement checking the number of open documents with:
tell application id "com.adobe.indesign"
set dl to count of documents
if dl is greater than 2 then
set ds to every document
set active document to item (dl - 1) of ds
set active document to item dl of ds
end if
end tell
Copy link to clipboard
Copied
Thanks Rob, I've tried it and I thought it worked but no. the third document may, or may not be there. The script needs to look at the two "visible" documents. If there are two documents, you select the table in both and run the script and everything works. If you have a third document, it was running weird and gave an error message (before your code and a change I had made from Shane's code). With your code, if you close a document, I had closed the Document1 because I did a revert on it. It ran all wrong assuming because the now doc ID wasn't then what was expected?
That's why I was asking if there is a way to tell a document that is in a particular window vs just the ID of the document.
Copy link to clipboard
Copied
Hi Jeff,
is there a chance that you selected a table or table cells in three of your open documents?
Regards,
Uwe Laubender
( ACP )
Copy link to clipboard
Copied
Hi Uwe,
No, usually, I only have two document open when I do this. BUT, on occasion, I need to look a third document to see if I need to make any change. I do annual reports, so I start with the English version, then, transfer the French data in the formatted table in the English, it works great. But sometimes, I need to adjust the table for the french, so I look at what had been done from last year's document. That's why sometimes, I need the script to run even if there is 3 document open. But I never actually select on more than two documents at a time.
Copy link to clipboard
Copied
Hi Jeff,
alright. Then we could look into every open document and see if and what actually is selected.
From your previous posts I understand that the target document is always the active one.
Where I am still unsure is:
In what order should the contents be applied.
Source cells selected:
Target cells selected:
Possible result A:
Possible result B:
FWIW: I think that something like that was already discussed years ago in the former InDesign Scripting Forum. With a solution. But I am not able to find the discussion again.
What I can offer for now is ExtendScript (JavaScript) code to discern the source selection from the target selection.
Also code that collects the unformatted content of the source and code to collect the target cells:
( function()
{
// Get all open documents:
var allOpenDocs = app.documents.everyItem().getElements();
// My assumption
// The target document is the one you clicked to the front in one of the layout windows:
var targetDoc = app.documents[0];
// In that document you did a selection of table cells.
// Either the whole table, all cells are selected, OR only some cells are selected:
var targetSelection = targetDoc.selection[0];
// Source selection is not known, we have to detect it:
var sourceSelection;
// Loop all documents but the top most with the target selection:
for( var n=1; n<allOpenDocs.length; n++ )
{
// The least we can do is to check if there is a selection with length 1.
// If the selection length is not 1 do nothing and continue the loop:
if( allOpenDocs[n].selection.length != 1 ){ continue };
// Next check if table cells are selected, when identified break the loop:
if( allOpenDocs[n].selection[0].hasOwnProperty("cells") )
{
sourceSelection = allOpenDocs[n].selection[0] ;
break;
};
};
// No source selection found, alert and do nothing:
if( sourceSelection == undefined ){ alert( "No target selection found. | SCRIPT " ); return };
// All unformatted contents of the source is stored in an array:
var sourceContentsArray = sourceSelection.cells.everyItem().contents;
// We identified the target selection, made sure that cells are selected.
// Store all selected cells in an array:
var targetCells = targetSelection.cells.everyItem().getElements();
}() )
Regards,
Uwe Laubender
( ACP )
Copy link to clipboard
Copied
Thanks Uwe,
I can live with always having my target document the active one, that's usually what I do anyway.
For the question of how do I deal with mapping the cells, I check if I have the same number of rows and columns, if it's not the same, then the script stops and tells me the difference between the two. So either I selected the wrong range or something funny is happening. So your results A and B are moot in my case.
Good idea to check if the document has a selection, assuming that the target document is always the active one, that should work. Now I have to figure out how to do it in Applescript;-) Thanks for the idea!
Copy link to clipboard
Copied
You can refer to documents by name. In JavaScript that would something like
app.documents.item ('document1.indd')
app.documents.item ('document2.indd')
and you can assign these to variables for easy reference:
var doc1 = app.documents.item ('document1.indd');
var doc2 = app.documents.item ('document2.indd');
Something similar should be possible in AppleScript.
P.
Copy link to clipboard
Copied
Hi,
In AppleScript it would be some thing like
tell application "Adobe InDesign 2020"
set doc1 to every document whose title is "Untitled-1"
end tell
Regards
Malcolm
Copy link to clipboard
Copied
Could you add a label to the documents when they are created, so they can be reliably id’d? So:
tell application id "com.adobe.indesign"
set label of active document to "Unformatted"
end tell
tell application id "com.adobe.indesign"
set label of active document to "Formatted"
end tell
Then you could have any number of documents open and bring the two documents to the front or make them variables
tell application id "com.adobe.indesign"
set active document to item 1 of every document whose label is "Formatted"
set active document to item 1 of every document whose label is "Unformatted"
end tell
Copy link to clipboard
Copied
Great idea Ray!
I'm not setting the label on the creation of the document, but I can run a small script to apply that label, which won't change anyway and will be sticky so I would have to apply it just once for the source document since it will be used for multiple formatted documents.
I'm just stock with the variable though. In your exemple,
set formattedDoc to item 1 of every document whose label is "Formatted"
I get
{Document ID 1 of application "Adobe InDesign CC 2019"}
if I do
set formattedDoc to active document
I get
Document ID 1 of application "Adobe InDesign CC 2019"
Which I can then reference with selections and all that good stuff. I know this is basic stuff but for the life of me, how do I get the content of item 1 not as a list?
Copy link to clipboard
Copied
I think you are looking for the index, not the id
tell application id "com.adobe.indesign"
set formatDoc to item 1 of every document whose label is "Formatted"
get formatDoc
--a single item list: {document id 2 of application "Adobe InDesign 2020"}
get item 1 of formatDoc
--document id 2 of application "Adobe InDesign 2020"
get id of item 1 of formatDoc
--returns the document’s id, which is not its display order, for that you need index
get index of item 1 of formatDoc
--the index is the display order, the active document‘s index is 1
end tell
tell application id "com.adobe.indesign"
set formatDoc to item 1 of every document whose label is "Formatted"
set i to index of item 1 of formatDoc
--these are equivalent
get properties of document i
get properties of item 1 of formatDoc
end tell
Copy link to clipboard
Copied
Thanks to everyone!
I found the solution, don't know if it was the right way to do it, but it works and I worked with the script all day yesterday and it was fantastic!
For those interested, here it is.
--Table Data replace
--Use this script to replace data in a table already designed.
--This script requires two documents open, before running this script,
--run the 02-set label formatted on the document with the formatted table and 02-set label unformatted on the document with the unformatted table.
tell application id "com.adobe.indesign"
if (count of documents) is less than 2 then
beep
activate
display dialog "This script requires two documents open, please open another document." buttons {"OK"}
return
end if
try
set formattedDoc to item 1 of every document whose label is "Formatted"
set myFormattedDoc to item 1 of formattedDoc
on error
beep
activate
display dialog "This script requires two documents open, one with a Formatted Label, please run the script 02-set label formatted." buttons {"OK"}
return
end try
try
set unformattedDoc to item 1 of every document whose label is "Unformatted"
set myUnformattedDoc to item 1 of unformattedDoc
on error
beep
activate
display dialog "This script requires two documents open, one with a Unformatted Label, please run the script 02-set label unformatted." buttons {"OK"}
return
end try
set columnCount1 to count of columns of selection of myFormattedDoc
set rowCount1 to count of rows of selection of myFormattedDoc
set columnCount2 to count of columns of selection of myUnformattedDoc
set rowCount2 to count of rows of selection of myUnformattedDoc
if (rowCount1 is not equal to rowCount2) then
beep
activate
display dialog "The number of rows don't match." & return & " You have " & rowCount1 & " rows for the document formatted vs " & return & rowCount2 & " rows for the document unformatted." buttons {"OK"}
return
else if (columnCount1 is not equal to columnCount2) then
beep
activate
display dialog "The number of columns don't match." & return & " You have " & columnCount1 & " columns for the document in formatted vs " & return & columnCount2 & " columns for the document unformatted." buttons {"OK"}
return
end if
set ourData to contents of selection of myUnformattedDoc
set contents of selection of myFormattedDoc to ourData
end tell
The only thing still not working is if I have merged cells in the formatted table, then the number of column or row don't match and it gives me the error. But other then that, all is good. Thanks again guys!