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

Table resize (script) - match column width but proportionally

Community Expert ,
Apr 16, 2024 Apr 16, 2024

Copy link to clipboard

Copied

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.");
}

 

 

TOPICS
Scripting

Views

207

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

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

 

 

Before

Screen Shot 25.png

 

After

Screen Shot 26.png

 

 

 

 

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

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

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

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

Very good - just not taking into account if the text frame has an inset - but excellent
I'll see if I can tweak it.

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

I'll see if I can tweak it.

 

Would scaling the column insets along with the column widths work?

 


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];
            tc[i].leftInset = tc[i].leftInset*a[i];
            tc[i].rightInset = tc[i].rightInset*a[i];
        }; 
    } 
}

 

 

Before and after
Screen Shot 29.png
 
Screen Shot 30.png

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

Seems to - I'll know more tomorrow
Thanks for the help so far.

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

just not taking into account if the text frame has an inset

 

Scaling the insets for each column differently, probably doesn’t work. Might be better to get the first column’s scaled inset and use it for all?

 

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

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

quote

just not taking into account if the text frame has an inset

 

Scaling the insets for each column differently, probably doesn’t work. Might be better to get the first column’s scaled inset and use it for all?


By @rob day

 

I'm pretty sure, if you use my method - calculate the "scale" of the transformation - you can multiply insets by it - or any other aspect of the table - even the thickness of the edges - vertical ones of course.

 

For horizontal properties - scale of the difference in height should be calculated and used.

 

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

@rob day 

 

If I may, but I'm not sure if I get the reason for this part:

        // 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)

 

Right now, you are calcuating scale/percentage for each column - but isn't it the same for each column?

 

Can't we calculate it once:

var myScale = myAvailableWidth / table.width;

 

and then multiply each column by it?

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

I'm sorry if I'm missing something.

 

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

but isn't it the same for each column?

 

I think Eugene’s starting columns are different widths, and when he changes the width of the table they become the same—which he doesn’t want. If I run his OP code I get this:

 

Screen Shot 36.png

 

Screen Shot 34.png

 

He wants the resized table’s columns to keep their original proportions:

 

Screen Shot 37.png

 

 

 

 

 

 

Votes

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
community guidelines
Community Expert ,
Apr 17, 2024 Apr 17, 2024

Copy link to clipboard

Copied

quote

[...]

He wants this where the resized table’s columns are proportionally the same:


By @rob day

 

Yes, that's my point.

 

If you have a table with 4x columns:

20 | 30 | 40 | 50

Total width = 140

 

Let's assume - for simplicity - that the end width will be 70, then:

 

70 / 140 = 0.5

 

so:

20 * 0.5 = 10

30 * 0.5 = 15

40 * 0.5 = 20

50 * 0.5 = 25

 

and the total is 70...

 

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

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

 

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

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

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

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. 

 

 

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

I just added a tiny but extra reduction to account for table spill into the gutter

 

By spill do you mean the table/cells have stroke, which crosses into the gutter? Can you share a sample?

 

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

Just a basic table set into any multicolumn text frame 

If the text inset is 0.3mm then the reduction into the column should be the same on the right hand side.

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

But the "spill over" is caused by the stroke not the inset right? I get this with my code:

 

A table inside of a non square text frame

Screen Shot 38.pngScreen Shot 39.png

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

Yeh, I think so - so no part of the table can go past the gutter

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

One slight issue
It says NaN error when the text frame is not exactly square...

no part of the table can go past the gutter

 

The NaN is happening because you are skipping my getter function and writing your own loop, which is ok but you are getting the values after the table has been resized—if you don‘t want to use the getter function move your loop to before the table resize.

 

If the table/cell stroke value is known you could use it to adjust the final width, otherwise you would have to loop through the cells and get the max left and right stroke value, which could get tricky if there are different weights.

 

So in this example the left/right stroke is 5 points:

 

Screen Shot 40.pngScreen Shot 41.png

 

The stroke weight values are returned as points so I’ve set the measurement units to points at the top:

 

// 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) {
        //use points for measurements
        app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
        
        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
        //get the widths before the table is resized
        var ca = getColumnWidths(table);

        // Set the table width to match the calculated column width minus a stroke value
        // if the stroke value is unknown add a function to get
        table.width = myColumnWidth-5;

        //adjust the table’s column percentages
        setColumnWidths(table, ca)

        app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;

        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).toFixed(2))
        //$.writeln(tc[i].width)
    };   
    return ca
}


/**
* Set a table’s column widths to the provided array aof 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) {
        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;
        }; 
    } 
}

Votes

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
community guidelines
Community Expert ,
Apr 18, 2024 Apr 18, 2024

Copy link to clipboard

Copied

LATEST

Thanks for the explanation 

I'll try again tomorrow

I don't know how I missed the getter function. 
Anyway, I'll give it a go. 

For the most part it takes the laborious part out of it - and final tweaks are needed anyway.

But hopefully this resolves it.

Votes

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
community guidelines