Last active
November 16, 2020 08:22
-
-
Save tcavaletto/be64a6c0ec0974e204d8807618001f5f to your computer and use it in GitHub Desktop.
Rock Solid Church Template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.Composition; | |
using System.IO; | |
using System.Linq; | |
using com.centralaz.RoomManagement.Attribute; | |
using com.centralaz.RoomManagement.Model; | |
using com.centralaz.RoomManagement.ReportTemplates; | |
using iTextSharp.text; | |
using iTextSharp.text.pdf; | |
using Rock; | |
using Rock.Data; | |
using Rock.Model; | |
namespace org.rocksolidchurch.CustomReportTemplate.ReportTemplates | |
{ | |
/// <summary> | |
/// | |
/// </summary> | |
[System.ComponentModel.Description( "A custom report built for Rock Solid Church" )] | |
[Export( typeof( ReportTemplate ) )] | |
[ExportMetadata( "ComponentName", "Rock Solid Church" )] | |
public class RockSolidChurchReportTemplate : ReportTemplate | |
{ | |
/// <summary> | |
/// Gets or sets the exceptions. | |
/// </summary> | |
/// <value> | |
/// The exceptions. | |
/// </value> | |
public override List<Exception> Exceptions { get; set; } | |
/// <summary> | |
/// Creates the document. | |
/// </summary> | |
/// <param name="reservationSummaryList"></param> | |
/// <param name="logoFileUrl"></param> | |
/// <param name="font"></param> | |
/// <param name="filterStartDate"></param> | |
/// <param name="filterEndDate"></param> | |
/// <returns></returns> | |
public override byte[] GenerateReport( List<ReservationService.ReservationSummary> reservationSummaryList, string logoFileUrl, string font, DateTime? filterStartDate, DateTime? filterEndDate, string lavaTemplate = "" ) | |
{ | |
// Here we list the different fonts used by different sections of the report | |
var titleFont = FontFactory.GetFont( font, 16, Font.BOLD ); | |
var listHeaderFont = FontFactory.GetFont( font, 12, Font.BOLD, Color.DARK_GRAY ); | |
var listSubHeaderFont = FontFactory.GetFont( font, 10, Font.BOLD, Color.DARK_GRAY ); | |
var listItemFontNormal = FontFactory.GetFont( font, 8, Font.NORMAL ); | |
var listItemFontBold = FontFactory.GetFont( font, 8, Font.BOLD ); | |
var listItemFontUnapproved = FontFactory.GetFont( font, 8, Font.ITALIC, Color.MAGENTA ); | |
var noteFont = FontFactory.GetFont( font, 8, Font.NORMAL, Color.GRAY ); | |
// Here we massage a list of the summaries into the format we want for the report. For example, | |
// in this report we're grouping summaries by date and starting a new page for each date, | |
// so we group them by date here. | |
var reservationSummaries = reservationSummaryList.Select( r => new | |
{ | |
Id = r.Id, | |
ReservationName = r.ReservationName, | |
ApprovalState = r.ApprovalState.ConvertToString(), | |
Locations = r.ReservationLocations.ToList(), | |
Resources = r.ReservationResources.ToList(), | |
CalendarDate = r.EventStartDateTime.ToLongDateString(), | |
EventStartDateTime = r.EventStartDateTime, | |
EventEndDateTime = r.EventEndDateTime, | |
ReservationStartDateTime = r.ReservationStartDateTime, | |
ReservationEndDateTime = r.ReservationEndDateTime, | |
EventDateTimeDescription = r.EventDateTimeDescription, | |
ReservationDateTimeDescription = r.ReservationDateTimeDescription, | |
Ministry = r.ReservationMinistry, | |
ContactInfo = String.Format( "{0} {1}", r.EventContactPersonAlias.Person.FullName, r.EventContactPhoneNumber ), | |
SetupPhotoId = r.SetupPhotoId, | |
Note = r.Note | |
} ) | |
.OrderBy( r => r.EventStartDateTime ) | |
.GroupBy( r => r.EventStartDateTime.Date ) | |
.Select( r => r.ToList() ) | |
.ToList(); | |
// Setup the document - Here is where we dictate whether the report is using portrait or landscape mode. | |
var document = new Document( PageSize.A4.Rotate(), 25, 25, 25, 25 ); | |
var outputStream = new MemoryStream(); | |
var writer = PdfWriter.GetInstance( document, outputStream ); | |
// Our custom Header and Footer is done using Event Handler. | |
RockSolidChurchHeaderFooter PageEventHandler = new RockSolidChurchHeaderFooter(); | |
writer.PageEvent = PageEventHandler; | |
// Define the page header | |
PageEventHandler.HeaderFont = listHeaderFont; | |
PageEventHandler.SubHeaderFont = listSubHeaderFont; | |
PageEventHandler.HeaderLeft = "Group"; | |
PageEventHandler.HeaderRight = "1"; | |
document.Open(); | |
// Add logo | |
try | |
{ | |
iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance( logoFileUrl ); | |
logo.Alignment = iTextSharp.text.Image.RIGHT_ALIGN; | |
logo.ScaleToFit( 100, 55 ); | |
document.Add( logo ); | |
} | |
catch { } | |
// Add the Title | |
var today = RockDateTime.Today; | |
var filterStartDateTime = filterStartDate.HasValue ? filterStartDate.Value : today; | |
var filterEndDateTime = filterEndDate.HasValue ? filterEndDate.Value : today.AddMonths( 1 ); | |
String title = String.Format( "Reservations for: {0} - {1}", filterStartDateTime.ToString( "MMMM d" ), filterEndDateTime.ToString( "MMMM d" ) ); | |
document.Add( new Paragraph( title, titleFont ) ); | |
Font zapfdingbats = new Font( Font.ZAPFDINGBATS ); | |
// Loop through the reservations. This particular report starts a new page for each new day, so we first loop through the days | |
foreach ( var reservationDay in reservationSummaries ) | |
{ | |
var firstReservation = reservationDay.FirstOrDefault(); | |
if ( firstReservation != null ) | |
{ | |
//Build Report Header | |
document.Add( Chunk.NEWLINE ); | |
String listHeader = PageEventHandler.CalendarDate = firstReservation.CalendarDate; | |
document.Add( new Paragraph( listHeader, listHeaderFont ) ); | |
// Build Column Headers | |
var listSubHeaderTable = new PdfPTable( 6 ); | |
listSubHeaderTable.LockedWidth = true; | |
listSubHeaderTable.TotalWidth = PageSize.A4.Rotate().Width - document.LeftMargin - document.RightMargin; | |
listSubHeaderTable.HorizontalAlignment = 0; | |
listSubHeaderTable.SpacingBefore = 10; | |
listSubHeaderTable.SpacingAfter = 0; | |
listSubHeaderTable.DefaultCell.BorderWidth = 0; | |
listSubHeaderTable.DefaultCell.BorderWidthBottom = 1; | |
listSubHeaderTable.DefaultCell.BorderColorBottom = Color.DARK_GRAY; | |
listSubHeaderTable.AddCell( new Phrase( "Name", listSubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Event Time", listSubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Event Contact", listSubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Reservation Time", listSubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Locations", listSubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Resources", listSubHeaderFont ) ); | |
PageEventHandler.IsHeaderShown = true; | |
document.Add( listSubHeaderTable ); | |
// Build Rows | |
foreach ( var reservationSummary in reservationDay ) | |
{ | |
if ( reservationSummary == reservationDay.Last() ) | |
{ | |
PageEventHandler.IsHeaderShown = false; | |
} | |
//Build the row for the reservation | |
var listItemTable = new PdfPTable( 6 ); | |
listItemTable.LockedWidth = true; | |
listItemTable.TotalWidth = PageSize.A4.Rotate().Width - document.LeftMargin - document.RightMargin; | |
listItemTable.HorizontalAlignment = 0; | |
listItemTable.SpacingBefore = 0; | |
listItemTable.SpacingAfter = 1; | |
listItemTable.DefaultCell.BorderWidth = 0; | |
// Build the columns in the reservation row | |
listItemTable.AddCell( new Phrase( reservationSummary.ReservationName, listItemFontNormal ) ); | |
listItemTable.AddCell( new Phrase( reservationSummary.EventDateTimeDescription, listItemFontNormal ) ); | |
listItemTable.AddCell( new Phrase( reservationSummary.ContactInfo, listItemFontNormal ) ); | |
listItemTable.AddCell( new Phrase( reservationSummary.ReservationDateTimeDescription, listItemFontNormal ) ); | |
List locationList = new List( List.UNORDERED, 8f ); | |
locationList.SetListSymbol( "\u2022" ); | |
foreach ( var reservationLocation in reservationSummary.Locations ) | |
{ | |
var listItem = new iTextSharp.text.ListItem( reservationLocation.Location.Name, listItemFontNormal ); | |
if ( reservationLocation.ApprovalState == ReservationLocationApprovalState.Approved ) | |
{ | |
listItem.Add( new Phrase( "\u0034", zapfdingbats ) ); | |
} | |
// Here we add any questions and answers tied to the location. The LoadReservationLocationAttributes method specifically pulls | |
// Attributes and Attribute Values tied to questions about the location. | |
reservationLocation.LoadReservationLocationAttributes(); | |
foreach ( var attribute in reservationLocation.AttributeValues ) | |
{ | |
listItem.Add( new Phrase( Environment.NewLine+attribute.Value.AttributeName + ": ", listItemFontBold ) ); | |
listItem.Add( new Phrase( attribute.Value.ValueFormatted, listItemFontNormal ) ); | |
} | |
locationList.Add( listItem ); | |
} | |
PdfPCell locationCell = new PdfPCell(); | |
locationCell.Border = 0; | |
locationCell.PaddingTop = -2; | |
locationCell.AddElement( locationList ); | |
listItemTable.AddCell( locationCell ); | |
List resourceList = new List( List.UNORDERED, 8f ); | |
resourceList.SetListSymbol( "\u2022" ); | |
foreach ( var reservationResource in reservationSummary.Resources ) | |
{ | |
var listItem = new iTextSharp.text.ListItem( String.Format( "{0}({1})", reservationResource.Resource.Name, reservationResource.Quantity ), listItemFontNormal ); | |
if ( reservationResource.ApprovalState == ReservationResourceApprovalState.Approved ) | |
{ | |
listItem.Add( new Phrase( "\u0034", zapfdingbats ) ); | |
} | |
// Here we add any questions and answers tied to the resource. The LoadReservationResourceAttributes method specifically pulls | |
// Attributes and Attribute Values tied to questions about the resource. | |
reservationResource.LoadReservationResourceAttributes(); | |
foreach ( var attribute in reservationResource.AttributeValues ) | |
{ | |
listItem.Add( new Phrase( Environment.NewLine + attribute.Value.AttributeName + ": ", listItemFontBold ) ); | |
listItem.Add( new Phrase( attribute.Value.ValueFormatted, listItemFontNormal ) ); | |
} | |
resourceList.Add( listItem ); | |
} | |
PdfPCell resourceCell = new PdfPCell(); | |
resourceCell.Border = 0; | |
resourceCell.PaddingTop = -2; | |
resourceCell.AddElement( resourceList ); | |
listItemTable.AddCell( resourceCell ); | |
document.Add( listItemTable ); | |
// Add a note at the bottom if one exists | |
if ( !string.IsNullOrWhiteSpace( reservationSummary.Note ) ) | |
{ | |
//document.Add( Chunk.NEWLINE ); | |
var listNoteTable = new PdfPTable( 1 ); | |
listNoteTable.LockedWidth = true; | |
listNoteTable.TotalWidth = PageSize.A4.Width - document.LeftMargin - document.RightMargin - 50; | |
listNoteTable.HorizontalAlignment = 1; | |
listNoteTable.SpacingBefore = 0; | |
listNoteTable.SpacingAfter = 1; | |
listNoteTable.DefaultCell.BorderWidth = 0; | |
listNoteTable.AddCell( new Phrase( reservationSummary.Note, noteFont ) ); | |
document.Add( listNoteTable ); | |
} | |
} | |
} | |
document.NewPage(); | |
} | |
document.Close(); | |
return outputStream.ToArray(); | |
} | |
} | |
} | |
public class RockSolidChurchHeaderFooter : PdfPageEventHelper | |
{ | |
// This is the contentbyte object of the writer | |
PdfContentByte cb; | |
// we will put the final number of pages in a template | |
PdfTemplate template; | |
// this is the BaseFont we are going to use for the header / footer | |
BaseFont bf = null; | |
// This keeps track of the creation time | |
DateTime PrintTime = DateTime.Now; | |
#region Properties | |
private string _Title; | |
public string Title | |
{ | |
get { return _Title; } | |
set { _Title = value; } | |
} | |
private string _CalendarDate; | |
public string CalendarDate | |
{ | |
get { return _CalendarDate; } | |
set { _CalendarDate = value; } | |
} | |
private string _HeaderLeft; | |
public string HeaderLeft | |
{ | |
get { return _HeaderLeft; } | |
set { _HeaderLeft = value; } | |
} | |
private string _HeaderRight; | |
public string HeaderRight | |
{ | |
get { return _HeaderRight; } | |
set { _HeaderRight = value; } | |
} | |
private Font _HeaderFont; | |
public Font HeaderFont | |
{ | |
get { return _HeaderFont; } | |
set { _HeaderFont = value; } | |
} | |
private Font _SubHeaderFont; | |
public Font SubHeaderFont | |
{ | |
get { return _SubHeaderFont; } | |
set { _SubHeaderFont = value; } | |
} | |
private bool _IsHeaderShown; | |
public bool IsHeaderShown | |
{ | |
get { return _IsHeaderShown; } | |
set { _IsHeaderShown = value; } | |
} | |
#endregion | |
// we override the onOpenDocument method | |
public override void OnOpenDocument( PdfWriter writer, Document document ) | |
{ | |
try | |
{ | |
PrintTime = DateTime.Now; | |
bf = BaseFont.CreateFont( BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED ); | |
cb = writer.DirectContent; | |
template = cb.CreateTemplate( 50, 50 ); | |
} | |
catch | |
{ | |
// not implemented | |
} | |
} | |
public override void OnStartPage( PdfWriter writer, Document document ) | |
{ | |
base.OnStartPage( writer, document ); | |
int pageN = writer.PageNumber; | |
// This method adds a new header everytime the report starts a new page for a new date. | |
if ( pageN > 1 && IsHeaderShown ) | |
{ | |
// Add Page Header | |
document.Add( new Paragraph( CalendarDate, HeaderFont ) ); | |
//Build Column Headers | |
var listSubHeaderTable = new PdfPTable( 6 ); | |
listSubHeaderTable.LockedWidth = true; | |
listSubHeaderTable.TotalWidth = PageSize.A4.Rotate().Width - document.LeftMargin - document.RightMargin; | |
listSubHeaderTable.HorizontalAlignment = 0; | |
listSubHeaderTable.SpacingBefore = 10; | |
listSubHeaderTable.SpacingAfter = 0; | |
listSubHeaderTable.DefaultCell.BorderWidth = 0; | |
listSubHeaderTable.DefaultCell.BorderWidthBottom = 1; | |
listSubHeaderTable.DefaultCell.BorderColorBottom = Color.DARK_GRAY; | |
listSubHeaderTable.AddCell( new Phrase( "Name", SubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Event Time", SubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Event Contact", SubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Reservation Time", SubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Locations", SubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Resources", SubHeaderFont ) ); | |
listSubHeaderTable.AddCell( new Phrase( "Notes", SubHeaderFont ) ); | |
document.Add( listSubHeaderTable ); | |
} | |
} | |
public override void OnEndPage( PdfWriter writer, Document document ) | |
{ | |
// This section adds a 'X of Y' page number to the bottom left hand of the page. The final page count will be calculated | |
// and added when the document is closed. | |
base.OnEndPage( writer, document ); | |
int pageN = writer.PageNumber; | |
String text = "Page " + pageN + " of "; | |
float len = bf.GetWidthPoint( text, 8 ); | |
Rectangle pageSize = document.PageSize; | |
cb.SetRGBColorFill( 100, 100, 100 ); | |
cb.BeginText(); | |
cb.SetFontAndSize( bf, 8 ); | |
cb.SetTextMatrix( pageSize.GetLeft( 40 ), pageSize.GetBottom( 30 ) ); | |
cb.ShowText( text ); | |
cb.EndText(); | |
cb.AddTemplate( template, pageSize.GetLeft( 40 ) + len, pageSize.GetBottom( 30 ) ); | |
// This section adds a 'Printed on' date to the bottom right hand of the page so that workers can reference when the report was printed. | |
cb.BeginText(); | |
cb.SetFontAndSize( bf, 8 ); | |
cb.ShowTextAligned( PdfContentByte.ALIGN_RIGHT, | |
"Printed On " + PrintTime.ToString(), | |
pageSize.GetRight( 40 ), | |
pageSize.GetBottom( 30 ), 0 ); | |
cb.EndText(); | |
} | |
public override void OnCloseDocument( PdfWriter writer, Document document ) | |
{ | |
// This section adds the page total to the page number section | |
base.OnCloseDocument( writer, document ); | |
template.BeginText(); | |
template.SetFontAndSize( bf, 8 ); | |
template.SetTextMatrix( 0, 0 ); | |
template.ShowText( "" + ( writer.PageNumber - 1 ) ); | |
template.EndText(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment