Ocultar objetos en base de datos Access remota

Empiezo mi colaboración con el blog de mi amigo Ángel agradeciendo su generosidad, simpatía y sobre todo sus ganas de enseñar y compartir. Es un placer escribir para todos vosotros, espero que os gusten mis aportaciones.

Algunos me conoceréis por mi blog ProgramadorDePalo, otros por anteriores proyectos (aquellos maravillosos años de PHP-Nuke y Songohack.com) y otros no habréis oído hablar de mí. Para ponernos en situación, os cuento que estoy escribiendo una serie de artículos sobre seguridad en Access con VBA, que es mi herramienta de trabajo además de mi pasión. El objetivo es llegar a tener una aplicación lo suficientemente segura como para cumplir los requerimientos de la LOPD para datos de nivel alto.

En el último artículo de la serie, Ocultar tablas en base de datos Access, expliqué la forma más sencilla y segura (por lo menos desde mi punto de vista) de ocultar tablas tanto en una base de datos local como en una base de datos remota. Aunque parezca que utilizando el resto de Medidas de seguridad para aplicaciones Access, no tiene sentido ocultar los objetos de una base de datos, yo creo que cuantas más capas de seguridad tengamos, más difícil le resultará a un usuario malintencionado saltarse nuestra seguridad (además evita que usuarios no malintencionados pero del tipo «me gusta tocar donde no debo» accedan a objetos que no queremos que accedan).

En este artículo os mostraré la manera de ocultar consultas (similar a ocultar tablas), macros, módulos de VBA, informes, relaciones y formularios. Como en el resto de artículos, explicaré brevemente cómo se hace y los posibles problemas que os encontraréis y al final del artículo insertaré las funciones que podréis copiar para utilizarlas en vuestras aplicaciones.

Empezaremos con la función que utilizo para ocultar consultas que es muy similar a la de ocultar tablas ya que utiliza el mismo método. Le pasamos a la función la ruta de la base de datos, la contraseña y un parámetro booleano para que oculte o muestre las consultas. Utilizaremos los mismos métodos que en el artículo anterior, GetHiddenAttribute y SetHiddenAttribute.

Declaramos la función:

Function ocultarConsultas(ByVal Oculta As Boolean, ByVal Basedatos As String, ByVal pass As String)

Y declaramos las variables:

Dim trabajo As dao.Workspace
Dim Base As dao.Database
Dim ConsulDef As QueryDef
Dim Aplicacion As Access.Application

Como veis, en este caso no declaramos un Tabledef ya que en vez de recorrer tablas, queremos recorrer consultas. Para ello utilizaremos un Querydef. Lo que sigue igual son las variables Workspace (para bases de datos remotas), Database (le pasaremos la ruta de nuestra base de datos) y el objeto Application (necesario para abrir la base de datos y utilizar GetHiddenAttribute y SetHiddenAttribute).

Una vez declaradas las variables, abrimos la base de datos y el objeto Application:

Set trabajo = DBEngine.Workspaces(0)
Set Base = trabajo.OpenDatabase(Basedatos, False, False, "MS Access;PWD=" & pass & "") 'Abrimos base de datos remota

Set Aplicacion = New Access.Application 'Creamos el objeto Application para utilizar los métodos GetHiddenAttribute y SetHiddenAttribute
Aplicacion.OpenCurrentDatabase Basedatos, , pass

Y pasamos a recorrer las consultas de nuestra base de datos teniendo cuidado de no modificar las consultas «de sistema» (realmente son consultas para campos calculados, etc):

For Each ConsulDef In Base.QueryDefs
If Left(ConsulDef.name, 3) "~sq" Then 'Comprobamos que no sea una consulta de sistema
If Aplicacion.GetHiddenAttribute(acQuery, ConsulDef.name) = Not Oculta Then
Aplicacion.SetHiddenAttribute acQuery, ConsulDef.name, Oculta
End If

