Show All Days For Monthly Time Tracking

We incorporate time allocation in our client invoices at the end of each month. The time tracking data resides in a custom object within our Salesforce org, and we typically generate a report and export it to send to clients during the billing process. This export, usually in the form of a spreadsheet, includes details such as date, hours, a brief description, and the employee responsible.

However, if a client wishes to view the time allocation for every day of the month, even if an employee did not work on certain days, we encounter a challenge. Salesforce reports can only present data that has been entered into the database. To address this limitation, one workaround is to export the Salesforce report and manipulate the resulting file to meet the client’s specific requirement.

An alternative solution involves creating a Visualforce page that identifies all the dates in a given month and includes allocation details only if a time tracking record exists for that date. Going a step further, you can configure the Visualforce page to render as an Excel file, enhancing efficiency.

In this post, we will guide you through the process of creating a Visualforce page that displays all the days for a specified month.

To begin, we need an Apex Class controller for the page:

/*
	Created by: Greg Hacic
	Last Update: 2 February 2017 by Greg Hacic
	Questions?: greg@interactiveties.com
	
	Notes:
		- controller for monthlyTime.page
*/
public class monthlyTime {
	
	public Integer monthSelection = Date.Today().Month(); //month > declared here so it can be overwritten in afuture enhancement
	public Integer yearSelection = Date.Today().Year(); //year > declared here so it can be overwritten in afuture enhancement
	public List<timeEntry> timeEntries = new List<timeEntry>(); //custom wrapper object for Date and Time_Card__c details
	public Decimal totalHours = 0.0; //total hours
	
	//constructor
	public monthlyTime() {
		grabTimecards(); //build the list of wrapper objects to display
	}
	
	//grab all of the Time_Card__c records for the employee, project and month
	private void grabTimecards() {
		
		List<Date> daysForMonth = buildDaysInMonth(); //create the list of all days for the month
		timeEntries.clear(); //empty the timeEntries list
		totalHours = 0; //reset the total to zero
		
		//placeholder for loop to grab your custom time card records and increment the overall hours
		
		//construct the list of time entry objects
		for (Date d : daysForMonth) { //for all of the dates in our list
			timeEntries.add(new timeEntry(d, 'placeholder')); //create a new timeEntry object for the date
		}
	}
	
	//grabs all of the days in the month for the selected month & year
	private List<Date> buildDaysInMonth() {
		List<Date> returnList = new List<Date>(); //return list of Dates
		Integer daysInMonth = Date.daysInMonth(yearSelection, monthSelection); //number of days in month
		for (Integer day = 1; day <= daysInMonth; day++) { //for first to last day in month
			returnList.add(Date.newInstance(yearSelection, monthSelection, day)); //add the date to our list
		}
		return returnList; //return the list
	}
	
	//returns the list of wrapper objects
	public List<timeEntry> getTimeEntries() {
		return timeEntries; //return the list
	}
	
	//returns the total of all hours
	public Decimal getTotalHours() {
		return totalHours; //return total hours
	}
	
	//wrapper for Time Card records with Date
	public class timeEntry {
		public Date day {get; set;} //Date
		public String allocationDetails {get; set;} //placeholder for your custom time entry record details
		
		//constructor
		public timeEntry(Date d, String t) {
			this.day = d;
			this.allocationDetails = t;
		}
	}

}

Next is the Visualforce page:

<apex:page controller="monthlyTime">
<!--
	Created by: Greg Hacic
	Last Update: 2 February 2017 by Greg Hacic
	Questions?: greg@interactiveties.com
-->
<apex:pageMessages></apex:pageMessages>
<table>
	<tr>
		<th>Date</th>
		<th>Hours</th>
		<th>Description</th>
		<th>Purpose</th>
		<th>Employee</th>
	</tr>
	<apex:repeat id="timecarddetails" value="{!timeEntries}" var="t">
		<tr>
			<td><c:localeFormattedDate dateProvided="{!t.day}"></c:localeFormattedDate></td>
			<td colspan="4">{!t.allocationDetails}</td>
		</tr>
	</apex:repeat>
	<tr>
		<th colspan="2">Total Hours</th>
		<th>{!totalHours}</th>
		<th colspan="2"></th>
	</tr>
</table>
</apex:page>