Sample Project

The sample project includes:

License

Licensed for testing and evaluation purposes. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for ASP.NET WebForms.

ASP.NET Core Timesheet

There is a new version of this tutorial available: ASP.NET Core Timesheet (.NET, SQL Server, Entity Framework)

asp.net core timesheet

Features

  • Monthly time sheet

  • Filtering by employee

  • Drag and drop editing

  • Daily summary

Requirements

  • .NET Framework 4.0+

  • Visual Studio

  • SQL Server 2014+

Initial Setup

Create a new ASP.NET WebForms project and add DayPilot.dll from the trial package to the Bin directory.

Monthly Timesheet View

timesheet asp.net days

Add a new ASP.NET scheduler control to the WebForms page. The Scheduler is designed to display calendar for multiple resources side-by-side (one resource per row) but it also supports Days mode (24 hours per row). This mode allows you to create the timesheet.

Switch the Scheduler Days mode using ViewType="Days":

<DayPilot:DayPilotScheduler
    ID="DayPilotScheduler1" 
    runat="server" 
    ...
    ViewType="Days"
>
</DayPilot:DayPilotScheduler>

In the code behind, we will configure the Scheduler to display a time sheet for the current month (StartDate and Days properties).

C#

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
      // ...
      DayPilotScheduler1.StartDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
      DayPilotScheduler1.Days = DateTime.DaysInMonth(DateTime.Today.Year, DateTime.Today.Month);
      DayPilotScheduler1.DataSource = new DataManager().GetRecords(employee);
      DayPilotScheduler1.DataBind();
    }
}

VB.NET

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
  If Not IsPostBack Then
    ' ...
    DayPilotScheduler1.StartDate = New Date(Date.Today.Year, Date.Today.Month, 1)
    DayPilotScheduler1.Days = Date.DaysInMonth(Date.Today.Year, Date.Today.Month)
    DayPilotScheduler1.DataSource = (New DataManager()).GetRecords(employee)
    DayPilotScheduler1.DataBind()
  End If
End Sub

Timesheet Properties

Now we can set the timesheet properties:

  • One cell will represent 15 minutes (CellDuration="15")

  • The header cells will be grouped by hour (CellGroupBy="Hour")

  • The cell width will be 25 pixels (CellWidth="25")

<DayPilot:DayPilotScheduler
  ID="DayPilotScheduler1" 
  runat="server" 
  ViewType="Days"
  ...
  CellDuration="15"
  CellGroupBy="Hour"
  CellWidth="25" 
/>

Apply a CSS Theme

timesheet asp.net css theme

Apply the Green theme to the timesheet using the Theme property.

You can also design your own theme using the online WYSIWYG theme designer.

<DayPilot:DayPilotScheduler
  ID="DayPilotScheduler1" 
  runat="server" 
  ViewType="Days"
  CellDuration="15"
  CellGroupBy="Hour"
  CellWidth="25" 
  ...
  Theme="scheduler_green"
/>

ASP.NET Timesheet Business Hours

timesheet asp.net business hours

The timesheet uses a different color for business and non-business hours.

By default, the business hours are set to start at 9 am and end at 5 pm. You can use your own hours (use BusinessBeginsHour and BusinessEndsHour properties).

<DayPilot:DayPilotScheduler
    ID="DayPilotScheduler1" 
    runat="server" 

    BusinessBeginsHour="9"
    BusinessEndsHour="18"
>
</DayPilot:DayPilotScheduler>

You can se set custom cell background color using BeforeCellRender event handler.

C#

protected void DayPilotScheduler1_BeforeCellRender(object sender, BeforeCellRenderEventArgs e)
{
    if (!e.IsBusiness)
    {
        e.BackgroundColor = "#e3e3e3";
    }
}

VB.NET

Protected Sub DayPilotScheduler1_BeforeCellRender(ByVal sender As Object, ByVal e As BeforeCellRenderEventArgs)
  If Not e.IsBusiness Then
    e.BackgroundColor = "#e3e3e3"
  End If
End Sub

Timesheet Daily Totals

timesheet asp.net daily totals

Create additional row header columns that will display daily timesheet totals.

<HeaderColumns>
  <DayPilot:RowHeaderColumn Title="Date" Width="100" />
  <DayPilot:RowHeaderColumn Title="Day" Width="100" />
  <DayPilot:RowHeaderColumn Title="Total" Width="100" />
</HeaderColumns>

You can set column values for each day using BeforeResHeaderRender event handler.

C#

