Ocultar tablas en Access remoto – DB_HIDDENOBJECT y SetHiddenAttribute
El otro día llegó a mis manos unas base de datos Access con las tablas ocultas y recordé una función que colgó el Búho en su día para ocultar y volver a mostrar tablas:
'Por el Buho Function OcultaDesoculta(Ocultar As Boolean) Dim Tablas As TableDef For Each Tablas In CurrentDb.TableDefs If Ocultar = True Then If Not (Tablas.Attributes And DB_HIDDENOBJECT) Then Tablas.Attributes = Tablas.Attributes + DB_HIDDENOBJECT End If Else If (Tablas.Attributes And DB_HIDDENOBJECT) Then Tablas.Attributes = Tablas.Attributes - DB_HIDDENOBJECT End If End If Next End Function 'Y llama a esta funcion con el parametro False/TRUE, es decir '*********************** ' OcultaDesoculta False '*********************** 'y no se verán las tablas de la base de datos ni de coña
Así que decidí probar el código ya que recordaba que en algún sitio había leído que nunca se utilizara (no hay mayor motivo que este para trastear) ya que al compactar la base de datos, la tabla era eliminada. Parece ser que había un bug en algunas versiones de Access que hacía que la tabla se marcara como temporal, procediendo a su borrado al compactar. Pero como se suponía que estaba arreglado, decidí probarlo tal cual.
En principio todo funcionaba correctamente, pasando TRUE a la función, las tablas se ocultaban y pasando FALSE, se volvían a mostrar. Entonces pasó algo muy curioso, al intentar cerrar la base de datos me apareció el siguiente cuadro de dialogo:
Y entonces se me encendió la luz…
¡Las tablas de sistema!
Pues sí, al recorrer todo el tabledef, también modificas las tablas de sistema y esto hace que después nuestra base de datos quede inservible. He intentado volver a modificar las tablas de sistema, pero inspeccionando las modificaciones (me he cargado 3 bases de datos) veo que no actúa como con el resto de tablas y no puedo volver a dejarlas igual.
El siguiente paso, lógicamente era intentar que sólo se modificaran las tablas que no son de sistema, comprobando antes de realizar las modificaciones. Así que volví a escribir el código (cambio las variables porque así me aclaro mejor):
Function ocultarTablas(ByVal Oculta As Boolean) On Error GoTo mal Dim TablaDef As TableDef For Each TablaDef In CurrentDb.TableDefs If Left(TablaDef.name, 4) <> "MSys" Then If Oculta = True Then If Not (TablaDef.Attributes And DB_HIDDENOBJECT) Then TablaDef.Attributes = TablaDef.Attributes Or DB_HIDDENOBJECT End If Else If (TablaDef.Attributes And DB_HIDDENOBJECT) Then TablaDef.Attributes = TablaDef.Attributes - DB_HIDDENOBJECT End If End If End If Next Exit Function mal: MsgBox ("Error al ocultar tablas"), vbCritical, "Error" End Function
Es la misma función sólo que cuando la tabla es de sistema no la toca (además en vez de sumar he puesto un operador lógico «or», que viene a ser lo mismo para bits).
-¿Funciona?
-Sí.
-Pues nada, artículo terminado.
-Ya, pero me da miedo, me he cargado 3 bases de datos. Además, no funciona con tablas vinculadas.
-¿No hay otra forma de hacerlo?
-Vamos a ver…
Entonces empecé a buscar en la web de Microsoft algo relacionado con el tema y encontré los métodos GetHiddenAttribute y SetHiddenAttribute.
Pues nada, vuelvo a construir la función y probamos:
Function ocultarTablas(ByVal Oculta As Boolean) Dim TablaDef As TableDef On Error GoTo mal For Each TablaDef In CurrentDb.TableDefs If Application.GetHiddenAttribute(acTable, TablaDef.name) = Not Oculta Then Application.SetHiddenAttribute acTable, TablaDef.name, Oculta End If Next Exit Function mal: MsgBox ("Error al ocultar tablas"), vbCritical, "Error" End Function
Si habéis leído el artículo en profundidad, sabréis que posiblemente con este código tendría una 4ª base de datos inservible (no controlo si es una tabla de sistema), pero esta vez no, esta vez no actuamos a nivel de bits, estamos intentando modificar un atributo de una tabla de sólo lectura y Access nos avisa:
Esto me dejaba mucho más tranquilo, así que volviendo a rehacer el código con la comprobación de las tablas de sistema podíamos decir que la función estaba correctamente terminada. Y está vez sí que funcionaba con tablas tanto vinculadas como locales:
Function ocultarTablas(ByVal Oculta As Boolean) Dim TablaDef As TableDef On Error GoTo mal For Each TablaDef In CurrentDb.TableDefs If Left(TablaDef.name, 4) <> "MSys" Then If Application.GetHiddenAttribute(acTable, TablaDef.name) = Not Oculta Then Application.SetHiddenAttribute acTable, TablaDef.name, Oculta End If End If Next Exit Function mal: MsgBox ("Error al ocultar tablas"), vbCritical, "Error" End Function
-Ahora sí ¿no?, artículo terminado.
-Ya, pero es que… ¿y si quiero modificar una base de datos remota?
Entonces tenemos que modificar un poco (un poco bastante) la función. Empecemos por la llamada, tenemos que pasarle el nombre de la base de datos que queremos modificar (y ya de paso adelantamos y le pasamos la posible contraseña):
Function ocultarTablas(ByVal Oculta As Boolean, ByVal baseDatos As String, ByVal pass As String)
El resto era bastante sencillo, abrir la base de datos remota y recorrer el tabledef. Pero había un problema, los métodos GetHiddenAttribute y SetHiddenAttribute actúan sobre un elemento Application, así que tenía que crearlo (buscando un poco encontré la manera de hacerlo). Así que el código final queda de la siguiente manera (comprobado y funcionando correctamente):
Function ocultarTablas(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 tablas de una base de datos que le pasemos (local o remota) 'Funciona para tablas locales o vinculadas 'Pasando contraseña funciona para bases de datos encriptadas 'Utiliza GetHiddenAttribute y SetHiddenAttribute en vez de DB_HIDDENOBJECT (problemas en versiones viejas de Access y posibilidad de dejar inservible la base de datos en la actuales) 'Probada y ni borra tablas ni deja de sólo lectura 'Más información www.programadordepalo.com/ocultar-tablas-en-access-remoto-db_hiddenobject-y-sethiddenattribute/ ' '************************************************************************************************************************************* '************************************************************************************************************************************* '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 TablaDef As TableDef 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 TablaDef In base.TableDefs If Left(TablaDef.name, 4) <> "MSys" Then 'Comprobamos que no sea una tabla de sistema If Aplicacion.GetHiddenAttribute(acTable, TablaDef.name) = Not Oculta Then Aplicacion.SetHiddenAttribute acTable, TablaDef.name, Oculta End If End If Next Aplicacion.RefreshDatabaseWindow 'Actualizamos la ventana por si está abierta Aplicacion.Quit Set Aplicacion = Nothing Exit Function mal: MsgBox ("Error al modificar las propiedades. " & Err.Description), vbCritical, "Error al modificar las propiedades" End Function
En unos días intentaré rehacer la función para ocultar otro tipo de objetos de nuestra base de datos (Módulos de VBA, consultas, etc.). Edito: He incluido en el nuevo Administrador de Aplicaciones Access esta funcionalidad y unas cuántas más.
Arkaitz Arteaga
Latest posts by Arkaitz Arteaga (see all)
- Access: Encriptar contraseñas con SHA-256 utilizando biblioteca de clases .NET con C# - 4 mayo, 2014
- Rendimiento de Access contra backend Access en servidor de archivos remoto. Cuarta parte. - 27 abril, 2014
- Rendimiento de Access contra backend Access en servidor de archivos remoto. Aclaración. - 21 abril, 2014
- Utilizar biblioteca de clases .NET en Access. Tercera aproximación a la Interoperabilidad COM - 14 abril, 2014
- Vincular tablas en Access con Visual Basic - 11 abril, 2014
3 Respuestas a Ocultar tablas en Access remoto – DB_HIDDENOBJECT y SetHiddenAttribute
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.
Hola Arkaitz,
tal como te comenté en el email hace tiempo, el problema del procedimiento SetHiddenAttribute es que, aun a pesar de que la tabla se oculta, el usuario puede seguir consultandola mediante la opcion «Mostrar objetos ocultos».
Actuando directamente sobre Table.Attributes la tabla nunca se nos mostrará en el navegador pero, efectivamente, no funciona con tablas vinculadas.
No sabras por casualidad si hay algun modo de evitar al usuario que muestre los objetos ocultos, o alguna otra opcion con la que se pueda resolver el problema?
Muchas gracias y un saludo
alguien que me ayude! deseo tener en mi programa de access.mdb la opcion de lector de codigo de barra, lo que se utiliza en los supermercados, tengo entendido que ya algunos superexperto los tienen, si alguien colabora con este proyecto, gracias.
agradecido de antemano.
Hola Arkaitz, me puedes ayudar porfa con la parte de como llamar esta funcion? estoy tratando con la manera que conozco que es: ocultarTablas true, esto en un boton, pero me sale que el argumento no es opcional. Y te felicito por este excelente block.