Contexte: Je dois fournir un package de rapport hebdomadaire pour mon personnel de vente. Ce paquet contient plusieurs (5-10) rapports de cristal.
Problème: Je voudrais autoriser un utilisateur à exécuter tous les rapports et également à exécuter un seul rapport. Je pensais que je pouvais le faire en créant les rapports puis en faisant:
List<ReportClass> reports = new List<ReportClass>();
reports.Add(new WeeklyReport1());
reports.Add(new WeeklyReport2());
reports.Add(new WeeklyReport3());
<snip>
foreach (ReportClass report in reports)
{
report.ExportToDisk(ExportFormatType.PortableDocFormat, @"c:\reports\" + report.ResourceName + ".pdf");
}
Cela me fournirait un dossier complet des rapports, mais je voudrais envoyer à chacun un seul PDF PDF avec tous les rapports hebdomadaires. Je dois donc les combiner.
Existe-t-il un moyen simple de le faire sans installer d'autres contrôles tiers? J'ai déjà DevExpress & CrystalReports et je préfère ne pas en ajouter trop.
Serait-il préférable de les combiner dans la boucle foreach ou dans une boucle séparée? (ou d'une autre manière)
J'ai dû résoudre un problème similaire et j'ai fini par créer un petit utilitaire pdfmerge qui utilise le projet PDFSharp qui est essentiellement MIT sous licence.
Le code est simple, j'avais besoin d'un utilitaire cmdline donc j'ai plus de code dédié à l'analyse des arguments que je n'en ai pour la fusion PDF:
using (PdfDocument one = PdfReader.Open("file1.pdf", PdfDocumentOpenMode.Import))
using (PdfDocument two = PdfReader.Open("file2.pdf", PdfDocumentOpenMode.Import))
using (PdfDocument outPdf = new PdfDocument())
{
CopyPages(one, outPdf);
CopyPages(two, outPdf);
outPdf.Save("file1and2.pdf");
}
void CopyPages(PdfDocument from, PdfDocument to)
{
for (int i = 0; i < from.PageCount; i++)
{
to.AddPage(from.Pages[i]);
}
}
Voici une seule fonction qui fusionnera X quantité de PDF à l'aide de PDFSharp
using PdfSharp;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
public static void MergePDFs(string targetPath, params string[] pdfs) {
using(PdfDocument targetDoc = new PdfDocument()){
foreach (string pdf in pdfs) {
using (PdfDocument pdfDoc = PdfReader.Open(pdf, PdfDocumentOpenMode.Import)) {
for (int i = 0; i < pdfDoc.PageCount; i++) {
targetDoc.AddPage(pdfDoc.Pages[i]);
}
}
}
targetDoc.Save(targetPath);
}
}
C'est quelque chose que j'ai compris et que je voulais partager avec vous.
Ici, vous pouvez joindre plusieurs Pdfs en un (en suivant l'ordre de la liste d'entrée)
public static byte[] MergePdf(List<byte[]> pdfs)
{
List<PdfSharp.Pdf.PdfDocument> lstDocuments = new List<PdfSharp.Pdf.PdfDocument>();
foreach (var pdf in pdfs)
{
lstDocuments.Add(PdfReader.Open(new MemoryStream(pdf), PdfDocumentOpenMode.Import));
}
using (PdfSharp.Pdf.PdfDocument outPdf = new PdfSharp.Pdf.PdfDocument())
{
for(int i = 1; i<= lstDocuments.Count; i++)
{
foreach(PdfSharp.Pdf.PdfPage page in lstDocuments[i-1].Pages)
{
outPdf.AddPage(page);
}
}
MemoryStream stream = new MemoryStream();
outPdf.Save(stream, false);
byte[] bytes = stream.ToArray();
return bytes;
}
}
PDFsharp semble permettre la fusion de plusieurs documents PDF en un seul).
Et la même chose est également possible avec ITextSharp .
J'ai utilisé iTextsharp avec c # pour combiner des fichiers pdf. C'est le code que j'ai utilisé.
string[] lstFiles=new string[3];
lstFiles[0]=@"C:/pdf/1.pdf";
lstFiles[1]=@"C:/pdf/2.pdf";
lstFiles[2]=@"C:/pdf/3.pdf";
PdfReader reader = null;
Document sourceDocument = null;
PdfCopy pdfCopyProvider = null;
PdfImportedPage importedPage;
string outputPdfPath=@"C:/pdf/new.pdf";
sourceDocument = new Document();
pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPdfPath, System.IO.FileMode.Create));
//Open the output file
sourceDocument.Open();
try
{
//Loop through the files list
for (int f = 0; f < lstFiles.Length-1; f++)
{
int pages =get_pageCcount(lstFiles[f]);
reader = new PdfReader(lstFiles[f]);
//Add pages of current file
for (int i = 1; i <= pages; i++)
{
importedPage = pdfCopyProvider.GetImportedPage(reader, i);
pdfCopyProvider.AddPage(importedPage);
}
reader.Close();
}
//At the end save the output file
sourceDocument.Close();
}
catch (Exception ex)
{
throw ex;
}
private int get_pageCcount(string file)
{
using (StreamReader sr = new StreamReader(File.OpenRead(file)))
{
Regex regex = new Regex(@"/Type\s*/Page[^s]");
MatchCollection matches = regex.Matches(sr.ReadToEnd());
return matches.Count;
}
}
Il y a déjà de bonnes réponses ici, mais j'ai pensé que je pourrais mentionner que pdftk pourrait être utile pour cette tâche. Au lieu d'en produire un PDF directement, vous pouvez produire chacun PDF dont vous avez besoin, puis les combiner en tant que post-processus avec pdftk. Cela pourrait même être fait à partir de votre programme en utilisant un appel system () ou ShellExecute ().
Voici un exemple utilisant iTextSharp
public static void MergePdf(Stream outputPdfStream, IEnumerable<string> pdfFilePaths)
{
using (var document = new Document())
using (var pdfCopy = new PdfCopy(document, outputPdfStream))
{
pdfCopy.CloseStream = false;
try
{
document.Open();
foreach (var pdfFilePath in pdfFilePaths)
{
using (var pdfReader = new PdfReader(pdfFilePath))
{
pdfCopy.AddDocument(pdfReader);
pdfReader.Close();
}
}
}
finally
{
document?.Close();
}
}
}
Le constructeur PdfReader a de nombreuses surcharges. Il est possible de remplacer le type de paramètre IEnumerable<string>
avec IEnumerable<Stream>
et cela devrait aussi fonctionner. Veuillez noter que la méthode ne ferme pas OutputStream, elle délègue cette tâche au créateur du flux.
Je sais que beaucoup de gens ont recommandé PDF Sharp, mais il ne semble pas que ce projet ait été mis à jour depuis juin 2008. De plus, la source n'est pas disponible.
Personnellement, j'ai joué avec iTextSharp qui a été assez facile à travailler.
J'ai combiné les deux ci-dessus, car je devais fusionner 3 pdfbytes et retourner un octet
internal static byte[] mergePdfs(byte[] pdf1, byte[] pdf2,byte[] pdf3)
{
MemoryStream outStream = new MemoryStream();
using (Document document = new Document())
using (PdfCopy copy = new PdfCopy(document, outStream))
{
document.Open();
copy.AddDocument(new PdfReader(pdf1));
copy.AddDocument(new PdfReader(pdf2));
copy.AddDocument(new PdfReader(pdf3));
}
return outStream.ToArray();
}
Combiner deux byte[]
en utilisant iTextSharp jusqu'à la version 5.x:
internal static MemoryStream mergePdfs(byte[] pdf1, byte[] pdf2)
{
MemoryStream outStream = new MemoryStream();
using (Document document = new Document())
using (PdfCopy copy = new PdfCopy(document, outStream))
{
document.Open();
copy.AddDocument(new PdfReader(pdf1));
copy.AddDocument(new PdfReader(pdf2));
}
return outStream;
}
À la place du byte[]
il est possible de passer aussi Stream
Voici un lien vers un exemple utilisant PDFSharp et ConcatenateDocuments
Je l'ai fait avec PDFBox. Je suppose que cela fonctionne de manière similaire à iTextSharp.
Vous pouvez essayer pdf-shufflergtk-apps.org
La méthode suivante fusionne deux fichiers PDF (f1 et f2) à l'aide d'iTextSharp. Le deuxième pdf est ajouté après un index spécifique de f1.
string f1 = "D:\\a.pdf";
string f2 = "D:\\Iso.pdf";
string outfile = "D:\\c.pdf";
appendPagesFromPdf(f1, f2, outfile, 3);
public static void appendPagesFromPdf(String f1,string f2, String destinationFile, int startingindex)
{
PdfReader p1 = new PdfReader(f1);
PdfReader p2 = new PdfReader(f2);
int l1 = p1.NumberOfPages, l2 = p2.NumberOfPages;
//Create our destination file
using (FileStream fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
Document doc = new Document();
PdfWriter w = PdfWriter.GetInstance(doc, fs);
doc.Open();
for (int page = 1; page <= startingindex; page++)
{
doc.NewPage();
w.DirectContent.AddTemplate(w.GetImportedPage(p1, page), 0, 0);
//Used to pull individual pages from our source
}// copied pages from first pdf till startingIndex
for (int i = 1; i <= l2;i++)
{
doc.NewPage();
w.DirectContent.AddTemplate(w.GetImportedPage(p2, i), 0, 0);
}// merges second pdf after startingIndex
for (int i = startingindex+1; i <= l1;i++)
{
doc.NewPage();
w.DirectContent.AddTemplate(w.GetImportedPage(p1, i), 0, 0);
}// continuing from where we left in pdf1
doc.Close();
p1.Close();
p2.Close();
}
}
Pour résoudre un problème similaire, j'ai utilisé iTextSharp comme ceci:
//Create the document which will contain the combined PDF's
Document document = new Document();
//Create a writer for de document
PdfCopy writer = new PdfCopy(document, new FileStream(OutPutFilePath, FileMode.Create));
if (writer == null)
{
return;
}
//Open the document
document.Open();
//Get the files you want to combine
string[] filePaths = Directory.GetFiles(DirectoryPathWhereYouHaveYourFiles);
foreach (string filePath in filePaths)
{
//Read the PDF file
using (PdfReader reader = new PdfReader(vls_FilePath))
{
//Add the file to the combined one
writer.AddDocument(reader);
}
}
//Finally close the document and writer
writer.Close();
document.Close();
La méthode suivante obtient un tableau List
de byte
qui est PDF byte
tableau, puis renvoie un tableau byte
.
using ...;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
public static class PdfHelper
{
public static byte[] PdfConcat(List<byte[]> lstPdfBytes)
{
byte[] res;
using (var outPdf = new PdfDocument())
{
foreach (var pdf in lstPdfBytes)
{
using (var pdfStream = new MemoryStream(pdf))
using (var pdfDoc = PdfReader.Open(pdfStream, PdfDocumentOpenMode.Import))
for (var i = 0; i < pdfDoc.PageCount; i++)
outPdf.AddPage(pdfDoc.Pages[i]);
}
using (var memoryStreamOut = new MemoryStream())
{
outPdf.Save(memoryStreamOut, false);
res = Stream2Bytes(memoryStreamOut);
}
}
return res;
}
public static void DownloadAsPdfFile(string fileName, byte[] content)
{
var ms = new MemoryStream(content);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("content-disposition", $"attachment;filename={fileName}.pdf");
HttpContext.Current.Response.Buffer = true;
ms.WriteTo(HttpContext.Current.Response.OutputStream);
HttpContext.Current.Response.End();
}
private static byte[] Stream2Bytes(Stream input)
{
var buffer = new byte[input.Length];
using (var ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, read);
return ms.ToArray();
}
}
}
Ainsi, le résultat de PdfHelper.PdfConcat
la méthode est passée à PdfHelper.DownloadAsPdfFile
méthode.
PS: un package NuGet
nommé [PdfSharp][1]
doit être installé. Donc, dans le Package Manage Console
type de fenêtre:
Install-Package PdfSharp
Voici la solution http://www.wacdesigns.com/2008/10/03/merge-pdf-files-using-c Il utilise la bibliothèque iTextSharp open source gratuite http: // sourceforge.net/projects/itextsharp