Skip to content

Instantly share code, notes, and snippets.

@NDiiong
Forked from tcavaletto/RockSolidChurchTemplate.cs
Created November 16, 2020 08:22
Show Gist options
  • Save NDiiong/615522e1ff71a7a7cfb39e9f1e37a100 to your computer and use it in GitHub Desktop.
Save NDiiong/615522e1ff71a7a7cfb39e9f1e37a100 to your computer and use it in GitHub Desktop.
Rock Solid Church Template
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