Multipage PDF does not open on iPad - c#

I am working with a project where I am generating PDF Files from PSR Files. The PDF Files works fine if its a single page but if It has more than two PSR Files and I generate two files it does not open on iPad and works fine on Desktop.
The Third library tool I am using here is 'dbatuotrack' and I am using C#.
Can anyone please guide me how to resolve this problem?
Thanks,
S.
foreach (var pdfform in pdfPagesID)
{
//dbAutoTrack.PDFWriter.Document objDoc = null;
//dbAutoTrack.PDFWriter.Page objPage = null;
objDoc = new dbAutoTrack.PDFWriter.Document();
pdfPagesID.Clear();
pdfPagesID = GetSpecPageID(pdfform);
if (pdfPagesID.Count > 1)
{
foreach (var pdfPage in pdfPagesID)
{
dbAutoTrack.PDFWriter.Page objPage2 = null;
var lastItem = pdfPagesID.Last();
prefixPageID = prefixSpecPageID(pdfPage);
suffixPageIDPSR = prefixPageID + ".psr";
if (File.Exists(PSRPath + suffixPageIDPSR))
{
objDs = new CDatasheet(this.PSRPath + suffixPageIDPSR, false);
objDs.pdfDbHelper = pdfhelper;
//Giving the specformId as SpecFornName
pdfFormName = "Form" + pdfform + ".pdf";
if (!(pdfPage == pdfPagesID.First()))
{
objPage2 = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage2);
}
else
{
objPage = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage);
}
if (objPage != null)
{
if (pdfWithNotePage == true && pdfPage.Equals(lastItem))
{
objNotePage = objDs.GetNotePage();
objDoc.Pages.Add(objPage);
objDoc.Pages.Add(objNotePage);
}
else
{
//objDoc.Pages.Add(objPage);
//objDoc.Pages.Add(objPage2);
}
fsOutput = new FileStream(TemplatePath + pdfFormName, FileMode.Create, FileAccess.Write);
objDoc.Generate(fsOutput);
}
if (fsOutput != null)
{
fsOutput.Close();
fsOutput.Dispose();
fsOutput = null;
}
}
}
objDoc = null;
objPage = null;
}

This how I tweaked the code to make it work. Thanks for the suggestion DJ KRAZE
foreach (var pdfform in pdfPagesID)
{
//dbAutoTrack.PDFWriter.Document objDoc = null;
//dbAutoTrack.PDFWriter.Page objPage = null;
objDoc = new dbAutoTrack.PDFWriter.Document();
pdfPagesID.Clear();
pdfPagesID = GetSpecPageID(pdfform);
if (pdfPagesID.Count > 1)
{
foreach (var pdfPage in pdfPagesID)
{
dbAutoTrack.PDFWriter.Page objPage2 = null;
var lastItem = pdfPagesID.Last();
prefixPageID = prefixSpecPageID(pdfPage);
suffixPageIDPSR = prefixPageID + ".psr";
if (File.Exists(PSRPath + suffixPageIDPSR))
{
objDs = new CDatasheet(this.PSRPath + suffixPageIDPSR, false);
objDs.pdfDbHelper = pdfhelper;
//Giving the specformId as SpecFornName
pdfFormName = "Form" + pdfform + ".pdf";
if (!(pdfPage == pdfPagesID.First()))
{
objPage2 = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage2);
}
else
{
objPage = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage);
}
if (objPage != null)
{
if (pdfWithNotePage == true && pdfPage.Equals(lastItem))
{
objNotePage = objDs.GetNotePage();
objDoc.Pages.Add(objPage);
objDoc.Pages.Add(objNotePage);
}
else
{
//objDoc.Pages.Add(objPage);
//objDoc.Pages.Add(objPage2);
}
}
}
}
fsOutput = new FileStream(TemplatePath + pdfFormName, FileMode.Create, FileAccess.Write);
objDoc.Generate(fsOutput);
//This region was the problem, disposing the output everytime.
//Needed it to be included after completion of iteration
if (fsOutput != null)
{
fsOutput.Close();
fsOutput.Dispose();
fsOutput = null;
}
}

