Landscape and Portrait in same pdf - c#

I need to generate a pdf report from a URL in our application. Is it possible to have both Landscape and Portrait pages in the same pdf document that is generated?
I'd like to have the bar charts as Portrait, and the Tables as Landscape (horizontal). Looking at the EVO doc's I don't know if this is possible.
I know that you can define either Landscape or Portrait with
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation
But this is applied to the whole document. I'd like something I could potentially define the html that would tell EVO to print this section as Landscape.

You can have Portrait and Landscape section in the same PDF. For this you can create a blank Document object and add a PDF page with the desired orientation to this document. On the newly created PDF page you can add a HtmlToPdfElement object to render the HTML and automatically add PDF pages with the same orientation with the PDF page you initially created. The procedure can be repeated with PDF pages of different orientations. There is a live sample with C# code for this approach in Merge Multiple HTML Pages into a Single PDF demo. The code sample is also copied below:
protected void convertToPdfButton_Click(object sender, EventArgs e)
{
// Create the PDF document where to add the HTML documents
Document pdfDocument = new Document();
// Create a PDF page where to add the first HTML
PdfPage firstPdfPage = pdfDocument.AddPage();
try
{
// Create the first HTML to PDF element
HtmlToPdfElement firstHtml = new HtmlToPdfElement(0, 0, firstUrlTextBox.Text);
// Optionally set a delay before conversion to allow asynchonous scripts to finish
firstHtml.ConversionDelay = 2;
// Add the first HTML to PDF document
AddElementResult firstAddResult = firstPdfPage.AddElement(firstHtml);
PdfPage secondPdfPage = null;
PointF secondHtmlLocation = Point.Empty;
if (startNewPageCheckBox.Checked)
{
// Create a PDF page where to add the second HTML
secondPdfPage = pdfDocument.AddPage();
secondHtmlLocation = PointF.Empty;
}
else
{
// Add the second HTML on the PDF page where the first HTML ended
secondPdfPage = firstAddResult.EndPdfPage;
secondHtmlLocation = new PointF(firstAddResult.EndPageBounds.Left, firstAddResult.EndPageBounds.Bottom);
}
// Create the second HTML to PDF element
HtmlToPdfElement secondHtml = new HtmlToPdfElement(secondHtmlLocation.X, secondHtmlLocation.Y, secondUrlTextBox.Text);
// Optionally set a delay before conversion to allow asynchonous scripts to finish
secondHtml.ConversionDelay = 2;
// Add the second HTML to PDF document
secondPdfPage.AddElement(secondHtml);
// Save the PDF document in a memory buffer
byte[] outPdfBuffer = pdfDocument.Save();
// Send the PDF as response to browser
// Set response content type
Response.AddHeader("Content-Type", "application/pdf");
// Instruct the browser to open the PDF file as an attachment or inline
Response.AddHeader("Content-Disposition", String.Format("attachment; filename=Merge_Multipe_HTML.pdf; size={0}", outPdfBuffer.Length.ToString()));
// Write the PDF document buffer to HTTP response
Response.BinaryWrite(outPdfBuffer);
// End the HTTP response and stop the current page processing
Response.End();
}
finally
{
// Close the PDF document
pdfDocument.Close();
}
}

Related

hiqpdf, how to save file to server instead of attachment?

I am trying to save a PDF file to a server path rather than downloading it as an attachment, which I have made with the "hiqpdf" tool. :
protected void btnPrint_Click(object sender, EventArgs e)
{
// create the HTML to PDF converter
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
// set browser width
htmlToPdfConverter.BrowserWidth = int.Parse("805");
// set browser height if specified, otherwise use the default
//if (textBoxBrowserHeight.Text.Length > 0)
// htmlToPdfConverter.BrowserHeight = int.Parse(textBoxBrowserHeight.Text);
// set HTML Load timeout
htmlToPdfConverter.HtmlLoadedTimeout = int.Parse("180");
// set PDF page size and orientation
htmlToPdfConverter.Document.PageSize = PdfPageSize.A4;
htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait;
// set PDF page margins
htmlToPdfConverter.Document.Margins = new PdfMargins(0);
// set a wait time before starting the conversion
htmlToPdfConverter.WaitBeforeConvert = int.Parse("5");
// convert HTML to PDF
byte[] pdfBuffer = null;
//if (radioButtonConvertUrl.Checked)
//{
// convert URL to a PDF memory buffer
string url = System.Configuration.ConfigurationManager.AppSettings["SiteURL"] + "PrintFullApplicantProfile.aspx?MaidID=" + Request.QueryString["aid"].ToString();
pdfBuffer = htmlToPdfConverter.ConvertUrlToMemory(url);
// inform the browser about the binary data format
HttpContext.Current.Response.AddHeader("Content-Type", "application/pdf");
// let the browser know how to open the PDF document, attachment or inline, and the file name
//HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("{0}; filename=HtmlToPdf.pdf; size={1}",
// checkBoxOpenInline.Checked ? "inline" : "attachment", pdfBuffer.Length.ToString()));
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("{0}; filename=Applicant-" + Request.QueryString["aid"].ToString() + ".pdf; size={1}", "attachment", pdfBuffer.Length.ToString()));
// write the PDF buffer to HTTP response
HttpContext.Current.Response.BinaryWrite(pdfBuffer);
// call End() method of HTTP response to stop ASP.NET page processing
HttpContext.Current.Response.End();
}
Any suggestion to save the file to the server path?
Thanks in advance.

