Página inicial

 

ACCESO A DATOS EN LIBROS PROTEGIDOS

 

0.- Introducción

Sabemos que es posible acceder a las celdas de una hoja que se encuentra en un libro protegido mediante la sintaxis normal en Excel:

=[Ruta\LibroProtegido.xls]Hoja1!A1

ó

='[Ruta\Libro Protegido.xls]Hoja1'!A1

si hubiera algún espacio en la ruta y/o el nombre del libro.

Esta forma de acceder a la información tiene, en el caso de los libros protegidos, el inconveniente de que es necesario facilitar la contraseña del libro.

Otras formas de acceder a los libros sin proteger, como por ejemplo ADO, no funcionan con libros protegidos porque estos tienen la información encriptada.

Hay (al menos) una forma de conseguir recuperar información de libros protegidos cerrados sin tener que suministrar la contraseña. Es bastante complicada, pero dependiendo de los casos y de las necesidades de cada cual puede merecer la pena (o no). Yo me limito a exponerla :-)

Debo aclarar que en ningún caso me estoy refiriendo a acceder a los datos de un libro protegido del que no se conoce la contraseña. Ignoro cómo hacer esto, suponiendo que sea posible hacerlo (que creo que no lo es). A lo que me refiero es a un caso que en mi trabajo se da con alguna frecuencia: no se desea que los usuarios puedan abrir uno o varios libros determinados, por lo que se protegen con contraseña, pero sí interesa que puedan obtener determinados datos de dichos libros. En este caso, es posible "dejar expuestos" dichos datos, de forma que puedan ser accedidos sin necesidad de abrir el libro protegido. Lo que sigue es la forma de conseguirlo.

 

1.- Las propiedades del libro

Cada libro de Excel (y algunos otros tipos de archivos de Office, especialmente Word) tiene un conjunto de propiedades a las cuales, en el caso de Excel, se puede acceder haciendo Archivo->Propiedades. El diálogo de esta opción es

Es posible establecer estas propiedades, que se almacenarán al guardar el libro. Otras propiedades, como la última fecha en que se imprimió algo en el libro, su fecha de creación, etc. son creadas y guardadas automáticamente.

En algunos sistemas operativos (como p. ej. en Windows XP) algunas de dichas propiedades aparecen si en el explorador o en el diálogo de apertura de libros se deja quieto unos instantes el puntero del ratón sobre el nombre de un libro. Esto puede ayudar a saber cual es el contenido del libro sin necesidad de abrirlo, a condición de que nos hayamos tomado la molestia de teclear la información que luego vamos a poder necesitar. La siguiente imagen corresponde al diálogo "Abrir" de Excel, habiendo seleccionado "Propiedades" en el desplegable "Vistas":

En la zona derecha se pueden ver las propiedades del libro. También es posible guardar una imagen de la hoja activa en el momento de guardar el libro, la cual puede revisarse después sin necesidad de abrir el libro. Esto se consigue marcando la opción "Guardar vista previa". Para ver la imagen guardada hay que seleccionar "Vista previa" en el desplegable "Vistas".

 

2.- Las propiedades personalizadas del libro

Pero lo que nos interesa para lo que estamos intentando conseguir está en la solapa "Personalizar":

En la imagen se puede apreciar cómo ya está creada una propiedad personalizada llamada Hoja1A1, la cual hace referencia a un rango con el mismo nombre. Es necesario crear dicho rango con nombre antes de intentar crear la propiedad personalizada, porque si no se hace así la opción "Vincular al contenido" no se encontrará habilitada.

Los eslabones que aparecen a la izquierda del nombre de la propiedad indican que está vinculada a un rango con nombre, lo que significa que cualquier cambio que se haga en la celda referenciada por dicho rango modificará también el valor de la propiedad personalizada.

Si se deseara poder acceder a los valores de varias celdas del libro, sería necesario crear un rango con nombre para cada una de ellas. Si algún rango con nombre hiciera referencia a varias celdas, el valor que tomará la propiedad asociada a dicho rango será el de la primera de sus celdas (la de la esquina superior izquierda si fuera un rango bidimensional, y la de la esquina superior izquierda de la primera de sus áreas si se tratara de un rango múltiple).

La propiedad personalizada no tiene porqué llamarse igual que el rango con nombre, pero, por cuestiones de organización, es buena idea hacerlo así si se necesita obtener el valor de varias celdas, lo que requeriría la creación de varias propiedades.

La propiedad personalizada tampoco tiene porqué estar vinculada tan solo a un rango con nombre que se refiera a una celda o a un rango de celdas en concreto, sino que puede estar vinculada a cualquier rango con nombre creado mediante una fórmula desde Insertar->Nombre->Definir, incluyendo rangos dinámicos. Por ejemplo, podría existir un rango con nombre llamado SumaA1A10 que se refiriera a la suma de dicho rango mediante la fórmula

=SUMA(Hoja1!$A$1:$A$10)

y si la propiedad personalizada estuviera vinculada a dicho rango con nombre, su valor sería el de la suma en el momento en que el libro fue guardado.

