Skip to main content
Community Expert
April 17, 2024
Question

Table resize (script) - match column width but proportionally

  • April 17, 2024
  • 2 replies
  • 817 views

Originally I have this script which works on an entire frame width

So if you have multiple text frames in columns it's fine - and resizes it proportionally enough for me.

 

// Check if a document is open
if (app.documents.length > 0) {
  var doc = app.activeDocument;
  
  // Check if a table is selected
  if (app.selection.length > 0 && app.selection[0] instanceof Table) {
    var table = app.selection[0];
    var frame = table.parent;

    // Get the width of the text frame
    var frameWidth = frame.geometricBounds[3] - frame.geometricBounds[1];

    // Consider text frame insets
    var frameInset = frame.textFramePreferences.insetSpacing;

    // Adjust frameWidth for insets
    frameWidth -= frameInset[1] + frameInset[3];

    // Get the number of columns
    var numColumns = table.columns.length;

    // Calculate the total width of all columns
    var totalColumnWidth = 0;
    for (var i = 0; i < numColumns; i++) {
      totalColumnWidth += table.columns[i].width;
    }

    // Calculate the ratio to maintain the proportional relationship
    var ratio = frameWidth / totalColumnWidth;

    // Resize each column proportionally
    for (var i = 0; i < numColumns; i++) {
      table.columns[i].width *= ratio;
    }

    // Resize the table to the width of the text frame (considering insets)
    table.width = frameWidth;

    alert("Table resized to the width of the text frame while maintaining column proportions!");
  } else {
    alert("Please select a table before running the script.");
  }
} else {
  alert("Open a document before running the script.");
}

 

 

But now I am encountering situations where there is a single text frame set to columns.
But I can't seem to get the table cells to be proportional (I don't want them all the same width)

---THIS IS THE SCRIPT I'M WORKING ON ----

// Check if a document is open
if (app.documents.length > 0) {
  var doc = app.activeDocument;
  
  // Check if a table is selected
  if (app.selection.length > 0 && app.selection[0] instanceof Table) {
    var table = app.selection[0];
    var frame = table.parent;

    // Get the selected text frame
    var myTextFrame = frame;

    // Get the number of columns and gutter width
    var myColAmount = myTextFrame.textFramePreferences.textColumnCount;
    var myGutterWidth = myTextFrame.textFramePreferences.textColumnGutter;

    // Calculate the total width of the text frame and available width for columns
    var myTextFrameBounds = myTextFrame.geometricBounds;
    var myTotalWidth = myTextFrameBounds[3] - myTextFrameBounds[1];
    var myAvailableWidth = myTotalWidth - (myGutterWidth * (myColAmount - 1));

    // Calculate the width of each column
    var myColumnWidth = myAvailableWidth / myColAmount;

    // Set the table width to match the calculated column width
    table.width = myColumnWidth;

    alert("Table width set to match the column width of the text frame!");
  } else {
    alert("Please select a table before running the script.");
  }
} else {
  alert("Open a document before running the script.");
}

 

 

This topic has been closed for replies.

2 replies

Community Expert
April 18, 2024

@rob day @Robert at ID-Tasker 

Thank you both so much 

I managed to tweak it a bit further - it wasn't quite right but amazing to get to this point, I didn't think I'd ever there!
I just added a tiny but extra reduction to account for table spill into the gutter so added a -0.3mm to compensate.

Wasn't sure of a better way to do it.

Seems to work, if you have any other ideas or better ways, that would be great. 
If not, thanks for all the help, once again! 

