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.");
}
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
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]
};
}
}
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
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.
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
Copy link to clipboard
Copied
Seems to - I'll know more tomorrow
Thanks for the help so far.
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;
};
}
}
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?
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.
Copy link to clipboard
Copied
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.
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:
He wants the resized table’s columns to keep their original proportions:
Copy link to clipboard
Copied
[...]
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...
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;
};
}
}
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
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.
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?
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.
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
Copy link to clipboard
Copied
Yeh, I think so - so no part of the table can go past the gutter
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:
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;
};
}
}
Copy link to clipboard
Copied
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.