I created a scheduled task that is supposed to scrape data from a website, store this in the database, create a daily pdf and send a weekly mail.
The first 2 parts run smoothly, but it seems that the other 2 are skipped regardless of what I try to do.
Creating a file is not the problem because it creates a daily .log file and writes to it.
For the pdf I use the PdfSharp library, for the mail the System.Net.Mail.
PDF
PdfDocumentRenderer renderer = new PdfDocumentRenderer(false, PdfFontEmbedding.Always);
renderer.Document = document;
renderer.RenderDocument();
string directory = DateTime.Now.Year.ToString();
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
string filename = directory + #"\NewCos" + DateTime.Now.DayOfWeek + ".pdf";
if (renderer.PageCount > 0)
renderer.PdfDocument.Save(filename);
Any help would be much appreciated.
first of all add iTextSharp nuget Pack to your project
itextsharp
then for creating a pdf you just need to do something like this:
Document myDocument = new Document(PageSize.A4, -60, -40, 10, 10);
PdfPTable MainTable = new PdfPTable(1);
PdfPCell pdfTableCell11 = new PdfPCell(new Paragraph("Hellod PDF!", RegularFont10));
MainTable.AddCell(pdfTableCell11);
string path = "C:\\Customer\\";
PdfWriter.GetInstance(myDocument, new FileStream(path + "\\Invoice_" + DateTime.Now.DayOfWeek + ".pdf", FileMode.Create));
myDocument.Open();
myDocument.Add(MainTable);
myDocument.Close();
if you have a complex pdf you can manage it by creating tables inside tables ... based on my experience it is better to have a main table with just one cell (which is all your doc) and then create any desire table and add those to this main table. so instead of "PdfPCell" you might have different "PdfPTable"s for each section.
It were simply some components that were not installed and the fact that I used relative paths iso fixed direcory settings
Related
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.
I'm using IText7 version 7.0.2.2, I'm new with it, I'm trying to merge several pdfs at the same time into one that I'm uploading first, that is working fine, the problem is when I try dynamically to insert some text in one of the pdfs and then merge it, I'm using PdfWriter to write some content into the pdf and then try to merge it, but I'm getting this exception: 'Cannot copy indirect object from the document that is being written.
This is some of the code I'm using:
private byte[] MergePdfForms( HttpPostedFileBase firstPdf, List<SectionAndPdfs> sectionsAndPdf)
{
var dest = new MemoryStream();
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
PdfMerger merger = new PdfMerger(pdf);
firstSourcePdf = new PdfDocument(new PdfReader(keyValuePair.Value), new PdfWriter(dest));
Document document = new Document(firstSourcePdf);
document.Add(new Paragraph(sectionsAndPdf[i].Key).SetBackgroundColor(iText.Kernel.Colors.Color.GRAY));
merger.Merge(firstSourcePdf, 1, subPages); //I'm getting the exception here..
firstSourcePdf.Close();
}
This is a known bug in the class PdfDestination. It was fixed, and will be present in our next release. At the moment you can of course use the snapshot release, which should solve the problem.
I have the Graphics.DrawString method for Print Preview.
Now I would like to use the same code to save it as a PDF. I have a Form, I have created a printprewiew and I would like to save as it is in printPrview to pdf.
Is it posible to do this?
I have a solution this may help you, but it requires to download and install "CutePDF Writer". CutePDF Writer is free software. You can download it from there official website.
PrintDialog pDia = New PrintDialog()
PrinterSettings ps = New PrinterSettings()
pDia.Document = PrintDocument1
pDia.Document.DocumentName = "Your File Name"
ps.PrinterName = item.ToString()
ps.PrintToFile = False
//Create folder inside Bin folder to save PDFs
String strReportBackupPath = "C:\\"
String strFilePath = strReportBackupPath & "\\" & pDia.Document.DocumentName & ".pdf"
//To avoid the replace dialog of cutePDF - To save new file if have same name
ps.PrintFileName = strFilePath
PrintDocument1.PrinterSettings = ps
PrintDocument1.Print()
but it will show you save as dialog to save the file to pdf.
I'm using iText to generate a PDF document that consists of several copies of almost the same information.
E.g.: An invoice. One copy is given to the customer, another is filed and a third one is given to an accountant for book-keeping.
All the copies must be exactly the same except for a little piece of text that indicates who is the copy to (Customer, Accounting, File, ...).
There are two possible scenarios (I don't know if the solution is the same for both of them):
a) Each copy goes in a different page.
b) All the copies goes in the same page (the paper will have cutting holes to separete copies).
There will be a wrapper or helper class which uses iText to generate the PDF in order to be able to do something like var pdf = HelperClass.CreateDocument(DocuemntInfo info);. The multiple-copies problem will be solved inside this wrapper/helper.
What does iText provides to accomplish this? Do I need to write each element in the document several times in different positions/pages? Or does iText provide some way to write one copy to the document and then copy it to other position/page?
Note: It's a .Net project, but I tagged the question with both java and c# because this qustion is about how to use iText properly the answer will help both laguage developers.
If each copy goes on a different page, you can create a new document and copy in the page multiple times. Using iText in Java you can do it like this:
// Create output PDF
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();
// Load existing PDF
PdfReader reader = new PdfReader(templateInputStream);
PdfImportedPage page = writer.getImportedPage(reader, 1);
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your first piece of text here
document.add(new Paragraph("Customer"));
// Copy second page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your second piece of text here
document.add(new Paragraph("Accounting"));
// etc...
document.close();
If you want to put all the copies on the same page, the code is similar but instead of using zeroes in addTemplate(page, 0, 0) you'll need to set values for the correct position; the numbers to use depend on the size and shape of your invoice.
See also iText - add content to existing PDF file — the above code is based on the code I wrote in that answer.
Here's how I see this working.
PdfReader reader = new PdfReader( templatePDFPath );
Document doc = new Document();
PdfWriter writer = PdfWriter.createInstance( doc, new FileOutputStream("blah.pdf" ) );
PdfImportedPage inputPage = writer.getImportedPage( reader, 1 );
PdfDirectContent curPageContent = writer.getDirectContent();
String extraStuff[] = getExtraStuff();
for (String stuff : extraStuff) {
curPageContent.saveState();
curPageContent.addTemplate( inputPage /*, x, y*/ );
curPageContent.restoreState();
curPageContent.beginText();
curPageContent.setTextMatrix(x, y);
curPageContent.setFontAndSize( someFont, someSize );
// the actual work:
curPageContent.showText( stuff );
curPageContent.EndText();
// save the contents of curPageContent out to the file and reset it for the next page.
doc.newPage();
}
That's the bare minimum of work on the computer's part. Quite Efficient, and it'll result in a smaller PDF. Rather than having N copies of that page, with tweaks, you have one copy of that page that's reused on N pages, with little tweaks on top.
You could do the same thing, and use the "x,y" parameters in addTemplate to draw them all on the same page. Up to you.
PS: you'll need to figure out the coordinates for setTextMatrix in advance.
You could also use PDfCopy Or PDfSmartCopy to do this.
PdfReader reader = new PdfReader("Path\To\File");
Document doc = new Document();
PdfCopy copier = new PdfCopy(doc, ms1);
//PdfSmartCopy copier = new PdfSmartCopy(doc, ms1);
doc.Open();
copier.CloseStream = false;
PdfImportedPage inputPage = writer.GetImportedPage(reader, 1);
PdfContentByte curPageContent = writer.DirectContent;
for (int i = 0; i < count; i++)
{
copier.AddPage(inputPage);
}
doc.Close();
ms1.Flush();
ms1.Position = 0;
The difference between PdfCopy and PdfSmartCopy is that PdfCopy copies the entire PDF for each page, while PdfSmartCopy outputs a PDF that internally contains only one copy and all pages reference it, resulting in a smaller file and less bandwidth on a network, however it uses more memory on the server and takes longer to process.
Question 298829 describes how linearizing your PDFs lets them stream page-by-page into the user's browser, so the user doesn't have to wait for the whole document to download before starting to view it. We have been using such PDFs successfully, but now have a new wrinkle: We want to keep the page-by-page streaming, but we also want to insert a fresh cover page at the front of the PDF documents each time we serve them up. (The cover-page will have time-sensitive information, such as the date, so it's not practical to include the cover page in the PDFs on disk.)
To help with this, are there any PDF libraries that can quickly append a cover page to a pre-linearized PDF and yield a streamable, linearized PDF as output? What's of the greatest concern is not the total time to merge the PDFs, but how soon we can start streaming part of the merged document to the user.
We were trying to do this with itextsharp, but it turns out that library can't output linearized PDFs. (See http://itext.ugent.be/library/question.php?id=21) Nonetheless, the following ASP.NET/itextsharp scratch code demonstrates the sort of API we're thinking of. In particular, if itextsharp always output linearized PDFs, something like this might already be the solution:
public class StreamPdf : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/pdf";
RandomAccessFileOrArray ramFile = new RandomAccessFileOrArray(#"C:\bigpdf.pdf");
PdfReader reader1 = new PdfReader(ramFile, null);
Document doc = new Document();
// We'll stream the PDF to the ASP.NET output
// stream, i.e. to the browser:
PdfWriter writer = PdfWriter.GetInstance(doc, context.Response.OutputStream);
writer.Open();
doc.Open();
PdfContentByte cb = writer.DirectContent;
// output cover page:
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
Font font = new Font(bf, 11, Font.NORMAL);
ColumnText ct = new ColumnText(cb);
ct.SetSimpleColumn(60, 300, 600, 300 + 28 * 15, 15, Element.ALIGN_CENTER);
ct.AddText(new Phrase(15, "This is a cover page information\n", font));
ct.AddText(new Phrase(15, "Date: " + DateTime.Now.ToShortDateString() + "\n", font));
ct.Go();
// output src document:
int i = 0;
while (i < reader1.NumberOfPages)
{
i++;
// add next page from source PDF:
doc.NewPage();
PdfImportedPage page = writer.GetImportedPage(reader1, i);
cb.AddTemplate(page, 0, 0);
// use something like this to flush the current page to the
// browser:
writer.Flush();
s.Flush();
context.Response.Flush();
}
doc.Close();
writer.Close();
s.Close();
}
}
}
Ideally we're looking for a .NET library, but it would be worth hearing about any other options as well.
You could try GhostScript, I think its possible to stitch PDF's together but dont know about linearizing when it comes to PDF. I have a C# GhostScript Wrapper that can be used with the GhostScript dll directly, I am sure this can be modified to Merge PDFs. contact details at: redmanscave.blogspot.com