ProInf.net

Enviar informes personalizados

Francisco 24-06-08
Símbolo de enviar informes personalizados.

Queremos enviar un informe de Access personalizado para cada remitente. Cada remitente recibirá en su correo electrónico un informe con los datos que le atañen. Para ello crearemos un informe que filtre los datos por el remitente. El informe se ha de ejecutar tantas veces como remitentes haya. Todo este proceso debe ser automático; que se ponga en marcha tan solo pulsando un botón.

Índice

  1. La base de datos con los campos y las tablas utilizados en el ejemplo.
  2. La consulta para el informe con el filtro GetProperty
  3. El informe que usa la consulta
  4. El formulario para gestionar el envío. Botones con llamadas a SetProperty y a EnviarInformesPersonalizados.
  5. El módulo con las tres funciones utilizadas.
  6. Descargar código fuente con la base de datos de ejemplo

1) La base de datos

Tomaremos como ejemplo la base de datos Neptuno y sus tablas Clientes, Pedidos, Detalles y Empleados.

Queremos enviar a cada cliente un informe de todos los pedidos que ha realizado.

Veamos que tablas y campos vamos a utilizar:

clientes pedidos pedidos_detalles empleados
cliente_id
codigo_cliente
cliente
contacto
correo
enviar
pedido_id
cliente_id
empleado_id
fecha_pedido
cargo
pedido_id
precio
cantidad
descuento
empleado_id
nombre
apellidos

En la tabla clientes están los remitentes para enviar los correos. El resto de tablas nos servirá para crear un informe con los pedidos que ha realizado cada cliente

Relaciones entre las tablas

La tabla clientes

Cada cliente puede realizar varios pedidos.

  • El campo cliente_id es la clave principal
  • El campo codigo_cliente es un texto de cinco letras que identifica al cliente
  • El campo cliente es el nombre de la empresa
  • El campo contacto es la persona de contacto en la empresa, nuestro remitente.
  • El campo correo es el correo electrónico de la persona de contacto
  • El campo enviar es un campo sí o no que utilizaremos para indicar que clientes recibirán el informe.

La tabla pedidos

Cada pedido puede tener varias líneas de detalles; una por cada producto que se pida.

  • El campo pedido_id es el número de pedido y la clave principal.
  • El campo fecha_pedido indica la fecha en la que se realizó el pedido.
  • El campo cargo indica el precio del cargo.

La tabla pedidos_detalles

  • El campo precio indica el precio del producto en el pedido
  • El campo cantidad es el número de unidades pedidas de un producto
  • El campo descuento indica un porcentaje de descuento en el precio

Sumando la fórmula precio*cantidad*(1-descuento) podemos averiguar el importe de cada pedido.

La tabla empleados

Cada empleado puede gestionar varios pedidos.

2)La consulta para el informe de pedidos por cliente

Se trata de una consulta de totales donde aparecen todas las tablas que se han descrito. Se trata de agrupar por pedido, sumar el importe de los detalles y de filtrar por el cliente.

Podemos ver una imagen del diseño de la consulta.

Importante: Como queremos crear un informe distinto para cada cliente filtramos por el cliente con la fórmula:

GetProperty("cliente_id")

Esta fórmula obtiene el cliente a filtrar a partir de una propiedad que aún no está definida. De momento este filtro impide que se muestre dato alguno en la consulta. Si borrásemos el filtro aparecerían todos los pedidos.

3) El informe pedidos por cliente

En el informe creamos una representación visual de los datos de la consulta anterior. El informe toma todo sus datos de la consulta. Si la consulta filtra los datos en el informe aparecerán los datos filtrados.

Podemos ver una imagen del diseño del informe y un ejemplo de los pedidos para un determinado cliente.

4) El formulario para enviar el informe de pedidos a cada cliente

Formulario Access de enviar informe de pedidos a cada cliente

En el formulario vemos que el remitente será la pesona de contacto.

El botón "Vista preliminar"

Este botón muestra el informe personalizado para un determinado cliente. El código del botón es el siguiente:

Call SetProperty("cliente_id", Me.cliente_id)
DoCmd.OpenReport "InformePedidosPorCliente", acViewPreview

A traves de la función SetProperty establecemos que cliente queremos filtrar en el informe. Esta función escribe la propiedad que luego leemos mediante GetProperty en la consulta del informe.

El botón "Enviar informes por correo a todos los que están marcados"

La casilla "Marcar para enviar" se utiliza para indicar a que clientes se desea enviar los informes. Esta casilla modifica a sí o a no el campo enviar de la tabla clientes.

El código del botón es el siguiente:

Call EnviarInformesPersonalizados( _
    nombreInforme := "InformePedidosPorCliente", _
    consultaDestinatarios := "SELECT cliente_id, contacto, correo FROM clientes WHERE enviar = TRUE")