Excel admite que el rango con nombre sea tanto de nivel de libro como de nivel de hoja (recordemos que los rangos con nombre a nivel de hoja se crean anteponiendo al nombre del rango el de la hoja + un signo de admiración, por ejemplo: Hoja1!SumaA1A10)

 

3.- La librería DSOFile.DLL

Tanto las propiedades que los libros tienen por defecto como las personalizadas pueden ser accedidas desde VBA de varias formas, pero para poder acceder a las propiedades de libros cerrados es necesario instalar en el equipo una librería que se encuentra disponible en el sitio de Microsoft:

Artículo de Microsoft sobre la librería DSOFile.DLL

Descargar la librería DSOFile.DLL

Una vez registrada la librería en el equipo (lo cual sucede automáticamente ejecutando el fichero descargado), es posible usar las siguientes dos funciones para averiguar el nombre, tipo y valor de una propiedad determinada por su número de Item o para devolver el valor de dicha propiedad usando su nombre.

 

4.- La función ObValLibCerrado

Esta primera función es la encargada de devolver el valor de una propiedad personalizada de un libro

Function ObValLibCerrado(strLibro As String, strPropiedad As String) As Variant
    Application.Volatile
    'Obtener Valor de un Libro Cerrado
    'Función que sirve para obtener el valor de una propiedad personalizada de un libro.
    'Autor: jrgc
    'Sintaxis: =ObValLibCerrado("Ruta y nombre del libro";"Propiedad personalizada")
    'Es necesario haber instalado en el equipo la librería DSOFile.dll, la cual puede _
     ser descargada desde _
     http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q224/3/51.asp&NoWebContent=1
    If Dir(strLibro) = "" Then
        ObValLibCerrado = "Error: no existe el libro."
        Exit Function
    End If
    Dim pr As Object
    Dim dsD As Object
    Dim prPers As Object
    Set pr = CreateObject("DSOleFile.PropertyReader")
    If pr Is Nothing Then
        ObValLibCerrado = "Esta función necesita que esté instalada en el equipo la librería DSOFile.dll, la cual puede ser descargada desde http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q224/3/51.asp&NoWebContent=1"
        GoSub Salir
    End If
    Set dsD = pr.GetDocumentProperties(strLibro)
    If dsD.CustomProperties.Count = 0 Then
        ObValLibCerrado = "Error: el libro no tiene ninguna propiedad personalizada."
        GoSub Salir
    End If
    For Each prPers In dsD.CustomProperties
        If LCase(prPers.Name) = LCase(strPropiedad) Then
            ObValLibCerrado = prPers.Value
            GoSub Salir
        End If
    Next prPers
    ObValLibCerrado = "Error: no existe la propiedad indicada."
Salir:
    Set pr = Nothing
    Set dsD = Nothing
    Set prPers = Nothing
End Function

La sintaxis es la indicada al principio de la función.

 

5.- La función VerPropPers

Y esta segunda función es la encargada de devolver el nombre, tipo y valor de una propiedad determinada, según su número de Item en la colección CustomProperties del libro:

Function VerPropPers(strLibro As String, lngNúmero As Long) As String
    Application.Volatile
    'Ver Propiedades Personalizadas
    'Función que sirve para averiguar el nombre, tipo y valor de una propiedad _
     personalizada de un libro.
    'Autor: jrgc
    'Sintaxis: =VerPropPers(Ruta y nombre del libro";Número)
    'Es necesario haber instalado en el equipo la librería DSOFile.dll, la cual puede _
     ser descargada desde _
     http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q224/3/51.asp&NoWebContent=1
    If Dir(strLibro) = "" Then
        VerPropPers = "Error: no existe el libro."
        Exit Function
    End If
    Dim pr As Object
    Dim dsD As Object
    Set pr = CreateObject("DSOleFile.PropertyReader")
    If pr Is Nothing Then
        VerPropPers = "Esta función necesita que esté instalada en el equipo la librería DSOFile.dll, la cual puede ser descargada desde http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q224/3/51.asp&NoWebContent=1"
        GoSub Salir
    End If
    Set dsD = pr.GetDocumentProperties(strLibro) 
    If dsD.CustomProperties.Count = 0 Then
        VerPropPers = "Error: el libro no tiene ninguna propiedad personalizada."
        GoSub Salir
    End If
    With dsD.CustomProperties(lngNúmero)
        VerPropPers = "Nombre: " & .Name & " - " & "Tipo: " & .Type & " - " & "Valor: " & .Value
    End With
Salir:
    Set pr = Nothing
    Set dsD = Nothing
End Function

Ésta función es útil cuando no se sabe el número y/o los nombres de las propiedades del libro. Por ejemplo, para listar todas las propiedades del libro C:\Datos\Libro1, se podría poner la siguiente fórmula en la fila 1 de cualquier columna:

=VerPropPers("C:\Datos\Libro1.xls";FILA())

y copiarla y extenderla hacia abajo. Se mostrarán todas las propiedades personalizadas, y cuando ya no queden más comenzará a aparecer el error #¡VALOR!

La lista de propiedades tendrá siempre al menos un elemento más de las creadas, porque automáticamente se crea una llamada _PID_LINKBASE, cuyo tipo es 0 y que no tiene ningún valor.

 

Tema relacionado: complementos que usan la librería DSOFile.dll

 

Página inicial