// Check if a document is open
if (app.documents.length > 0) {
    var doc = app.activeDocument;
    
    // Check if a table is selected
    if (app.selection.length > 0 && app.selection[0] instanceof Table) {
        var table = app.selection[0];
        var frame = table.parent;
  
        // Get the selected text frame
        var myTextFrame = frame;
  
        // Get the number of columns and gutter width
        var myColAmount = myTextFrame.textFramePreferences.textColumnCount;
        var myGutterWidth = myTextFrame.textFramePreferences.textColumnGutter;

        // Get the inset values
        var myInsets = myTextFrame.textFramePreferences.insetSpacing;

        // Calculate the total width of the text frame considering insets
        var myTextFrameBounds = myTextFrame.geometricBounds;
        var myTotalWidth = myTextFrameBounds[3] - myTextFrameBounds[1] - myInsets[1] - myInsets[3];
  
        // Calculate the total gutter width
        var totalGutterWidth = myGutterWidth * (myColAmount - 1);

        // Calculate the available width for columns
        var myAvailableWidth = myTotalWidth - totalGutterWidth;
  
        // Calculate the width of each column
        var myColumnWidth = myAvailableWidth / myColAmount;

        // Reduce the calculated column width by 0.3mm
        var adjustedTableWidth = myColumnWidth - 0.3;

        // Set the table width to match the adjusted width
        table.width = adjustedTableWidth;

        // Get the width of each column as a percentage of the adjusted table width
        var ca = [];
        var tw = adjustedTableWidth;
        var tc = table.columns.everyItem().getElements();
        for (var i = 0; i < tc.length; i++) {
            ca.push(tc[i].width / tw);
        }

        // Adjust the resized table’s column percentages
        setColumnWidths(table, ca);
  
        //alert("Table width set to match the column width of the text frame minus 0.3mm!");
    } else {
        alert("Please select a table before running the script.");
    }
} else {
    alert("Open a document before running the script.");
}

/**
* Sets a table’s column widths
* @ param the table 
* @ param percentage 
* @ return void 
* 
*/
function setColumnWidths(t, a){
    var tw = t.width;
    var tc = t.columns.everyItem().getElements();
    if (tc.length == a.length) {
        var ci = tc[0].leftInset * a[0]
        for (var i = 0; i < tc.length; i++){
            tc[i].width = tw*a[i];
            tc[i].leftInset = ci;
            tc[i].rightInset = ci;
        }; 
    } 
}

 

Community Expert
April 18, 2024

One slight issue
It says NaN error when the text frame is not exactly square
I'm guessing this is because the Text Frame inset left and right are not relevant for a text frame that's not exactly a rectangle/square.

Hmm.. the plot thickens

Community Expert
April 18, 2024

For reference, it must fit within a specific area and some areas are reserved for specific items, so some text frames are kinda done with the pen tool so the text avoids the specific areas - which is a legacy thing and won't change. 

 

 

rob day
Community Expert
Community Expert
April 17, 2024

Hi @Eugene Tyson , I think you would have to get and set the column widths—you are looking for something like this?

 

 

Before

 

After

 

 

 

 

// Check if a document is open
if (app.documents.length > 0) {
    var doc = app.activeDocument;
    
    // Check if a table is selected
    if (app.selection.length > 0 && app.selection[0] instanceof Table) {
        var table = app.selection[0];
        var frame = table.parent;
  
        // Get the selected text frame
        var myTextFrame = frame;
  
        // Get the number of columns and gutter width
        var myColAmount = myTextFrame.textFramePreferences.textColumnCount;
        var myGutterWidth = myTextFrame.textFramePreferences.textColumnGutter;
  
        // Calculate the total width of the text frame and available width for columns
        var myTextFrameBounds = myTextFrame.geometricBounds;
        var myTotalWidth = myTextFrameBounds[3] - myTextFrameBounds[1];
        var myAvailableWidth = myTotalWidth - (myGutterWidth * (myColAmount - 1));
  
        // Calculate the width of each column
        var myColumnWidth = myAvailableWidth / myColAmount;

        //get the width of each column as a percentage of the table width
        var ca = getColumnWidths(table)

        // Set the table width to match the calculated column width
        table.width = myColumnWidth;

        //adjust the resized table’s column percentages
        setColumnWidths(table, ca)
  
      //alert("Table width set to match the column width of the text frame!");
    } else {
      alert("Please select a table before running the script.");
    }
  } else {
    alert("Open a document before running the script.");
  }


/**
* Gets an array of column widths as a percentage relative to the table width 
* @ param the table 
* @ return an array of column percentages 
* 
*/
function getColumnWidths(t){
    var ca = []
    var tw = t.width;
    var tc = t.columns.everyItem().getElements()
    for (var i = 0; i < tc.length; i++){
        ca.push(tc[i].width/tw)
    };   
    return ca
}


/**
* Sets a table’s column widths to the provided array of percentages
* @ param the table 
* @ param an array of column percentages 
* @ return void 
* 
*/
function setColumnWidths(t, a){
    var tw = t.width;
    var tc = t.columns.everyItem().getElements();
    if (tc.length == a.length) {
        for (var i = 0; i < tc.length; i++){
            tc[i].width = tw*a[i]
        }; 
    } 
}
Community Expert
April 17, 2024

Yeh, I thought I was getting the column widths - because it resized it to the column width, but equal proportions.
I'll give it a go. 

Thanks