Rotativa Display HTML header and footer - c#

I have recently started using Rotativa and works excellently! Except for attempting to configure the headers and the footers of the PDF documents.
string customSwitches = string.Format("--header-html \"{4}\" --footer-left \"{0} {1} - {2}\" --footer-center \"{3}\" --footer-right \"Page: [page]/[toPage]\" --footer-line --footer-font-size \"9\" --footer-spacing 6", "Billing Report", FromDate.Value.ToString("yyyy-MM-dd"), ToDate.Value.ToString("yyyy-MM-dd"), customerData.Name, Url.Action("BillingRunHeader", "Report", new { area = "Admin" }, "http"));
var actionResult = new ViewAsPdf("_BillingRunPDF", GetBillingReport(UserFilterReport, ProductFilterReport, ProjectFilterReport, CustomerFilterReport.Where(x => x == customer).ToArray(), TypeFilterReport, ReportType, FromDate, ToDate, Billable, TaskId).ToList())
{
PageSize = Size.A4,
PageOrientation = Orientation.Landscape,
FileName = customerData.Name.Replace(" ","_") + "_Billing_Report_" + DateTime.Now.Date.ToString("yyyy-MM-dd") + ".pdf",
CustomSwitches = customSwitches
};
Above I have created a string format to replace certain placeholders with data. The --header-html \"{4}\" is pulled from a View template stored which contains a image for the header and this displays perfectly. The issue is that the footer does not display at all.
If I remove the --header-html \"{4}\" then the footer displays perfectly fine. Issue is I need both the header and footer being displayed.
Any help would be greatly appreciated.

For me, it only worked after leaving the header and footer with HTML.
return new ViewAsPdf
{
ViewName = "RptVistoriador",
PageSize = Rotativa.Options.Size.A4,
Model = lstVistoriadorRptViewModel.ToPagedList(1, lstVistoriadorRptViewModel.Count()),
CustomSwitches = $"--footer-html \"{Url.Action("ReportHeader", "Vistoriador", new { area = "" }, "http")}\" --header-html \"{Url.Action("ReportHeader", "Vistoriador", new { area = "" }, "http")}\""
};

Related

Exporting to excel export converts special characters to HTML codes