End If
Next

Ya solo nos queda cerrar la base de datos y el objeto Application (si vamos a ocultar varios objetos a la vez, podemos crear una función para abrir objetos y otra para cerrarlos y utilizarlas solo una vez. Si abrimos y cerramos para cada objeto, las funciones tardan bastante más).

Aplicacion.RefreshDatabaseWindow
Aplicacion.Quit

Set Aplicacion = Nothing

Ahora sólo nos quedaría llamar a la función con el parámetro Oculta=TRUE para ocultar y con Oculta=FALSE para mostrar.

El procedimiento para el resto de objetos es similar con una pequeña modificación, necesitamos introducir el Objeto Containers de una base de datos para recorrer cada uno de los objetos. También necesitaremos un objeto Document para que nos dé información sobre cada instancia del objeto. Vamos con las declaraciones de uno de los objetos (por ejemplo módulos), el resto serán iguales:

Dim trabajo As dao.Workspace
Dim Base As dao.Database
Dim ModuloDoc As Document
Dim Aplicacion As Access.Application

Abrimos la base de datos y el objeto Application (realmente lo que hace es abrir la aplicación Access):

Set trabajo = DBEngine.Workspaces(0)
Set Base = trabajo.OpenDatabase(Basedatos, False, False, "MS Access;PWD=" & pass & "") 'Abrimos base de datos remota

Set Aplicacion = New Access.Application 'Creamos el objeto Application para utilizar los métodos GetHiddenAttribute y SetHiddenAttribute
Aplicacion.OpenCurrentDatabase Basedatos, , pass

Y pasamos a recorrer el tipo de objeto:

For Each ModuloDoc In Base.Containers("Modules").Documents
If Aplicacion.GetHiddenAttribute(acModule, ModuloDoc.name) = Not Oculta Then
Aplicacion.SetHiddenAttribute acModule, ModuloDoc.name, Oculta
End If
Next

Y cerramos:

Aplicacion.RefreshDatabaseWindow
Aplicacion.Quit

Set Aplicacion = Nothing

