PDFsharp MigraDoc set height of element - c#

Is there a way to set fixed height of an element? Could be a table, row or section. This element is dynamically generated from database and it can have a variable number of rows. I need to do that, because the section below needs to be in a fixed position for print out. I am using WPF v1.31. I know it is not the latest, but it's an addition to a quite old application.

You can set the height of a Paragraph or a table Row.
I think you cannot set the height of a Table - but that will be the sum of the heights of all rows. Automatic page breaks will make things complicated if a table does not fit a single page.
A Section always starts on a new page.
TextFrame can be used to place text at a fixed position. Depending on the requirements, this could be simple or complicated.
You can prepare a document to let MigraDoc determine sizes and positions. Then you code can decide whether the items with the fixed position will be on the same page or on a new page.
Here is sample code that shows how to show the progress while creating a PDF:
http://forum.pdfsharp.net/viewtopic.php?f=8&t=3172
The same technique can be used to stitch several MigraDoc documents together to create a single PDF. If I understand your requirements correctly, this could be the way to go - without setting the height of any elements.

Related

Migradoc TextFrame Page Break - Get current page position

I have a MigraDoc pdf I am generating and have had the requirement to have some 'inline' tables, I needed to get two tables on a line so after investigating this I found TextFrames worked perfectly... Until it encounters the end of the page. Turns out TextFrames do not recognize the end of the page:
(TextFrame are the red boxes)
So, I was wondering if anyone else had come up with a work around for this?
I had thought if I could find the position of the 'current location' I could calculate if the text frame is going to be too tall then manually inject a page break - but I can not seem to find the 'current position' - probably because it doesn't exist until post render??
Is there any way of getting the rendered height position of the 'current line' when coding or is there a better/easier way of doing what I am looking for?
I have found a piece of code that returns the current position using a kind of pre-render:
public double GetMigraHeightPosition()
{
MigraDoc.Rendering.DocumentRenderer docRenderer = new DocumentRenderer(this.document);
docRenderer.PrepareDocument();
RenderInfo[] RenderInfos = docRenderer.GetRenderInfoFromPage(docRenderer.FormattedDocument.PageCount);
RenderInfo r = RenderInfos[RenderInfos.Count() - 1];
return r.LayoutInfo.ContentArea.Y + r.LayoutInfo.ContentArea.Height;
}
So I am using this plus the height of the table to check if that is greater than the active page size (pagesize minus margins & header/footers). Seems to do the trick with regards to stopping the tables spilling into the footer... I still seem to be having the problem with the second table in the first row going onto the next page...?? Havent got a clue what is happening there?!
Object positions are determined when a document is being "prepared" before it is being rendered. If you make changes at that stage, you have to prepare the document again.
You can create tables with "invisible" cells. You can create tables within tables, but inner tables will not have pagebreaks within, so make sure each nested table fits on a single page.
See also:
https://stackoverflow.com/a/36304148/162529

MigraDoc: Align text or a table at the bottom of the page above the footer

