Introducción
Hola a todos, ahora veremos cómo crear reportes en una arquitectura en capas con Windows Forms, C#, VB.NET, SQL Server, SSRS (SQL Server Reporting Services – RDLC – Report Viewer) y Full Programación Orientada a Objetos.
En esta ocasión crearemos un reporte de ventas por rango de fechas y periodos, divididos en dos partes: un resumen general y las ventas a detalle, por ejemplo, las ventas de la fecha actual, los últimos 7 días, del mes actual, los últimos 30 días, del año actual o cualquier fecha personalizada. Ademas de agrupar las ventas netas por periodos, es decir, agrupar por días, semanas, meses o años, dependiendo al rango de fechas del reporte. Por otro lado las funciones de búsqueda de datos y exportar a PDF, Excel, Word o poder imprimir el reporte.
Observaciones
Reportes y Arquitectura en Capas
Ya mencioné en varios vídeos y artículos: La arquitectura en capas generalmente se divide en tres capas de aplicación y está destinada para aplicaciones complejas, puedes utilizar cualquier otra arquitectura según necesidades y complejidad de la aplicación, por ejemplo, si la aplicación es pequeña y con poca lógica de negocio bastará utilizar la arquitectura MVC, MVP, o uno personalizado. Solo recuerda en separar responsabilidades agrupar clases o componentes y organizar el código para obtener una buena estructura.
En este caso usaremos la arquitectura en capas ya que es la estructura más popular entre los programadores, bien recuerden que:
- La capa de presentación solamente es responsable de manejar la interfaz gráfica de usuario como vistas renderizadas , archivos HTML, la interfaz de línea de comandos o los formularios de una aplicación de escritorio.
- La capa de dominio o negocio es responsable de las reglas comerciales y el flujo de trabajo, que determina como se puede crear, validar, realizar cálculos, almacenar y cambiar los datos de un objeto comercial.
- La capa de acceso a datos es responsable de almacenar u obtener datos desde un almacén de datos, como una base de datos, un servicio externo o un archivo plano.

El conjunto de datos, archivo y diseño de los reportes se crean en la capa de presentación (Visor de reportes y los archivos de datos del generador de informes). Sin embargo en muchas ocasiones cuando somos principiantes, accedemos a la base de datos y ejecutamos comandos SQL directamente desde los reportes de la capa de presentación, además de colocar algunas reglas comerciales como validaciones, cálculos complejos u otras actividades relacionado a negocios.

Esto es un grave error, estamos en contra de los principios de la arquitectura en capas y la programación orientada a objetos.
Acceder a la base de datos y ejecutar comandos SQL es responsabilidad de la capa de acceso a datos, y realizar cálculos o validaciones es responsabilidad de la capa de dominio, en cuanto al conjunto de datos, archivo y diseño de los reportes es responsabilidad de la capa de presentación . Del mismo modo si utilizas la arquitectura MVC, el modelo es quien se encarga de gestionar todos los datos e implementar las reglas del negocio.

Si bien es cierto que cualquier generador de reportes permite acceder a la base de datos y realizar validaciones y cálculos, entonces puedes usarlos con fines de prueba práctica o aplicaciones muy simples que trabajan a una sola capa.
Por otro lado, tener en cuenta que las imágenes mostradas de la arquitectura en capas es una representación gráfica muy superficial. En una aplicación muy compleja con muchas reglas de negocio, cada capa puede tener muchos componentes o sub-capas, además de agregar otras capas con sus propias responsabilidades, por ejemplo, la capa de aplicación, la capa de infraestructura, en ella la capa de soporte, acceso a datos, servicios externos o servicios de correo electrónico.

Recuerden que la estructura de las capas puede cambiar según necesidades y complejidad de la aplicación, en donde cada capa puede tener su propia arquitectura, cada componente puede tener su propio micro-arquitectura o cada clase o conjunto de clases puede tener su propia estructura, por ejemplo, puedes estructurar la capa de presentación utilizando el patrón modelo vista controlador (MVC) y si es una aplicación de escritorio, puedes usar el patrón modelo vista presentador (MVP). Pero a menudo, las aplicaciones que realizamos con fines de práctica o formación, son pequeñas, con poca lógica de negocio, entonces bastará utilizar únicamente estas tres capas, sin ningún componente, sub-capa o capas adicionales.
Tutorial
Bueno, espero que la introducción haya aclarado algunas cosas sobre crear reportes con un arquitectura en capas, ahora empecemos a crear la base de datos y aplicación.
Base de Datos
Tenemos 4 tablas relacionadas de una orden de venta y los miles y miles de inserciones de datos. Puedes descargar desde el botón de abajo el script completo de la base de datos y así puedas y realizar la práctica.
Crear Base de Datos Relacional (BDR)
Diagrama

