I am trying to create reports in my asp.net MVC3 application after a lot of search I found many blog posts talks about ITextSharp to convert my Html/Razor to Pdf I am trying to parse razor view to get PDf as follows
public void Render(ViewContext viewContext, TextWriter writer)
{
var doc = new Document();
// associate output with response stream
var pdfWriter = PdfWriter.GetInstance(doc, viewContext.HttpContext.Response.OutputStream);
pdfWriter.CloseStream = false;
viewContext.HttpContext.Response.ContentType = "application/pdf";
viewContext.HttpContext.Response.ContentEncoding = System.Text.Encoding.UTF8;
// generate view into string
var sb = new System.Text.StringBuilder();
TextWriter tw = new System.IO.StringWriter(sb);
_result.View.Render(viewContext, tw);
var resultCache = sb.ToString();
//Path to our font
string arialuniTff = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ARIALUNI.TTF");
//Register the font with iTextSharp
iTextSharp.text.FontFactory.Register(arialuniTff);
//Create a new stylesheet
iTextSharp.text.html.simpleparser.StyleSheet ST = new iTextSharp.text.html.simpleparser.StyleSheet();
//Set the default body font to our registered font's internal name
ST.LoadTagStyle(HtmlTags.BODY, HtmlTags.FACE, "Arial Unicode MS");
//Set the default encoding to support Unicode characters
ST.LoadTagStyle(HtmlTags.BODY, HtmlTags.ENCODING, BaseFont.IDENTITY_H);
//Parse our HTML using the stylesheet created above
List<IElement> list = HTMLWorker.ParseToList(new StringReader(resultCache), ST);
doc.Open();
//Loop through each element, don't bother wrapping in P tags
foreach (var element in list)
{
doc.Add(element);
}
doc.Close();
pdfWriter.Close();
}
the result of that code is
which is not correct, the arabic word should be "محمد". so what I need is to set document direction to be from right to left
EDIT
Thanks to #Romulus
I made a little changes to his code i just replaced adding element to PdfPCell to looping on my Html and set some attributes
//Loop through each element, don't bother wrapping in P tags
foreach (var element in list)
{
//Create a cell and add text to it
//PdfPCell text = new PdfPCell(new Phrase(element.ToString(), f));
//Ensure that wrapping is on, otherwise Right to Left text will not display
//text.NoWrap = false;
//Add the cell to the table
//table.AddCell(text);
if (element is iTextSharp.text.pdf.PdfPTable)
{
table = (iTextSharp.text.pdf.PdfPTable)element;
table.DefaultCell.NoWrap = false;
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
foreach (PdfPRow row in table.Rows)
{
foreach (PdfPCell cell in row.GetCells())
{
cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
cell.NoWrap = false;
}
}
}
}
That's working for me now well Thanks :)
You need to use container elements which support RunDirection, such as ColumnText or PdfPCell and then set their element.RunDirection = PdfWriter.RUN_DIRECTION_RTL
List<IElement> list = HTMLWorker.ParseToList(new StringReader(resultCache), ST);
doc.Open();
//Use a table so that we can set the text direction
PdfPTable table = new PdfPTable(1);
//Ensure that wrapping is on, otherwise Right to Left text will not display
table.DefaultCell.NoWrap = false;
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
//Loop through each element, don't bother wrapping in P tags
foreach (var element in list)
{
//Create a cell and add text to it
PdfPCell text = new PdfPCell(new Phrase(element, font));
//Ensure that wrapping is on, otherwise Right to Left text will not display
text.NoWrap = false;
//Add the cell to the table
table.AddCell(text);
}
//Add the table to the document
document.Add(table);
doc.Close();
pdfWriter.Close();
For addition reference, have a look at this sample.
Related
I have generated a spreadsheet with data and a chart based on the data using C# OpenXML.
I am now wanting to now embed this chart into a word document, so that when these reports are sent out, the charts can be edited if need be (Not an external link).
I have looked around for hours and can't find any consistent documentation for articles which achieve this. Most leads seem to talk about 'EmbeddedPackageParts'.
If anyone has any helpful articles or can provide some clarity it would be appreciated.
Cheers,
Duncan.
I ended up figuring this out!
Steps:
Generate xlsx file with my data in it.
Save the xlsx file locally
In my word document create a new chart part and generate the graph contents
ChartPart wordChartPart = document.MainDocumentPart.AddNewPart<ChartPart>();
string wordChartId = document.MainDocumentPart.GetIdOfPart(wordChartPart);
WordDocumentBuilder.Workflows.SpreadsheetUtils.GenerateBarChartPart(wordChartPart, categories, dataRows);
Embed the spreadsheet in the ChartPart
EmbeddedPackagePart embeddedObjectPart = wordChartPart.AddEmbeddedPackagePart(#"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
using (FileStream stream = new FileStream(file, FileMode.Open))
{
byte[] documentBytes = new byte[stream.Length];
stream.Read(documentBytes, 0, documentBytes.Length);
using (BinaryWriter writer = new BinaryWriter(embeddedObjectPart.GetStream()))
{
writer.Write(documentBytes);
writer.Flush();
}
}
I could then insert an Inline Drawing into my word document which referenced the chart part.
you can open both the new word document and the excel sheet that your charts are included currently.
You can add some rich text content controls to the word document and insert the Chartparts of the excel sheet in those places.
Make sure that your charts have titles. You can read the charts from the titles
To append them to the word document you need to create a paragraph object and append it to a Run object and also you need to define an Inline also in order to append the charts.
I hope you can make the things I said clear by looking at the following example.
private string WordReportGeneration(string docPath, string excelPath)
{
string[] chartTitles = new string[] {"","","","","","",.... };//Chart titles
string[] bookMark = new string[] { "C1", "C2", "C3",..... };//rich text controls of the word doc
for (int i = 0; i < chartTitles.Length; i++) //going through the chart title array
{
using (WordprocessingDocument myWordDoc = WordprocessingDocument.Open(docPath, true))
{
MainDocumentPart mainPart = myWordDoc.MainDocumentPart;
SdtBlock sdt = null;
mainPart.Document.Descendants<SdtBlock>().ToList().ForEach(b => {
var child = b.SdtProperties.GetFirstChild<Tag>();
if (child != null && child.Val.Equals(bookMark[i]))
sdt = b;
});
Paragraph p = sdt.SdtContentBlock.GetFirstChild<Paragraph>();
p.RemoveAllChildren();
Run r = new Run();
p.Append(r);
Drawing drawing = new Drawing();
r.Append(drawing);
Inline inline = new Inline(
new Extent()
{ Cx = 5486400, Cy = 3200400 });
using (SpreadsheetDocument mySpreadsheet = SpreadsheetDocument.Open(excelPath, true))
{
WorkbookPart workbookPart = mySpreadsheet.WorkbookPart;
Sheet theSheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(s => s.Name == "Report");
WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(theSheet.Id);
DrawingsPart drawingPart = worksheetPart.DrawingsPart;
ChartPart chartPart = (ChartPart)drawingPart.ChartParts.FirstOrDefault(x =>
x.ChartSpace.ChildElements[4].FirstChild.InnerText.Trim() == chartTitles[i]);
ChartPart importedChartPart = mainPart.AddPart<ChartPart>(chartPart);
string relId = mainPart.GetIdOfPart(importedChartPart);
DocumentFormat.OpenXml.Drawing.Spreadsheet.GraphicFrame frame = drawingPart.WorksheetDrawing.Descendants<DocumentFormat.OpenXml.Drawing.Spreadsheet.GraphicFrame>().First();
Graphic clonedGraphic = (Graphic)frame.Graphic.CloneNode(true);
ChartReference c = clonedGraphic.GraphicData.GetFirstChild<ChartReference>();
c.Id = relId;
DocProperties docPr = new DocProperties();
docPr.Name = "XXX";
docPr.Id = GetMaxDocPrId(mainPart) + 1;
inline.Append(docPr, clonedGraphic);
drawing.Append(inline);
}
myWordDoc.Save();
myWordDoc.Close();
}
}
return docPath;
}
enter code here
enter code here
Paragraph CommentsofExaminerData = new Paragraph();
if (DTO.QuestionComment != null)
{
CommentsofExaminerData = new Paragraph(DTO.QuestionComment, fontH2);
}
cell1 = new PdfPCell(new Paragraph(CommentsofExaminerData));
I have html richtextbox value in DTO.QuestionComment and i want to convert to html Format.
How can I parse the data?
I have a PDfTable like below, my problem is if Phrase text too big than it makes blank line between header and phrase. How can I bound together so if phrase text too big for one page than fit what ever text you can on the same page with headers and rest of the phrase text you can start with new page.
problem:
.............................
. header1 : header2 :header3: Page1 // here I want to fit the phrase as much as can if phrase needs new page than put rest of the text on the next page
. :
. phrase too big to fit here:
............................:
.............................
. phrase starts here . Page2
. .
.............................
code:
private String WritePDF(DataTable dt)
{
String fileName = "";
//Creating iTextSharp Table from the DataTable data
PdfPTable pdfTable = new PdfPTable(m_PDFColumnCount);
pdfTable.DefaultCell.Padding = 1;
pdfTable.WidthPercentage = 100;
pdfTable.HorizontalAlignment = Element.ALIGN_JUSTIFIED;
pdfTable.DefaultCell.BackgroundColor = new iTextSharp.text.BaseColor(194, 214, 155);
//pdfTable.DefaultCell.BorderWidth = 1;
this.BuildPDFHeader(pdfTable, "DATE");
this.BuildPDFHeader(pdfTable, "TIME");
this.BuildPDFHeader(pdfTable, "RESULT");
this.BuildPDFHeader(pdfTable, "FULLNAME");
this.BuildPDFHeader(pdfTable, "REGARDING");
//Adding DataRow
for (int intIndex = 0; intIndex < dt.Rows.Count; intIndex++)
{
dt.Rows[intIndex]["details"] = getplaintext(dt.Rows[intIndex]["details"].ToString());
pdfTable.AddCell(dt.Rows[intIndex]["date"].ToString());
pdfTable.AddCell(dt.Rows[intIndex]["time"].ToString());
pdfTable.AddCell(dt.Rows[intIndex]["result"].ToString());
pdfTable.AddCell(dt.Rows[intIndex]["fullname"].ToString());
pdfTable.AddCell(dt.Rows[intIndex]["regarding"].ToString());
PdfPCell cell = new PdfPCell(new Phrase(dt.Rows[intIndex]["details"].ToString()));
cell.BackgroundColor = new iTextSharp.text.BaseColor(227, 234, 235);
cell.Colspan = 5;
pdfTable.AddCell(cell);
}
//String folderPath = ConfigurationManager.AppSettings["Path"].ToString();
String folderPath = "C:\\PDFs\\";
fileName = String.Format("{0}{1}{2}",folderPath, dt.Rows[0]["id"].ToString(),".pdf" );
//Exporting to PDF
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate ))
{
Document pdfDoc = new Document(PageSize.A4, 20, 20, 20, 20);
PdfWriter.GetInstance(pdfDoc, stream);
pdfDoc.Open();
pdfDoc.Add(pdfTable);
pdfDoc.Close();
stream.Close();
}
return fileName;
}
private void BuildPDFHeader( PdfPTable pdfTable, String strText)
{
PdfPCell cell = new PdfPCell(new Phrase(strText));
cell.BackgroundColor = new iTextSharp.text.BaseColor(51, 102,102);
pdfTable.AddCell(cell);
}
Introduce the following line right after you define the table:
pdfTable.SplitLate = false;
This will split rows early. In you case, the rows are split only if a row takes up the space of an entire page.
Im writing a simple app that allows a user to export the created datagrid (here its dataGridView1) to a pdf file with a little help from itextsharp reference.
I've found a useful sample code on the internet but im having some problems in configuring it to export the data that the user enters during his work with the app. The user enters the data in textbox, saves it to the datagrid.
The result pdf file only contains the headers taken from the textbox and no cell content (data entered and saved by users using the textboxes).
Here is the code
//Creating iTextSharp Table from the DataTable data
PdfPTable pdfTable = new PdfPTable(dataGridView1.ColumnCount);
pdfTable.DefaultCell.Padding = 3;
pdfTable.WidthPercentage = 30;
pdfTable.HorizontalAlignment = Element.ALIGN_LEFT;
pdfTable.DefaultCell.BorderWidth = 1;
//Adding Header row
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
PdfPCell cell = new PdfPCell(new Phrase(column.HeaderText));
cell.BackgroundColor = new iTextSharp.text.BaseColor(240, 240, 240);
pdfTable.AddCell(cell);
}
//Exporting to PDF
string folderPath = "C:\\Users\\Marcus\\PDFs\\";
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
using (FileStream stream = new FileStream(folderPath + "DataGridViewExport.pdf", FileMode.Create))
{
Document pdfDoc = new Document(PageSize.A2, 10f, 10f, 10f, 0f);
PdfWriter.GetInstance(pdfDoc, stream);
pdfDoc.Open();
pdfDoc.Add(pdfTable);
pdfDoc.Close();
stream.Close();
}
}
Okay so this is your header code (which you said works so lets leave that alone)
//Adding Header row
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
PdfPCell cell = new PdfPCell(new Phrase(column.HeaderText));
cell.BackgroundColor = new iTextSharp.text.BaseColor(240, 240, 240);
pdfTable.AddCell(cell);
}
//Lets add code that actually gets the cell contents down below it:
//add the cell contents
foreach(DataGridViewRow row in dataGridView1.Rows) {
foreach(DataGridViewCell cell in row.Cells) {
//we need to call .Value to get the value of the cell, but since a Phrase takes in
//a String, we need to convert the .Value to a String using .ToString()
PdfPCell pdfCell = new PdfPCell(new Phrase(cell.Value.ToString())); //this .Value property is that of a DataGridViewCell
pdfTable.AddCell(pdfCell);
}
}
DataGridViewCell should have a Value property. Use that to get your value of the cells.
I'm using C#, ASP.NET, iTextSharp for my application.
I have formatting issues when I print my datatable to PDF.
I have two datatables: dt and dt_child
foreach (DataRow dr in dt.Rows)
{
foreach (DataColumn dc in dt.Columns)
{
stringWrite.Write(dr[dc]);
}
indentno=dr["REF"].ToString();
dt_child = getDataTablebyProcedure("ChildProcedure",ref);
stringWrite = getStringWriterbyDataTable(dt_child, stringWrite);
}
Code is working fine. I have an issue with formatting.
The picture shows how it is currently displayed.
I want
1: The header row of dt to be displayed. It is currently not displayed.
2: The row of dt to be displayed in table form. Currently I'm iterating rows in each column.
You will need to set UI for PDF.
Try this if it helps
private void ExportDataToPDFTable()
{
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
try
{
string pdfFilePath = Server.MapPath(".") + "/pdf/myPdf.pdf";
//Create Document class object and set its size to letter and give space left, right, Top, Bottom Margin
PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream(pdfFilePath, FileMode.Create));
doc.Open();//Open Document to write
Font font8 = FontFactory.GetFont("ARIAL", 7);
//Write some content
Paragraph paragraph = new Paragraph("Using ITextsharp I am going to show how to create simple table in PDF document ");
DataTable dt = GetDataTable();
if (dt != null)
{
//Craete instance of the pdf table and set the number of column in that table
PdfPTable PdfTable = new PdfPTable(dt.Columns.Count);
PdfPCell PdfPCell = null;
//Add Header of the pdf table
PdfPCell = new PdfPCell(new Phrase(new Chunk("ID", font8)));
PdfTable.AddCell(PdfPCell);
PdfPCell = new PdfPCell(new Phrase(new Chunk("Name", font8)));
PdfTable.AddCell(PdfPCell);
//How add the data from datatable to pdf table
for (int rows = 0; rows < dt.Rows.Count; rows++)
{
for (int column = 0; column < dt.Columns.Count; column++)
{
PdfPCell = new PdfPCell(new Phrase(new Chunk(dt.Rows[rows][column].ToString(), font8)));
PdfTable.AddCell(PdfPCell);
}
}
PdfTable.SpacingBefore = 15f; // Give some space after the text or it may overlap the table
doc.Add(paragraph);// add paragraph to the document
doc.Add(PdfTable); // add pdf table to the document
}
}
catch (DocumentException docEx)
{
//handle pdf document exception if any
}
catch (IOException ioEx)
{
// handle IO exception
}
catch (Exception ex)
{
// ahndle other exception if occurs
}
finally
{
//Close document and writer
doc.Close();
}
}
Courtesy
Add table into existing PDF using iTExtsharp
For reference
http://www.codeproject.com/Tips/573907/Generating-PDF-using-ItextSharp-with-Footer-in-Csh