I am using MigraDoc to generate a PDF. I want to align some content to the bottom of the last page. This is boilerplate disclaimer information that my company always includes in these types of documents. The goal is to keep the content altogether and always have it appear just above the footer on the last page. If there isn't room on the last page of actual content to keep it together, there should be a page break and the boilerplate content will be on a page by itself.
I would like to do this without measuring the height of the content.
I get the impression that I can use TextFrame to assist with this in some way, but I can't find any documentation on it. The questions and examples I've found online refer to being able to "absolutely position" the TextFrame, but none of the examples seem to do that, exactly.
As a starting point, I am trying to position a paragraph of text in the way I described on an otherwise blank page. Here's my latest experiment:
static void AddBoilerPlate(Section section) {
var sectionWidth = PdfSharp.PageSizeConverter.ToSize(PageSize.Letter).Width - section.Document.DefaultPageSetup.LeftMargin.Point -
section.Document.DefaultPageSetup.RightMargin.Point;
section.AddPageBreak();
var frame = section.AddTextFrame();
frame.RelativeVertical = RelativeVertical.Page;
frame.Width = sectionWidth;
frame.Top = ShapePosition.Bottom;
frame.AddParagraph(DisclaimerText);
}
The text starts just above the footer (the blue line in this screenshot) and then runs over the footer:
Once I get a paragraph of text aligned, then I think I will be able to use a table with one column and one row instead, and then put all of my content in there.
Update: here is a screenshot showing my goal (faked using a page break and SpaceBefore):
Update: here are some related articles that don't quite get me where I'm trying to go:
Centering a table on a page using a TextFrame: http://forum.pdfsharp.net/viewtopic.php?p=753#p753
Seems to answer the same question, but doesn't provide information about how to absolutely position the TextFrame: http://forum.pdfsharp.com/viewtopic.php?f=2&t=587
Keeping table together on a page ("in one piece"). This will be useful once I figure out the issue with aligning relative to the bottom of the page: Keep table in one piece MigraDoc / PDFsharp
Update: Note that adding a height to the TextFrame does make the text align the way I need it to. It's not ideal, because I would rather not hard-code the height. But it does produce the desired effect:
static void AddBoilerPlate(Section section) {
var sectionWidth = PdfSharp.PageSizeConverter.ToSize(PageSize.Letter).Width - section.Document.DefaultPageSetup.LeftMargin.Point -
section.Document.DefaultPageSetup.RightMargin.Point;
section.AddPageBreak();
var frame = section.AddTextFrame();
frame.RelativeVertical = RelativeVertical.Page;
**frame.Height = new Unit(75, UnitType.Millimeter);**
frame.Width = sectionWidth;
frame.Top = ShapePosition.Bottom;
frame.AddParagraph(DisclaimerText);
}
Update: Note, though, that setting the TextFrame height doesn't resolve the ultimate issue. Content added before the boilerplate should push the boilerplate to the next page if there isn't enough space for it, and that's not happening.
Update: After trying it out myself (I've had the same Problem), add an invisible element with the Height you want to have just before the bottom element. In case the invisible Element doesn't fit it will seem that the page break occurred because of the bottom element.
Works like a charm.
(tip I added a border to both elements for testing so I was able to make sure the layout was proper)

MigraDoc Columns not wrapping to new page

I'm producing a PDF Export document for a project i'm working on using MigraDoc; the document can contain many rows spans multiple pages, the document can have a user specified number of columns also, this is where i'm having an issue if there are more columns than can fit onto the page it just gets cut off; what i'm after achieving is to get it to wrap round to a new page.
The current implementation of MigraDoc cannot split tables vertically. All columns have to fit on one page or they will be cut off.
For use with PDF files, you can increase the width of the page in order to get all columns. Could this be a solution?

MS Reports rdlc c# win forms multiple columns

I am trying to create a Report with two columns.
Records should add in as below...
1.Bob 6.Sarch
2.Sue 7.Barrie
3.Adam 8.James
4.Dave 9.Steve
5.Robin 10.Euan
11.Fred
12.Heidi
13.Liz
For the first column (1-5 in this example), a page break should wrap the data to the second column (6-10). After the second column is full (11-13) the the data should page wrap.
The data used to generate the report will have a fixed number of columns. The height and width required for the data will not change.
I am using with C#, WinForms, .net4. I have tried several various approaches with no success. Thus far I have only managed
1.Bob 2.Sue
3.Adam...
Please help or point me in the right direction :-)
Many Thanks
TL;DR ---> This isn't possible with SSRS, afaik.
If I understand correctly, you want to list the items in a data set, that when rendered with a hard page break renderer will render with these requirements:
items are added vertically as long as there's space on the page
a new column of items is started when the first column ran out of space, vertically
a page break is inserted when the second column filled up the vertical space, thus starting a new, first column on a new page
Now, there's only these controls in SSRS:
Textbox
Table, Matrix
Chart
Gauge
List
Image
Subreport
Line, Rectangle
Out of these only the Tablix (Table/Matrix) and List are remotely capable of such a thing, but they can't satisfy your requirements. I'm afraid the answer to your question is that this can't be (easily) done.
The hard way that this may still be possible is perhaps by creating a custom report item and/or by creating a custom rendering extension. But that may be overkill for just wanting to create a nice little list.

Calculate height of a HTML-Table generated by HtmlTextWriter (C#)

I generate a HTML-Page from C#. In the HTML-Page there are a lot of elements. All of them have a absolute position.
One of these elements is a table. This table represents a object that keeps a double[]. Every double value is a new cell in a new row.
I iterate over double[] and create my table:
for (int i = 0; i < dbl.Length; i++)
{
htmlTextWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
htmlTextWriter.RenderBeginTag(HtmlTextWriterTag.Td);
htmlTextWriter.Write(dbl[i]);
htmlTextWriter.RenderEndTag(); // td
htmlTextWriter.RenderEndTag(); // tr
}
If the table has so much elements, that it cross an element that is below this table, I have to be responsive to this issue.
This means, I need to know how many pixels this table is long.
Of course I do know how many cells I generate and I also know BorderSize, Padding, Margin, etc.
But there are two problems. First although I know FontSize, FontFamily, FontWeight, I do not know how to include these information into a mathematical calculation.
Second I think in every browser the actual size is also different. I created a dummy table and recognized, that in one screen height I already have one cell difference between Opera and Firefox.
So I think in C# I am only able to approximate the actual height?!
The next idea I have is to include a JavaScript into my HTML. I've no experience with JavaScript, but my approach would be to find my tables and read out size. Then iterate over all elements and find all overlappings.
My questions are:
Are my consideration true or do I miss some aspects?
Are my approaches the right way (in C# I only will get an
approximated result?!, JavaScript I do not know if it is really
possible what I want to do)
Are there other possibilities I do not see right now?
Hint: Other script languages than JavaSript are not applicable for my solution. JavaScript I only use if really necessary.
I think javascript is the answer, not c#.
http://api.jquery.com/height/
You cannot calculate the height in C#. Please use javascript to do this.

Categories