Script
create database BikeStore create table products ( product_id int identity (1,1) primary key, product_name varchar (200) NOT NULL, model_year smallint NOT NULL, price decimal (10, 2) NOT NULL ); CREATE TABLE customers ( customer_id INT IDENTITY (1, 1) PRIMARY KEY, first_name VARCHAR (255) NOT NULL, last_name VARCHAR (255) NOT NULL, phone VARCHAR (25), email VARCHAR (255) NOT NULL, street VARCHAR (255), city VARCHAR (50), state VARCHAR (25), zip_code VARCHAR (5) ); create table orders ( order_id int identity (1,1) primary key, customer_id int not null, order_date date not null, constraint FK_Customer foreign key (customer_id) references customers(customer_id) ); create table order_items ( order_item_id int identity (1,1) primary key, order_id int not null, product_id INT NOT NULL, quantity INT NOT NULL, price DECIMAL (10, 2) NOT NULL, discount DECIMAL (4, 2) NOT NULL DEFAULT 0, constraint fk_Order foreign key (order_id) references orders(order_id), constraint fk_Product foreign key (product_id) references products(product_id) );
Consulta SQL/Procedimiento – Reporte de Ventas Detallada por Rango de Fechas
Para realizar reportes, es simplemente hacer consultas a la base de datos, por ejemplo, un reporte de listado y stock de productos, reporte de productos que sean del modelo 2019, un reporte de clientes o un reporte general de ventas.
En este caso, en una única consulta , mostraremos un reporte de ventas a todo detalle, es decir, el ID de la venta, la fecha, el cliente, el nombre del producto, la cantidad del producto vendido y el monto total de la venta en un rango de fechas. Además de esta única consulta; desde la capa de dominio de la aplicación, agruparemos las ventas netas totales por períodos, ya sea por días, semanas, meses o años, dependiendo del rango de fecha.
Si deseas puedes crear un procedimiento almacenado para mostrar la consulta ( ver pestaña 2) e invocar el procedimiento desde la capa de acceso a datos de la aplicación.
select o.order_id,
o.order_date,
c.first_name+', '+c.last_name as customer,
products=stuff((select ' - ' +'x'+convert(varchar (10),oi2.quantity)+' '+ product_name
from order_items oi2
inner join products on products.product_id= oi2.product_id
where oi2.order_id = oi1.order_id
for xml path('')), 1, 2, ''),
sum((quantity*price)-discount) as total_amount
from orders o
inner join customers c on c.customer_id=o.customer_id
inner join order_items oi1 on oi1.order_id =o.order_id
where o.order_date between '2017/01/01' and '2017/12/30'
group by o.order_id, oi1.order_id, o.order_date, c.first_name, c.last_name
order by o.order_id asccreate proc getSalesOrder
@fromDate Date,
@toDate Date
as
select o.order_id,
o.order_date,
c.first_name+', '+c.last_name as customer,
products=stuff((select ' - ' +'x'+convert(varchar (10),oi2.quantity)+' '+ product_name
from order_items oi2
inner join products on products.product_id= oi2.product_id
where oi2.order_id = oi1.order_id
for xml path('')), 1, 2, ''),
sum((quantity*price)-discount) as total_amount
from orders o
inner join customers c on c.customer_id=o.customer_id
inner join order_items oi1 on oi1.order_id =o.order_id
where o.order_date between @fromDate and @toDate
group by o.order_id, oi1.order_id, o.order_date, c.first_name, c.last_name
order by o.order_id asc
goAplicación
Una vez creado la base de datos, crear las 4 tablas relacionadas, insertar los registros de la orden de venta, haber probado la consulta anterior para obtener las ventas a detalle o haber creado el procedimiento almacenado, pasemos a estructurar la aplicación.
Crear Proyecto en Capas – Visual Studio
- Creamos una solución en blanco de Visual Studio (Archivo-> Nuevo-> Proyecto-> Plantillas-> Otros tipos de proyectos -> Soluciones de Visual Studio-> Solución en Blanco) y asígnele el nombre que desee.
- Agregamos un proyecto nuevo de tipo Aplicación de Windows Forms para la Capa de Presentación.
- Agregamos un proyecto nuevo de tipo Biblioteca de Clases para la Capa de Dominio o Negocio.
- Agregamos un proyecto nuevo de tipo Biblioteca de Clases para la Capa de Acceso a Datos o Persistencia.

