tcavaletto
10/2/2018 - 9:19 PM

Rock Solid Church Template

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();
    }

}