Crear un Tablero de Datos por Rango de Fechas, por Este Mes, Hoy, Últimos 7 Días, Últimos 30 Días o una Fecha Personalizada, utilizando lenguaje de programación C#, base de datos SQL Server, Windows Forms y Programación Orientada a Objetos (POO).
Base de datos

Descarga del script completo de la base de datos en el siguiente botón:
Clase Conexión a SQL
public abstract class DbConnection { private readonly string connectionString; public DbConnection() { connectionString = "Server=(local); DataBase=NorthwindStore; Integrated Security=true"; } protected SqlConnection GetConnection() { return new SqlConnection(connectionString); } }
Clase Modelo Dashboard
public struct RevenueByDate { public string Date { get; set; } public decimal TotalAmount { get; set; } } public class Dashboard : DbConnection { //Fields & Properties private DateTime startDate; private DateTime endDate; private int numberDays; public int NumCustomers { get; private set; } public int NumSuppliers { get; private set; } public int NumProducts { get; private set; } public List<KeyValuePair<string, int>> TopProductsList { get; private set; } public List<KeyValuePair<string, int>> UnderstockList { get; private set; } public List<RevenueByDate> GrossRevenueList { get; private set; } public int NumOrders { get; set; } public decimal TotalRevenue { get; set; } public decimal TotalProfit { get; set; } //Constructor public Dashboard() { } //Private methods private void GetNumberItems() { using (var connection = GetConnection()) { connection.Open(); using (var command = new SqlCommand()) { command.Connection = connection; //Get Total Number of Customers command.CommandText = "select count(id) from Customer"; NumCustomers = (int)command.ExecuteScalar(); //Get Total Number of Suppliers command.CommandText = "select count(id) from Supplier"; NumSuppliers = (int)command.ExecuteScalar(); //Get Total Number of Products command.CommandText = "select count(id) from Product"; NumProducts = (int)command.ExecuteScalar(); //Get Total Number of Orders command.CommandText = @"select count(id) from [Order]" + "where OrderDate between @fromDate and @toDate"; command.Parameters.Add("@fromDate", System.Data.SqlDbType.DateTime).Value = startDate; command.Parameters.Add("@toDate", System.Data.SqlDbType.DateTime).Value = endDate; NumOrders = (int)command.ExecuteScalar(); } } } private void GetProductAnalisys() { TopProductsList = new List<KeyValuePair<string, int>>(); UnderstockList = new List<KeyValuePair<string, int>>(); using (var connection = GetConnection()) { connection.Open(); using (var command = new SqlCommand()) { SqlDataReader reader; command.Connection = connection; //Get Top 5 products command.CommandText = @"select top 5 P.ProductName, sum(OrderItem.Quantity) as Q from OrderItem inner join Product P on P.Id = OrderItem.ProductId inner join [Order] O on O.Id = OrderItem.OrderId where OrderDate between @fromDate and @toDate group by P.ProductName order by Q desc "; command.Parameters.Add("@fromDate", System.Data.SqlDbType.DateTime).Value = startDate; command.Parameters.Add("@toDate", System.Data.SqlDbType.DateTime).Value = endDate; reader = command.ExecuteReader(); while (reader.Read()) { TopProductsList.Add( new KeyValuePair<string, int>(reader[0].ToString(), (int)reader[1])); } reader.Close(); //Get Understock command.CommandText = @"select ProductName, Stock from Product where Stock <= 6 and IsDiscontinued = 0"; reader = command.ExecuteReader(); while (reader.Read()) { UnderstockList.Add( new KeyValuePair<string, int>(reader[0].ToString(), (int)reader[1])); } reader.Close(); } } } private void GetOrderAnalisys() { GrossRevenueList = new List<RevenueByDate>(); TotalProfit = 0; TotalRevenue = 0; using (var connection = GetConnection()) { connection.Open(); using (var command = new SqlCommand()) { command.Connection = connection; command.CommandText = @"select OrderDate, sum(TotalAmount) from[Order] where OrderDate between @fromDate and @toDate group by OrderDate"; command.Parameters.Add("@fromDate", System.Data.SqlDbType.DateTime).Value = startDate; command.Parameters.Add("@toDate", System.Data.SqlDbType.DateTime).Value = endDate; var reader = command.ExecuteReader(); var resultTable = new List<KeyValuePair<DateTime, decimal>>(); while (reader.Read()) { resultTable.Add( new KeyValuePair<DateTime, decimal>((DateTime)reader[0], (decimal)reader[1]) ); TotalRevenue += (decimal)reader[1]; } TotalProfit = TotalRevenue * 0.2m;//20% reader.Close(); //Group by Hours if (numberDays <= 1) { GrossRevenueList = (from orderList in resultTable group orderList by orderList.Key.ToString("hh tt") into order select new RevenueByDate { Date = order.Key, TotalAmount = order.Sum(amount => amount.Value) }).ToList(); } //Group by Days else if (numberDays <= 30) { GrossRevenueList = (from orderList in resultTable group orderList by orderList.Key.ToString("dd MMM") into order select new RevenueByDate { Date = order.Key, TotalAmount = order.Sum(amount => amount.Value) }).ToList(); } //Group by Weeks else if (numberDays <= 92) { GrossRevenueList = (from orderList in resultTable group orderList by CultureInfo.CurrentCulture.Calendar.GetWeekOfYear( orderList.Key, CalendarWeekRule.FirstDay, DayOfWeek.Monday) into order select new RevenueByDate { Date = "Week " + order.Key.ToString(), TotalAmount = order.Sum(amount => amount.Value) }).ToList(); } //Group by Months else if (numberDays <= (365 * 2)) { bool isYear = numberDays <= 365 ? true : false; GrossRevenueList = (from orderList in resultTable group orderList by orderList.Key.ToString("MMM yyyy") into order select new RevenueByDate { Date = isYear ? order.Key.Substring(0, order.Key.IndexOf(" ")) : order.Key, TotalAmount = order.Sum(amount => amount.Value) }).ToList(); } //Group by Years else { GrossRevenueList = (from orderList in resultTable group orderList by orderList.Key.ToString("yyyy") into order select new RevenueByDate { Date = order.Key, TotalAmount = order.Sum(amount => amount.Value) }).ToList(); } } } } //Public methods public bool LoadData(DateTime startDate, DateTime endDate) { endDate = new DateTime(endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, 59); if (startDate != this.startDate || endDate != this.endDate) { this.startDate = startDate; this.endDate = endDate; this.numberDays = (endDate - startDate).Days; GetNumberItems(); GetProductAnalisys(); GetOrderAnalisys(); Console.WriteLine("Refreshed data: {0} - {1}", startDate.ToString(), endDate.ToString()); return true; } else { Console.WriteLine("Data not refreshed, same query: {0} - {1}", startDate.ToString(), endDate.ToString()); return false; } } }
Diseño del Formulario

Código del Formulario
public partial class Form1 : Form { //Fields private Dashboard model; //Constructor public Form1() { InitializeComponent(); //Default - Last 7 days dtpStartDate.Value = DateTime.Today.AddDays(-7); dtpEndDate.Value = DateTime.Now; btnLast7Days.Select(); model = new Dashboard(); LoadData(); } //Private methods private void LoadData() { var refreshData = model.LoadData(dtpStartDate.Value, dtpEndDate.Value); if (refreshData == true) { lblNumOrders.Text = model.NumOrders.ToString(); lblTotalRevenue.Text = "$" + model.TotalRevenue.ToString(); lblTotalProfit.Text = "$" + model.TotalProfit.ToString(); lblNumCustomers.Text = model.NumCustomers.ToString(); lblNumSuppliers.Text = model.NumSuppliers.ToString(); lblNumProducts.Text = model.NumProducts.ToString(); chartGrossRevenue.DataSource = model.GrossRevenueList; chartGrossRevenue.Series[0].XValueMember = "Date"; chartGrossRevenue.Series[0].YValueMembers = "TotalAmount"; chartGrossRevenue.DataBind(); chartTopProducts.DataSource = model.TopProductsList; chartTopProducts.Series[0].XValueMember = "Key"; chartTopProducts.Series[0].YValueMembers = "Value"; chartTopProducts.DataBind(); dgvUnderstock.DataSource = model.UnderstockList; dgvUnderstock.Columns[0].HeaderText = "Item"; dgvUnderstock.Columns[1].HeaderText = "Units"; Console.WriteLine("Loaded view :)"); } else Console.WriteLine("View not loaded, same query"); } private void DisableCustomDates() { dtpStartDate.Enabled = false; dtpEndDate.Enabled = false; btnOkCustomDate.Visible = false; } //Event methods private void btnToday_Click(object sender, EventArgs e) { dtpStartDate.Value = DateTime.Today; dtpEndDate.Value = DateTime.Now; LoadData(); DisableCustomDates(); } private void btnLast7Days_Click(object sender, EventArgs e) { dtpStartDate.Value = DateTime.Today.AddDays(-7); dtpEndDate.Value = DateTime.Now; LoadData(); DisableCustomDates(); } private void btnLast30Days_Click(object sender, EventArgs e) { dtpStartDate.Value = DateTime.Today.AddDays(-30); dtpEndDate.Value = DateTime.Now; LoadData(); DisableCustomDates(); } private void btnThisMonth_Click(object sender, EventArgs e) { dtpStartDate.Value = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); dtpEndDate.Value = DateTime.Now; LoadData(); DisableCustomDates(); } private void btnCustomDate_Click(object sender, EventArgs e) { dtpStartDate.Enabled = true; dtpEndDate.Enabled = true; btnOkCustomDate.Visible = true; } private void btnOkCustomDate_Click(object sender, EventArgs e) { LoadData(); } }
Descargas
Video Tutorial – Parte 1
Inglés
Español
Video Tutorial – Parte 2/ Personalización
Inglés
Español
No disponible