Copy link to clipboard
Copied
Hi everybody.
I browsed hours and hours without finding a useful solution to my issue: I will have to import data within a table.
Among the imported data, there will be a string of text having RGB or CMKY value.
I'd like that such content will be processed by the script in order to fill a cell background based on value.
Is is possible?
If we assume 3 numbers equals an RGB value and 4 a CMYK value, then here’s an example that checks all the cells in the 3rd column of the document’s first table, and sets the fillColor to the content values:
var d = app.activeDocument
var c = d.stories.everyItem().tables[0].columns[2].cells.everyItem().getElements();
var fc, cv;
var ca= []
for (var i = 0; i < c.length; i++){
cv = c[i].contents.split(",");
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
...
You could remove the contents:
var d = app.activeDocument
var tf = d.textFrames.everyItem().getElements();
var fc, cv, vn;
var ca= []
for (var i = 0; i < tf.length; i++){
cv = tf[i].contents.split(",");
if (cv.length == 3 || cv.length == 4) {
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
vn=0
for (var x in ca) {
vn += ca[x]
}
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
...
This should work:
var tf = d.pages.everyItem().textFrames.everyItem().getElements();
Copy link to clipboard
Copied
Yes, that's possible. Show us what you've got.
Copy link to clipboard
Copied
Techincally speaking, I am not a developer and I'm sorry because I cannot write a working script.
I assumed it is possible to start from a basic concept like this and working on something like this one.
I sneaked peak into this link to understand a bit object, method, properties, and it seems feasible.
I was wondering if I'm the only one in need for this matter.
Copy link to clipboard
Copied
Hi @zaitexspa , the fill color’s value is an array of numbers (.colorValue), so for a script to work you would have to convert the cell’s text into an array of numbers and know what the exprected color mode is. Is the text 0/0/0/0, or 0|0|0|0, or 0,0,0,0? If it’s 4 numbers we can assume it’s a CMYK value, but if it’s 3 is it RGB, Lab, or HSB?
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Color.html
Copy link to clipboard
Copied
This thread may be a better help for a base script for you to work off of:
https://community.adobe.com/t5/indesign-discussions/applying-cell-style-to-specific-cells-in-table-b...
Copy link to clipboard
Copied
Same question as Rob: can you show how those values appear in the cells? A screenshot would help.
Copy link to clipboard
Copied
@rob day said: "If it’s 4 numbers we can assume it’s a CMYK value…"
Playing devil's advocate: Or perhaps an rgba value ??!
Fun aside, the OP states that it will be RGB or CMYK. So that's clear, I think:
"Among the imported data, there will be a string of text having RGB or CMKY value."
@zaitexspa , it's important how the data is presented.
The word "Among" is showing that there is perhaps more than three or four numbers.
So you'd need an algorithm to part the color values from all other contents in a given table cell.
In essence: we need examples.
Regards,
Uwe Laubender
( Adobe Community Expert )
Copy link to clipboard
Copied
Hi guys, thanks for your reply.
I can import RGB or CMYK value like 255,255,255 or 0,0,0,100 - I would rather import those values from csv, so no problem.
Attached an example.
Copy link to clipboard
Copied
That doesn't make it much clearer. Whre are the colour values? How are they represented?
Copy link to clipboard
Copied
If we assume 3 numbers equals an RGB value and 4 a CMYK value, then here’s an example that checks all the cells in the 3rd column of the document’s first table, and sets the fillColor to the content values:
var d = app.activeDocument
var c = d.stories.everyItem().tables[0].columns[2].cells.everyItem().getElements();
var fc, cv;
var ca= []
for (var i = 0; i < c.length; i++){
cv = c[i].contents.split(",");
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
}
ca = [];
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}
Sample result:
Copy link to clipboard
Copied
Hi @rob day
many many thanks for your help!
I managed to assign a fill color to the text frame.
Plus, I managed to assign the same color to the included text, which is useless to keep readable.
I just tweaked your code as follows:
var d = app.activeDocument
//var c = d.stories.everyItem().tables[0].columns[2].cells.everyItem().getElements();
var c = d.textFrames.everyItem().getElements();
var fc, cv, cn;
var ca= []
for (var i = 0; i < c.length; i++){
cn = c[i].lines; // change color of the included text
cv = c[i].contents.split(",");
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
}
ca = [];
for(var w = 0; w < cn.length; w++) {
cn[w].fillColor = fc;
}
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}
My last concern is: how can I change the background fill color (and the included text color) of a specific textframe?
If I'm not wrong, in your case, you pointed out every cell of the third column of a table; in my case, I'd like to select a specific textframe.
So, rather than use
var c = d.textFrames.everyItem().getElements();
which might be catching all the textFrames in the document, I'd like to run the script just for a specific one.
I tried alternatively unsuccessfully to use this:
var c = d.textFrames.itemByName("test");
cn = d.contents;
but... it won't work and it makes useless the for loop. I got an error by Indesign.
Copy link to clipboard
Copied
Can you share a sample document?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hi @zaitexspa , itemByName probably won‘t work unless you actually give the text frame a name in the Layers panel. In the doc you posted "test" is a layer name not a text frame name, and a text frame’s name returns "" unless you give it a name.
You could get all of the text frames and assume if their contents gets split into an array using the "," delimiter and the length is either 3 or 4 it’s a color value string. You could also set up your color values with a less common separator something like 0|0|0, then use .contents.split("|"). Maybe some one else has a better idea?
Also here I’m getting the color’s total value and setting the contents color to either black or white depending on the value returned:
var d = app.activeDocument
var tf = d.textFrames.everyItem().getElements();
var fc, cv, vn;
var ca= []
for (var i = 0; i < tf.length; i++){
cv = tf[i].contents.split(",");
if (cv.length == 3 || cv.length == 4) {
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
vn=0
for (var x in ca) {
vn += ca[x]
}
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
tf[i].fillColor = fc;
if (vn/3 < 128) {
tf[i].texts[0].fillColor = "Paper"
} else {
tf[i].texts[0].fillColor = "Black"
}
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
tf[i].fillColor = fc;
if (vn/4 < 50) {
tf[i].texts[0].fillColor = "Black"
} else {
tf[i].texts[0].fillColor = "Paper"
}
}
}
ca = [];
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}
Copy link to clipboard
Copied
Thanks @rob day
my purpose is to get rid of the text which makes the textframe fill color, so I rather changed to "None" Black or White to hide it in a way.
Other solutions on that? Maybe cancel the textframe content? Otherwise it's ok for me.
This is the final code:
var d = app.activeDocument
//var c = d.stories.everyItem().tables[0].columns[2].cells.everyItem().getElements();
var c = d.textFrames.everyItem().getElements();
var fc, cv, cn;
var ca= []
for (var i = 0; i < c.length; i++){
cn = c[i].contents; // change color of the included text
cv = c[i].contents.split(",");
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
c[i].texts[0].fillColor = "None"
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
c[i].texts[0].fillColor = "None"
}
ca = [];
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}
Copy link to clipboard
Copied
You could remove the contents:
var d = app.activeDocument
var tf = d.textFrames.everyItem().getElements();
var fc, cv, vn;
var ca= []
for (var i = 0; i < tf.length; i++){
cv = tf[i].contents.split(",");
if (cv.length == 3 || cv.length == 4) {
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
vn=0
for (var x in ca) {
vn += ca[x]
}
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
tf[i].fillColor = fc;
tf[i].contents = "";
tf[i].contentType = ContentType.UNASSIGNED;
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
tf[i].fillColor = fc;
tf[i].contents = "";
tf[i].contentType = ContentType.UNASSIGNED;
}
}
ca = [];
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}
Copy link to clipboard
Copied
Super solved this thread! Thank you all guys. I hope this will be useful for someone else.
Copy link to clipboard
Copied
@rob day is there a way to only select the pages of a document, excluding the master page?
Copy link to clipboard
Copied
This should work:
var tf = d.pages.everyItem().textFrames.everyItem().getElements();
Copy link to clipboard
Copied
Hi @rob day
I switched to Ventura and latest Indesign.
It happens the script affects the master pages too.
How to avoid?
Copy link to clipboard
Copied
Not sure if the upgrade would change anything, but try this:
var d = app.activeDocument
var c = d.stories.everyItem().tables[0].columns[2].cells.everyItem().getElements();
var fc, cv;
var ca= []
for (var i = 0; i < c.length; i++){
if (c[i].parent.parent.parent.parentPage.documentOffset > -1) {
cv = c[i].contents.split(",");
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
c[i].fillColor = fc;
}
ca = [];
}
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}
Copy link to clipboard
Copied
@rob day this is the error I get with your latest piece of code:
Copy link to clipboard
Copied
@zaitexspa said: "It happens the script affects the master pages too."
Hm. Hard to believe with a code like the one by Rob Day that text frames on parent pages are the scope.
Let's do a test document. Put one text frame on parent page A and another one on the first page of a new document. Run code 1 below and look into the alert. It should give you this result:
1, [object Spread]
The name of the page the text frame is positioned is "1" ; its spread is a normal spread and no parent one.
Code 1
var tf = app.documents[0].pages.everyItem().textFrames.everyItem().getElements();
var resultArray = [];
for( var n=0; n<tf.length; n++ )
{
resultArray[n] = tf[n].parentPage.name +", "+ tf[n].parent.toString();
};
alert
(
resultArray.join("\r")
);
Run code 2 on the same document.
Now the text frame on one of the pages of parent spread A is detected. Thus the alert message should look a bit different:
A, [object MasterSpread]
Code 2
var tf = app.documents[0].masterSpreads.everyItem().pages.everyItem().textFrames.everyItem().getElements();
var resultArray = [];
for( var n=0; n<tf.length; n++ )
{
resultArray[n] = tf[n].parentPage.name +", "+ tf[n].parent.toString();
};
alert
(
resultArray.join("\r")
);
If you see A, [object MasterSpread] also with code 1 in the alert, you have a serious problem with InDesign or your particular document.
FWIW: I cannot see a change in behavior with my German InDesign 2023 version 18.3.0 on Windows 10.
All results like expected. Rob's code should work:
var tf = d.pages.everyItem().textFrames.everyItem().getElements();
Regards,
Uwe Laubender
( Adobe Community Expert )
Copy link to clipboard
Copied
@Laubender this is a video for you demonstrating it affects master pages too...
Notice that I still have to try latest @rob day edit.
Copy link to clipboard
Copied
I actually re-test the following code and it seems to work - thanks to everybody for the success! I hope it could be useful for someone else.
var d = app.activeDocument
var tf = d.pages.everyItem().textFrames.everyItem().getElements();
var fc, cv, vn;
var ca= []
for (var i = 0; i < tf.length; i++){
cv = tf[i].contents.split(",");
if (cv.length == 3 || cv.length == 4) {
for (var n = 0; n < cv.length; n++){
ca.push(Number(cv[n]))
};
vn=0
for (var x in ca) {
vn += ca[x]
}
if (ca.length == 3) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.RGB, model:ColorModel.PROCESS, colorValue:ca}
tf[i].fillColor = fc;
tf[i].contents = "";
tf[i].contentType = ContentType.UNASSIGNED;
}
if (ca.length == 4) {
fc = makeSwatch(d, ca.toString())
fc.properties = {space:ColorSpace.CMYK, model:ColorModel.PROCESS, colorValue:ca}
tf[i].fillColor = fc;
tf[i].contents = "";
tf[i].contentType = ContentType.UNASSIGNED;
}
}
ca = [];
};
/**
* Makes a new named Swatch
* @ param the document to add the color to
* @ param color name
* @ return the new swatch
*/
function makeSwatch(d, n){
if (d.colors.itemByName(n).isValid) {
return d.colors.itemByName(n);
} else {
return d.colors.add({name:n});
}
}