I'm creating a PDFSharp document with an embedded table created using Migradoc.
This works just fine.
As the table has a variable number of rows, I need to know the actual height after rendering it into the main PDFsharp document. I need this to continue drawing other sections just after the table created using Migradoc.
This is the code that actually prepares and renders the table:
DocumentRenderer docRenderer = new DocumentRenderer(doc);
docRenderer.PrepareDocument();
docRenderer.RenderObject(gfx, XUnit.FromPoint(x), XUnit.FromPoint(y), XUnit.FromPoint(width), populatedTable);
In the docRenderer.PrepareDocument().FormatedDocument I can get the number of pages (in my case will always be one) and the size of the actual page (A4, for example) but not the height of the actual object.
How can I achieve this?
Well, I just found out how to do it.
After you call PrepareDocument(), you can access the RenderInfo array and check its content:
RenderInfo[] info = docRenderer.GetRenderInfoFromPage(1);
double yTableHeight = info[info.Length - 1].LayoutInfo.ContentArea.Height.Point;
In my case I'm rendering directly the table to a PDFsharp document, the whole ContentArea height is for the table. On a normal page, you will have also margins to add to this number.
Related
I dont know how achieve this, I have to create an informative report with images. For this, I use an excell template (It helps me with the format and with the position of the text where to place the respective information). The images are generated perfectly. I convert this XLS to PDF with the property
DocumentToMemoryStream (excelTemplate, XlsxSaveOptions.XlsxDefault);
This report generate blank pages in the PDF. How can I remove these blank pages, before the excel is generated?
Without checking your spreadsheet it's impossible to tell from where do those empty pages come from, so can you upload your XLS?
Anyway, do you perhaps have some explicitly defined horizontal or vertical page breaks?
If yes, can you remove the ones you don't need?
Or, do you perhaps have empty columns at the end which have some kind of styling or formatting?
If yes, then you could try using something like this to remove those empty columns from exporting to PDF:
var workbook = ExcelFile.Load("input.xls");
var worksheet = workbook.Worksheets.ActiveWorksheet;
worksheet.NamedRanges.SetPrintArea(
worksheet.GetUsedCellRange(true));
var options = new PdfSaveOptions();
options.SelectionType = SelectionType.ActiveSheet;
workbook.Save("output.pdf", options);
I had a counter of the rows of the document I was writing on, thanks to the help of #Mario Z, I use this function, before the save and solve my problem of blank pages
wsimgs.NamedRanges.SetPrintArea(wsimgs.Cells.GetSubrange("A1",CellRange.RowColumnToPosition (countRow, 10)));
I'm using SelectPDF's HTML to PDF converter to generate a PDF based on an HTML document containing a wide table of data. I'd like this table to wrap onto a second page (or Nth) page if needed, but instead SelectPDF squeezes the table into the space available on the page size I've selected.
I'm creating a PdfFlowDocument using Xfinium.PDF for UWP. I need to insert a page break but only if a certain section (containing paragraphs and tables) does not fit on the current page. It's a kind of "keep together" feature.
How could I accomplish my task?
UPDATE: I've minimized the amount of content that I need to keep together to just a single table. Although it is a flow table, I understand I will need to convert it to a fixed-sized table to calculate its height. If I could somehow find out the current position on the page after rendering all flow content, I would be able to calculate how much space left on the page. If there is enough space for the table, I would render it on the page. If not, I would issue a page break and render it on the next page.
Is there a feature to find out the current position on the page after rendering the flow content?
You can force a page break by calling PdfFlowDocument.StartNewPage.
Size information for flow content is not available in the public API, you cannot test in your code if a content object fits the current available space.
We'll support this in the next release.
Create a table with a single row and cell. For the cell use a PdfFlowTableCompositeCell. It has a property Content which is a collection of flow content objects. On the row set EnableRowSplit = false.
var table = new PdfFlowTableContent(1);
//column width in %
table.Columns[0].Width = 100;
var row = table.Rows.Add();
row.EnableRowSplit = false;
var cell = new PdfFlowTableCompositeCell();
//text
cell.Content.Add(new PdfFlowTextContent(new PdfFormattedContent(KswModuleTranslator.PdfFaultReportStationAssuranceText)));
//image
var image = new PdfPngImage(new MemoryStream(signatureData.Signature));
var imgDings = new PdfFlowImageContent(image);
cell.Content.Add(imgDings);
//text
cell.Content.Add(new PdfFlowTextContent(new PdfFormattedContent(signatureInfo.SigneeName)));
row.Cells.Add(cell);
document.AddContent(table);
I have a RDLC report in C# which displays a table.
I am providing a facility to the user to select the required columns to be displayed in the report.
So when the number of columns in the report are reduced half of the page on the right side appears blank due to which the presentation of the report looks bad.
I want to find out a way using which either I can set the column size of the visible columns dynamically.
OR
I can change the table location so that the table is displayed in the centre of the page.
So far I have found that I cannot write an Expression or pass parameter to set the size or location of a control in RDLC Report.
I would like to know if there is alternative way of achieving this.
What you could do is to change the rdlc at runtime, it is just and xml file, so you can parse it and go to set the width of the table programmatically. I use this approach to translate my reports for multilanguage and it works fine.
This link shows you how to translate the report, but this code is a good starting point. I think you can easily customize it for your purpose. Change RDLC XML
This might be an alternative:
Make columns small
Add group row
In the top group row, add image that will be used to "push" col width of both rows in the group
On the image properties, set it to use External image source and use a report parameter to set which image to use
On image, set "keep original size"
Edit: You may also generate such "padding image" dynamically to allow different widths, for example in MVC:
public class ImageUtilController : Controller
{
public FileContentResult GenerateTransparentRectangle(int width, int height)
{
var image = new Bitmap(width, height, PixelFormat.Format32bppArgb);
using (var g = Graphics.FromImage(image))
{
g.Clear(Color.Transparent);
g.FillRectangle(new SolidBrush(Color.Transparent), 0, 0, width, height);
}
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return File(ms.ToArray(), "image/png");
}
}
To make visible columns expand and fill the space of excluded (hidden) columns so that report width is maintained, work needs to be done is as under.
The rdlc file is an xml document. It defines column widths as following xml (This is specific to RDLC file created using Visual Studio 2005, it may differ for other version). Below xml suggests that there are 6 columns in the table.
<TableColumns>
<TableColumn>
<Width>0.5in</Width>
</TableColumn>
<TableColumn>
<Width>1.125in</Width>
</TableColumn>
<TableColumn>
<Width>1in</Width>
</TableColumn>
<TableColumn>
<Width>1in</Width>
</TableColumn>
<TableColumn>
<Width>0.5in</Width>
</TableColumn>
<TableColumn>
<Width>1.375in</Width>
</TableColumn>
</TableColumns>
Basically logic is simple, just increase the width of visible columns. But its implementation requires few lines of code.
Calculate the sum of width of hidden columns and then re-calculate width of visible columns
float[] resizedwidth;
// code for recalculation goes here
Read entire report xml into string variable 'rptxml'
String rptxml = System.IO.File.ReadAllText(#"D:\SO\WinFormQ\WinFormQ\Report1.rdlc");
Replace above xml segment with modified xml segment
int start = rptxml.IndexOf("<TableColumns>");
int end = rptxml.IndexOf("</TableColumns>") + "</TableColumns>".Length;
String resizedcolumns = String.format(
"<TableColumns>"
+ "<TableColumn><Width>{0}in</Width></TableColumn>"
+ "<TableColumn><Width>{1}in</Width></TableColumn>"
+ "<TableColumn><Width>{2}in</Width></TableColumn>"
+ "<TableColumn><Width>{3}in</Width></TableColumn>"
+ "<TableColumn><Width>{4}in</Width></TableColumn>"
+ "<TableColumn><Width>{5}in</Width></TableColumn>"
+ "</TableColumns>"
, resizedwidth[0], resizedwidth[1], resizedwidth[2], resizedwidth[3], resizedwidth[4], resizedwidth[5]
);
rptxml = rptxml.Substring(0, start) + resizedcolumns + rptxml.Substring(end);
Create TextReader from string variable 'rptxml'
TextReader tr = new StringReader(rptxml);
Use LoadReportDefinition() method to load the modified report definition
reportViewer1.LocalReport.LoadReportDefinition(tr);
Continue with specifying DataSources and ReportParameters etc. and finally display the report. NOTE: Don't forget to close TextReader tr.Close().
How To adjust each column size, Check Image
Click any column header and you will see the structure of that table will be visible just above the table in gray, from there you will be able to adjust your column size. Refer to the attached image, the top part pointed "red arrow" that's your table structure and that's where you modify the structure of your table. Hope it helps.
I have a basic PDF file that I has 5 different blank content areas that I want to use iTextSharp to write text too. The problem is I'm not sure the best way to accomplish this. I have attempted to use ColumnText to accomplish this, but I cannot seem to add multiple ColumnText objects.
ColumnText tagColumn = new ColumnText(pdfContentByte);
tagColumn.SetSimpleColumn(460, 100, 620, 160);
string[] tagColors = bt.DealerTagColor.Split('|');
Font tagFont = FontFactory.GetFont(bt.DealerTagFont, bt.DealerTagSize, Font.NORMAL, new BaseColor(int.Parse(tagColors[0]), int.Parse(tagColors[1]), int.Parse(tagColors[2])));
Paragraph p = new Paragraph(dto.Tag, tagFont);
p.Leading = bt.DealerTagSize;
tagColumn.AddElement(p);
tagColumn.Go();
What I like about the ColumnText is it allows me to essential define a heigth/width, and position of the text area.
Any thoughts on how I can accomplish this with or without using ColumnText? I just need to have control of the font/fontsize/font color/leading/and width of the area which will allow the text to wrap.
The easiest way would be to create and use form fields on your template PDF. This way you can reference a form field by name and set its value with a simple function call.
This article helped me:
Fill in PDF Form Fields using the Open Source iTextSharp Dynamic Link Library
EDIT: PdfPTables?
If your ColumnTexts are tabularly arranged consider using a PdfPTable. I've used PdfPTables to fill rows of data in forms generated from a blank template form. You need to figure out the x-coordinate of each of your columns and use these values when adding PdfPCells to your table, but it does work. I've never had to set an upper limit to the height of a PdfPCell but I image you can do it.
Check this page for more on PdfPTables.