How to dynamically link bookmarks to table of contents using PDFsharp + MigraDoc

I'm trying to create a Table of Contents using MigraDoc and PDFsharp and I've gotten really close but the problem I'm currently having is that the links on the Table of Contents all take me to the very first page of the PDF. I'm trying to link them to their respective pages. PDFSharp bookmarks work fine but when trying to create a table of contents based on the merged PDF it's not working.
static void TableOfContents(PdfDocument document)
{
// Puts the Table of contents on the second page
PdfPage page = document.Pages[1];
XGraphics gfx = XGraphics.FromPdfPage(page);
gfx.MUH = PdfFontEncoding.Unicode;
// Create MigraDoc document + Setup styles
Document doc = new Document();
Styles.DefineStyles(doc);
// Add header
Section section = doc.AddSection();
Paragraph paragraph = section.AddParagraph("Table of Contents");
paragraph.Format.Font.Size = 14;
paragraph.Format.Font.Bold = true;
paragraph.Format.SpaceAfter = 24;
paragraph.Format.OutlineLevel = OutlineLevel.Level1;
// Add links - these are the PdfSharp outlines/bookmarks
// added previously when concatinating the pages
foreach (var bookmark in document.Outlines)
{
paragraph = section.AddParagraph();
paragraph.Style = "TOC";
paragraph.AddBookmark(bookmark.Title);
Hyperlink hyperlink = paragraph.AddHyperlink(bookmark.Title);
hyperlink.AddText($"{bookmark.Title}\t");
hyperlink.AddPageRefField(bookmark.Title);
}
// Render document
DocumentRenderer docRenderer = new DocumentRenderer(doc);
docRenderer.PrepareDocument();
docRenderer.RenderPage(gfx, 1);
gfx.Dispose();
}
Ideally I want it to return the file's name (which it's doing) and the page number (it's only returning the first page). This is what it's currently outputting.
Table of Contents
file name here......................... 1
file name here......................... 1
file name here......................... 1
file name here......................... 1
As I understand it, the Hyperlink and bookmark should be unique to the document.
Otherwise the link will be made to the first paragraph containing the bookmark.
I simply use a number which I increase for a simple report I make.
private void DefineTOCLine(int level, string text, Paragraph linkTo)
{
var tocIndex = (tocindex++).ToString(CultureInfo.InvariantCulture);
var paragraph = tocsection.AddParagraph();
paragraph.Style = level == 1 ? "TOC1" : "TOC2";
var hyperlink = paragraph.AddHyperlink(tocIndex);
hyperlink.AddText(text + "\t");
hyperlink.AddPageRefField(tocIndex);
linkTo.AddBookmark(tocIndex);
}
You invoke hyperlink.AddPageRefField to set a reference, but as far as I can tell you never create the MigraDoc bookmark for the target of the reference by calling MigraDoc's AddBookmark method.
MigraDoc bookmarks are different from PDF file bookmarks.

Getting Paper Size of a PDF

I am using PDFsharp to read / write PDF in our application. I am trying to get the paper size of a page to show in metadata window. I am using following code to do the same:
// read PDF document into memory
      var pdfDocument = PdfReader.Open(pdfPath);
      // if PDF document has more than one page, then try to get the page size from first page
      if (pdfDocument.Pages.Count > 0)
      {
        var pageSize = pdfDocument.Pages[0].Size.ToString();
      } // if
But every time it returns 'Undefined', I even tried to create A4 page document for MS Word. But still it returns 'Undefined'.
I also created a PDF from HTML but then also page size comes as undefined.
static void Main(string[] args)
{
// create PDF config to generate PDF
var config = new PdfGenerateConfig()
{
PageSize = PageSize.Letter,
PageOrientation = PageOrientation.Landscape
};
// load the HTML file
var html = System.IO.File.ReadAllText(#"C:\Users\mohit\Desktop\Temp\Ekta\Test.html");
// generate the PDF
var pdf = PdfGenerator.GeneratePdf(html,
PageSize.Letter);
// get the paper size of first page
var size = pdf.Pages[0].Size;
// save the pdf document
pdf.Save(#"C:\Users\mohit\Desktop\Temp\Ekta\A13.pdf");
Console.ReadKey();
}
The properties you have to use are Width and Height. Convert them to millimeter or inch if you do not want to show the size in points.
The property Size is a convenient way to set standard page sizes for new pages as you can specify A4 or Letter. It will not be set for imported PDF files.

Create Multi-page Index File(TOC) for merged pdf using itext library in java

How can I write a multi-page ToC to the end of a PDF consisting of merged documents, using iTextSharp?
The answer to Create Index File(TOC) for merged pdf using itext library in java explains how to create a ToC page when merging PDFs (catalogued in the iTextSharp book http://developers.itextpdf.com/examples/merging-pdf-documents/merging-documents-and-create-table-contents#795-mergewithtoc.java). Code in this answer is based on those examples.
However it only works if the ToC is 1 page long. If the content becomes longer, then it repeats itself on the same page rather than spanning into the next page.
Trying to add the link directly to the text via:
ct.Add(new Chunk("link").SetLocalGoto("p1"))
causes an exception ("Cannot add Annotations, not enough pages in document").
Can anyone explain a method that will allow me to append multiple pages of content to a PDF when merging them (the more general the approach, the better). Is there a way to write into the document using Document.Add() instead of having to copy in template pages and write on the top of them?
(Note, code is in c#)
This answer is based on the example from the iTextSharp documentation, but converted to C#.
To make the added text span multiple pages, I found I could use ColumnText.HasMoreText(ct.Go()) to tell me if there was more text than could fit on the current page. You can then save the current page, re-create a new page template, and move the columntext to the new page. Below this is in a function called CheckForNewPage:
private bool CheckForNewPage(PdfCopy copy, ref PdfImportedPage page, ref PdfCopy.PageStamp stamp, ref PdfReader templateReader, ColumnText ct)
{
if (ColumnText.HasMoreText(ct.Go()))
{
//Write current page
stamp.AlterContents();
copy.AddPage(page);
//Start a new page
ct.SetSimpleColumn(36, 36, 559, 778);
templateReader = new PdfReader("template.pdf");
page = copy.GetImportedPage(templateReader, 1);
stamp = copy.CreatePageStamp(page);
ct.Canvas = stamp.GetOverContent();
ct.Go();
return true;
}
return false;
}
This should be called each time text is added to the ct variable.
If CheckForNewPage returns true you can then increment the page count, and reset the y variable to the top of the new page so that link annotation is in the correct place on the new page.
e.g.
var tocPageCount = 0;
var para = new iTextSharp.text.Paragraph(documentName);
ct.AddElement(para);
ct.Go();
if (CheckForNewPage(context, copy, ref page, ref stamp, ref tocReader, ct))
{
tocPageCount++;
y = 778;
}
//Add link annotation
action = PdfAction.GotoLocalPage(d.DocumentID.ToString(), false);
link = new PdfAnnotation(copy, TOC_Page.Left, ct.YLine, TOC_Page.Right, y, action);
stamp.AddAnnotation(link);
y = ct.YLine;
This creates the pages correctly. The below code adapts the end of ToC2 example for re-ordering the pages, in order to handle more than 1 page.
var rdr = new PdfReader(baos.toByteArray());
var totalPageCount = rdr.NumberOfPages;
rdr.SelectPages(String.Format("{0}-{1}, 1-{2}", totalPageCount - tocPageCount +1, totalPageCount, totalPageCount - tocPageCount));
PdfStamper stamper = new PdfStamper(rdr, new FileStream(outputFilePath, FileMode.Create));
stamper.Close();
By re-using the CheckForNewPage function, you should be able to add any content to new pages you create, and have it span multiple pages. If you don't need the annnotations you call CheckForNewPage in a loop at the end of adding all your content (just don't call ct.Go() beforehand).

Generate PDF from large html

I am generating a PDF from an HTML string.
When this string is really long, I would like to create a new page, split the text (without breaking the html) and so on.
Here is my code :
// instantiate Pdf object
Aspose.Pdf.Generator.Pdf pdf = new Aspose.Pdf.Generator.Pdf();
// specify the Character encoding for for HTML file
pdf.HtmlInfo.CharSet = "UTF-8";
pdf.HtmlInfo.Margin.Left = 10;
pdf.HtmlInfo.Margin.Right = 10;
pdf.HtmlInfo.PageHeight = 1050;
pdf.HtmlInfo.PageWidth = 730;
pdf.HtmlInfo.ShowUnknownHtmlTagsAsText = true;
pdf.HtmlInfo.TryEnlargePredefinedTableColumnWidthsToAvoidWordBreaking = true;
pdf.HtmlInfo.CharsetApplyingLevelOfForce = Aspose.Pdf.Generator.HtmlInfo.CharsetApplyingForceLevel.UseWhenImpossibleDetectFromContent;
// bind the source HTML
pdf.BindHTML("MyVeryVeryLongHTML");
MemoryStream stream = new MemoryStream();
pdf.Save(stream);
byte[] pdfBytes = stream.ToArray();
This code works for the HTML, but the overflow is not handled. The text continue after the page. Is it possible to set a max "height" of the page to not cross, and if it does, it recreates a new page ?
Hope it makes sense !
Thanks a lot
You can set the Page height by selecting type of PDF page you require like A1, A2, etc . Afterwords , your problem of page height will automatically be taken care by the Aspose. For more refer the link..
Aspose PDF Page Height
Update
update pdf.HtmlInfo to pdf.PageSetup (or pdf.PageInfo) and add bottom margin also.

Categories

Resources