I need to export Date, Title and Description to excel file, right now i am facing two issue with the export of excel file.
one special characters such as '," an other characters turn into ‘ & etc....
All these issue are with the Description column, which stored text in HTML format. Below is the example of text in various formats
Actual Text
The ‘ Golf Season Opening’ marked the official opening of the at Golf Club, Season to start on March 10, 2018.
Text Stored in Database MS SQL SERVER
The ‘Golf Season Opening ‘ marked the official opening of the at Golf Club& Season to start on March 10& 2018.
Text exported to Excel
The ‘Golf Season Opening ‘ marked the official opening of the at Golf Club& Season to start on March 10& 2018.
I am using below code to create excel file but i am facing above issue.
How can i store text without being decoding text is excel should be store in text format & all special characters show properly without any issue
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Calendar");
DataTable dt = ds.Tables[0];
var rowIndex = 2; // 1 = header row
foreach (DataRow row in dt.Rows)
{
ws.Cell("A" + rowIndex).Value = row["Year"];
ws.Cell("B" + rowIndex).Value = row["Title"];
string noHTML = Regex.Replace(row["Description"].ToString(), #"<[^>]+>| ", "").Trim();
string noHTMLNormalised = Regex.Replace(noHTML, #"\s{2,}", " ");
ws.Cell("C" + rowIndex).Value = noHTMLNormalised;
rowIndex++;
}
//// From worksheet
var rngTable = ws.Range("A1:C" + rowIndex);
var rngHeader = ws.Range("A1:C1");
var rngYear = ws.Range("A2:A" + rowIndex);
//var rngDate = ws.Range("B2:B" + rowIndex);
var rngTitle = ws.Range("B2:D" + rowIndex);
var rngDesc = ws.Range("C2:C" + rowIndex);
rngHeader.Style.Fill.SetBackgroundColor(XLColor.CoolGrey);
rngHeader.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
rngHeader.Style.Font.Bold = true;
rngHeader.Style.Font.FontColor = XLColor.White;
// rngYear.Style.Fill.SetBackgroundColor(XLColor.CoolGrey);
rngYear.Style.Font.Bold = true;
rngYear.Style.Font.FontColor = XLColor.Black;
rngYear.Style.Alignment.Indent = 1;
//rngDate.Style.DateFormat.Format = "MM/DD/YYYY";
//rngDate.Style.Alignment.Indent = 10;
rngDesc.Style.Alignment.SetWrapText();
ws.RangeUsed().Style.Border.OutsideBorder = XLBorderStyleValues.Thick;
var col3 = ws.Column("C");
//col3.Style.Fill.BackgroundColor = XLColor.Red;
col3.Width = 100;
ws.Columns().AdjustToContents();
string fileName;
fileName = "Golf_Calendat.xlsx";
wb.SaveAs(HttpContext.Current.Server.MapPath("../excel/" + fileName));
Any help to fixed the above issue and also if we we can wrap the text in description column and if row can take the auto height based on the wrapped text.
Just to mention i am using using Excel = Microsoft.Office.Interop.Excel; for excel export
you can replace it in a string
str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
Solved Both issue with following code
First by using HTML HttpUtility.HtmlDecode
string htmlDec = HttpUtility.HtmlDecode(row["Description"].ToString());
and text wrap issue with ws.Column(2).AdjustToContents(5, 7);
string htmlEnc = HttpUtility.HtmlEncode(row["Description"].ToString());
string htmlDec = HttpUtility.HtmlDecode(row["Description"].ToString());
string noHTML = Regex.Replace(htmlDec, #"<[^>]+>| ", "").Trim();
string noHTMLNormalised = Regex.Replace(noHTML, #"\s{2,}", " ");
ws.Cell("C" + rowIndex).Value = noHTMLNormalised;

c# Itextsharp copy content table / goto local page

I have a big problem and i hope you can help me out.
I have a PDF file which I split in more files.
Problem: There is a table content (goto page X), but in the new pdf files it doesnt work anymore.
I cant find a solution to copy this table content to the new pdf files.
For your understanding:
I have three pdf files which are equal.
PDF:
Page 1:
Text
Page 2:
Contenttable:
Content x Page 3 (Goto Page 3)
Content x Page 4 ""
content x Page 5 ""
...
...
I put all these pdf files together in one big pdf. (Content table still working)
And now, i will split these back in to single once (Content table not working)
My idea was to export the content table out of the original pdf(Where table content is still working) and to import it in the new once.
But i dont know how.
Second idea: search for keywords in the PDF and change the keyword to an goto local page action.
But i find no solution how i can do this.
However in the end i want to repair the table content in each single pdf file.
any ideas?
code so far:
PdfReader reader = null;
Document sourceDocument = null;
Document remote = null;
PdfCopy pdfCopyProvider = null;
PdfImportedPage importedPage = null;
PdfStamper stamp = null;
Chunk chunk = null;
reader = new PdfReader(path);
Seitenanzahl = reader.NumberOfPages;
sourceDocument = Document(reader.GetPageSizeWithRotation(startpage));
tmp = PdfTextExtractor.GetTextFromPage(reader, startpage);
string[] strsplit = tmp.Split(' ');
vorname = strsplit[4];
nachname = strsplit[5];
ort = strsplit[6];
perso = strsplit[7];
vorname = vorname.Replace("\n", "");
vorname = vorname.Replace(" ", "");
nachname = nachname.Replace("\n", "");
nachname = nachname.Replace(" ", "");
ort = ort.Replace("\n", "");
ort = ort.Replace(" ", "");
perso = perso.Replace("\n", "");
perso = perso.Replace(" ", "");
if (Directory.Exists("test/" + ort))
{
}
else
{
DirectoryInfo di = Directory.CreateDirectory("test/" + ort);
}
outputpdfpath = "test/" + ort + "/" + "p_" + ort + "_" + perso + "_" + vorname.ToLower() + "_" + nachname.ToLower() + "_hj1_booklet_2017" + ".pdf";
pdfCopyProvider = new PdfCopy(sourceDocument,
new FileStream(outputpdfpath, FileMode.Create, FileAccess.ReadWrite));
sourceDocument.Open();
for (int i = startpage; i <= endpage; i++)
{
importedPage = pdfCopyProvider.GetImportedPage(reader, i);
pdfCopyProvider.AddPage(importedPage);
}
sourceDocument.Close();
reader.Close();
}

TuesPechkin adding  in front of Currency £ Symbol

I have been using Tues Pechkin for html to PDF Conversion
But there is one issue
Tues Pechkin is adding by default  this symbol in front of £ Symbol
Example :- £85,000
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "TEST",
PaperSize = PaperKind.A4, // Implicit conversion to PechkinPaperSize
Margins =
{
All = 1.375,
Unit = Unit.Centimeters
}
}}
Please help
Thanku.
added a new Websettings
new ObjectSettings { HtmlText = strContent,
WebSettings = new WebSettings
{
DefaultEncoding = "UTF-8",
LoadImages = true,
PrintBackground = true
}
}
So that it can accept UTF-8 character ,And it is resolved. Thanku

How can I add a header and footer to the generated PDF

I'm using Gmanny's Pechkin Pdf library and it's working perfectly. Here's is my code:
private void CreatePdfPechkin(string htmlString, string fileName)
{
//Transform the HTML into PDF
var pechkin = Factory.Create(new GlobalConfig()
.SetMargins(new Margins(100, 50, 100, 100))
.SetDocumentTitle("Test document")
.SetPaperSize(PaperKind.A4)
.SetCopyCount(1)
//.SetPaperOrientation(true)
// .SetOutputFile("F:/Personal/test.pdf")
);
ObjectConfig oc = new ObjectConfig();
oc.Footer.SetLeftText("[page]");
oc.Footer.SetTexts("[page]", "[date]", "[time]");
oc.Header.SetCenterText("TEST HEADER TEST1");
oc.Header.SetHtmlContent("<h1>TEST HEADER V2</h1>");
oc.SetAllowLocalContent(true);
//// create converter
//IPechkin ipechkin = new SynchronizedPechkin(pechkin);
// set it up using fluent notation
var pdf = pechkin.Convert(new ObjectConfig()
.SetLoadImages(true).SetZoomFactor(1.5)
.SetPrintBackground(true)
.SetScreenMediaType(true)
.SetCreateExternalLinks(true), htmlString);
//Return the PDF file
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename=test.pdf; size={0}", pdf.Length));
Response.BinaryWrite(pdf);
Response.Flush();
Response.End();
// byte[] pdf = new Pechkin.Synchronized.SynchronizedPechkin(
//new Pechkin.GlobalConfig()).Convert(
// new Pechkin.ObjectConfig()
// .SetLoadImages(true)
// .SetPrintBackground(true)
// .SetScreenMediaType(true)
// .SetCreateExternalLinks(true), htmlString);
// using (FileStream file = System.IO.File.Create(#"F:\Pankaj WorkSpace\"+ fileName))
// {
// file.Write(pdf, 0, pdf.Length);
// }
}
But now I want to add header, footer and page Number, can somebody suggest how to do that?
I know it is possible through Object config I tried but its not working..
Headers and footers using the below very basic examples work for me.
Using Pechkin:
GlobalConfig gc = new GlobalConfig();
gc.SetMargins(new Margins(300, 100, 150, 100))
.SetDocumentTitle("Test document")
.SetPaperSize(PaperKind.Letter);
IPechkin pechkin = new SynchronizedPechkin(gc);
ObjectConfig oc = new ObjectConfig();
oc.SetCreateExternalLinks(false);
oc.SetFallbackEncoding(Encoding.ASCII);
oc.SetLoadImages(false);
oc.Footer.SetCenterText("I'm a footer!");
oc.Footer.SetLeftText("[page]");
oc.Header.SetCenterText("I'm a header!");
byte[] result = pechkin.Convert(oc, "<h1>My Website</h1>");
System.IO.File.WriteAllBytes(#"c:\pechkinTest.pdf", result);
I'd recommend you switch to Tuespechkin though. This is an active fork of Pechkin which includes many bugfixes. Unfortunately active development on Pechkin ceased since 2013.
Using Tuespechkin:
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "My Website",
PaperSize = PaperKind.A4,
Margins =
{
All = 1.375,
Unit = Unit.Centimeters
}
},
Objects = {
new ObjectSettings
{
HtmlText = "<h1>My Website</h1>",
HeaderSettings = new HeaderSettings{CenterText = "I'm a header!"},
FooterSettings = new FooterSettings{CenterText = "I'm a footer!", LeftText = "[page]"}
}
}
};
IPechkin converter = Factory.Create();
byte[] result = converter.Convert(document);
System.IO.File.WriteAllBytes(#"c:\tuespechkinTest.pdf", result);
Your issue is this. Instead of creating a new second ObjectConfig, you need to pass the OC you created before which includes the header and footer. Just combine them like this:
ObjectConfig oc = new ObjectConfig();
oc.SetLoadImages(true);
oc.SetZoomFactor(1.5);
oc.SetPrintBackground(true);
oc.SetScreenMediaType(true);
oc.SetCreateExternalLinks(true);
oc.Footer.SetLeftText("[page]");
oc.Footer.SetCenterText("I'm a footer!");
oc.Header.SetCenterText("TEST HEADER TEST1");
var result = pechkin.Convert(oc, "<h1>My Website</h1>");
System.IO.File.WriteAllBytes(#"c:\pechkinTest.pdf", result);

New page in ITextSharp does not create new page

In the following code I create a pdf dynamically using ITextSharp.
I want the 2nd table to be splitted when there is not room enough on the page.
How can this be accomplished ? I tried it with the newPage method on the pdf stamper, but no new page has been created...
(not all codepaths included for readability)
private byte[] DoGenerateStatisticsPerOrganisationalUnitPdf(
string emptyPdfFile,
DateTime currentDateTime,
string organisationalUnit,
int? roleId,
DateTime? fromDate,
DateTime? toDate)
{
var pdfReader = new ITextSharp.pdf.PdfReader(emptyPdfFile); // note that PdfReader is not IDisposeable
using (MemoryStream memoryStream = new MemoryStream())
using (ITextSharp.pdf.PdfStamper pdfStamper = new ITextSharp.pdf.PdfStamper(pdfReader, memoryStream))
{
// Get content bytes of first page
var pdfContentByte = pdfStamper.GetOverContent(1);
// Make a page width/height large rectangle column for write actions
var ct = new ITextSharp.pdf.ColumnText(pdfContentByte);
ct.SetSimpleColumn(
PageStartX,
PageStartY,
PageEndX,
PageEndY);
var paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk("Statistieken Profchecks", titleFont));
ct.AddElement(paragraph);
// Add printed date time
var dateTimeText = string.Format(
CultureInfo.CurrentCulture,
"Afdrukdatum: {0}",
currentDateTime.ToString(DateFormat, CultureInfo.CurrentCulture));
paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk(dateTimeText, rowFont));
ct.AddElement(paragraph);
// Add selected filter
var filterItems = string.Empty;
if (!string.IsNullOrEmpty(organisationalUnit))
{
filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, " ° Organisatie: {0}", organisationalUnit);
}
if (roleId.HasValue)
{
filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, " ° Rol: {0}", roleService.GetById(roleId.Value).Name);
}
if (fromDate.HasValue)
{
filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, " ° Datum van: {0}", fromDate.Value.ToString(DateFormat, CultureInfo.CurrentCulture));
}
if (toDate.HasValue)
{
filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, " ° Datum t/m: {0}", toDate.Value.ToString(DateFormat, CultureInfo.CurrentCulture));
}
var filterText = string.Format(
CultureInfo.CurrentCulture,
"Geselecteerde filter: {0}",
filterItems.Length > 0 ? filterItems : "(geen filter)");
paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk(filterText, rowFont));
ct.AddElement(paragraph);
paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk("\nResultaten per game", titleFont));
ct.AddElement(paragraph);
// Table: Results per game
var table = CreateTable(new string[] { "Game", "Unieke spelers", "Resultaat" });
var gameResultList = statisticsService.GetOrganisationalUnitStatistics(1, 20, organisationalUnit, roleId, fromDate, toDate);
foreach (var gameResultItem in gameResultList)
{
table.AddCell(new iTextSharp.text.Phrase(gameResultItem.Game, rowFont));
table.AddCell(new iTextSharp.text.Phrase(gameResultItem.NumberOfUsers.ToString(CultureInfo.CurrentCulture), rowFont));
var percentage = gameResultItem.AveragePercentage.HasValue ? string.Format(CultureInfo.CurrentCulture, "{0}%", gameResultItem.AveragePercentage) : "?";
table.AddCell(new iTextSharp.text.Phrase(percentage, rowFont));
}
table.CompleteRow();
ct.AddElement(table);
paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk("\nResultaten per kenniscategorie", titleFont));
ct.AddElement(paragraph);
// Table: Results per knowledgecategory
table = CreateTable(new string[] { "Kenniscategorie", "Gemiddeld", "Laagste", "Hoogste", "Standaard deviatie" });
var knowledgeCategoryResultList = statisticsService.GetGlobalKnowledgeCategoryResultStatistics(
organisationalUnit,
roleId,
fromDate,
toDate);
foreach (var knowledgeCategoryResultItem in knowledgeCategoryResultList)
{
table.AddCell(new iTextSharp.text.Phrase(knowledgeCategoryResultItem.KnowledgeCategory.Name, rowFont));
table.AddCell(new iTextSharp.text.Phrase(
knowledgeCategoryResultItem.Statistics.Average.ToString(CultureInfo.CurrentCulture),
rowFont));
table.AddCell(new iTextSharp.text.Phrase(
knowledgeCategoryResultItem.Statistics.Minimum.ToString(CultureInfo.CurrentCulture),
rowFont));
table.AddCell(new iTextSharp.text.Phrase(
knowledgeCategoryResultItem.Statistics.Maximum.ToString(CultureInfo.CurrentCulture),
rowFont));
table.AddCell(new iTextSharp.text.Phrase(
knowledgeCategoryResultItem.Statistics.StDev.HasValue ? knowledgeCategoryResultItem.Statistics.StDev.Value.ToString(
CultureInfo.CurrentCulture) : "?",
rowFont));
}
table.CompleteRow();
ct.AddElement(table);
// Parse
ct.Go();
pdfStamper.FormFlattening = true;
pdfStamper.FreeTextFlattening = true;
// Close stamper explicitly, otherwise the pdf gets corrupted (don't wait until the Dispose is called in the using-clause)
pdfStamper.Close();
// Always call ToArray, to get all the bytes returned.
return memoryStream.ToArray();
}
}
I see you take an existing PDF file (referred to as "emptyPdfFile") add content to that PDF (2 tables) and want to add pages as necessary. So I assume you actually want to create a PDF from scratch.
In that case it's most likely easier to use PdfWriter and add your tables using Document.Add(). Tables will be split and pages will be added automatically when the end of the current page is reached.
A simple example of adding a table with Document.Add() can be found here in the MyFirstTable example (that's iText code in Java, check the C# port for iTextSharp code).
If you do want to follow the approach of your example code, using PdfReader, PdfStamper and ColumnText:
ColumnText.Go() adds content to the defined area until that area is full. Any remaining content stays in the ColumnText object. So if you want to split the content over multiple areas, you have to loop and call ColumnText.Go() until all content is consumed.
Here's an example of the ColumnText.Go() looping: ColumnTable (Again, you may want to check the C# port).
In that example the tables are layed out in 2 columns on each page, but the approach stays the same for 1 table per page.
Note that Document.NewPage() is used in the example to add an extra page. You'll have to replace this call with PdfStamper.InsertPage() in your case.

Categories