De la función EnviarInformesPersonalizados usamos dos parámetros: nombreInforme y consultaDestinatarios. Esta función utiliza internamente la función SetProperty para crear un informe distinto para cada cliente.

El parámetro consultaDestinatarios utiliza una consulta SQL para extraer los datos de los remitentes. En vez de de usar SQL podríamos haber utilizado el nombre de una consulta que realizase el mismo cometido. El orden de los campos de la consulta es importante:

  • El primer campo de la consulta es el campo que usaremos como filtro en la consulta del informe.
  • El segundo campo es el nombre del remitente.
  • El tercer campo es el correo electrónico del remitente.

Además esta consulta extrae los clientes que estaban marcados para enviar filtrando por el campo enviar.

Al pulsar el botón se nos pregunta si queremos revisar uno por uno todos los correos que se van a enviar.

Diálogo de revisar correos

Eso sirve para que que podamos personalizar más en detalle algunos correos. Podemos ver una imagen de ejemplo de los correos a revisar que genera el botón. Si respondemos que no los queremos revisar, entonces los correos se envían inmediatamente. Si respondemos con cancelar se anula la orden.

En la carpeta de Mensajes envíados veremos algo como esto:

5) El módulo de envío de informes personalizados

Hay tres funciones en este módulo:

  • EnviarInformesPersonalizados - Se encarga de ejecutar el informe por cada remitente y de enviarlo por correo electrónico.
  • SetProperty - Guarda una propiedad en la base de datos. Una propiedad es como una variable global. Utilizamos esta función para establecer el filtro en la consulta del informe.
  • GetProperty - Obtiene el valor de una propiedad de la base de datos. Usamos esta función para leer el valor del filtro en la consulta del informe.

Código

Option Explicit
Option Compare Database

Public Function EnviarInformesPersonalizados( _
ByVal nombreInforme As String, _
ByVal consultaDestinatarios As String, _
Optional ByVal correoAsunto As String = "", _
Optional ByVal correoMensaje As String = "", _
Optional ByVal revisarCorreo As Boolean = True _
) As Boolean
'
'Envía un informe personalizado a cada persona
'
'ProInf.net, junio 2008
'GNU General Public License: http://creativecommons.org/licenses/GPL/2.0/deed.es
'
'Parámetros:
' - nombreInforme...........Nombre del informe que se va enviar como archivo adjunto del correo electrónico
' - consultaDestinatarios...Lista de las personas con tres campos
' - Primer campo.....El nombre del campo identificador de la persona tal y como aparece en el informe
' - Segundo campo....Nombre y apellidos
' - Tercer campo.....Dirección de correo electrónico
' - correoAsunto............Título del correo. Sino se indica se crea uno automático
' - correoMensaje...........Texto del cuerpo del correo.
' - revisarCorreo...........Revisa uno a uno los correos antes de enviarlos.
'
'Importante:
' El informe debe incluir el siguiente filtro por el campo identificador del destinatario
' GetProperty("nombreCampo")
'
'Ejemplo:
' Se quiere enviar un informe a cada cliente sobre los pedidos que ha realizado
'
' Call EnviarInformesPersonalizados( _
' nombreInforme := "InformePedidosAnual", _
' consultaDestinatarios := "SELECT cliente_id, contacto, correo FROM clientes")
'
' En el informe habrá un filtro en el campo "cliente_id" así:
' GetProperty("cliente_id")
'

On Error GoTo Errores
Const CANCELED_SENDOBJECT = 2501
Const CAMPO_FILTRO = 0
Const CAMPO_NOMBRE = 1
Const CAMPO_CORREO = 2

Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim nombreFiltro As String
Dim valorFiltro As String
Dim destinatario As String

If revisarCorreo Then
Select Case MsgBox("¿Revisar los correos antes de enviarlos?", vbYesNoCancel + vbQuestion)
Case vbYes: revisarCorreo = True
Case vbNo: revisarCorreo = False
Case vbCancel: Exit Function
End Select
End If

If Trim(correoAsunto) = "" Then
correoAsunto = nombreInforme
End If

Set db = CurrentDb
Set rs = db.OpenRecordset(consultaDestinatarios, dbOpenForwardOnly)
nombreFiltro = rs.Fields(CAMPO_FILTRO).Name

Do Until rs.EOF

destinatario = rs(CAMPO_NOMBRE) & "<" & rs(CAMPO_CORREO) & ">"

valorFiltro = rs(CAMPO_FILTRO)
Call SetProperty(nombreFiltro, valorFiltro)

DoCmd.SendObject ObjectType:=acSendReport, _
ObjectName:=nombreInforme, _
OutputFormat:=acFormatSNP, _
To:=destinatario, _
Subject:=correoAsunto, _
MessageText:=correoMensaje, _
EditMessage:=revisarCorreo