Como veis, es muy sencillo hacerlo en remoto ya que realmente abrimos la base de datos y la tratamos como si estuviera en local. He añadido todas estas funcionalidades al Administrador de Aplicaciones Access utilizando básicamente estas funciones (mejorando un poco el código para no tener que abrir cada vez y cerrando las conexiones persistentes en caso de estar en desconexión pasiva de usuarios. Pero aquí os las dejo todas por si las necesitáis:

Ocultar Consultas

Function ocultarConsultas(ByVal Oculta As Boolean, ByVal Basedatos As String, ByVal pass As String)
'*************************************************************************************************************************************
'Autor: Arkaitz Arteaga
'Más artículos: www.programadordepalo.com
'Mail de contacto: admin@programadordepalo.com
'Fecha: Enero 2014
'Version: 1.0
'*************************************************************************************************************************************
'Función que oculta las consultas de una base de datos que le pasemos (local o remota)
'Funciona para consultas locales o vinculadas
'Pasando contraseña funciona para bases de datos encriptadas

'*************************************************************************************************************************************
'*************************************************************************************************************************************
'Copyright: Por favor, no cuesta nada mantener un enlace a mi web en el código.
'Incluso pudes dejar los formularios tal cual, con un enlace a mi web.
'Si vas a utilizar este código con fines lucrativos (es decir, te van a pagar por ello) contacta conmigo por favor.
'*************************************************************************************************************************************

Dim trabajo As dao.Workspace
Dim Base As dao.Database
Dim ConsulDef As QueryDef
Dim Aplicacion As Access.Application

On Error GoTo mal

Set trabajo = DBEngine.Workspaces(0)
Set Base = trabajo.OpenDatabase(Basedatos, False, False, "MS Access;PWD=" & pass & "") 'Abrimos base de datos remota

Set Aplicacion = New Access.Application 'Creamos el objeto Application para utilizar los métodos GetHiddenAttribute y SetHiddenAttribute
Aplicacion.OpenCurrentDatabase Basedatos, , pass

For Each ConsulDef In Base.QueryDefs
If Left(ConsulDef.name, 3) "~sq" Then 'Comprobamos que no sea una consulta de sistema
If Aplicacion.GetHiddenAttribute(acQuery, ConsulDef.name) = Not Oculta Then
Aplicacion.SetHiddenAttribute acQuery, ConsulDef.name, Oculta
End If

End If
Next

Aplicacion.RefreshDatabaseWindow
Aplicacion.Quit

Set Aplicacion = Nothing

Exit Function
mal:
MsgBox ("Error al ocultar las consultas. " & Err.Description), vbCritical, "Error al modificar las propiedades"

End Function

Ocultar Módulos

Function ocultarModulos(ByVal Oculta As Boolean, ByVal Basedatos As String, ByVal pass As String)
'*************************************************************************************************************************************
'Autor: Arkaitz Arteaga
'Más artículos: www.programadordepalo.com
'Mail de contacto: admin@programadordepalo.com
'Fecha: Enero 2014
'Version: 1.0
'*************************************************************************************************************************************
'Función que oculta los módulos de una base de datos que le pasemos (local o remota)
'Pasando contraseña funciona para bases de datos encriptadas

'*************************************************************************************************************************************
'*************************************************************************************************************************************
'Copyright: Por favor, no cuesta nada mantener un enlace a mi web en el código.
'Incluso pudes dejar los formularios tal cual, con un enlace a mi web.
'Si vas a utilizar este código con fines lucrativos (es decir, te van a pagar por ello) contacta conmigo por favor.
'*************************************************************************************************************************************

Dim trabajo As dao.Workspace
Dim Base As dao.Database
Dim ModuloDoc As Document
Dim Aplicacion As Access.Application

On Error GoTo mal

Set trabajo = DBEngine.Workspaces(0)
Set Base = trabajo.OpenDatabase(Basedatos, False, False, "MS Access;PWD=" & pass & "") 'Abrimos base de datos remota

Set Aplicacion = New Access.Application 'Creamos el objeto Application para utilizar los métodos GetHiddenAttribute y SetHiddenAttribute
Aplicacion.OpenCurrentDatabase Basedatos, , pass

For Each ModuloDoc In Base.Containers("Modules").Documents
If Aplicacion.GetHiddenAttribute(acModule, ModuloDoc.name) = Not Oculta Then
Aplicacion.SetHiddenAttribute acModule, ModuloDoc.name, Oculta
End If
Next

Aplicacion.RefreshDatabaseWindow
Aplicacion.Quit

Set Aplicacion = Nothing

Exit Function
mal:
MsgBox ("Error al ocultar los módulos. " & Err.Description), vbCritical, "Error al modificar las propiedades"

End Function

Ocultar Macros

Function ocultarMacros(ByVal Oculta As Boolean, ByVal Basedatos As String, ByVal pass As String)
'*************************************************************************************************************************************
'Autor: Arkaitz Arteaga
'Más artículos: www.programadordepalo.com
'Mail de contacto: admin@programadordepalo.com
'Fecha: Enero 2014
'Version: 1.0
'*************************************************************************************************************************************
'Función que oculta las macros de una base de datos que le pasemos (local o remota)
'Pasando contraseña funciona para bases de datos encriptadas

'*************************************************************************************************************************************
'*************************************************************************************************************************************
'Copyright: Por favor, no cuesta nada mantener un enlace a mi web en el código.
'Incluso pudes dejar los formularios tal cual, con un enlace a mi web.
'Si vas a utilizar este código con fines lucrativos (es decir, te van a pagar por ello) contacta conmigo por favor.
'*************************************************************************************************************************************

Dim trabajo As dao.Workspace
Dim Base As dao.Database
Dim MacroDoc As Document
Dim Aplicacion As Access.Application

On Error GoTo mal

Set trabajo = DBEngine.Workspaces(0)
Set Base = trabajo.OpenDatabase(Basedatos, False, False, "MS Access;PWD=" & pass & "") 'Abrimos base de datos remota

Set Aplicacion = New Access.Application 'Creamos el objeto Application para utilizar los métodos GetHiddenAttribute y SetHiddenAttribute
Aplicacion.OpenCurrentDatabase Basedatos, , pass

For Each MacroDoc In Base.Containers("Scripts").Documents
If Left(MacroDoc.name, 3) "~TM" Then 'Controlamos que no sea de la "raras"
If Aplicacion.GetHiddenAttribute(acMacro, MacroDoc.name) = Not Oculta Then
Aplicacion.SetHiddenAttribute acMacro, MacroDoc.name, Oculta
End If
End If
Next

Aplicacion.RefreshDatabaseWindow
Aplicacion.Quit

Set Aplicacion = Nothing

Exit Function
mal:
MsgBox ("Error al ocultar las macros. " & Err.Description), vbCritical, "Error al modificar las propiedades"

End Function

Ocultar Informes

Function ocultarInformes(ByVal Oculta As Boolean, ByVal Basedatos As String, ByVal pass As String)
'*************************************************************************************************************************************
'Autor: Arkaitz Arteaga
'Más artículos: www.programadordepalo.com
'Mail de contacto: admin@programadordepalo.com
'Fecha: Enero 2014
'Version: 1.0
'*************************************************************************************************************************************
'Función que oculta los informes de una base de datos que le pasemos (local o remota)
'Pasando contraseña funciona para bases de datos encriptadas

'*************************************************************************************************************************************
'*************************************************************************************************************************************
'Copyright: Por favor, no cuesta nada mantener un enlace a mi web en el código.
'Incluso pudes dejar los formularios tal cual, con un enlace a mi web.
'Si vas a utilizar este código con fines lucrativos (es decir, te van a pagar por ello) contacta conmigo por favor.
'*************************************************************************************************************************************

Dim trabajo As dao.Workspace
Dim Base As dao.Database
Dim InformeDoc As Document
Dim Aplicacion As Access.Application

On Error GoTo mal

Set trabajo = DBEngine.Workspaces(0)
Set Base = trabajo.OpenDatabase(Basedatos, False, False, "MS Access;PWD=" & pass & "") 'Abrimos base de datos remota

Set Aplicacion = New Access.Application 'Creamos el objeto Application para utilizar los métodos GetHiddenAttribute y SetHiddenAttribute
Aplicacion.OpenCurrentDatabase Basedatos, , pass

For Each InformeDoc In Base.Containers("Reports").Documents
If Left(InformeDoc.name, 3) "~" Then 'Controlamos que no sea de la "raras"
If Aplicacion.GetHiddenAttribute(acReport, InformeDoc.name) = Not Oculta Then
Aplicacion.SetHiddenAttribute acReport, InformeDoc.name, Oculta
End If
End If
Next

Aplicacion.RefreshDatabaseWindow
Aplicacion.Quit

Set Aplicacion = Nothing

Exit Function
mal:
MsgBox ("Error al ocultar las macros. " & Err.Description), vbCritical, "Error al modificar las propiedades"

End Function

El resto de objetos se ocultarían de la misma manera, cambiando el nombre del Container. Podéis investigar un poco agregando una inspección en una de las funciones anteriores al objeto Base.Containers. Os mostrará todas la posibilidades.

Para cualquier duda o petición, utilizad los comentarios de este artículo.

photo credit: Frederic Poirot via photopin cc

Un comentario

  1. me parece un error en la funcion para ocultar consultas
    muestra un error en la linea
    If Left(ConsulDef.name, 3) «~sq»

    me podrias apoyaar

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.