Feature: Document Template Packages
Document Templates can be grouped into a package and generated on-demand in the same was as individual document templates. Packages can be generated in bulk.
This commit is contained in:
@@ -10,6 +10,7 @@ using iTextSharp.text.pdf;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
@@ -45,15 +46,15 @@ namespace Disco.BI.Extensions
|
||||
return dt.PdfExpressionsFromCache(Database).Values.OrderBy(e => e.Ordinal).ToList();
|
||||
}
|
||||
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params string[] DataObjectsIds)
|
||||
public static Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, params string[] DataObjectsIds)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjectsIds);
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjectsIds);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params IAttachmentTarget[] DataObjects)
|
||||
public static Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, params IAttachmentTarget[] DataObjects)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
public static Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
{
|
||||
bool generateExpression = !string.IsNullOrEmpty(dt.OnGenerateExpression);
|
||||
string generateExpressionResult = null;
|
||||
@@ -70,7 +71,37 @@ namespace Disco.BI.Extensions
|
||||
|
||||
return pdfStream;
|
||||
}
|
||||
|
||||
public static Stream GeneratePdfPackage(this DocumentTemplatePackage package, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateFromPackage(package, Database, Target, CreatorUser, TimeStamp, State);
|
||||
}
|
||||
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjectsIds);
|
||||
}
|
||||
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
|
||||
}
|
||||
|
||||
public static List<bool> PdfPageHasAttachmentId(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
string templateFilename = dt.RepositoryFilename(Database);
|
||||
if (!File.Exists(templateFilename))
|
||||
throw new FileNotFoundException("PDF template not found", templateFilename);
|
||||
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
var result = new bool[pdfReader.NumberOfPages];
|
||||
var fieldNames = pdfReader.AcroFields.Fields.Keys.Where(key => key.Equals("DiscoAttachmentId", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
var fieldPositions = fieldNames.SelectMany(name => pdfReader.AcroFields.GetFieldPositions(name));
|
||||
foreach (var fieldPosition in fieldPositions)
|
||||
{
|
||||
result[fieldPosition.page - 1] = true;
|
||||
}
|
||||
pdfReader.Close();
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public static void Delete(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
// Find & Rename all references
|
||||
|
||||
@@ -21,8 +21,106 @@ namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class PdfGenerator
|
||||
{
|
||||
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects)
|
||||
{
|
||||
if (DataObjects.Count > 0)
|
||||
{
|
||||
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Count);
|
||||
using (var state = DocumentState.DefaultState())
|
||||
{
|
||||
foreach (var d in DataObjects)
|
||||
{
|
||||
generatedPdfs.Add(package.GeneratePdfPackage(Database, d, CreatorUser, Timestamp, state));
|
||||
state.SequenceNumber++;
|
||||
state.FlushScopeCache();
|
||||
}
|
||||
}
|
||||
if (generatedPdfs.Count == 1)
|
||||
{
|
||||
return generatedPdfs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = Utilities.JoinPdfs(InsertBlankPages, generatedPdfs);
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params IAttachmentTarget[] DataObjects)
|
||||
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds)
|
||||
{
|
||||
List<IAttachmentTarget> DataObjects;
|
||||
|
||||
switch (package.Scope)
|
||||
{
|
||||
case AttachmentTypes.Device:
|
||||
DataObjects = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).ToList<IAttachmentTarget>();
|
||||
break;
|
||||
case AttachmentTypes.Job:
|
||||
int[] intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToArray();
|
||||
DataObjects = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToList<IAttachmentTarget>();
|
||||
break;
|
||||
case AttachmentTypes.User:
|
||||
DataObjects = new List<IAttachmentTarget>(DataObjectsIds.Count);
|
||||
for (int idIndex = 0; idIndex < DataObjectsIds.Count; idIndex++)
|
||||
{
|
||||
string dataObjectId = DataObjectsIds[idIndex];
|
||||
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
|
||||
if (user == null)
|
||||
throw new Exception($"Unknown Username specified: {dataObjectId}");
|
||||
DataObjects.Add(user);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid DocumentType Scope");
|
||||
}
|
||||
|
||||
return GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
|
||||
}
|
||||
|
||||
public static Stream GenerateFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime Timestamp, DocumentState State)
|
||||
{
|
||||
var templates = package.GetDocumentTemplates(Database);
|
||||
|
||||
if (templates.Count == 0)
|
||||
return null;
|
||||
|
||||
bool generateExpression = !string.IsNullOrEmpty(package.OnGenerateExpression);
|
||||
string generateExpressionResult = null;
|
||||
|
||||
if (generateExpression)
|
||||
generateExpressionResult = package.EvaluateOnGenerateExpression(Data, Database, CreatorUser, Timestamp, State);
|
||||
|
||||
List<Stream> generatedPdfs = new List<Stream>(templates.Count);
|
||||
foreach (var template in templates)
|
||||
{
|
||||
generatedPdfs.Add(template.GeneratePdf(Database, Data, CreatorUser, Timestamp, State, true));
|
||||
|
||||
State.SequenceNumber++;
|
||||
State.FlushScopeCache();
|
||||
}
|
||||
|
||||
if (generateExpression)
|
||||
DocumentsLog.LogDocumentPackageGenerated(package, Data, CreatorUser, generateExpressionResult);
|
||||
else
|
||||
DocumentsLog.LogDocumentPackageGenerated(package, Data, CreatorUser);
|
||||
|
||||
if (generatedPdfs.Count == 1)
|
||||
{
|
||||
return generatedPdfs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = Utilities.JoinPdfs(package.InsertBlankPages, generatedPdfs);
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
}
|
||||
}
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, params IAttachmentTarget[] DataObjects)
|
||||
{
|
||||
if (DataObjects.Length > 0)
|
||||
{
|
||||
@@ -42,7 +140,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = Utilities.JoinPdfs(generatedPdfs.ToArray());
|
||||
Stream bulkPdf = Utilities.JoinPdfs(InsertBlankPages, generatedPdfs);
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
@@ -51,7 +149,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params string[] DataObjectsIds)
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, params string[] DataObjectsIds)
|
||||
{
|
||||
IAttachmentTarget[] DataObjects;
|
||||
|
||||
@@ -72,14 +170,14 @@ namespace Disco.BI.Interop.Pdf
|
||||
|
||||
DataObjects[idIndex] = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
|
||||
if (DataObjects[idIndex] == null)
|
||||
throw new Exception(string.Format("Unknown Username specified: {0}", dataObjectId));
|
||||
throw new Exception($"Unknown Username specified: {dataObjectId}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid DocumentType Scope");
|
||||
}
|
||||
|
||||
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
|
||||
}
|
||||
|
||||
public static Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
|
||||
@@ -1,41 +1,50 @@
|
||||
using iTextSharp.text;
|
||||
using iTextSharp.text.pdf;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
public static System.IO.Stream JoinPdfs(params System.IO.Stream[] Pdfs)
|
||||
public static Stream JoinPdfs(bool InsertBlankPages, List<Stream> Pdfs)
|
||||
{
|
||||
if (Pdfs.Length == 0)
|
||||
throw new System.ArgumentNullException("Pdfs");
|
||||
if (Pdfs.Count == 0)
|
||||
throw new System.ArgumentNullException(nameof(Pdfs));
|
||||
|
||||
// Only One PDF - Possible Reference Bug v's Memory/Speed (Returning Param Memory Stream)
|
||||
if (Pdfs.Length == 1)
|
||||
if (Pdfs.Count == 1)
|
||||
return Pdfs[0];
|
||||
|
||||
// Join Pdfs
|
||||
System.IO.MemoryStream msBuilder = new System.IO.MemoryStream();
|
||||
|
||||
Document pdfDoc = new Document();
|
||||
PdfCopy pdfCopy = new PdfCopy(pdfDoc, msBuilder);
|
||||
var msBuilder = new MemoryStream();
|
||||
|
||||
var pdfLastPageSize = PageSize.A4;
|
||||
var pdfDoc = new Document();
|
||||
var pdfCopy = new PdfSmartCopy(pdfDoc, msBuilder);
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
for (int i = 0; i < Pdfs.Length; i++)
|
||||
for (int i = 0; i < Pdfs.Count; i++)
|
||||
{
|
||||
System.IO.Stream pdf = Pdfs[i];
|
||||
PdfReader pdfReader = new PdfReader(pdf);
|
||||
var pdf = Pdfs[i];
|
||||
var pdfReader = new PdfReader(pdf);
|
||||
|
||||
for (int indexPage = 1; indexPage <= pdfReader.NumberOfPages; indexPage++)
|
||||
{
|
||||
iTextSharp.text.Rectangle pageSize = pdfReader.GetPageSizeWithRotation(indexPage);
|
||||
PdfImportedPage page = pdfCopy.GetImportedPage(pdfReader, indexPage);
|
||||
pdfDoc.SetPageSize(pageSize);
|
||||
pdfLastPageSize = pdfReader.GetPageSizeWithRotation(indexPage);
|
||||
var page = pdfCopy.GetImportedPage(pdfReader, indexPage);
|
||||
pdfDoc.SetPageSize(pdfLastPageSize);
|
||||
pdfDoc.NewPage();
|
||||
pdfCopy.AddPage(page);
|
||||
}
|
||||
|
||||
if (InsertBlankPages && (pdfCopy.PageNumber % 2) != 0)
|
||||
{
|
||||
pdfDoc.NewPage();
|
||||
pdfCopy.AddPage(pdfLastPageSize, 0);
|
||||
}
|
||||
|
||||
pdfReader.Close();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user