Agregar referencias entre capas (Dependecias)
- Agregamos las referencias entre capas según la arquitectura tradicional en capas, donde una capa superior sólo conoce la capa inmediatamente debajo de ella.
- En Capa de Presentación: Referenciamos a la Capa de Dominio.
- En Capa de Dominio: Referenciamos a la Capa de Acceso a Datos.

Una vez creado y agregar las referencias entre capas, pasemos a codificar las capas.
Capa de acceso a Datos
Clase Conexión (ConnectionSql.cs/vb)
- Agreguemos una clase abstracta para la conexión a SQL Server.
- Importamos la librería System.Data.SqlClient.
- Creamos un método protegido de tipo SqlConnection para obtener la conexión.
- En el método creado, simplemente retornamos una instancia de conexión a sql, como parámetro, enviamos la cadena de conexión, servidor local, indicamos la base de datos, y nos conectamos mediante las credenciales de Windows.
public abstract class ConnectionSql
{
protected SqlConnection getConnection()
{
return new SqlConnection(
"Server=(local); DataBase=BikeStore; integrated security=true"
);
}
}Public MustInherit Class ConnectionSql
Protected Function getConnection() As SqlConnection
Return New SqlConnection(
"Server=(local); DataBase=BikeStore; integrated security=true")
End Function
End ClassClase Objeto de Acceso a Datos Orden (OrderDao.cs)
- Agregamos otra clase publica para el objeto de acceso a datos de la entidad órdenes de venta.
- Indicamos que la clase hereda de la clase conexión a SQL.
- Importamos las librería System.Data y System.DataSqlClient.
- Creamos un método de tipo DataTable o List<Object> para obtener las órdenes de venta por rango de fecha, para ello creamos 2 parámetros,una para la fecha de inicio y la otra para fecha final de la consulta.
- Agregamos lo siguiente códigos para realizar la consulta.
public class OrderDao:ConnectionSql
{
public DataTable getSalesOrder(DateTime fromDate, DateTime toDate)
{
using (var connection = getConnection())
{
connection.Open();
using (var command = new SqlCommand())
{
command.Connection = connection;
command.CommandText = @"getSalesOrder";
command.Parameters.AddWithValue("@fromDate", fromDate );
command.Parameters.AddWithValue("@toDate", toDate );
command.CommandType = CommandType.StoredProcedure;
var reader = command.ExecuteReader();
var table = new DataTable();
table.Load(reader );
reader.Dispose();
return table;
}
}
}
} public DataTable getSalesOrder(DateTime fromDate, DateTime toDate)
{
using (var connection = getConnection())
{
connection.Open();
using (var command = new SqlCommand())
{
command.Connection = connection;
command.CommandText = @"select o.order_id,
o.order_date,
c.first_name+', '+c.last_name as customer,
products=stuff((select ' , ' +'x'+convert(varchar (10),oi2.quantity)+' '+ product_name
from order_items oi2
inner join products on products.product_id= oi2.product_id
where oi2.order_id = oi1.order_id
for xml path('')), 1, 2, ''),
sum((quantity*price)-discount) as total_amount
from orders o
inner join customers c on c.customer_id=o.customer_id
inner join order_items oi1 on oi1.order_id =o.order_id
where o.order_date between @fromDate and @toDate
group by o.order_id, oi1.order_id, o.order_date, c.first_name, c.last_name
order by o.order_id asc";
command.CommandType = CommandType.Text;
command.Parameters.Add("@fromDate", SqlDbType.Date).Value=fromDate;
command.Parameters.Add("@toDate", SqlDbType.Date).Value = toDate;
SqlDataReader reader = command.ExecuteReader();
var table = new DataTable();
table.Load(reader);
reader.Dispose();
return table;
}
}
}
}
Public Class OrderDao
Inherits ConnectionSql
Public Function getSalesOrder(fromDate As DateTime, toDate As DateTime) As DataTable
Using connection = getConnection()
connection.Open()
Using command = New SqlCommand()
command.Connection = connection
command.CommandText = "getSalesOrder"
command.Parameters.AddWithValue("@fromDate", fromDate)
command.Parameters.AddWithValue("@toDate", toDate)
command.CommandType = CommandType.StoredProcedure
Dim reader = command.ExecuteReader()
Dim table = New DataTable()
table.Load(reader)
reader.Dispose()
Return table
End Using
End Using
End Function
End ClassPublic Function getSalesOrder(fromDate As DateTime, toDate As DateTime) As DataTable
Using connection = getConnection()
connection.Open()
Using command = New SqlCommand()
command.Connection = connection
command.CommandText = "select o.order_id,
o.order_date,
c.first_name+', '+c.last_name as customer,
products=stuff((select ' , ' +'x'+convert(varchar (10),oi2.quantity)+' '+ product_name
from order_items oi2
inner join products on products.product_id= oi2.product_id
where oi2.order_id = oi1.order_id
for xml path('')), 1, 2, ''),
sum((quantity*price)-discount) as total_amount
from orders o
inner join customers c on c.customer_id=o.customer_id
inner join order_items oi1 on oi1.order_id =o.order_id
where o.order_date between @fromDate and @toDate
group by o.order_id, oi1.order_id, o.order_date, c.first_name, c.last_name
order by o.order_id asc"
command.CommandType = CommandType.Text
command.Parameters.Add("@fromDate", SqlDbType.Date).Value = fromDate
command.Parameters.Add("@toDate", SqlDbType.Date).Value = toDate
Dim reader As SqlDataReader = command.ExecuteReader()
Dim table = New DataTable()
table.Load(reader)
reader.Dispose()
Return table
End Using
End Using
End FunctionCapa de Dominio – Negocio
Ahora codificaremos la capa de dominio o negocio, agregamos las siguientes clases/Objetos para guardar el listado de ventas a detalle y para agrupar las ventas netas por periodo.
Clase Listado de Ventas (SalesListing.cs)
public class SalesListing
{
public int orderId { get; set; }
public DateTime orderDate { get; set; }
public string customer { get; set; }
public string products { get; set; }
public double totalAmount { get; set; }
}Public Class SalesListing
Public Property orderId As Integer
Public Property orderDate As DateTime
Public Property customer As String
Public Property products As String
Public Property totalAmount As Double
End ClassClase Ventas Netas Por Periodo (NetSalesByPeriod.cs)
public class NetSalesByPeriod
{
public string period { get; set; }
public double netSales { get; set; }
}Public Class NetSalesByPeriod
Public Property period As String
Public Property netSales As Double
End Class
Clase Reporte de Ventas (SalesReport.cs)
- Agregamos una clase para el reporte de ventas.
- Importamos la capa de acceso a datos
- Declaramos los atributos y propiedades necesarios para el reporte.
- Declaramos una lista de objetos de tipo listado de ventas para almacenar la consulta de la base de datos.
- Declaramos una lista de objetos de tipo ventas netas por periodo para agrupar las ventas netas por periodo según rango de fechas del reporte.
- Finalmente creamos un método para crear el reporte e inicializar los objetos.
public class SalesReport
{
//Attributes-Properties
public DateTime reportDate { get; private set; }
public DateTime startDate { get; private set; }
public DateTime endDate{ get; private set; }
public List <SalesListing> salesListing { get; private set; }
public List<NetSalesByPeriod> netSalesByPeriod { get; private set; }
public double totalNetSales { get; private set; }
//Methods
public void createSalesOrderReport(DateTime fromDate, DateTime toDate)
{
//implement dates
reportDate = DateTime.Now;
startDate = fromDate;
endDate = toDate;
//create sales listing
var orderDao = new OrderDao();
var result = orderDao.getSalesOrder(fromDate,toDate );
salesListing = new List<SalesListing>();
foreach (System.Data.DataRow rows in result.Rows)
{
var salesModel = new SalesListing()
{
orderId = Convert.ToInt32(rows[0]),
orderDate = Convert.ToDateTime(rows[1]),
customer = Convert.ToString(rows[2]),
products = Convert.ToString(rows[3]),
totalAmount = Convert.ToDouble(rows[4])
};
salesListing.Add(salesModel);
//calculate total net sales
totalNetSales += Convert.ToDouble(rows[4]);
}
//create net sales by period
////create temp list net sales by date
var listSalesByDate = (from sales in salesListing
group sales by sales.orderDate
into listSales
select new
{
date = listSales.Key,
amount = listSales.Sum(item => item.totalAmount)
}).AsEnumerable();
////get number of days
int totalDays = Convert.ToInt32((toDate-fromDate ).Days);
////group period by days
if (totalDays <= 7)
{
netSalesByPeriod = (from sales in listSalesByDate
group sales by sales.date.ToString("dd-MMM-yyyy")
into listSales
select new NetSalesByPeriod
{
period = listSales.Key,
netSales = listSales.Sum(item => item.amount)
}).ToList();
}
////group period by weeks
else if (totalDays <= 30)
{
netSalesByPeriod = (from sales in listSalesByDate
group sales by
System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
sales.date, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday)
into listSales
select new NetSalesByPeriod
{
period = "Week " + listSales.Key.ToString(),
netSales = listSales.Sum(item => item.amount)
}).ToList();
}
////group period by months
else if (totalDays <= 365)
{
netSalesByPeriod = (from sales in listSalesByDate
group sales by sales.date.ToString("MMM-yyyy")
into listSales
select new NetSalesByPeriod
{
period = listSales.Key,
netSales = listSales.Sum(item => item.amount)
}).ToList();
}
////group period by years
else {
netSalesByPeriod = (from sales in listSalesByDate
group sales by sales.date.ToString("yyyy")
into listSales
select new NetSalesByPeriod
{
period = listSales.Key,
netSales = listSales.Sum(item => item.amount)
}).ToList();
}
}
}
Public Class SalesReport
'Attributes-Properties
Public Property reportDate As Date
Public Property startDate As Date
Public Property endDate As Date
Public Property salesListing As List(Of SalesListing)
Public Property netSalesByPeriod As List(Of NetSalesByPeriod)
Public Property totalNetSales As Double
'Methods
Public Sub createSalesOrderReport(fromDate As Date, toDate As Date)
'implement dates
reportDate = Date.Now
startDate = fromDate
endDate = toDate
'create sales listing
Dim orderDao = New OrderDao
Dim result = orderDao.getSalesOrder(fromDate, toDate)
salesListing = New List(Of SalesListing)
For Each row As DataRow In result.Rows
Dim salesModel = New SalesListing With {
.orderId = Convert.ToInt32(row(0)),
.orderDate = Convert.ToDateTime(row(1)),
.customer = Convert.ToString(row(2)),
.products = Convert.ToString(row(3)),
.totalAmount = Convert.ToDouble(row(4))
}
salesListing.Add(salesModel)
'calculate total net sales
totalNetSales += Convert.ToDouble(row(4))
Next
'create net sales by period
'create temp list net sales by date
Dim listSalesByDate = (From sales In salesListing
Group sales By keyDateGroup = sales.orderDate
Into listSales =
Group Select New With {
.date = keyDateGroup,
.amount = listSales.Sum(Function(item) item.totalAmount)
}).AsEnumerable
'////get number of days
Dim totalDays = Convert.ToInt32((toDate - fromDate).Days)
'////group period by days
If totalDays <= 7 Then
netSalesByPeriod = (From sales In listSalesByDate
Group sales By keyDateGroup = sales.date.ToString("dd-MMM-yyyy")
Into listSales =
Group Select New NetSalesByPeriod With {
.period = keyDateGroup,
.netSales = listSales.Sum(Function(item) item.amount)
}).ToList
'////group period by weeks
ElseIf totalDays <= 30 Then
netSalesByPeriod = (From sales In listSalesByDate
Group sales By keyDateGroup =
System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
sales.date, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday)
Into listSales =
Group Select New NetSalesByPeriod With {
.period = "Week " & keyDateGroup.ToString,
.netSales = listSales.Sum(Function(item) item.amount)
}).ToList
'////group period by months
ElseIf totalDays <= 365 Then
netSalesByPeriod = (From sales In listSalesByDate
Group sales By keyDateGroup = sales.date.ToString("MMM-yyyy")
Into listSales =
Group Select New NetSalesByPeriod With {
.period = keyDateGroup,
.netSales = listSales.Sum(Function(item) item.amount)
}).ToList
'////group period by years
Else
netSalesByPeriod = (From sales In listSalesByDate
Group sales By keyDateGroup = sales.date.ToString("yyyy")
Into listSales =
Group Select New NetSalesByPeriod With {
.period = keyDateGroup,
.netSales = listSales.Sum(Function(item) item.amount)
}).ToList
End If
End Sub
End ClassCapa de Presentación
Una vez terminado de codificar la capa de dominio, ahora agregaremos los conjuntos de datos para el reporte, crearemos el archivo de reporte y agregaremos un formulario para inicializar el visor de reporte y crear los botones con un rango de fechas en específicos o personalizado.
Generador de Reportes
Puedes utilizar cualquier generador de reportes, ya sea Crystal Reports, Report Viewer-SSRS, Component One, DevExpress, Jasper Reports o cualquier otro, ya que simplemente lo usaremos como diseñador y visor de reportes, y la capa de dominio ya dispone de todos los datos listos para ser mostrados.


