Comments (6)
Thank you for reaching out 😄
I am not entirely sure of what behavior you want to achieve. Would you please provide some visual examples?
from questpdf.
Examples
In all of the examples, the part of the content with the red background color is user-generated. This is the part of the content that we do not want to span multiple pages unless we have no other option.
Example 1
The content is short enough to comfortably fit inside the first page..
Example 2
The content is too long to fit inside the first page, but is short enough to fit inside a single page. Using ShowEntire
, we can ensure the content is displayed in a single page in its entirety.
Page 1:
Page 2:
Example 3
This is where we run into a problem. The content is too long to fit into a single page. Since we're using ShowEntire
to achieve the desired result for the second example, QuestPDF now throws an exception.
Instead of this behavior, ideally we'd like to have a method available (i.e. TryShowEntire
), which would behave the same way as ShowEntire
did in examples 1 and 2, but in this case, instead of throwing an exception, would simply render the content as if ShowEntire
wasnt used:
Page 1:
Page 2:
Obviously I have very little idea about the inner workings of the library, and if what I'm asking for is even feasible. But if it is, it would greatly help us out.
Code used to generate the examples
private List<string> Paragraphs = new List<string>()
{
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ultricies dignissim commodo. Suspendisse cursus ultrices mi eu cursus. Nulla ultrices tortor aliquet erat faucibus tempus vel eu magna. Fusce non elit rhoncus, congue elit sed, tristique dolor. Pellentesque diam odio, luctus ac lectus id, pretium luctus eros. Ut eu blandit velit. Pellentesque at faucibus sem. Morbi ac diam id augue porta dapibus eget quis ipsum. Aenean volutpat diam in blandit egestas. Mauris sagittis semper nibh id dignissim. Nullam tempus mi ac augue dapibus, gravida laoreet nulla cursus. Aenean finibus, sapien ac aliquet molestie, dui ante tristique ante, sit amet viverra metus erat vel est. Integer ut congue dui.",
"Praesent mattis diam eget congue convallis. Phasellus velit eros, gravida eget enim at, iaculis sollicitudin nisl. Mauris pulvinar arcu non velit vehicula, sit amet molestie elit lobortis. Nam eleifend felis quis lorem malesuada, eu feugiat urna cursus. Nulla vehicula a ante dignissim facilisis. Cras elit lacus, ornare vel suscipit at, dapibus ac nisi. Phasellus ac arcu posuere, pretium augue sed, euismod purus. Nullam lacinia, ligula convallis aliquet aliquam, odio erat dictum urna, ut mattis massa nulla vel mi. Quisque cursus nisi arcu, aliquam blandit neque euismod sed. Vestibulum elementum sapien hendrerit justo tempus pharetra. Nam ac malesuada ante. Sed eget libero arcu. Vivamus sit amet placerat dolor, vitae sagittis tortor.",
"In vitae iaculis erat, ultricies convallis risus. Donec quis pharetra quam. Mauris semper erat in malesuada vehicula. Phasellus at nulla vulputate, posuere tellus et, pellentesque nunc. Morbi elementum dui fermentum tempus tempus. Praesent a cursus ex. Sed pellentesque maximus libero. Quisque rhoncus velit a pulvinar tempus. Integer at est non justo interdum scelerisque. Donec urna ipsum, tempus non ante eu, viverra interdum orci. Duis vitae porta libero, ac molestie sem. Nunc id arcu vel dolor tincidunt lacinia. Etiam ac diam accumsan, vulputate ante nec, scelerisque augue. Donec sed pellentesque augue, semper finibus dolor.",
"Vivamus vel rutrum dui. Duis mattis mi ac convallis mollis. Donec a nisl et dui consequat malesuada. Aliquam a lacus odio. Vivamus et lectus in elit mattis porta. Donec a suscipit est. Donec blandit, ligula nec bibendum tempor, metus mi mollis eros, varius rutrum justo arcu in neque. Morbi varius molestie massa, in mollis ipsum volutpat eu. Nunc venenatis enim sit amet eros gravida, eget venenatis turpis commodo. In molestie vitae mauris ac congue. Cras facilisis, metus vitae consequat fringilla, lacus felis scelerisque ligula, quis auctor nisl nulla quis velit. Duis maximus, nisi id egestas feugiat, leo elit aliquam nisl, efficitur sagittis ipsum lectus cursus libero. Mauris at finibus sem.",
"Nullam fermentum rutrum elementum. Nullam porttitor, dolor a dapibus auctor, quam dolor facilisis nunc, a pulvinar nisi lectus vel diam. Curabitur tempor, massa vel blandit consequat, turpis urna blandit justo, quis mattis justo libero nec velit. Cras imperdiet nulla eu nisl tincidunt, a euismod ligula pellentesque. Proin iaculis mi at orci finibus, non sagittis ante ornare. Nullam vitae risus id sem ornare malesuada eget ut odio. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis sit amet urna vitae nisi hendrerit imperdiet. Sed id est sapien. Pellentesque in odio ut nunc interdum dictum. Phasellus eu elementum lacus, et interdum ipsum. Praesent nec lacus congue lacus cursus euismod nec vitae massa."
};
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(10f, Unit.Millimetre);
page.DefaultTextStyle(TextStyle
.Default
.FontFamily(Fonts.SegoeUI)
.FontSize(12f)
.LineHeight(1.2f)
.NormalWeight());
page.Header()
.Background("#FFFF00")
.DefaultTextStyle(style => style.FontSize(48f))
.Text("Page Header");
page.Content()
.Column(column =>
{
column.Item()
.Background("#00FFFF")
.PaddingVertical(5f, Unit.Millimetre)
.Text(text =>
{
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Line("This part is not user generated");
text.Span("This part is not user generated");
});
column.Item()
.Background("#FF0000")
.ShowEntire()
.PaddingVertical(5f, Unit.Millimetre)
.Text(string.Join('\n', Paragraphs.Take(5)));
column.Item()
.Background("#00FFFF")
.PaddingVertical(5f, Unit.Millimetre)
.Text("This part is not user generated");
column.Item()
.Background("#00FFFF")
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2f);
columns.RelativeColumn(5f);
columns.RelativeColumn(3f);
columns.RelativeColumn(2f);
});
table.Header(header =>
{
header.Cell().Text("Column 1").Bold();
header.Cell().Text("Column 2").Bold();
header.Cell().Text("Column 3").Bold();
header.Cell().Text("Column 4").Bold();
});
for (var i = 0; i < 30; i++)
{
table.Cell().Text(i.ToString());
table.Cell().Text(i.ToString());
table.Cell().Text(i.ToString());
table.Cell().Text(i.ToString());
}
});
});
page.Footer()
.Background("#FFFF00")
.DefaultTextStyle(style => style.FontSize(9f))
.Text("Page Footer");
});
}
from questpdf.
My suggestion is to use the EnsureSpace
with a value slightly smaller than the content height (page height - header - footer). If I am not mistaken, it may produce the desired outcome.
from questpdf.
Well, as I mentioned in the original post, I don't know in advance how large the the header or footer are going to be. For a simplified example of our use case, lets presume the user can modify the following properties:
public struct HeaderSettings {
public HeaderType Type { get; set; } // Text or Image
public string Text { get; set; } // Used when header type is "Text".
public float FontSize { get; set; } // Used when header type is "Text".
public byte[] Image { get; set; } // Used when header type is "Image".
}
public struct FooterSettings {
public FooterType Type { get; set; } // Text or Image
public string Text { get; set; } // Used when footer type is "Text".
public float FontSize { get; set; } // Used when footer type is "Text".
public byte[] Image { get; set; } // Used when footer type is "Image".
}
I have no idea how big the header or footer are going to be. That also means there is no easy way for me to safely use EnsureSpace
.
The only way I could think of to safely use EnsureSpace
is to essentially do a dry run, where I only render the header and footer, and use a dynamic component that renders nothing and just measures the available space on the page. If I then take the calculated height value (and perhaps subtract a millimetre or so), it should probably be safe to use in EnsureSpace
.
from questpdf.
I wonder... we could create a variant of EnsureSpace that attempts to use all available vertical space as its argument.
I already have trouble with naming: ShowEntire, EnsureSpace... and how that third option could be named?
from questpdf.
I think this is something like a feature I would also need for my current project, I need to show a table, and I need the table to be shown in its entirety unless absolutely impossible, I don't know how many rows the table will have, and the rows can have different heights. Using ShowEntire mostly works but can throw stray exceptions once in a while, I think that a 'safe' version of the ShowEntire, something like a TryShowEntire() that would try to fit the content on the current page, if that is not enough, tries to fit it in 1 page, if it still does not fit, it just breaks the content to 2 or more pages.
As @MercinaM said I was about to implement this using Dynamic Component, but a more native way to do this would be greatly appreciated.
from questpdf.
Related Issues (20)
- Add Support for AcroFields
- The previewer doesn't show any buttons HOT 1
- Showing an svg image spams the log HOT 4
- Random segfaults caused by trying to dispose a `null` `SkSvgImage` object in `SvgImage` class finalizer HOT 4
- Unable to find an entry point named 'svg_get_size' in DLL 'QuestPdfSkia' HOT 3
- Reintroduce Win-x86 support HOT 10
- License related question HOT 2
- Colors in SVG which are specified by name do not work HOT 1
- Query regarding License HOT 4
- Text Padding Issue
- Generating PDF produces blank document when using async/await HOT 2
- Header not working as expected HOT 3
- border-radius HOT 3
- Is there an asynchronous version of GeneratePdf to write to an output stream (web API)? HOT 2
- Underline is coming over the text HOT 8
- Copy of native DLL does not work for restricted processes HOT 3
- Align text and number into Content HOT 2
- Missing Calling Convention for x86 platform produces debugging issues HOT 8
- .Text automatically trims spaces in strings HOT 2
- "Table continued" indicator HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from questpdf.