Copy link to clipboard
Copied
@frameexpert - Appreciate you looking at this. I have about 1/3 of what I need, but I'm over my head and hopefully, there is a simpler way.
What I want to do is take - https://community.adobe.com/t5/framemaker-discussions/script-to-change-red-text-to-black/td-p/152932... and expand it to work with a table selection.
I also saw: https://community.adobe.com/t5/framemaker-discussions/iterate-all-tables-in-framemaker/m-p/10338583
I found a couple of supposedly decent scripts from a google search - first:
// Get the active document
var doc = app.ActiveDoc;
// Check if a table is selected
if (doc.SelectedTbl.ObjectValid()) {
var oTable = doc.SelectedTbl;
// Get the row and column information of the selection
var topRow = oTable.TopRowSelection;
var bottomRow = oTable.BottomRowSelection;
var leftCol = oTable.LeftColNum;
var rightCol = oTable.RightColNum;
// Iterate through the selected rows and columns to access individual cells
var currentRow = topRow;
while (currentRow.ObjectValid() && currentRow.RowNum <= bottomRow.RowNum) {
var currentCol = leftCol;
while (currentCol <= rightCol) {
// Get the current cell object (using currentRow.Cell[currentCol] if needed to be more efficient, but let's stick to the current API)
var oCell = currentRow.Cell(currentCol);
// Do something with the cell (e.g., get its contents, format it)
Alert("Row: " + currentRow.RowNum + ", Column: " + currentCol + ", Cell Content: " + oCell.FirstPgf.GetText());
currentCol++;
}
currentRow = currentRow.NextRowInTable; // Move to the next row in the table
}
} else {
Alert("No table selected. Please select a table or cells within a table and run the script again.");
}
Gives me an error that currentRow.Cell is not a valid function.
and
#target framemaker
var doc = app.ActiveDoc; // Get the active FrameMaker document
if (doc) {
// var table = doc.Tables.First(); // Get the first table in the document (adjust as needed)
var table = doc.SelectedTbl;
if (table) {
var cell = table.Cells.Item(1, 1); // Get the cell at row 1, column 1 (adjust row and column)
if (cell) {
var textRange = cell.TextRanges.First(); // Get the first text range within the cell
if (textRange) {
var charProps = new PropVals(); // Create a new PropVals object for character properties
var propVal = new PropVal();
// Set the color property
propVal.propType = Constants.FP_CharColor;
propVal.propValType = Constants.FV_Color;
propVal.propVal = Constants.FV_ColorRed; // Set to red (you can use other color constants or define custom colors)
charProps.push(propVal);
// Apply the character properties to the text range
doc.SetTextPropVals(textRange.beg, textRange.end, charProps);
}
}
}
}
Gives me an error that table.Cells.item(1, 1) is undefined.
From the linked thread, I think I need to do something like (based on the first Google script):
...
var oCell = currentRow.FirstCellInRow
if (leftCol > 1){
For i = 1 to leftCol-1 { \\ If leftCol = 2, run the loop once
oCell = oCell.NextCellinRow
}
\\ Do something with current cell.
}
\\ *****
But I think I have the for loop syntax incorrect, and I'm not sure if this is an overcomplicated approach.
Thanks in advance!
In my opinion, a best practice for coding is to break things down into individual functions. This facilitates easier troubleshooting and code reuse. For example, here I have a utility function that collects all of the selected cells in an array, which can then be processed elsewhere.
main ();
function main () {
var doc, tbl;
doc = app.ActiveDoc;
if (doc.ObjectValid () === 1) {
tbl = doc.SelectedTbl;
if (tbl.ObjectValid () === 1) {
processTbl (tb
...
Because your beg.offset and end.offset are both zero, you are essentially making a selection at the beginning of the paragraph. You need to select the whole paragraph:
textRange = new TextRange ();
textRange.beg.obj = textRange.end.obj = pgf;
textRange.beg.offset = 0;
textRange.end.offset = Constants.FV_OBJ_END_OFFSET;
Copy link to clipboard
Copied
What is the basic task here? Are you trying to loop through all of the paragraphs in a table?
Copy link to clipboard
Copied
I think I see what you are trying to do; just process the paragraphs in the selected cells.
Copy link to clipboard
Copied
Correct, I'm having a hard time getting to the apppropriate cells, though ... See error messages above.
Copy link to clipboard
Copied
In my opinion, a best practice for coding is to break things down into individual functions. This facilitates easier troubleshooting and code reuse. For example, here I have a utility function that collects all of the selected cells in an array, which can then be processed elsewhere.
main ();
function main () {
var doc, tbl;
doc = app.ActiveDoc;
if (doc.ObjectValid () === 1) {
tbl = doc.SelectedTbl;
if (tbl.ObjectValid () === 1) {
processTbl (tbl, doc);
}
}
}
function processTbl (tbl, doc) {
var cells, count, i;
// Get all of the selected cells in the table.
cells = getSelectedCells (tbl);
// Process the cells.
count = cells.length;
for (i = 0; i < count; i += 1) {
processCell (cells[i], doc);
}
}
function processCell (cell, doc) {
var pgf;
pgf = cell.FirstPgf;
while (pgf.ObjectValid () === 1) {
// Process the paragraph.
processPgf (pgf, doc);
pgf = pgf.NextPgfInFlow;
}
}
function processPgf (pgf, doc) {
// Process your paragraph here.
}
function getSelectedCells (tbl) {
var cells, row, bottomRow, leftCol, rightCol, cell;
// An array of table cell objects.
cells = [];
// Get the current table selection boundaries.
row = tbl.TopRowSelection;
bottomRow = tbl.BottomRowSelection;
leftCol = tbl.LeftColNum;
rightCol = tbl.RightColNum;
// Loop through the selected rows and pick up the selected cells.
while (row.ObjectValid () === 1) {
cell = row.FirstCellInRow;
while (cell.ObjectValid () === 1) {
if ((cell.CellColNum >= leftCol) && (cell.CellColNum <= rightCol)) {
// Ignore straddled cells; they contain no paragraphs.
if (cell.CellIsStraddled === 0) {
// The cell is within the selection; push it onto the array.
cells.push (cell);
}
}
cell = cell.NextCellInRow;
}
// If we are at the bottom selected row;
// break out of the loop.
if (row.id === bottomRow.id) {
break;
}
row = row.NextRowInTbl;
}
return cells;
}
Copy link to clipboard
Copied
@frameexpert - Simply amazing and thank you, but I'm not getting it to work. It doesn't give me an error, but it doesn't change the color either. Here's what I'm trying for processPgf:
function processPgf (pgf, doc) {
// Process your paragraph here.
var textRange = new TextRange();
textRange.beg.obj = textRange.end.obj = pgf;
textRange.beg.offset = textRange.end.offset = 0;
applyTextColor(textRange, 'Red', doc)
}
Where applyTextColor is your function from the previous thread. What am I doing incorrectly?
Copy link to clipboard
Copied
Because your beg.offset and end.offset are both zero, you are essentially making a selection at the beginning of the paragraph. You need to select the whole paragraph:
textRange = new TextRange ();
textRange.beg.obj = textRange.end.obj = pgf;
textRange.beg.offset = 0;
textRange.end.offset = Constants.FV_OBJ_END_OFFSET;
Copy link to clipboard
Copied
@frameexpert Works like a charm!!! - THANK YOU!!!!
Copy link to clipboard
Copied
@frameexpert - I have a follow-up question, which is hardly worth bothering with, but I'll ask anyway:
Now, if I happen to select text before and after a table with the table included:
Ideally, I would like the script(s) to change ALL of the selected text red, whether it is part of a table or not.
Is there an EASY way to accomplish this?
If not, what I have is still a tremendous improvement!
Copy link to clipboard
Copied
This doesn't answer your question directly, but did notice something about my code. There are situations where an entire table is selected, including the table title. My script would skip the selected table title, so I added a test for it and renamed one of the functions.
function processTbl (tbl, doc) {
var cells, count, i;
// See if the title is selected.
if (tbl.TblTitleSelected === 1) {
processTitleOrCell (tbl, doc);
}
// Get all of the selected cells in the table.
cells = getSelectedCells (tbl);
// Process the cells.
count = cells.length;
for (i = 0; i < count; i += 1) {
processTitleOrCell (cells[i], doc);
}
}
function processTitleOrCell (obj, doc) {
// obj is either a table or cell object.
var pgf;
pgf = obj.FirstPgf;
while (pgf.ObjectValid () === 1) {
// Process the paragraph.
processPgf (pgf, doc);
pgf = pgf.NextPgfInFlow;
}
}
Copy link to clipboard
Copied
Here is a complete script that should do what you want.
main ();
function main () {
var colorName, doc, tbl;
colorName = "Black";
doc = app.ActiveDoc;
if (doc.ObjectValid () === 1) {
tbl = doc.SelectedTbl;
if (tbl.ObjectValid () === 1) {
processSelectedTbl (tbl, doc, colorName);
}
else {
processSelection (doc.TextSelection, doc, colorName);
}
}
}
function processSelection (textRange, doc, colorName) {
var textList, count, i, tbl;
// Process the text range here.
applyTextColor (textRange, colorName, doc);
// See if the text range has any tables in it.
textList = doc.GetTextForRange (textRange, Constants.FTI_TblAnchor);
count = textList.length;
for (i = 0; i < count; i += 1) {
tbl = textList[i].obj;
processTbl (tbl, doc, colorName);
}
}
function processTbl (tbl, doc, colorName) {
var cell;
if (tbl.TblTitlePosition === Constants.FV_TBL_TITLE_ABOVE) {
processTitleOrCell (tbl, doc, colorName);
}
cell = tbl.FirstRowInTbl.FirstCellInRow;
while (cell.ObjectValid () === 1) {
if (cell.CellIsStraddled === 0) {
processTitleOrCell (cell, doc, colorName);
}
cell = cell.NextCellInTbl;
}
if (tbl.TblTitlePosition === Constants.FV_TBL_TITLE_BELOW) {
processTitleOrCell (tbl, doc, colorName);
}
}
function processSelectedTbl (tbl, doc, colorName) {
var cells, count, i;
// See if the title is selected.
if (tbl.TblTitleSelected === 1) {
processTitleOrCell (tbl, doc, colorName);
}
// Get all of the selected cells in the table.
cells = getSelectedCells (tbl);
// Process the cells.
count = cells.length;
for (i = 0; i < count; i += 1) {
processTitleOrCell (cells[i], doc, colorName);
}
}
function processTitleOrCell (obj, doc, colorName) {
// obj is either a table or cell object.
var pgf;
pgf = obj.FirstPgf;
while (pgf.ObjectValid () === 1) {
// Process the paragraph.
processPgf (pgf, doc, colorName);
pgf = pgf.NextPgfInFlow;
}
}
function applyTextColor (textRange, colorName, doc) {
var color, prop;
// Get the color object.
color = doc.GetNamedColor (colorName);
// Make sure the color exists in the document.
if (color.ObjectValid () === 1) {
// Make a property list containing the color.
prop = new PropVal ();
prop.propIdent.num = Constants.FP_Color;
prop.propVal.valType = Constants.FT_Id;
prop.propVal.obj = color;
// Apply the color to the text.
doc.SetTextPropVal (textRange, prop);
}
}
function processPgf (pgf, doc, colorName) {
var textRange;
// Process the paragraph.
textRange = new TextRange ();
textRange.beg.obj = textRange.end.obj = pgf;
textRange.beg.offset = 0;
textRange.end.offset = Constants.FV_OBJ_END_OFFSET;
applyTextColor (textRange, colorName, doc);
}
function getSelectedCells (tbl) {
var cells, row, bottomRow, leftCol, rightCol, cell;
// An array of table cell objects.
cells = [];
// Get the current table selection boundaries.
row = tbl.TopRowSelection;
bottomRow = tbl.BottomRowSelection;
leftCol = tbl.LeftColNum;
rightCol = tbl.RightColNum;
// Loop through the selected rows and pick up the selected cells.
while (row.ObjectValid () === 1) {
cell = row.FirstCellInRow;
while (cell.ObjectValid () === 1) {
if ((cell.CellColNum >= leftCol) && (cell.CellColNum <= rightCol)) {
// Ignore straddled cells; they contain no paragraphs.
if (cell.CellIsStraddled === 0) {
// The cell is within the selection; push it onto the array.
cells.push (cell);
}
}
cell = cell.NextCellInRow;
}
// If we are at the bottom selected row;
// break out of the loop.
if (row.id === bottomRow.id) {
break;
}
row = row.NextRowInTbl;
}
return cells;
}
Find more inspiration, events, and resources on the new Adobe Community
Explore Now