Related

How can tell the difference between the link and the footnote using C# ITextSharp?

I have a simple PDF file that has the Link and the Footnote on a page. When I run the annotation check using iTextSharp, both of the links return the sub type as Link. Is there a way to tell the difference between those two items?
I did examine through an intellisence the structure of an annotation dictionary and notice the annotation object dictionary for the Footnote has once extra item, which is named "F", and that item has a value of 4. That item is NOT present at all in the annotation dictionary for the Link. Can I use the 'F' item/parameter as a way to tell the difference between the Link and the Footnote?
Thank you very much in advance
Here is the PDF file
Here is our code
public string AnyPDFCheckComments(string inFileName, string strUsername, string strFilename)
{
string strCommentType = string.Empty;
string strWidgetFound = string.Empty;
string strPageNumber = string.Empty;
string message = string.Empty;
string strComments = string.Empty;
string strCommentsFound = string.Empty;
int intCommentCount = 0;
PdfReader reader = new PdfReader(inFileName);
for (int i = 1; i <= reader.NumberOfPages; ++i)
{
strPageNumber = i.ToString();
PdfDictionary pagedic = reader.GetPageN(i);
PdfArray annotarray = (PdfArray)PdfReader.GetPdfObject(pagedic.Get(PdfName.ANNOTS));
if (annotarray == null || annotarray.Size == 0)
{
continue;
}
// Finding out the links
foreach (object annot in annotarray.ArrayList)
{
PdfDictionary annotationDic = null;
if (annot is PdfIndirectReference)
{
annotationDic = (PdfDictionary)PdfReader.GetPdfObject((PdfIndirectReference)annot);
}
else
{
annotationDic = (PdfDictionary) annot;
}
PdfName subType = (PdfName)annotationDic.Get(PdfName.SUBTYPE);
if ((subType.Equals(PdfName.TEXT)) && (strCommentsVariables.IndexOf("text") != -1))
{
strCommentType = "text";
//break;
}
else if ((subType.Equals(PdfName.LINK)) && (strCommentsVariables.IndexOf("Link") != -1))
{
strCommentType = "Link";
//break;
}
if ((strCommentType != ""))
{
strCommentsFound = "Yes";
intCommentCount = ++intCommentCount;
strComments = strComments + "<BR>" + "A comment type of '" + "<b>" + strCommentType + "</b>" + "' has been found on page no: " + "<b>" + strPageNumber + "</b>";
if (intCommentCount == 5)
{
break;
}
else
{
strCommentType = string.Empty;
}
}
}
}
return strComments;
}
This code worked for us
var footnoteIdentifier = annotationDic.Get(PdfName.F);
if (footnoteIdentifier != null)
{
continue;
}

How to save the image while updating the BARCODE?