protected void DayPilotScheduler1_OnBeforeResHeaderRender(object sender, BeforeResHeaderRenderEventArgs e)
{
    e.Columns[0].Html = e.Date.ToString("dddd");

    TimeSpan total = new DataManager().GetTotalMinutesForDay(e.Date);

    if (total > TimeSpan.Zero)
    {
        e.Columns[1].Html = total.ToString("hh\\:mm");
    }
}

VB.NET

Protected Sub DayPilotScheduler1_OnBeforeResHeaderRender(ByVal sender As Object, ByVal e As BeforeResHeaderRenderEventArgs)
  e.Columns(0).Html = e.Date.ToString("dddd")

  Dim eid As String = CStr(If(DayPilotScheduler1.ClientState("employee"), DropDownListEmployee.SelectedValue))
  Dim employee As Integer = Convert.ToInt32(eid)

  Dim total As TimeSpan = (New DataManager()).GetTotalMinutesForDay(e.Date, employee)

  If total > TimeSpan.Zero Then
    e.Columns(1).Html = total.ToString("hh\:mm")
  End If
End Sub

Filtering Timesheet Data by Employee

timesheet asp.net employee

Add a DropDownList with a list of employees.

<div class="space">
  Employee: 

  <asp:DropDownList 
    runat="server" 
    ID="DropDownListEmployee" 
    ClientIDMode="Static" 
    DataTextField="EmployeeName" 
    DataValueField="EmployeeId" />
</div>

Store the selected drop down list value in the clientState property using jQuery. The clientState property will be persisted until page reload. It will be accessible on the server side using ClientState property. We will use it to filter the data source to display the timesheet for a specific employee.

To request a refresh of the timesheet control, use the commandCallBack() JavaScript method.

<script type="text/javascript">
    $(document).ready(function () {
        dp.clientState.employee = $("#<%= DropDownListEmployee.ClientID %>").val();
        $("#<%= DropDownListEmployee.ClientID %>").change(function () {
            dp.clientState.employee = this.value;
            dp.commandCallBack("refresh");
        });
    });
</script>

On the server side, handle the Command event and reload the timesheet records.

C#

protected void DayPilotCalendar1_Command(object sender, CommandEventArgs e)
{
  switch (e.Command)
  {
    case "refresh":
        UpdateScheduler();
        DayPilotScheduler1.Update(CallBackUpdateType.Full);
        break;
  }
}

VB.NET

Protected Sub DayPilotCalendar1_Command(ByVal sender As Object, ByVal e As CommandEventArgs)
  Select Case e.Command
    Case "refresh"
      UpdateScheduler()
      DayPilotScheduler1.Update(CallBackUpdateType.Full)
  End Select
End Sub

Read the selected filter value using ClientState property in the UpdateScheduler() method.

If the ClientState["employee"] value is not available read the current DropDownList selection.

C#

private void UpdateScheduler()
{
  string eid = (string) (DayPilotScheduler1.ClientState["employee"] ?? DropDownListEmployee.SelectedValue);
  int employee = Convert.ToInt32(eid);

  DayPilotScheduler1.StartDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
  DayPilotScheduler1.Days = DateTime.DaysInMonth(DateTime.Today.Year, DateTime.Today.Month);
  DayPilotScheduler1.DataSource = new DataManager().GetRecords(employee);
  DayPilotScheduler1.DataBind();
  DayPilotScheduler1.Update();
}

VB.NET

Private Sub UpdateScheduler()
  Dim eid As String = CStr(If(DayPilotScheduler1.ClientState("employee"), DropDownListEmployee.SelectedValue))
  Dim employee As Integer = Convert.ToInt32(eid)

  DayPilotScheduler1.StartDate = New Date(Date.Today.Year, Date.Today.Month, 1)
  DayPilotScheduler1.Days = Date.DaysInMonth(Date.Today.Year, Date.Today.Month)
  DayPilotScheduler1.DataSource = (New DataManager()).GetRecords(employee)
  DayPilotScheduler1.DataBind()
  DayPilotScheduler1.Update()
End Sub

Timesheet Database Schema (SQL Server)

timesheet asp.net sql schema

Here is the Microsoft SQL Server database schema used by the sample project:

[Timesheet] Table

CREATE TABLE [Timesheet](
	[TimesheetId] [int] IDENTITY(1,1) NOT NULL,
	[TimesheetIn] [datetime] NULL,
	[TimesheetOut] [datetime] NULL,
	[EmployeeId] [int] NOT NULL
)

[Employee] Table

CREATE TABLE [Employee](
	[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
	[EmployeeName] [nvarchar](100) NOT NULL
)