rs.MoveNext
Loop

Salida:
On Error Resume Next
rs.Close: Set rs = Nothing
db.Close: Set db = Nothing
Exit Function
Errores:
If Err.Number = CANCELED_SENDOBJECT Then
Resume Next
Else
MsgBox Err.Description, vbExclamation, "Error nº" & Err.Number & " en la función EnviarInformesPersonalizados "
Resume Salida
End If
End Function

Function SetProperty(ByVal nombrePropiedad As String, ByVal valor As Variant)
On Error GoTo Errores
Const PROPERTY_NOT_FOUND = 3270
Dim db As DAO.Database
Dim p As DAO.Property

Set db = CurrentDb
db.Properties(nombrePropiedad) = valor
db.Properties.Refresh
Salida:
On Error Resume Next
db.Close: Set db = Nothing
Exit Function
Errores:
If Err.Number = PROPERTY_NOT_FOUND Then
Set p = db.CreateProperty(nombrePropiedad, dbText, valor)
db.Properties.Append p
Else
MsgBox Err.Description, vbExclamation, "Error nº" & Err.Number & " en la función SetProperty"
End If
Resume Salida
End Function

Function GetProperty(ByVal nombrePropiedad As String) As Variant
On Error GoTo Errores
Const PROPERTY_NOT_FOUND = 3270
Dim p As Property
GetProperty = CurrentDb.Properties(nombrePropiedad)
Salida:
Exit Function
Errores:
If Err.Number = PROPERTY_NOT_FOUND Then
Resume Salida
Else
Resume Salida
End If
End Function

6) Descargar código fuente con la base de datos de ejemplo

Descargar la base de datos EnviarInformesPersonalizados.mdb…

El archivo está comprimido con 7-zip (software libre)

Compartir



12 comentarios:

1 → Marcelo Navia (no registrado) dice hace 8 años:

hola,
este programita me ha servido mucho
pero quiero hacer una pregunta, puedo enviar el informe en formato pdf, ya que lo necesito en este formato.

de antemano muchas gracias.

Saludos.

Marcelo Navia

2 → Norma Romero (no registrado) dice hace 8 años:

Hola
me sirvio de muha ayuda esta informacion gracias y espero y puedan publicar mas acerca de esto y aparte de todo esta muy completa su informacion.

saludos

norma

3 → PIPORRO (no registrado) dice hace 8 años:

me sirvio bastante. agradezco su valioso apoyo. saludos desde mexico

4 → alex (no registrado) dice hace 7 años:

enhorabuena y muchas gracias por poner al alcance de todos un código tan útil

5 → Jorge Rodriguez (no registrado) dice hace 7 años:

Me ha servido de mucho. para el envio de correos y el control de registros tambien.
Gracias.

6 → José Miguel (no registrado) dice hace 7 años:

Hola Buenas noches,

Estoy montando con la ayuda del código aqui expuesto, una pequeña aplicacion para reclamar los recibos de una pequeña empresa por correo electronico mediante informes.

Lo tengo bastante adelantado, el tema es que me da error nº 3061 en la funcion de enviar informes personalizados dice "Pocos parametros se esperaba 1", em puede alguien echar un cable.

Gracias.

Saludos

7 → Francisco dice hace 7 años:

Hola José Miguel
El error "Pocos parámetros se esperaba 1" es bastante común en Access. No es grave. Significa que el nombre de algún campo está mal puesto o falta. Has de repasar el código hasta encontrar el fallo.

8 → Lenin Ospiona (no registrado) dice hace 7 años:

Estoy intentando enviar un correo pero necesito que el cuerpo del mensaje sea en html, como puedo lograr esto?

9 → José Sánchez Sarduy (no registrado) dice hace 6 años:

Este artículo está muy bueno y práctico. Ya lo tengo montado en mi Empresa. Por Favor alguien podria ayudarme, Como enviar este mismo informe pero comprimido. Lo agradecería eternamente. Saludos JSánchez

10 → Mª José Escamilla (no registrado) dice hace 4 años:

Gracias, gracias, gracias... Funciona perfecto.

11 → Cesar Arias (no registrado) dice hace 3 años:

Excelente aplicación...
Me has ayudado mucho...
Les invito a utilizar esta gran donación de nuestro amigo...

12 → Romer (no registrado) dice hace 2 meses:

Muy buen modulo,
Lo estoy aplicando para enviar facturas de telefono,
Me faltaria que en el asunto pusiera "Factura y a continuacion cogiera el nº de telefono" (eje. Factura 666666666)

Añade tu comentario:

(El correo no será publicado)
 

Artículos relacionados:

Ir arriba