Script: conditional formatting of table cells but exclude header row

Jun 26, 2020

Copy link to clipboard

Copied

Hello all,

 

I've got a script set up to apply a fill color to cells within a table based on the value found within each cell.

 

It was working fine; however, I just added a piece to it in attempt to have the script exclude the header row. I've already spent hours adapting the original script to my needs, but unfortunately this is where my knowledge, patience, and Google-fu ends.

 

The error I'm getting is this:

 

  • Error Number: 55
    Error String: Object does not support the property or method 'rowType'
    Engine: main
    File: /Users/c059822/Library/Preferences/Adobe InDesign/Version 14.0/en_US/Scripts/Scripts Panel/stoplight-cell-colors.jsx
    Line: 1
    Source: app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main()

 

And here's the script in its current state:

 

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < rows.length; r++)
		{
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = bodyRows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

Any help I can get would be majorly appreciated! Also, I'm new to the forum, so forgive me for any formatting, subject phrasing, etiquette, etc. that is missing here.

The idea in the code snippet shared by LSH_246 is correct but i see that even the row variable is not defined in the code, so foe the sake of completion i am posting the full version of the code that i think will serve the purpose

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		//var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < tables[i].rows.length; r++)
		{
			if(tables[i].rows[r].rowType != RowTypes.BODY_ROW)
				continue;
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = tables[i].rows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

-Manan

TOPICS
Bug, How to, Scripting

Views

247

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Script: conditional formatting of table cells but exclude header row

Jun 26, 2020

Copy link to clipboard

Copied

Hello all,

 

I've got a script set up to apply a fill color to cells within a table based on the value found within each cell.

 

It was working fine; however, I just added a piece to it in attempt to have the script exclude the header row. I've already spent hours adapting the original script to my needs, but unfortunately this is where my knowledge, patience, and Google-fu ends.

 

The error I'm getting is this:

 

  • Error Number: 55
    Error String: Object does not support the property or method 'rowType'
    Engine: main
    File: /Users/c059822/Library/Preferences/Adobe InDesign/Version 14.0/en_US/Scripts/Scripts Panel/stoplight-cell-colors.jsx
    Line: 1
    Source: app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main()

 

And here's the script in its current state:

 

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < rows.length; r++)
		{
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = bodyRows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

Any help I can get would be majorly appreciated! Also, I'm new to the forum, so forgive me for any formatting, subject phrasing, etiquette, etc. that is missing here.

The idea in the code snippet shared by LSH_246 is correct but i see that even the row variable is not defined in the code, so foe the sake of completion i am posting the full version of the code that i think will serve the purpose

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		//var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < tables[i].rows.length; r++)
		{
			if(tables[i].rows[r].rowType != RowTypes.BODY_ROW)
				continue;
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = tables[i].rows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

-Manan

TOPICS
Bug, How to, Scripting

Views

248

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Jun 26, 2020 0
Jun 26, 2020

Copy link to clipboard

Copied

Hi Ryan,

 

The line that has the error is the following

var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);

 

Here the issue is that you are trying to access the property rowType on the object rows which is a collection of rows. This property exits on a row object and not on the collection of rows. See the documentation of row object below

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Row.html

 

-Manan

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jun 26, 2020 1
Jun 26, 2020

Copy link to clipboard

Copied

You're looking for `rowType` on the collection of rows, rather than on the individual row.  Try starting your for loop like this instead (and delete the line immediately preceding the for loop):

 

for (var r = 0; r < rows.length; r++)
{
    if (rows[r].rowType != RowTypes.BODY_ROW) {
        continue;
    }
    var cells = rows[r].cells;

 

[edit - Manan beat me to it by 2 minutes! Leaving this code snippet though in case it's helpful.]

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jun 26, 2020 2
Jun 26, 2020

Copy link to clipboard

Copied

Thank you so much! You and Manan are so fast! You were both right, technically, but he already tagged you as correct, so I guess we'll let you keep it? 🙂

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jun 26, 2020 0
Jun 26, 2020

Copy link to clipboard

Copied

The idea in the code snippet shared by LSH_246 is correct but i see that even the row variable is not defined in the code, so foe the sake of completion i am posting the full version of the code that i think will serve the purpose

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		//var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < tables[i].rows.length; r++)
		{
			if(tables[i].rows[r].rowType != RowTypes.BODY_ROW)
				continue;
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = tables[i].rows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

-Manan

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jun 26, 2020 2
Jun 26, 2020

Copy link to clipboard

Copied

Thank you! This was easy to just copy and paste into the file. It works!!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jun 26, 2020 0
Jun 27, 2020

Copy link to clipboard

Copied

Hi Ryan,

you could also check the number of header rows before doing the loop with headerRowCount :

// Text frame with table selected:
var table = app.selection[0].tables[0];

var tableRowsArray = table.rows.everyItem().getElements();
var tableRowsArrayLength = tableRowsArray.length;

var startLoopAt = table.headerRowCount - 1;

for( var n=startLoopAt ; n<tableRowsArrayLength; n++ )
{
// DO YOUR THING
};

 

And if you do not want affect footer rows you can restrict the loop even more.

You perhaps guessed it, there is a footerRowCount property with tables as well.

 

Regards,
Uwe Laubender

( ACP )

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jun 27, 2020 1