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.
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".
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)
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.
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.
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