En este caso usaremos el control REPORT VIEWER con modo de procesamiento local (RDLC) perteneciente a SSRS de Microsoft (SQL Server Reporting Services), personalmente prefiero este generador de informes porque es muy flexible, ligero, rápido, gratuito y muy fácil de usar e integrar en tu aplicación de .NET.
Reporting Services con Report Viewer-RDLC
Report Viewer es un control para visual studio, que permite visualizar reportes RDL y RDLC en nuestra aplicación web o de escritorio.
- RDLC (Lenguaje de Definición de Informes del lado del Cliente), se utiliza para crear archivos de «informes locales» en Visual Studio. Estos archivos se retienen localmente y no se almacenan en un servidor SSRS, es decir, se ejecuta en el lado de cliente a partir de un conjunto de datos.
- RDL, son archivos de informes que están diseñados para usarse con SQL Server Reporting Services (SSRS), y se almacenan en el servidor de informes y se ejecutan desde allí.
En este tutorial utilizaremos Reporting Services con modo de procesamiento local (RDLC) y mostraremos el informe mediante el control Report Viewer. A partir de Visual Studio 2015, este control y los servicios de reporte local ya no están integrados en la instalación por defecto de Visual Studio, tienes que instalarlo desde Nuget o Extensiones de Visual Studio.
Archivo de Informes de Ventas (SalesReport.rdlc)
- Agregamos el archivo / diseñador de reportes local RDLC en blanco, si deseas puedes usar el asistente de informes.