When I am saving an image, it is getting saved by the Barcode name.
But If I modify the barcode name, then the image is gone, not saving.
I have noticed while debugging that the if(System.IO.File.Exists(imageFilePath)) is not executing when I am updating the barcode. But at the time of saving a new one, its executing.
How to correct this?
Updating code
public object Update(ItemEntity item)
{
var val = _itemRepository.Save(item);
if (item.ImageFileName != string.Empty || item.ImageOriginalFileName != string.Empty)
{
string result = JsonConvert.SerializeObject(val);
var definition = new { Success = false, EntryMode = string.Empty, BarCode = string.Empty, ItemCode = string.Empty };
var info = JsonConvert.DeserializeAnonymousType(result, definition);
if (info.Success)
{
if (!string.IsNullOrEmpty(item.ImageOriginalFileName))
this.SaveImage(item.ImageFileName, (item.ImageOriginalFileName == "BARCODE" ? info.ItemCode : item.ImageOriginalFileName == "BARCODEYes" ? item.Barcode : item.ImageOriginalFileName));
}
}
if (item.DeleteImageFileName != string.Empty && item.ImageFileName == string.Empty) // Image file removed but no new image file is uploaded[Bug Id :34754 -No image is uploaded, when a user re-uploads an image after deleting a previous one.]
{
this.DeleteImage(item.DeleteImageFileName);
}
return val;
}
Saving Code
public void SaveImage(string fileName, string originalFileName)
{
string tempFileName = fileName;
if (!string.IsNullOrEmpty(tempFileName))
{
// move file from temp location to actual loation
var webAppPath = System.Web.Hosting.HostingEnvironment.MapPath("~");
var splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
var upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
var UIFolder = "WebUI";
splitPath.AddRange(new string[] { UIFolder, "Temp", "ImageUpload", CurrentSession.UserId.Value.ToString(), "ItemImage" });
var webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
var imageFilePath = Path.Combine(webUIPath.EnsureEndsWith('\\'), tempFileName);
if (System.IO.File.Exists(imageFilePath))
{
splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
splitPath.AddRange(new string[] { "Shared", "ItemImage" });
webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
// Check existence of folder, create if not found and Delete-Create if found
if (!Directory.Exists(webUIPath))
{
Logger.Debug("Create directory :" + webUIPath);
Directory.CreateDirectory(webUIPath);
}
originalFileName = originalFileName + ".jpg";
var imagDestPath = Path.Combine(webUIPath.EnsureEndsWith('\\'), originalFileName);
if (File.Exists(imagDestPath))
{
GC.Collect();
GC.WaitForPendingFinalizers();
Logger.Debug("Delete File :" + imagDestPath);
File.Delete(imagDestPath);
}
byte[] bytes = System.IO.File.ReadAllBytes(imageFilePath);
FileStream fs = new FileStream(imagDestPath, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
}
}
}

Create multi-file zip from stream and download on the fly

I'm using DotNetZip library to make multi-file zip archive and download it on the fly (no need to wait for download to start). However I can't make it to download instantly. From browser dev console, in network tab I noticed that first zip file is "transferred" and after being fully transferred it starts downloading.
Here is code fragment:
using (var vZipArchive = new ZipFile())
{
if (vFilesTable.Rows.Count > 0)
{
string vPathFormat = null;
string vKeyName = null;
string vPrimKey = null;
string vFileName = null;
vZipArchive.CompressionLevel = CompressionLevel.BestSpeed;
vZipArchive.CompressionMethod = CompressionMethod.Deflate;
vZipArchive.Comment = "Document Archive";
foreach (DataRow vFile in vFilesTable.Rows)
{
if (vKeyFieldName != null && !string.IsNullOrEmpty(vKeyFieldName))
{
vPathFormat = "{0}/";
}
else
{
vPathFormat = "/";
}
if (vFile.Table.Columns.Contains("FileName") && vFile.Table.Columns.Contains("PrimKey"))
{
vPrimKey = vFile["PrimKey"].ToString();
vFileName = vFile["FileName"].ToString();
if (vKeyFieldName != null)
{
vKeyName = vFile[vKeyFieldName].ToString();
}
string vPath = null;
if (vKeyFieldName != null)
{
vPath = string.Format(vKeyFieldName + " " + vPathFormat + "{1}", vKeyName, vFileName);
}
else
{
vPath = string.Format(vPathFormat + vFileName);
}
using (var vFileStream = vUserContext.GetFileStream(vRecordSource.ViewName, new Guid(vPrimKey)))
{
vFileStream.Position = 0;
vZipArchive.AddEntry(vPath, vFileStream);
}
}
else
{
throw new Exception("Select 'FileName' and 'PrimKey' fields in underlying DataSource");
}
} //end loop
pContext.Response.Clear();
pContext.Response.BufferOutput = false;
pContext.Response.ContentType = "application/zip";
pContext.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}.zip\"", vZipName));
vZipArchive.Save(pContext.Response.OutputStream);
}
else
{
return;
}
}
I also tried using ZipOutputStream and SharpCompress.dll library.
So, what I am missing to make it work? Or its impossible?

How do you mail merge a word document in c#

