At my church we take attendance of the whole congregation weekly during Sunday worship. This was always done manually by a guy with a clipboard in the back checking off people's names as he saw them. I figured this would be an easy thing to move to Rock, but quickly realized that we sorted our names differently than Rock's default. Our attendance sheet was grouped by families, which is not the same as ordering by last name. Several families have children with different last names and some families has the same last name as different families.

To solve this in Rock I made a copy of the Group Attendance Detail file, edited a little bit of the code, created a new Block Type for this modified file, then updated the Group Attendance page to use the new Block Type. Don't worry if that sounds daunting, I'll break it down the best I can since I just learned most of this myself!

1) Copy the Group Attendance file

  • For this step you'll need FTP access to your webserver, or some other way of downloading/uploading files to the server.
  • Find the files for the Group Attendance Details on the server.
  • The should be located at "<your Rock root folder>/Blocks/Groups/"
  • Copy "GroupAttendanceDetail.ascx.cs" and "GroupAttendanceDetail.ascx" to your local PC.
  • Rename your local copy to something different, but something that still make sense like,  "GroupAttendanceDetailFamily.ascx.cs" and "GroupAttendanceDetailFamily.ascx"


2) Edit the file

  • Open your newly created "GroupAttendanceDetailFamily.ascx" file in a text editor (like Notepad++, VS Code, etc.)
  • The very first line should look like the following:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="GroupAttendanceDetail.ascx.cs" Inherits="RockWeb.Blocks.Groups.GroupAttendanceDetail" %>

  • Replace it with the following:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="GroupAttendanceDetailFamily.ascx.cs" Inherits="RockWeb.Blocks.Groups.GroupAttendanceDetail" %>

  • Save and close the file and upload it to the server.
  • Next open the "GroupAttendanceDetailFamily.ascx.cs" file in a text editor.
  • Find the following bit of code:

[Serializable]

public class GroupAttendanceAttendee

{

/// <summary>

/// Gets or sets the person identifier.

  • After the "{", but before the first "/// <summary>" add the following code:

/// <summary>

/// Gets or sets the family name identifier.

/// </summary>

/// <value>

/// The family name identifier.

/// </value>

public string FamilyName { get; set; }

/// <summary>

/// Gets or sets the family identifier.

/// </summary>

/// <value>

/// The family identifier.

/// </value>

public int FamilyId { get; set; }

/// <summary>

/// Gets or sets the age classification.

/// </summary>

/// <value>

/// The age classification.

/// </value>

public string AgeClass { get; set; }

  • New find the following bit of code:

var attendee = new GroupAttendanceAttendee();

attendee.PersonId = person.Id;

attendee.NickName = person.NickName;

attendee.LastName = person.LastName;

attendee.Attended = true;

attendee.CampusIds = person.GetCampusIds();

  • And replace it with the following:

var attendee = new GroupAttendanceAttendee();

attendee.PersonId = person.Id;

attendee.NickName = person.NickName;

attendee.LastName = person.LastName;

attendee.FamilyName = person.PrimaryFamily.Name;

attendee.FamilyId = person.PrimaryFamilyId.ToString().AsInteger();

attendee.AgeClass = person.AgeClassification.ToString();

attendee.Attended = true;

attendee.CampusIds = person.GetCampusIds();

  • Again, find the following bit of code:

.Select( p => new GroupAttendanceAttendee()

{

PersonId = p.Id,

NickName = p.NickName,

LastName = p.LastName,

Attended = attendedIds.Contains( p.Id ),

CampusIds = p.GetCampusIds(),

MergedTemplate = template.ResolveMergeFields( mergeFields.Union( new Dictionary<string, object>() { { "Person", p } } ).ToDictionary( x => x.Key, x => x.Value ) )

} )

.ToList();

  • And replace it with the following:

.Select( p => new GroupAttendanceAttendee()

{

PersonId = p.Id,

NickName = p.NickName,

LastName = p.LastName,

FamilyName = p.PrimaryFamily.Name,

FamilyId = p.PrimaryFamilyId.ToString().AsInteger(),

AgeClass = p.AgeClassification.ToString(),

Attended = attendedIds.Contains( p.Id ),

CampusIds = p.GetCampusIds(),

MergedTemplate = template.ResolveMergeFields( mergeFields.Union( new Dictionary<string, object>() { { "Person", p } } ).ToDictionary( x => x.Key, x => x.Value ) )

} )

.ToList();

  • Finally, find the following line of code:

lvMembers.DataSource = campusAttendees.OrderBy( a => a.LastName ).ThenBy( a => a.NickName ).ToList();

  • And replace it with this:

lvMembers.DataSource = campusAttendees.OrderBy( a => a.FamilyName ).ThenBy( a => a.FamilyId ).ThenBy( a => a.AgeClass ).ThenBy( a => a.NickName ).ToList();

  • You can now save your file and upload it back to your server!


3) Create a new Block Type

  • Go to your Rock RMS site and go to Admin Tools > CMS Configuration > Block Types
  • Click the + to create a new Block Type
  • For the Name field enter: "Group Attendance Detail - Family Sort"
  • For the Description you can enter: "Lists the group members for a specific occurrence datetime and allows selecting if they attended or not - now sorted by family!"
  • For the path enter: "~/Blocks/Groups/GroupAttendanceDetailFamily.ascx"
  • Click Save.


4) Update Group Attendance Page to use new Block Type

  • Still inside Rock go to Admin Tools > CMS Configuration > Pages
  • Using the page tree navigate down to:
    Internal Homepage > People > Manage > Group Viewer > Group Attendance > Attendance
  • Under the "Blocks From Page" section there should only be "Group Attendance Detail"
  • Click the Delete Block button on the "Group Attendance Detail" section
  • Click the "Add Block to Zone" button
  • In the Name section type in "Group Attendance Detail - Family Sort"
  • In the Type section search for and select "Group Attendance Detail - Family Sort"
  • Make sure the Add To section is set to "Page (Attendance)"
  • Click the Save button.

That's it!

Now go to the group viewer and try to take attendance for your group. It should be sorted by families with adults listed first, then children.

I hope this helps someone!