- Compilamos la capa de presentación para cargar las referencias.
- Ajustamos el tamaño de pagina del informe (en este caso A4->21cm x 29.7 cm) y el cuerpo del informe (21cm x 15cm, el alto del cuerpo debe ser ajustado a los componentes del informe).
- Agregamos los objetos (clases) Reporte de ventas (salesReport), Listado de Ventas (salesListing) y Ventas netas por periodo (netSalesByPeriod) al conjunto de datos del reporte local.
- Finalmente diseñamos el informe de la siguiente manera y en ello, agregamos los campos a mostrar (Campos de nuestros objetos de reporte).

Diseño de Formulario
- Una vez terminado de diseñar el reporte local, agregamos los botones con fechas especificas para el reporte y 2 controles selector de fecha (DateTimePicker) para el reporte de fechas personalizados.
- Agregamos el control Report Viewer y acoplamos a todo el contenedor.
- En el visor de reporte, elegimos el archivo del reporte a mostrar, en este caso, el reporte de ventas (SalesReport.rdlc)
- Una vez elegido el reporte, en la parte baja se creará los 3 fuentes enlace a datos para los 3 objetos del conjunto de datos del informe.

Código de Formulario
- Importamos la capa de dominio o negocio.
- Creamos el método obtener reporte de ventas (getSalesReport), con 2 parámetros para la fecha de inicio y final del reporte.
- En el método, instanciamos a la clase reporte de venta de la capa de dominio e invocamos el método crear reporte de ordenes de venta.
- Inicializamos la fuente de datos del enlace de datos del visor de reporte (SalesReportBindingSource, SalesListingBindingSource, NetSalesByPeriodBindingSource) con el objeto reporte y sus propiedades (reportModel, reportModel.salesListing, reportModel.netSalesByPeriod).
- Finalmente invocamos el método anterior desde los botones con los respectivos rango de fechas.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void getSalesReport(DateTime startDate, DateTime endDate)
{
SalesReport reportModel = new SalesReport();
reportModel.createSalesOrderReport(startDate, endDate);
SalesReportBindingSource.DataSource = reportModel;
SalesListingBindingSource.DataSource = reportModel.salesListing;
NetSalesByPeriodBindingSource.DataSource = reportModel.netSalesByPeriod;
this.reportViewer1.RefreshReport();
}
private void btnToday_Click(object sender, EventArgs e)
{
var fromDate = DateTime.Today;
var toDate = DateTime.Now;
getSalesReport(fromDate,toDate);
}
private void btnLast7Days_Click(object sender, EventArgs e)
{
var fromDate = DateTime.Today.AddDays(-7);
var toDate = DateTime.Now;
getSalesReport(fromDate, toDate);
}
private void btnThisMonth_Click(object sender, EventArgs e)
{
var fromDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var toDate = DateTime.Now;
getSalesReport(fromDate, toDate);
}
private void btnLast30Days_Click(object sender, EventArgs e)
{
var fromDate = DateTime.Today.AddDays(-30);
var toDate = DateTime.Now;
getSalesReport(fromDate, toDate);
}
private void btnThisYear_Click(object sender, EventArgs e)
{
var fromDate = new DateTime(DateTime.Now.Year, 1, 1);
var toDate = DateTime.Now;
getSalesReport(fromDate, toDate);
}
private void btnApplyCustomDate_Click(object sender, EventArgs e)
{
var fromDate = dateTimePickerFromDate.Value;
var toDate = dateTimePickerToDate.Value;
getSalesReport(fromDate, new DateTime(toDate.Year,toDate.Month, toDate.Day,23,59,59));
}
}
Public Class Form1
Private Sub getSalesReport(ByVal startDate As DateTime, ByVal endDate As DateTime)
Dim reportModel As SalesReport = New SalesReport()
reportModel.createSalesOrderReport(startDate, endDate)
SalesReportBindingSource.DataSource = reportModel
SalesListingBindingSource.DataSource = reportModel.salesListing
NetSalesByPeriodBindingSource.DataSource = reportModel.netSalesByPeriod
Me.ReportViewer1.RefreshReport()
End Sub
Private Sub btnToday_Click(sender As Object, e As EventArgs) Handles btnToday.Click
Dim fromDate = DateTime.Today
Dim toDate = DateTime.Now
getSalesReport(fromDate, toDate)
End Sub
Private Sub btnLast7Days_Click(sender As Object, e As EventArgs) Handles btnLast7Days.Click
Dim fromDate = DateTime.Today.AddDays(-7)
Dim toDate = DateTime.Now
getSalesReport(fromDate, toDate)
End Sub
Private Sub btnThisMonth_Click(sender As Object, e As EventArgs) Handles btnThisMonth.Click
Dim fromDate = New DateTime(DateTime.Now.Year, DateTime.Now.Month, 1)
Dim toDate = DateTime.Now
getSalesReport(fromDate, toDate)
End Sub
Private Sub btnLast30Days_Click(sender As Object, e As EventArgs) Handles btnLast30Days.Click
Dim fromDate = DateTime.Today.AddDays(-30)
Dim toDate = DateTime.Now
getSalesReport(fromDate, toDate)
End Sub
Private Sub btnThisYear_Click(sender As Object, e As EventArgs) Handles btnThisYear.Click
Dim fromDate = New DateTime(DateTime.Now.Year, 1, 1)
Dim toDate = DateTime.Now
getSalesReport(fromDate, toDate)
End Sub
Private Sub btnApplyCustomDate_Click(sender As Object, e As EventArgs) Handles btnApplyCustomDate.Click
Dim fromDate = dateTimePickerFromDate.Value
Dim toDate = dateTimePickerToDate.Value
getSalesReport(fromDate, New DateTime(toDate.Year, toDate.Month, toDate.Day, 23, 59, 59))
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.ReportViewer1.RefreshReport()
End Sub
End ClassY eso es todo 🙂

Los comentarios están cerrados.