What I'm trying to achieve
In my c# application I would like to generate a report (word document) from data in my application, I figured that the best way to do this would be to perform something like a mail merge using the data source from my application.
What I've tried
I tried following this
Mail Merge into word
however this uses GemBox which you need to pay for
I have tried using Microsoft.Office.Interop.Word however I fell
short when I didn't know how to reference the saved template document:
Dictionary<string, string> MailMerge = new Dictionary<string, string>()
{
{ "ID", "123" },
{ "Name", "Test" },
{ "Address1", "Test" },
{ "Address2", "Test" },
{ "Address3", "Test" },
{ "Address4", "Test" },
{ "PostCode", "Test" },
{ "Year End", "Test" },
{ "SicCode", "123" },
};
Document doc = new Document();
doc.MailMerge.Execute(MailMerge);
Summary
I'm looking for some guidance as to what to research further as I believe there must be a 'standard' way of doing this.
Can't believe third party software charge thousands for interface functions with Word. I have perfectly solved this mail merge thing in my project -- no third party, no particular demands on IIS, just use OpenXML.
So, add these 4 functions to your project:
public static void dotx2docx(string sourceFile, string targetFile)
{
MemoryStream documentStream;
using (Stream tplStream = File.OpenRead(sourceFile))
{
documentStream = new MemoryStream((int)tplStream.Length);
CopyStream(tplStream, documentStream);
documentStream.Position = 0L;
}
using (WordprocessingDocument template = WordprocessingDocument.Open(documentStream, true))
{
template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
MainDocumentPart mainPart = template.MainDocumentPart;
mainPart.DocumentSettingsPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate",
new Uri(targetFile, UriKind.Absolute));
mainPart.Document.Save();
}
File.WriteAllBytes(targetFile, documentStream.ToArray());
}
public static void CopyStream(Stream source, Stream target)
{
if (source != null)
{
MemoryStream mstream = source as MemoryStream;
if (mstream != null) mstream.WriteTo(target);
else
{
byte[] buffer = new byte[2048];
int length = buffer.Length, size;
while ((size = source.Read(buffer, 0, length)) != 0)
target.Write(buffer, 0, size);
}
}
}
public static void Mailmerge(string templatePath, string DestinatePath, DataRow dr, DataColumnCollection columns)
{
try
{
dotx2docx(templatePath, DestinatePath);
}
catch //incase the server does not support MS Office Word 2003 / 2007 / 2010
{
File.Copy(templatePath, DestinatePath, true);
}
using (WordprocessingDocument doc = WordprocessingDocument.Open(DestinatePath, true))
{
var allParas = doc.MainDocumentPart.Document.Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>();
Text PreItem = null;
string PreItemConstant = null;
bool FindSingleAnglebrackets = false;
bool breakFlag = false;
List<Text> breakedFiled = new List<Text>();
foreach (Text item in allParas)
{
foreach (DataColumn cl in columns)
{
//<Today>
if (item.Text.Contains("«" + cl.ColumnName + "»") || item.Text.Contains("<" + cl.ColumnName + ">"))
{
item.Text = item.Text.Replace("<" + cl.ColumnName + ">", dr[cl.ColumnName].ToString())
.Replace("«" + cl.ColumnName + "»", dr[cl.ColumnName].ToString());
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
}
else if //<Today
(item.Text != null
&& (
(item.Text.Contains("<") && !item.Text.Contains(">"))
|| (item.Text.Contains("«") && !item.Text.Contains("»"))
)
&& (item.Text.Contains(cl.ColumnName))
)
{
FindSingleAnglebrackets = true;
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"\<" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"\«" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
}
else if //Today> or Today
(
PreItemConstant != null
&& (
(PreItemConstant.Contains("<") && !PreItemConstant.Contains(">"))
|| (PreItemConstant.Contains("«") && !PreItemConstant.Contains("»"))
)
&& (item.Text.Contains(cl.ColumnName))
)
{
if (item.Text.Contains(">") || item.Text.Contains("»"))
{
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
}
else
{
FindSingleAnglebrackets = true;
}
if (PreItemConstant == "<" || PreItemConstant == "«")
{
PreItem.Text = "";
}
else
{
PreItem.Text = global::System.Text.RegularExpressions.Regex.Replace(PreItemConstant, #"\<" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
PreItem.Text = global::System.Text.RegularExpressions.Regex.Replace(PreItemConstant, #"\«" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
}
if (PreItemConstant.Contains("<") || PreItemConstant.Contains("«")) // pre item is like '[blank]«'
{
PreItem.Text = PreItem.Text.Replace("<", "");
PreItem.Text = PreItem.Text.Replace("«", "");
}
if (item.Text.Contains(cl.ColumnName + ">") || item.Text.Contains(cl.ColumnName + "»"))
{
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\>", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\»", dr[cl.ColumnName].ToString());
}
else
{
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
}
}
else if (FindSingleAnglebrackets && (item.Text.Contains("»") || item.Text.Contains(">")))
{
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\>", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\»", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\>", "");
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\»", "");
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
}
else if (item.Text.Contains("<") || item.Text.Contains("«")) // no ColumnName
{
}
} //end of each columns
PreItem = item;
PreItemConstant = item.Text;
if (breakFlag
|| (item.Text.Contains("<") && !item.Text.Contains(">"))
|| (item.Text.Contains("«") && !item.Text.Contains("»"))
)
{
breakFlag = true;
breakedFiled.Add(item);
string combinedfiled = "";
foreach (Text t in breakedFiled)
{
combinedfiled += t.Text;
}
foreach (DataColumn cl in columns)
{
//<Today>
if (combinedfiled.Contains("«" + cl.ColumnName + "»") || combinedfiled.Contains("<" + cl.ColumnName + ">"))
{
//for the first part, remove the last '<' and tailing content
breakedFiled[0].Text = global::System.Text.RegularExpressions.Regex.Replace(breakedFiled[0].Text, #"<\w*$", "");
breakedFiled[0].Text = global::System.Text.RegularExpressions.Regex.Replace(breakedFiled[0].Text, #"<\w*$", "");
//remove middle parts
foreach (Text t in breakedFiled)
{
if (!t.Text.Contains("<") && !t.Text.Contains("«") && !t.Text.Contains(">") && !t.Text.Contains("»"))
{
t.Text = "";
}
}
//for the last part(as current item), remove leading content till the first '>'
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\>", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\»", dr[cl.ColumnName].ToString());
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
break;
}
}
}
}//end of each item
#region go through footer
MainDocumentPart mainPart = doc.MainDocumentPart;
foreach (FooterPart footerPart in mainPart.FooterParts)
{
Footer footer = footerPart.Footer;
var allFooterParas = footer.Descendants<Text>();
foreach (Text item in allFooterParas)
{
foreach (DataColumn cl in columns)
{
if (item.Text.Contains("«" + cl.ColumnName + "»") || item.Text.Contains("<" + cl.ColumnName + ">"))
{
item.Text = (string.IsNullOrEmpty(dr[cl.ColumnName].ToString()) ? " " : dr[cl.ColumnName].ToString());
FindSingleAnglebrackets = false;
}
else if (PreItem != null && (PreItem.Text == "<" || PreItem.Text == "«") && (item.Text.Trim() == cl.ColumnName))
{
FindSingleAnglebrackets = true;
PreItem.Text = "";
item.Text = (string.IsNullOrEmpty(dr[cl.ColumnName].ToString()) ? " " : dr[cl.ColumnName].ToString());
}
else if (FindSingleAnglebrackets && (item.Text == "»" || item.Text == ">"))
{
item.Text = "";
FindSingleAnglebrackets = false;
}
}
PreItem = item;
}
}
#endregion
#region replace \v to new Break()
var body = doc.MainDocumentPart.Document.Body;
var paras = body.Elements<Paragraph>();
foreach (var para in paras)
{
foreach (var run in para.Elements<Run>())
{
foreach (var text in run.Elements<Text>())
{
if (text.Text.Contains("MS_Doc_New_Line"))
{
string[] ss = text.Text.Split(new string[] { "MS_Doc_New_Line" }, StringSplitOptions.None);
text.Text = text.Text = "";
int n = 0;
foreach (string s in ss)
{
n++;
run.AppendChild(new Text(s));
if (n != ss.Length)
{
run.AppendChild(new Break());
}
}
}
}
}
}
#endregion
doc.MainDocumentPart.Document.Save();
}
}
public static void MergeDocuments(params string[] filepaths)
{
//filepaths = new[] { "D:\\one.docx", "D:\\two.docx", "D:\\three.docx", "D:\\four.docx", "D:\\five.docx" };
if (filepaths != null && filepaths.Length > 1)
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(#filepaths[0], true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
for (int i = 1; i < filepaths.Length; i++)
{
string altChunkId = "AltChunkId" + i;
AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(
AlternativeFormatImportPartType.WordprocessingML, altChunkId);
using (FileStream fileStream = File.Open(#filepaths[i], FileMode.Open))
{
chunk.FeedData(fileStream);
}
DocumentFormat.OpenXml.Wordprocessing.AltChunk altChunk = new DocumentFormat.OpenXml.Wordprocessing.AltChunk();
altChunk.Id = altChunkId;
//new page, if you like it...
mainPart.Document.Body.AppendChild(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));
//next document
mainPart.Document.Body.InsertAfter(altChunk, mainPart.Document.Body.Elements<Paragraph>().Last());
}
mainPart.Document.Save();
myDoc.Close();
}
}
And use them like this:
DataTable dt = new DataTable();
dt.Columns.Add("Date");
dt.Columns.Add("Today");
dt.Columns.Add("Addr1");
dt.Columns.Add("Addr2");
dt.Columns.Add("PreferContact");
dt.Columns.Add("TenantName");
//......
DataRow nr = dt.NewRow();
nr["Date"] = DateTime.Now.ToString("dd/MM/yyyy");
nr["Today"] = DateTime.Now.ToString("dd/MM/yyyy");
//......
dt.Rows.Add(nr);
string sourceFile = "c:\my_template.docx"; //this is where you store your template
string filePath = "c:\final.docx"; //this is where your result file locate
Mailmerge(sourceFile, filePath, nr, dt.Columns);
Your template(c:\my_template.docx) will be just like normal .docx file, and you need to specify your fields in it:
<field>
So, your template(c:\my_template.docx) should be like:
<Today>
<DebtorName>
<DebtorADDR>
<DebtorEmail>
Dear <Dear>,
Congratulations on yourr property <PlanNo> <BuildAddress>. Your unit number is <LotNo> ...............
In addition, if some of your fields contain line breaks, use this:
nr["Address"] = my_address_text_contains_line_breaks.Replace(Environment.NewLine, "MS_Doc_New_Line");
This is quite simple by using Microsoft.Office.Interop.Word. Here is a simple step by step tutorial on how to do this.
The code to replace a mergefield with a string is like this:
public static void TextToWord(string pWordDoc, string pMergeField, string pValue)
{
Object oMissing = System.Reflection.Missing.Value;
Object oTrue = true;
Object oFalse = false;
Word.Application oWord = new Word.Application();
Word.Document oWordDoc = new Word.Document();
oWord.Visible = true;
Object oTemplatePath = pWordDoc;
oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
foreach (Word.Field myMergeField in oWordDoc.Fields)
{
Word.Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text;
if (fieldText.StartsWith(" MERGEFIELD"))
{
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
fieldName = fieldName.Trim();
if (fieldName == pMergeField)
{
myMergeField.Select();
oWord.Selection.TypeText(pValue);
}
}
}
}
originally posted here and here
In case you wish to use a dictionary to replace many fields at once use the code below:
public static void TextToWord(string pWordDoc, Dictionary<string, string> pDictionaryMerge)
{
Object oMissing = System.Reflection.Missing.Value;
Object oTrue = true;
Object oFalse = false;
Microsoft.Office.Interop.Word.Application oWord = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document oWordDoc = new Microsoft.Office.Interop.Word.Document();
oWord.Visible = true;
Object oTemplatePath = pWordDoc;
oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
foreach (Microsoft.Office.Interop.Word.Field myMergeField in oWordDoc.Fields)
{
Microsoft.Office.Interop.Word.Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text;
if (fieldText.StartsWith(" MERGEFIELD"))
{
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
fieldName = fieldName.Trim();
foreach (var item in pDictionaryMerge)
{
if (fieldName == item.Key)
{
myMergeField.Select();
oWord.Selection.TypeText(item.Value);
}
}
}
}
}
I am also using the same thing but I have more complexity. I have to check the if condition also. In word template file
{ IF «Installment» = Monthly "then the table will appear" "nothing to show" }
when I use the above code shared in the answer. and for if condition in c# I have written
Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text.Trim();
if (fieldText.ToUpper().StartsWith("IF"))
{
myMergeField.UpdateSource();}
so the output is like
{ IF Monthly = Monthly "then table will appear" "nothing to show" }
but the desired output is only "then the table will appear".

ITextSharp Adding Multiple PDFStampers to memoryStream

I have a asp.net application that uses ITextSharp 5.4.5.0 to generate certificates. I have the code that generates one certificate working fine, but when I try to bundle these one page certificates into a single multi-page PDF and output the memorystream to the browser I get an error from Adobe Acrobat.
I have a feeling that I'm not adding eachof my byte arroys correctly, but I'm at a loss.
Here is the calling code:
protected void btnMakeCerts_Click(object sender, EventArgs e)
{
ICAgileEntities icae = new ICAgileEntities();
int classid =int.Parse(Request.QueryString["id"]);
var currentClass = (from c in icae.Classes
where c.id == classid
select c).FirstOrDefault();
Response.Clear();
Response.BufferOutput = true;
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=AllCertificates-" + currentClass.Title + ".pdf");
var pagesAll = new List<byte[]>();
pagesAll = Helper.Certificate.ProcessClassCerts(classid);
MemoryStream ms = new MemoryStream();
PdfConcatenate whole = new PdfConcatenate(ms);
foreach (byte[] pageAll in pagesAll)
{
PdfReader partReader = new PdfReader(pageAll);
whole.AddPages(partReader);
partReader.Close();
}
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
Response.Flush();
Response.End();
}
And this creates the individual pages and returns a byte array:
public static List<byte[]> ProcessClassCerts(int classId)
{
var icae = new ICAgileEntities();
string filename = DateTime.Now.ToString().Replace(#"/", "").Replace(":", "").Replace(" ", "") + ".pdf";
string sFileDir = ConfigurationManager.AppSettings["ServerPath"] + (#"\images\sigs\");
var currentClass = (from c in icae.Classes
where c.id == classId
select c).FirstOrDefault();
//make the Instructor Names
String instName = "test";
var students = (from up in icae.UserProfiles
from cl in up.UserProfile_Class_Details
where cl.ClassId == classId && cl.IsCertPaid == true && cl.IsClassPaid == true
select up);
var currentCourse = (from s in icae.Courses
where s.id == currentClass.CourseID
select s).FirstOrDefault();
var pageBytes = (byte[])null;
var pagesAll = new List<byte[]>();
try
{
string path = ConfigurationManager.AppSettings["ServerPath"] + #"\PDFs\";
int i = 1;
foreach (var s in students)
{
PdfStamper pst = null;
MemoryStream mstr = null;
using (mstr = new MemoryStream())
{
try
{
PdfReader reader = new PdfReader(path + #"\certFormPDF.pdf"); //new PdfReader(GetTemplateBytes());
pst = new PdfStamper(reader, mstr);
var acroFields = pst.AcroFields;
acroFields.SetField("Awardee Name", s.DisplayName);
pst.FormFlattening = true;
pst.SetFullCompression();
}
finally
{
if (pst != null)
pst.Close();
}
}
pageBytes = mstr.ToArray();
pagesAll.Add(pageBytes);
i++;
}
}
finally
{
}
return pagesAll;
}
Thanks for any help you can provide

Categories