Is there a way to autofit an InDesign table to the size of the text box bounding frame by adjusting row height and/or column width? I am using the script below to delete empty rows from tables, but after deleting the row, the table no longer fills the space it is designed for.
Any suggestions or resources that may be helpful would be very much appreciated!
Thank you!
var rows = app.activeDocument.textFrames.everyItem().tables.everyItem().rows.everyItem().getElements()
for (var i = rows.length - 1; i >= 0; i--) {
if (rows[i].cells.everyItem().contents.toString().replace(/,/g, "") == "")
rows[i].remove()
}
var columns = app.activeDocument.textFrames.everyItem().tables.everyItem().columns.everyItem().getElements()
for (var i = columns.length - 1; i >= 0; i--) {
if (columns[i].cells.everyItem().contents.toString().replace(/,/g, "") == "")
columns[i].remove()
}
Here is the simple solution:
try { var cells = app.selection[0].cells } catch(e) { exit() }
app.doScript(main, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, 'Fit table')
function main() {
// change the units to Points
var old_h_units = app.activeDocument.viewPreferences.horizontalMeasurementUnits;
app.activeDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.POINTS
var old_v_units = app.activeDocument.viewPreferences.verticalMeasurementUnits;
app.activeDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.POINTS
var first_cell = cells.firstItem().texts[0];
var last_cell = cells.lastItem().texts[0];
var id = first_cell.parentTextFrames[0].id;
// change heights
while (last_cell.parentTextFrames.length > 0
&& last_cell.parentTextFrames[0].id == id) {
change_heights(cells, +.1);
}
change_heights(cells, -.1); // one step back
// change widths
var row = cells[0].parentRow;
var borders = row.rightEdgeStrokeWeight/2 + row.leftEdgeStrokeWeight/2;
var frame_width = get_width(first_cell.parentTextFrames[0]) - borders;
while (cells[0].parentRow.width < frame_width) {
change_widths(cells, +.1);
}
// restore the old units
app.activeDocument.viewPreferences.horizontalMeasurementUnits = old_h_units;
app.activeDocument.viewPreferences.verticalMeasurementUnits = old_v_units;
}
// functions ------------------------------------------------------------------
function change_heights(cells, value) {
for (var i=0; i<cells.length; i++) cells[i].height += value;
}
function change_widths(cells, value) {
for (var i=0; i<cells.length; i++) cells[i].width += value;
}
function get_width(obj) {
return obj.geometricBounds[3] - obj.geometricBounds[1];
}
Select the cells you want to resize and run the script. It increases height and width of the selected cells until the cells are fit in the parent text frame.
But it suggests to run the script manually for every problem table. If you mean to change all the tables in the document at once automatically there should be more complicated solution. Let me know if you need it. And it wouldn't hurt if you provide a sample of your document with the tables — there can be details that affect the algorithm.
Update
Here is the 'full-automatic' variant of the script:
app.doScript(main, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, 'Fit table')
function main() {
// change the units to Points
var old_h_units = app.activeDocument.viewPreferences.horizontalMeasurementUnits;
app.activeDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.POINTS;
var old_v_units = app.activeDocument.viewPreferences.verticalMeasurementUnits;
app.activeDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.POINTS;
var doc = app.activeDocument;
var all_tables = [];
// get all the tables
var stories = doc.stories.everyItem().getElements();
while(s = stories.pop()) {
if (!s.textContainers[0].itemLayer.visible) continue; // exclude stories on hidden layers
var tables = s.tables.everyItem().getElements();
while(t = tables.pop()) all_tables.push(t);
}
// resize cells of all tables
while (t = all_tables.pop()) resize_cells(t.cells);
// restore the old units
app.activeDocument.viewPreferences.horizontalMeasurementUnits = old_h_units;
app.activeDocument.viewPreferences.verticalMeasurementUnits = old_v_units;
}
// functions ------------------------------------------------------------------
function resize_cells(cells) {
var first_cell = cells.firstItem().texts[0];
var last_cell = cells.lastItem().texts[0];
var id = first_cell.parentTextFrames[0].id;
// chahge heights
while (last_cell.parentTextFrames.length
&& last_cell.parentTextFrames[0].id === id) {
change_heights(cells, +.1);
}
change_heights(cells, -.1); // one step back
// change widths
var row = cells[0].parentRow;
var borders = row.rightEdgeStrokeWeight/2 + row.leftEdgeStrokeWeight/2;
var frame_width = get_width(first_cell.parentTextFrames[0]) - borders;
while (cells[0].parentRow.width < frame_width) {
change_widths(cells, +.1);
}
}
function change_heights(cells, value) {
for (var i=0; i<cells.length; i++) cells[i].height += value;
}
function change_widths(cells, value) {
for (var i=0; i<cells.length; i++) cells[i].width += value;
}
function get_width(obj) {
return obj.geometricBounds[3] - obj.geometricBounds[1];
}
It gets all the tables of current document (except hidden layers), select all cells of each table and resize the cells to fit them in their parent text frame.
Not sure, is it okay to change highs of first and second row? Let me know if you don't want change highs of the first two rows.