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>