Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Change Table Selected Cells to Red font

Enthusiast ,
Aug 12, 2025 Aug 12, 2025

@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!

TOPICS
Scripting
321
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Aug 12, 2025 Aug 12, 2025

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
...
Translate
Community Expert , Aug 12, 2025 Aug 12, 2025

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;
Translate
Community Expert ,
Aug 12, 2025 Aug 12, 2025

What is the basic task here? Are you trying to loop through all of the paragraphs in a table?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 12, 2025 Aug 12, 2025

I think I see what you are trying to do; just process the paragraphs in the selected cells.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 12, 2025 Aug 12, 2025

Correct, I'm having a hard time getting to the apppropriate cells, though ... See error messages above.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 12, 2025 Aug 12, 2025

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;
}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 12, 2025 Aug 12, 2025

@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?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 12, 2025 Aug 12, 2025

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;
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 12, 2025 Aug 12, 2025

@frameexpert Works like a charm!!! - THANK YOU!!!!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 13, 2025 Aug 13, 2025

@frameexpert - I have a follow-up question, which is hardly worth bothering with, but I'll ask anyway:

  • The script in this thread works great if I have a table or any part of a table selected (and nothing else).
  • The script in the previous thread mentioned in the initial post works fine if I have text selected (but no table).

Now, if I happen to select text before and after a table with the table included:

  • The previous script changes the text before and after the table red, but leaves the table alone.
  • The script in this thread does not change the table text, unless I specifically select the table.

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!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 20, 2025 Aug 20, 2025

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;
    }
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 20, 2025 Aug 20, 2025
LATEST

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;
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines