Copy link to clipboard
Copied
Hi,
I intended to fit the table to the pages in the InDesign document. In spite of this, it exceeds that particular page. I have attached the same document and the script I used to fit the table.
https://drive.google.com/drive/folders/166t-M93Jjm4Dpmp3IWo8Zc6u1kKDiXPN?usp=sharing
Copy link to clipboard
Copied
Hi @MonishaRajendran, I had a look at your sample file and script. What exactly are you trying to do to the table? Scale it down to fit margins width? Adjust every column width to fit margins width?
When you are asking for help with a script it is often helpful for you to post a screenshot of your desired result, also. That way we don't have to guess what you mean.
- Mark
Copy link to clipboard
Copied
Hi,
My first goal is to fit the table into the frame. Currently, I am unable to fit the table inside the frame. I have attached the screenshot that I wanted to achieve using my script.
Copy link to clipboard
Copied
Hi @MonishaRajendran, I had a look at your script, but I didn't quite understand your approach. Instead I have written a script to do an "autofit" type of operation on the table, which I think might be what you want.
Here is your sample document:
Note that I put line breaks in a couple of the header cells to match your desired result screenshot. Do this before running the script. Also make sure that the table isn't overset (ie. make sure the end of the table is visible in a text frame).
- Mark
The script:
/**
* Auto-fit Selected Table
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/fit-table-using-frame-to-content/m-p/13569385
*/
function main() {
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var selectedTable = getTable(app.selection[0]);
if (
selectedTable == undefined
|| !selectedTable.isValid
) {
alert('Please select a table or inside a table and run script again.');
return;
}
autoFitTable(selectedTable);
}
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Auto-fit Table');
/**
* Auto-fits the table: attempts to minimize
* the width of each column, without changing
* existing line breaks, similar to Microsoft
* Excel's auto-fit function.
* @author m1b
* @version 2023-02-12
* @param {Table} table - an Indesign Table.
* @param {Number} [minimumWidth] - the minimum desired table width, in pts (default: 0).
*/
function autoFitTable(table, minimumWidth) {
minimumWidth = minimumWidth || 0;
var bounds = getCellBounds(table.cells[0], 'geometricBounds'),
tableWidth = 0,
columnData = [];
// in this loop we collect all the
// measurements we'll need later on
columnsLoop:
for (var c = 0, left = bounds[1]; c < table.columns.length; c++) {
var column = table.columns[c],
columnCells = column.cells,
columnWidth = Number(table.columns[c].width);
columnData[c] = {
left: left,
leftInset: Math.max.apply(null, columnCells.everyItem().textLeftInset),
right: left + columnWidth,
rightInset: Math.max.apply(null, columnCells.everyItem().textRightInset),
maxLineMeasure: -Infinity,
maxLineIndex: undefined,
maxLineCellID: undefined,
maxLineContents: undefined,
width: columnWidth,
};
cellsLoop:
for (var i = 0; i < columnCells.length; i++) {
linesLoop:
for (var j = 0; j < columnCells[i].lines.length; j++) {
var cell = columnCells[i];
if (cell.texts[0].parentTextFrames.length == 0) {
alert('Some rows of this table appear to be overset. Please fix and try again.');
return;
}
var line = cell.lines[j],
start = line.insertionPoints[0].horizontalOffset,
end = start;
if (line.insertionPoints.length == 1)
end = line.insertionPoints[-1].horizontalOffset;
else
end = Math.max(line.insertionPoints[-1].horizontalOffset, line.insertionPoints[-2].horizontalOffset);
var lineMeasure = end - start;
if (lineMeasure > columnData[c].maxLineMeasure) {
columnData[c].maxLineMeasure = lineMeasure;
columnData[c].maxLineIndex = j;
columnData[c].maxLineCellID = cell.id;
columnData[c].maxLineContents = line.contents;
}
}
}
// set the column width
columnData[c].width = (columnData[c].maxLineMeasure + columnData[c].leftInset + columnData[c].rightInset);
// advance for the next column
left += columnWidth;
}
// this loop is to actually change the column widths
for (var c = table.columns.length - 1; c >= 0; c--) {
table.columns[c].width = columnData[c].width;
// If the longest line's contents no longer matches,
// gradually open up the column again until it matches.
// This is mostly to fix hyphenated words no longer
// being hyphenated at the new width.
var cell = table.cells.itemByID(columnData[c].maxLineCellID),
line = cell.lines[columnData[c].maxLineIndex],
counter = 100; // count down for safety
while (
line.contents !== columnData[c].maxLineContents
&& counter--
) {
table.columns[c].width += 0.5;
line = cell.lines[columnData[c].maxLineIndex];
}
// update the column data, in case the width changes
columnData[c].width = Number(table.columns[c].width);
// update the table width
tableWidth += columnData[c].width;
}
if (minimumWidth > tableWidth) {
// take the edge strokes into account so that
// a minimum width means the table will fit exactly
// in a textframe of that size.
var leftEdgeStrokeWeight = Math.max.apply(null, (table.columns.item(0).cells.everyItem().leftEdgeStrokeWeight)),
rightEdgeStrokeWeight = Math.max.apply(null, (table.columns.item(-1).cells.everyItem().rightEdgeStrokeWeight));
minimumWidth -= (leftEdgeStrokeWeight / 2) + (rightEdgeStrokeWeight / 2);
// the amount to add to each column
var adjustment = (minimumWidth - tableWidth) / table.columns.length;
// make the adjustment
for (var c = table.columns.length - 1; c >= 0; c--)
table.columns[c].width += adjustment;
}
};
/**
* Returns the geometricBounds of the cell;
* @author m1b
* @version 2023-02-06
* @param {Cell} cell - an Indesign Table Cell.
* @param {String} [boundsType] - can be 'geometricBounds' or 'visibleBounds' (default: 'geometricBounds').
* @returns {Array<Number>}
*/
function getCellBounds(cell, boundsType) {
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
boundsType = boundsType || 'geometricBounds';
if (!cell.hasOwnProperty('index'))
throw Error('getCellBounds failed: bad cell parameter.');
var table = cell.parent;
while (
// table.hasOwnProperty('parent')
table.constructor.name != 'Table'
)
table = table.parent;
var cellIndex = cell.index,
tableIndex = indexOf(table, table.storyOffset.parentTextFrames[0].tables),
// duplicate the textframe because we are going to convert the cell
dupTextFrame = table.storyOffset.parentTextFrames[0].duplicate(),
dupCell = dupTextFrame.tables[tableIndex].cells[cellIndex];
// convert cell to graphic, so we can get the bounds
dupCell.convertCellType(CellTypeEnum.GRAPHIC_TYPE_CELL);
var bounds = dupCell.rectangles[0].geometricBounds;
// clean up
dupTextFrame.remove();
// add strokeWidths
if (boundsType === 'visibleBounds') {
bounds[0] -= cell.topEdgeStrokeWeight;
bounds[1] -= cell.leftEdgeStrokeWeight;
bounds[2] += cell.bottomEdgeStrokeWeight;
bounds[3] += cell.rightEdgeStrokeWeight;
}
else if (boundsType === 'geometricBounds') {
bounds[0] -= cell.topEdgeStrokeWeight / 2;
bounds[1] -= cell.leftEdgeStrokeWeight / 2;
bounds[2] += cell.bottomEdgeStrokeWeight / 2;
bounds[3] += cell.rightEdgeStrokeWeight / 2;
}
return bounds;
};
/**
* Returns index of obj in arr.
* Returns -1 if not found.
* @param {any} obj
* @param {Array} arr
* @returns {Number}
*/
function indexOf(obj, arr) {
for (var i = 0; i < arr.length; i++)
if (arr[i] === obj)
return i;
return -1;
};
/**
* Attempts to return a Cell, given an object.
* @author m1b
* @version 2023-02-06
* @param {InsertionPoint|Text|Cells|Table} obj - an object related to a Cell.
* @returns {Cell}
*/
function getTable(obj) {
if (obj == undefined)
return;
if (obj.constructor.name == 'Cell')
return obj.parent;
if (obj.parent.constructor.name == 'Cell')
return obj.parent.parent;
if (
obj.hasOwnProperty('cells')
&& obj.cells.length > 0
)
return obj.cells[0].parent;
};
Edit 2023-02-12: I've added a "minimumWidth" parameter. If you use this, then the script will first auto-fit, so there is no wasted space, then will extend every column by the same amount so that the table matches the minimumWidth amount.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hi @MonishaRajendran, I'm afraid your script is too complicated for me to debug. I suggest you either create a simple version that just has the section that you want to ask about, or look at my script and see how I did it. Or maybe I am not understanding your needs at all, in which case my apologies, and please try to be much more specific with your question.
- Mark
Copy link to clipboard
Copied
Hi m1b.
As always, you are unbeatable.
The script is good, but needs to be improved.
It should adjust to typearea or column width, not just adapt to each column.
The text in the cell is hidden, it would be nice if it could be expanded automatically.