How to autofit table rows to text box height after deleting a row in InDesign

273 Views Asked by At

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()
}
1

There are 1 best solutions below

5
Yuri Khristich On BEST ANSWER

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.

enter image description here

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.