Skip to main content
Inspiring
August 12, 2025
Answered

Change Table Selected Cells to Red font

  • August 12, 2025
  • 2 replies
  • 550 views

@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/15293234/page/2 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!

Correct answer frameexpert

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;

2 replies

frameexpert
Community Expert
Community Expert
August 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;
}

 

Inspiring
August 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?

frameexpert
Community Expert
frameexpertCommunity ExpertCorrect answer
Community Expert
August 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;
frameexpert
Community Expert
Community Expert
August 12, 2025

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

frameexpert
Community Expert
Community Expert
August 12, 2025

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

Inspiring
August 12, 2025

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