I have a pdf document where I am filling all the values using the below code.
using(MemoryStream ms = new MemoryStream())
{
// Fill the PDF with the XFA
using(PdfStamper stamper = new PdfStamper(oInPDF, ms))
{
stamper.Writer.CloseStream = false;
XfaForm.SetXfa(oXFA, stamper.Reader, stamper.Writer);
}
// Code for Flatten the filled PDF.
}
I am trying to draw a box in red around the value displayed to highlight when the values are not in the expected range.
I would like to know, how do I locate the position of a control on a pdf page using iTextSharp and C#.
Any help or info on this, much appreciated.
Many Thanks.
Finally managed to draw borders around controls with below code.
XmlDocument newXMLDoc = new XmlDocument();
newXMLDoc.LoadXml(#"<border><edge thickness=""1.3mm""><color value=""0, 0, 255""/></edge></border>");
if (Rs.Rows.Count > 0)
{
foreach (DataRow query in Rs.Rows)
{
if(isRET)
{
if (oXFA.DomDocument.SelectSingleNode("//t:*[#name='" + Rs[0] + "']", oNameSpace) != null)
{
XmlNode newNode =
oXFA.DomDocument.ImportNode(newXMLDoc.SelectSingleNode("border"), true);
oXFA.DomDocument.SelectSingleNode("//t:*[#name='" + Rs[0] + "']", oNameSpace).AppendChild(newNode);
}
}
}
}
Related
I'm using iText 7 for printing some text in List (in Hebrew) to PDF file, but while printing the Hebrew characters are printed in a reverse way.
The input given was "קניון אם הדרך" while the data printed in PDF is "ךרדה םא ןוינק"
I have set the font encoding and the base direction for the elements but still the characters are printed in the reverse order.
Code to print list into the table in PDF:
public void PrintListData(string filename)
{
var writer = new PdfWriter(filename);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc, PageSize.A4);
SetFont(doc);
Table table = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();
table.SetTextAlignment(TextAlignment.RIGHT);
//table.SetBaseDirection(BaseDirection.RIGHT_TO_LEFT);
var index = 1;
foreach (var item in _data)
{
var para = new Paragraph(item);
para.SetTextAlignment(TextAlignment.RIGHT);
//para.SetBaseDirection(BaseDirection.RIGHT_TO_LEFT);
table.AddCell(index.ToString());
table.AddCell(para);
index++;
}
doc.Add(table);
doc.Close();
Process.Start(filename);
}
Set font function
void SetFont(Document doc)
{
FontSet _defaultFontSet = new FontSet();
var fontFolders = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
_defaultFontSet.AddFont(System.IO.Path.Combine(fontFolders, "arial.ttf"), PdfEncodings.IDENTITY_H);
_defaultFontSet.AddFont(System.IO.Path.Combine(fontFolders, "arialbd.ttf"), PdfEncodings.IDENTITY_H);
doc.SetFontProvider(new FontProvider(_defaultFontSet));
doc.SetProperty(Property.FONT, new String[] { "MyFontFamilyName" });
//doc.SetProperty(Property.BASE_DIRECTION, BaseDirection.RIGHT_TO_LEFT);
}
I'm not sure to where should we set the text direction to print RTL.
Using C# in VS, I am trying to change the author name in track changes found in a word document header based on their dates. Using the debugger, it seems that the author's name is getting changed, but the document changes are not getting saved. I have included the 'headerPart.Header.Save()' line, which would presumably do trick, but no luck. I need help saving the document after the changes have been made - thanks!
private void changeRevAuthor(string docPath, string input_project_date)
{
using (Stream stream = System.IO.File.Open(docPath, FileMode.OpenOrCreate))
{
stream.Seek(0, SeekOrigin.End);
XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))
{
foreach (HeaderPart headerPart in document.MainDocumentPart.HeaderParts)
{
foreach (OpenXmlElement headerElement in headerPart.RootElement.Descendants())
{
OpenXmlElement children = headerPart.RootElement;
XElement xchildren = XElement.Parse(children.OuterXml);
var ychildren = xchildren.Descendants().Where(x => x.Attributes(w + "author").Count() > 0);
foreach (XElement descendant in ychildren)
{
var date = descendant.Attribute(w + "date").ToString().Substring(8, 10);
if (DateTime.Parse(date) > DateTime.Parse(input_project_date))
{
descendant.SetAttributeValue(w + "author", "new author name");
Debug.WriteLine("this is the new one" + descendant);
}
}
}
headerPart.Header.Save();
Debug.WriteLine("We got here");
}
document.Close();
}
}
}
Use MainDocumentPart save() method to save the changes in the document.
ie:document.MainDocumentPart.Document.Save();
I am successfully merging PDF documents; now as I'm trying to implement the error handling in case no PDF document has been selected, it throws an error when closing the document: The document has no pages
In case no PDF document has been added in the "foreach" - loop, I still need to close the document!? Or not? If you open an object then it has do be closed at some point. So how to I escape correctly in case no page had been added?
private void MergePDFs()
{
DataSourceSelectArguments args = new DataSourceSelectArguments();
DataView view = (DataView)SourceCertCockpit.Select(args);
System.Data.DataTable table = view.ToTable();
List<PdfReader> readerList = new List<PdfReader>();
iTextSharp.text.Document document = new iTextSharp.text.Document();
PdfCopy copy = new PdfCopy(document, Response.OutputStream);
document.Open();
int index = 0;
foreach (DataRow myRow in table.Rows)
{
if (ListadoCertificadosCockpit.Rows[index].Cells[14].Text == "0")
{
PdfReader Reader = new PdfReader(Convert.ToString(myRow[0]));
Chapter Chapter = new Chapter(Convert.ToString(Convert.ToInt32(myRow[1])), 0);
Chapter.NumberDepth = 0;
iTextSharp.text.Section Section = Chapter.AddSection(Convert.ToString(myRow[10]), 0);
Section.NumberDepth = 0;
iTextSharp.text.Section SubSection = Section.AddSection(Convert.ToString(myRow[7]), 0);
SubSection.NumberDepth = 0;
document.Add(Chapter);
readerList.Add(Reader);
for (int i = 1; i <= Reader.NumberOfPages; i++)
{
copy.AddPage(copy.GetImportedPage(Reader, i));
}
Reader.Close();
}
index++;
}
if (document.PageNumber == 0)
{
document.Close();
return;
}
document.Close();
string SalesID = SALESID.Text;
Response.ContentType = "application/pdf";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.AppendHeader("content-disposition", "attachment;filename=" + SalesID + ".pdf");
}
In the old days, iText didn't throw an exception when you created a document and "forgot" to add any content. This resulted in a document with a single, blank page. This was considered a bug: people didn't like single-page, empty documents. Hence the design decision to throw an exception.
Something similar was done for newPage(). A new page can be triggered explicitly (when you add document.newPage() in your code) or implicitly (when the end of a page is reached). In the old days, this often resulted in unwanted blank pages. Hence the decision to ignore newPage() in case the current page is empty.
Suppose you have this:
document.newPage();
document.newPage();
One may expect that two new pages are created. That's not true. We've made a design decision to ignore the second document.newPage() because no content was added after the first document.newPage().
This brings us to the question: what if we want to insert a blank page? Or, in your case: what if it's OK to create a document with nothing more than a single blank page?
In that case, we have to tell iText that the current page shouldn't be treated as an empty page. You can do so by introducing the following line:
writer.setPageEmpty(false);
Now the current page will be fooled into thinking that it has some content, even though it may be blank.
Adding this line to your code will avoid the The document has no pages exception and solve your problem of streams not being closed.
Take a look at the NewPage example if you want to experiment with the setPageEmpty() method.
You can add an empty page before closing the document, or catch the exception and ignore it.
In case you are still interested in a solution, or may be someone else.
I had exactly the same issue and I workaround-ed it by:
Declaring a boolean to figure out if at least one page have been added and before closing the document I referred on it.
If no pages have been copied, I add a new page in the document thanks to the AddPages method, with a rectangle as parameter. I did not find a simplest way to add a page.
So the code should be as bellow (with possibly some syntax errors as I'm not familiar with C#):
private void MergePDFs()
{
DataSourceSelectArguments args = new DataSourceSelectArguments();
DataView view = (DataView)SourceCertCockpit.Select(args);
System.Data.DataTable table = view.ToTable();
List<PdfReader> readerList = new List<PdfReader>();
iTextSharp.text.Document document = new iTextSharp.text.Document();
PdfCopy copy = new PdfCopy(document, Response.OutputStream);
document.Open();
int index = 0;
foreach (DataRow myRow in table.Rows)
{
if (ListadoCertificadosCockpit.Rows[index].Cells[14].Text == "0")
{
PdfReader Reader = new PdfReader(Convert.ToString(myRow[0]));
Chapter Chapter = new Chapter(Convert.ToString(Convert.ToInt32(myRow[1])), 0);
Chapter.NumberDepth = 0;
iTextSharp.text.Section Section = Chapter.AddSection(Convert.ToString(myRow[10]), 0);
Section.NumberDepth = 0;
iTextSharp.text.Section SubSection = Section.AddSection(Convert.ToString(myRow[7]), 0);
SubSection.NumberDepth = 0;
document.Add(Chapter);
readerList.Add(Reader);
bool AtLeastOnePage = false;
for (int i = 1; i <= Reader.NumberOfPages; i++)
{
copy.AddPage(copy.GetImportedPage(Reader, i));
AtLeastOnePage = true;
}
Reader.Close();
}
index++;
}
if (AtLeastOnePage)
{
document.Close();
return true;
}
else
{
Rectangle rec = new Rectangle(10, 10, 10, 10);
copy.AddPage(rec, 1);
document.Close();
return false;
}
string SalesID = SALESID.Text;
Response.ContentType = "application/pdf";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.AppendHeader("content-disposition", "attachment;filename=" + SalesID + ".pdf");
}
I am working on creating a pdf from html template file where i defined placeholders. i am able to replace the place holders with some text like
content.Replace(["Product_ID"],TextBox1.text);
is there any way i can also replace a placeholder with a checkbox(with either checked or unchecked depending on a condition) ?
Create two images, one for the checkbox "checked" state, and "unchecked", and use an IF statement to get the right image: i.e:
string pdfpath = Server.MapPath("PDFs");
string imagepath = Server.MapPath("Images");
Document doc = new Document();
try
{
PdfWriter.GetInstance(doc, new FileStream(pdfpath + "/Images.pdf", FileMode.Create));
doc.Open();
doc.Add(new Paragraph("GIF"));
Image gif;
if (chkBoxExample.Checked)
{
gif = Image.GetInstance(imagepath + "/checked.gif");
}
else
{
gif = Image.GetInstance(imagepath + "/unchecked.gif");
}
doc.Add(gif);
}
finally
{
doc.Close();
}
I am using this library to convert an html text to word format.
Everything works perfectly.
I need to style some of the text now. what I am using right now to generate document is that I have a list of heading and sub headings and heading text, I am using for each loop to get heading and subheading and its text and output them but I want these heading and subheading to assign heading1 to category and heading2 to sub category. here is what I got so far:
Foreach loop to get catagories and sub categories with its text
foreach (var category in ct)
{
strDocumentText.Append(category.ParentCat.CategoryName);
strDocumentText.Append("<br />");
if(category.DocumentText != null)
{
strDocumentText.Append(category.DocumentText);
}
if (category.Children != null)
{
foreach (var subCategoreis in category.Children)
{
strDocumentText.Append("<p />");
strDocumentText.Append(subCategoreis.ParentCat.CategoryName);
strDocumentText.Append("<br />");
if (category.DocumentText != null)
{
strDocumentText.Append(subCategoreis.DocumentText);
}
}
}
}
Create word document :
StringBuilder strDocumentText = new StringBuilder();
string html = strDocumentText.ToString();
using (MemoryStream generatedDocument = new MemoryStream())
{
BuildDocument(generatedDocument, html);
using (WordprocessingDocument wordDoc = WordprocessingDocument.Create(generatedDocument, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
if (mainPart == null)
{
mainPart = wordDoc.AddMainDocumentPart();
new DocumentFormat.OpenXml.Wordprocessing.Document(new Body()).Save(mainPart);
}
HtmlConverter converter = new HtmlConverter(mainPart);
Body body = mainPart.Document.Body;
var paragraphs = converter.Parse(html);
for (int i = 0; i < paragraphs.Count; i++)
{
body.Append(paragraphs[i]);
}
mainPart.Document.Save();
}
fs.Close();
File.WriteAllBytes(saveFileDialog1.FileName, generatedDocument.ToArray());
First you need to add the style definitions to the document. The default styles are not included when constructing an OpenXml Document. After you define the styles, you can reference them in the paragraph properties element (serialized as "pPr") OR the run element properties. Take a look at: http://msdn.microsoft.com/en-us/library/cc850838.aspx