Open theophile-br opened 9 months ago
There is an overflow attribute to the Text, which can take span. Try that.
I already tried and unfortunately it doesn't work. The code below still produce the TooManyPagesException.
import 'dart:io';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
Future<void> main() async {
final pdf = pw.Document();
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) => [
pw.TableHelper.fromTextArray(
headerCount: 0,
cellStyle: const pw.TextStyle(
fontSize: 8,
),
cellAlignment: pw.Alignment.centerLeft,
cellAlignments: {
0: pw.Alignment.topRight,
1: pw.Alignment.centerLeft,
},
columnWidths: {
0: const pw.IntrinsicColumnWidth(flex: 0.3),
1: const pw.IntrinsicColumnWidth(flex: 0.7)
},
data: [
[
pw.Text("This one", overflow: pw.TextOverflow.span),
pw.Text("is fine", overflow: pw.TextOverflow.span),
],
[
pw.Text("This one isn't fine", overflow: pw.TextOverflow.span),
pw.Text(
"""because the content is too big for the page, it produce an TooManyPages error,
I would like to span the content of this cells to the next page
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
""",
overflow: pw.TextOverflow.span),
]
],
),
],
),
);
final file = File('example.pdf');
await file.writeAsBytes(await pdf.save());
}
This error happens because the Text is not on top level and the PDF don't know how to handle a cell bigger than the PDF page. The same thing happens with Column. See example below
import 'dart:io';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
Future<void> main() async {
final pdf = pw.Document();
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) => [
pw.Column(
children: [
pw.Text("This one is fine", overflow: pw.TextOverflow.span),
pw.Text(
"""This one isn't fine because the content is too big for the page, it produce an TooManyPages error,
I would like to span the content of this cells to the next page
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
""",
overflow: pw.TextOverflow.span),
],
),
],
),
);
final file = File('example.pdf');
await file.writeAsBytes(await pdf.save());
}
to fix Try to avoid using widgets that do not support pagination, such as Wrap or Column, and use widgets that can span across multiple pages, such as ListView or Table.this working for me .
Replacing Column with ListView (like the example below) still doesn't work for me.
import 'dart:io';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
Future<void> main() async {
final pdf = pw.Document();
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) => [
pw.ListView(
children: [
pw.Text("This one is fine", overflow: pw.TextOverflow.span),
pw.Text(
"""This one isn't fine because the content is too big for the page, it produce an TooManyPages error,
I would like to span the content of this cells to the next page
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
""",
overflow: pw.TextOverflow.span),
],
),
],
),
);
final file = File('example.pdf');
await file.writeAsBytes(await pdf.save());
}
I can confirm that the same is occurring for me [pdf 3.10.7, Flutter 3.19.0] having previously worked fine. I have not been able to identify which version caused the problem.
In my use, I use MultiPage to build a PDF containing a table of text. Optionally, images are added to the PDF if they are attached to the database record that builds the table. Previously an image either appeared embedded on the first PDF page (below the table) if there was room, or paginated to the next page where it was scaled down to fit as required. Perfect behaviour!
Now I also get the dreaded TooManyPagesException
error if an image is added that is too big to fit in the remaining space of the first page of the PDF.
As a temporary workaround I now build the PDF with any attachment images added as new (multi)pages, doc.addPage(pw.MultiPage(...))
with images in a sole container on the page, max height 720.
This was my original code that once worked but now gives the error:
doc.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4.copyWith(marginBottom: 0.7 * PdfPageFormat.cm, marginTop: 0.7 * PdfPageFormat.cm),
crossAxisAlignment: pw.CrossAxisAlignment.start,
header: ...,
footer: ...,
build: (pw.Context context) => <pw.Widget>[
pw.ListView(children: [
... TABLE CODE ...
// add attachments if present
if (attachmentImages.isNotEmpty)
pw.ListView(children: [
for (PdfImage attachmentImage in attachmentImages)
pw.Container(
alignment: pw.Alignment.center,
padding: const pw.EdgeInsets.only(left: 10, right: 10),
child: pw.Image(
pw.ImageProxy(attachmentImage),
// fit: pw.BoxFit.fitHeight <-- I tried many different values for fit
)),
])
]) ...
My updated code moves the image attachment loop outside the original MultiPage widget to its own widget, thus forcing (non-ideally) each image onto its own page where I can control the height of the container. Anything more than a height of 720 (the available height after allowing for margins & header/footer) raises TooManyPagesException
. I have yet to find a way to dynamically include the image (when it fits) on the first page below the table data, or to fit multiple smaller images together on single pages if they are small enough to fit.
// add attachments if present
// TEMP FIX for MultiPage bug giving TooManyPagesException
if (attachmentImages.isNotEmpty)
for (PdfImage attachmentImage in attachmentImages)
doc.addPage(pw.MultiPage(
pageFormat:
PdfPageFormat.a4.copyWith(marginBottom: 0.7 * PdfPageFormat.cm, marginTop: 0.7 * PdfPageFormat.cm),
crossAxisAlignment: pw.CrossAxisAlignment.start,
header: (pw.Context context) => pageHeader(context, event),
footer: (pw.Context context) => pageFooter(context, user),
build: (pw.Context context) {
return [
pw.Container(
alignment: pw.Alignment.center,
padding: const pw.EdgeInsets.all(10),
constraints: pw.BoxConstraints(maxHeight: 720),
child: pw.Image(
pw.ImageProxy(attachmentImage),
))
];
}));
}
Unfortunately I can't find any workaround for now.
Putting all my widget on the first level solve this issue (see code below)), but this is not what I need. I need to be able to build layout, table, row and column nested
import 'dart:io';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
Future<void> main() async {
final pdf = pw.Document();
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) => [
pw.Text("This one is fine", overflow: pw.TextOverflow.span),
pw.Text(
"""This one isn't fine because the content is too big for the page, it produce an TooManyPages error,
I would like to span the content of this cells to the next page
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
""",
overflow: pw.TextOverflow.span),
],
),
);
final file = File('example.pdf');
await file.writeAsBytes(await pdf.save());
}
up
Up
Do you have any update on this ?
A comment needs clarification in the file multi_page.dart line 317 "What to do if the widget is too big for the page?"
// What to do if the widget is too big for the page?
if (offsetStart! - child.box!.height < offsetEnd) {
// If it is not a multi-page widget and its height
// is smaller than a full new page, we schedule a new page creation
if (child.box!.height <= pageHeight - pageHeightMargin && !canSpan) {
context = null;
continue;
}
any update?
up
Hi,
I don't know if it's a bug or if I don't use the API correctly. I would like to span a big content of a cell's table in the next page of my pdf.
This code below produce a TooManyPagesException, one of the cell in the table is too big to fit in one PDF A4 page. Do you have a workaround ?
Thanks in advance for your support Best Regards