viernes, abril 24, 2009

OLE con Office y xHarbour de la manera fácil

Una de las mejores características de xHarbour es el soporte nativo a OLE (Object Linking and Embeding) el cual nos permite tener acceso a muchos componentes interesantes como librerías de terceros como Funcky, el acceso a distintos formatos de bases de datos con ADO (ActiveX Data Objects) y el acceso a los componentes de Office de Microsoft, entre otros.

La conectividad con Office hoy en día es fundamental, nuestros programas tienen que hablarse con Excel, con Word o con el Outlook, y es aquí donde entra en acción OLE.

Como es materialmente imposible saberse todos los objetos, métodos y propiedades de Excel o de Word, existe una manera fácil de saber con exactitud qué metodos y propieades utilizar para hacer determinados trabajos con estos productos.

La forma mas fácil de hacerlo, es utilizar el grabador de "macros" tanto de Word, como de Excel.

El grabador de macros lo que hace es ir "atrapando" todas las acciones y pulsos de teclas durante determinadas operaciones, hasta que detengas la grabación de la macro.

Una vez detenida la grabación de la "macro", todas las operaciones realizadas se "traducen" a un código fuente en Visual Basic for Applications, y a partir de ese código fuente es muy fácil traducirlo a código de OLE con (x)Harbour, con esto, nuestro programa puede hacer las mismas operaciones que grabamos en la macro.

Hasta aquí todo parece estar bien, pero el problema viene porque muchos métodos y propiedades utilizan constantes predefinidas (que están en archivos .h normalmente) aún en lo manuales de los objetos OLE de Excel se hace mención a dichas variables PERO NO A SU VALOR.

Veamos el ejemplo que me hizo escribir este artículo:

Supongamos que yo quiero poner bordes en un rango de celdas pero no sé como hacerlo, entonces creo una macro, selecciono un rango de celdas, oprimo los botones de la barra que dibujan los bordes, y listo, tengo mi macro, dentengo el grabador de macros y luego edito la macro graba y obtengo algo como esto:

Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With

Con algunos cambios mínimos, como por ejemplo cambiar los "." por ":" y los "=" por ":=" y algunas cosillas mas y este código en VBA puede ejecutarse desde xHarbour.

El problema es que hay un montón de constantes predefinas de las cuales desconozco el valor y que son:
  • xlDiagonalDown
  • xlDiagonalUp
  • xlNone
  • xlEdgeLeft
  • xlEdgeTop
  • xlEdgeBottom
  • xlEdgeRight
  • xlContinuous
  • xlInsideVertical
  • xlInsideHorizontal
Encontrar el valor de dichas constantes en el MSDN (Microsoft Developers Network) te puede llevar muchas horas porque en mucha documentación se hace referencia al nombre, pero no al valor.

Visto lo visto, decidí investigar un poco por internet la manera de obtener dichos valores, y me encontré con el método mas tonto de hacerlo y no solo para estas constantes sino para TODAS las constantes que en un momento dado se pueden llegar a necesitar..... ¿ porqué no se me ocurrió antes ?, dicen por ahí que las soluciones mas simples a los problemas suelen ser siempre las correctas.

La receta:

Crear una nueva macro en excel, y escribir lo siguiente en el editor de código:

Sub test3()
MsgBox xlNone
MsgBox xlContinuous
MsgBox xlMedium
MsgBox xlAutomatic
MsgBox xlDiagonalDown
MsgBox xlDiagonalUp
MsgBox xlEdgeLeft
MsgBox xlEdgeTop
MsgBox xlEdgeBottom
MsgBox xlEdgeRight
MsgBox xlInsideVertical
MsgBox xlInsideHorizontal
End Sub


La macro simplemente consiste en desplegar en un MsgBox el valor de la constante buscada, y listo, luego con los valores devueltos podemos hacer las constantes predefinidas equivalentes en xHarbour:

#DEFINE xlDiagonalDown 5
#DEFINE xlDiagonalUp 6
#DEFINE xlNone -4142
#DEFINE xlEdgeLeft 7
#DEFINE xlEdgeTop 8
#DEFINE xlEdgeBottom 9
#DEFINE xlEdgeRight 10
#DEFINE xlContinuous 1
#DEFINE xlInsideVertical 11
#DEFINE xlInsideHorizontal 12
#DEFINE xlThin 2

Y listo, con esto podemos usar el código de las macros generadas por excel en nuestro programa xHarbour.

Mejor... imposible !!!!

2 comentarios:

José F. Giménez dijo...

René,

hay una manera más fácil todavía:

- Abre el "Editor de Visual Basic" (Alt+F11)

- Dentro de este, abre el "Examinador de objetos" (F2)

- En la casilla para buscar escribe el nombre de la constante y pulsa Enter o haz click en el botón de búsqueda.

Y voila... en la parte inferior de la ventana del examinador de objetos aparece la constante con su valor ;-)

Un saludo.

Rene Flores dijo...

Gracias Jose, mi ignorancia de VBA es grande, con tu consejo seguro nos liaremos menos cuando tengamos que conectarnos con office