Hi again, I've had a play with some code and got this. It will accept an array of values and output an array of arrays of values whose sum do not exceed the specified capacity. By entering values denoting lengths in mm and capacity of 297 (length of A4 page in mm), you should have a basis to do your text frame layout script. Haven't tested much myself, so please let us know how it works out, or if you need more help.
/*
by m1b at https://community.adobe.com/t5/indesign/arrange-an-array-of-different-text-boxes-to-fit-in-pages/m-p/12182653#M437483
adapted from code found at https://www.geeksforgeeks.org/bin-packing-problem-minimize-number-of-used-bins/
*/
// example values (here representing lengths in mm)
var values = [125, 200, 205, 280, 30, 40, 170, 45, 77];
// capacity of each bin (here representing length of A4 page in mm)
var capacity = 297;
// get the result
var fittedLengths = getPackedBins(values, capacity);
// show the result as A4 pages
$.writeln("Number of pages required: " + fittedLengths.length);
for (var i = 0; i < fittedLengths.length; i++) {
$.writeln('Page ' + (i + 1) + ' lengths: ' + fittedLengths[i].join(' mm + ') + ' mm (' + (capacity - sumArray(fittedLengths[i])) + 'mm remaining)');
}
function getPackedBins(values, binCapacity) {
// sort values, descending order
values = values.sort(function (a, b) { return b - a });
// start with no bins
var bins = [];
// array to keep track of remaining capacity
var binRemainder = new Array(values.length); for (var i = 0; i < values.length; ++i) binRemainder[i] = 0;
// place each item in a bin
for (i = 0; i < values.length; i++) {
var j,
value = values[i],
freeSpace = binCapacity,
bestBinIndex = 0;
// find the best bin that can accommodate value
if (value > binCapacity) $.writeln('Value "' + value + '" cannot fit into an empty bin.');
// initialize minimum space left and index of best bin
for (j = 0; j < bins.length; j++) {
if (binRemainder[j] >= value && binRemainder[j] - value < freeSpace) {
bestBinIndex = j;
freeSpace = binRemainder[j] - value;
}
}
// can't fit value in any bin, so create a new bin
if (freeSpace == binCapacity) {
binRemainder[bins.length] = binCapacity - value;
bins.push([value]);
} else {
// put value in best bin
binRemainder[bestBinIndex] -= value;
bins[bestBinIndex].push(value);
}
// uncomment this line to see the bins array populate over time
// $.writeln('bins = [' + bins.join('], [') + ']');
}
return bins;
}
// only used for displaying the remainders
function sumArray(a) {
var sum = 0;
for (var i = 0; i < a.length; ++i) sum += a[i];
return sum;
}
By the way, this is the result for me, written to the console:
Number of pages required: 5
Page 1 lengths: 280 mm (17 mm remaining)
Page 2 lengths: 205 mm + 77 mm (15 mm remaining)
Page 3 lengths: 200 mm + 45 mm + 40 mm (12 mm remaining)
Page 4 lengths: 170 mm + 125 mm (2 mm remaining)
Page 5 lengths: 30 mm (267 mm remaining)