EPPlus: bug combining shapes and programmatic pictures - epplus

Problem:
When I programatically open an Excel file that has shapes in it (eg. arrows), and then I modify this file by adding a new image to it (programatically), if I try to get the bytes (GetAsByteArray) of this new modified Excel file, it crashes.
Steps to reproduce bug:
Create an Excel file (xlsx) and add a shape in it (eg. an arrow)
Use this code to open that file and add a programmatic picture
string path = Server.MapPath("~/Content/input.xlsx");
using (Stream stream = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// Read file
ExcelPackage excelPackage = new ExcelPackage(stream);
// Get worksheets
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.FirstOrDefault();
// Add programmatic picture
worksheet.Drawings
.AddPicture("logo", new FileInfo(Server.MapPath("~/Content/logo.png")))
.SetPosition(5, 0, 5, 0);
byte[] output = File(excelPackage.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "output.xlsx");
}
Any ideas or workarounds?

Try this code. It will give you the bytes after adding an image. But nothing else will happen to the Excel file.
//create a fileinfo object of an excel file on the disk
FileInfo file = new FileInfo(Server.MapPath(""~/Content/input.xlsx"));
//create a new Excel package from the file
using (ExcelPackage package = new ExcelPackage(file))
{
//create an instance of the the first sheet in the loaded file
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
//Add programmatic picture
worksheet.Drawings
.AddPicture("logo", new FileInfo(Server.MapPath("~/Content/logo.png")))
.SetPosition(5, 0, 5, 0);
//get the new size in byte array
byte[] output = package.GetAsByteArray();
}

Related

System.IO.IOException: path to ttf file not found as file or resource.'(xamarin.android)

I'm trying to use custom fonts for my itext7 to allow my pdf to write Arabic texts. what I did is the following:
var path2 = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
filePath = System.IO.Path.Combine(path2.ToString(), "myfile3.pdf");
stream = new FileStream(filePath, FileMode.Create);
iText.Layout.Element.Table table = new iText.Layout.Element.Table(3, false);
table.SetWidth(400).SetFixedLayout();
string[] sources = new string[] { "يوم","شهر 2020" };
PdfWriter writer2 = new PdfWriter(stream);
PdfDocument pdfDocument = new PdfDocument(writer2);
Document document2 = new Document(pdfDocument);
PdfFont arab= PdfFontFactory.CreateFont("NotoNaskhArabic-Regular.ttf");
document2.SetFont(arab);
foreach (string source in sources)
{
Paragraph paragraph = new Paragraph();
Bidi bidi = new Bidi(source, Bidi.DirectionDefaultLeftToRight);
if (bidi.BaseLevel != 0)
{
paragraph.SetTextAlignment(iText.Layout.Properties.TextAlignment.RIGHT);
}
paragraph.Add(source);
table.AddCell(new Cell(1,1).SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER).Add(paragraph));
}
document2.Add(table);
document2.Close();
I tried different paths for my font. I put it in my resources folder, in my assets, tried to reach it from C:\Windows\Fonts\ARIAL.TTF when I tried using arial font, but all of those didn't work, I don't get it, what should my path be so I won't get this exception: System.IO.IOException: path to ttf file not found as file or resource.'
Once you have your file in assets, you could use AssetManager to read the bytes from the font.Then create the font by the bytes.
You could refer to this and convert it to C# code.

Replace a page in a PDF with iText7

I am in the process of updating some PDF editing tools from iTextSharp to iText7.
In iTextSharp there was a method in the pdfStamper class: pdfStamper.ReplacePage().
However, the pdfStamper class has been removed in iText7 and I am having trouble replicating the same functionality.
Say I have document X that needs page 4 replaced with page 1 of document Y but I want the result to be save to a new document Z.
So far I have 3 lines that use the CopyPageTo method. However any PDF document that gets created is only 1kb in size and corrupted.
Anyone have experience with the newer iText7 and the CopyPageTo method?
NewPagesReader = New PdfReader(strNewPageDocPath)
docNewPages = New PdfDocument(NewPagesReader)
OriginalDocReader = New PdfReader(strOrigPageDocPath)
docOringal = New PdfDocument(OriginalDocReader)
Dim docNew As PdfDocument
Dim NewPDFWriter As New PdfWriter(saver.FileName)
docNew = New PdfDocument(NewPDFWriter)
docOringal.CopyPagesTo(1, 3, docNew)
docNewPages.CopyPagesTo(1, 1, docNew)
docOringal.CopyPagesTo(5, 6, docNew)
ToWriter.Close()
docNew.Close()
Your code looks fine. Instead of copying all the pages to a new document, you can also delete and insert a page:
NewPagesReader = New PdfReader(strNewPageDocPath)
docNewPages = New PdfDocument(NewPagesReader)
OriginalDocReader = New PdfReader(strOrigPageDocPath)
Dim NewPDFWriter As New PdfWriter(saver.FileName)
docOringal = New PdfDocument(OriginalDocReader, NewPDFWriter)
docOringal.RemovePage(4)
docNewPages.CopyPagesTo(1, 1, docOringal, 4)
docOringal.Close()

How to add watermark on existing pdf file

I am trying to add watermark on pdf file using PdfSharp, I tried from this link
http://www.pdfsharp.net/wiki/Watermark-sample.ashx
but am not able to get how to get the existing pdf file page object and how to watermark on that page.
Help?
Basically, the samples are only snippets. You can download the source and with that you get a bunch of samples, including this watermark example.
The following comes from PDFSharp-MigraDocFoundation-1_32/PDFsharp/samples/Samples C#/Based on GDI+/Watermark/Program.cs
Quite simple, really ... I am only showing the code up to the for loop that goes over each page. You should have a look at the full file.
[...]
const string watermark = "PDFsharp";
const int emSize = 150;
// Get a fresh copy of the sample PDF file
const string filename = "Portable Document Format.pdf";
File.Copy(Path.Combine("../../../../../PDFs/", filename),
Path.Combine(Directory.GetCurrentDirectory(), filename), true);
// Create the font for drawing the watermark
XFont font = new XFont("Times New Roman", emSize, XFontStyle.BoldItalic);
// Open an existing document for editing and loop through its pages
PdfDocument document = PdfReader.Open(filename);
// Set version to PDF 1.4 (Acrobat 5) because we use transparency.
if (document.Version < 14)
document.Version = 14;
for (int idx = 0; idx < document.Pages.Count; idx++)
{
//if (idx == 1) break;
PdfPage page = document.Pages[idx];
[...]

iText-merged editable PDF loses form data when Acrobat Pro saves as separate PDF

We're replacing Adobe LiveCycle Server with iText 5.4.1 in an existing webapp to merge XML data with LiveCycle Designer-generated PDF templates, generating editable PDF files from several hundred templates.
This code combines the data with the template, returning a PDF byte array:
// Import data into the PDF form
if (pdfTemplateFileName != null && inputXmlDataFile != null) {
// set up the objects
template = new PdfReader(pdfTemplateFileName);
filledPDF = new ByteArrayOutputStream();
stamper = new PdfStamper(template, filledPDF);
AcroFields form = stamper.getAcroFields();
// fill in the form with the data
XfaForm xfa = form.getXfa();
xfa.fillXfaForm(inputXmlDataFile);
//closing the stamper is necessary to flush to filledPDF
stamper.close();
returnPDF = filledPDF.toByteArray();
}
This code combines the PDF byte arrays into a portfolio:
List<byte[]> assemblingPdfList = assemblingPdfMap.get("newStyleForms");
// create PDF portfolio of editable documents
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
ByteArrayOutputStream mergedPDFOutput = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(document, mergedPDFOutput);
document.open();
Paragraph coverSheet = new Paragraph("Multiple files are bound together in this PDF Package");
coverSheet.setAlignment(com.itextpdf.text.Element.ALIGN_CENTER);
document.add(coverSheet);
// define the collection
PdfCollection collection = new PdfCollection(PdfCollection.DETAILS);
PdfCollectionSchema schema = new PdfCollectionSchema();
PdfCollectionField filename = new PdfCollectionField("Name", PdfCollectionField.FILENAME);
filename.setOrder(0);
schema.addField("FILENAME", filename);
PdfCollectionField description = new PdfCollectionField("Description", PdfCollectionField.TEXT);
description.setOrder(1);
schema.addField("DESCRIPTION", description);
PdfCollectionField modified = new PdfCollectionField("Modified", PdfCollectionField.MODDATE);
modified.setOrder(2);
schema.addField("MODIFIED", modified);
PdfCollectionField size = new PdfCollectionField("Size", PdfCollectionField.SIZE);
size.setOrder(3);
schema.addField("SIZE", size);
collection.setSchema(schema);
writer.setCollection(collection);
// loop through the PDF documents and add each to the portfolio
PdfFileSpecification fs;
PdfCollectionItem item;
int iNum = 0;
for (byte[] pdf : assemblingPdfList) {
fs = PdfFileSpecification.fileEmbedded(writer, null,
String.format("StylesResult_%s.pdf", iNum++), pdf);
fs.addDescription("Styles Result File", false);
item = new PdfCollectionItem(schema);
item.addItem("DESCRIPTION", "Styles Result File");
item.addItem("MODIFIED", new PdfDate() );
fs.addCollectionItem(item);
writer.addFileAttachment(fs);
}
// close document
document.close();
mergedPDFOutput.flush();
mergedPDFOutput.close();
return mergedPDFOutput.toByteArray();
At first, iText would not populate the form fields. We used LiveCycle Designer to change the data binding of most fields from Normal to Global, which enabled iText to populate most of them correctly. The exception were the repeating (think 'table') rows of data; setting the binding to 'Global' caused the first data value to be repeated down the column for each of the data records. Setting the repeating fields' bindings back to 'Normal' seemed to work.
The iText-merged editable PDF portfolios are launched in Internet Explorer 10. If we click 'Open File' to open an individual PDF in Adobe Acrobat XI Pro, all the data is there. However, if we click 'File' / 'Save As' in Acrobat Pro to save to a new PDF file, then open the new file, some or all of the form data has disappeared (In one case, the 'first generation' save left most of the data intact, but repeating subform data was erased. Saving again, creating a 'second generation' save, erased all data.)
My failed solution attempts include: (a) initializing PdfStamper in 'append' mode; (b) Modifying my PdfStamper with 'stamper.setEncryption(false, "", "", PdfWriter.ALLOW_{everything}...)'.
Adobe LiveCycle Server-generated portfolios do not lose data, no matter how many generations of saves are made.

Using ContentByteUtils for raw PDF manipulation

This is a follow up question to:
Programmatically change the color of a black box in a PDF file?
I have a pdf I created in Illustrator that has basically a black shape in the middle of the page and nothing else. I need to change the color of that shape dynamically.
From the response to the post above I am using iTextSharp (.NET C#) to get the raw contents of the PDF through ContentByteUtils.GetContentBytesForPage() and changing the color at the raw level.
Problem is that I can't find any way of saving the results back into either the original PDF or a new PDF file via iTextSharp. I'm currently stuck with a byte array of the raw contents but need to figure out how to save.
Help please!
Why are you using ContentByteUtils.GetContentBytesForPage()?
I would use:
PdfReader reader = new PdfReader(src);
byte[] content = reader.GetPageContent(pageNumber);
// do stuff with content
reader.SetPageContent(pageNumber, content);
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (PdfStamper stamper = new PdfStamper(reader, fs)) {
}
}