Serie ficheros virtuales 

 

 

C Ficheros Virtuales

 

 

 

B.I.2 COM Ficheros virtuales. El servicio COMw

 

 B.I.2.1 Introducción

 B.I.2.2 Relación de métodos de la clase COMw

 B.I.2.3 La creación del componente COMw

 B.I.2.4 El programa interfaz PruebasV

  B.I.2.5 Uso de COMw en Visual Basic para Aplicaciones (VBA) de Excell y Office

 

 

                                                                                                               _______

 

B.I.2.1 Introducción

 

El servicio COMw proporciona un interfaz COM de SRRCW con una funcionalidad limitada a cadenas *String, aunque mediante éstas cadenas se pueden emular estructuras y resolver problemas directamente en Visual Basic.

 

Se presentará el programa ejemplo PruebasV.

 

Una alternativa es construir clases interfaz COM especializadas, como se hace en COMmagic y en COMjvida que se verán en los próximos capítulos.

 

Posteriormente se presentará el mismo resultado en .NET con la clase vbFile

 

Al final del capítulo también se mostrará como integrar COMw en aplicaciones VBA para uso en excell.

 

                                                                                                               _______

 

 

B.I.2.2 Relación de métodos de la clase COMw

 

Como en COM no se permite el poliformismo, se emplean diferentes nombres de interfaz para las distintas versiones base que representan.

 

Así se hace por ejemplo con los nombres CHAIN, CHAINr y CHAINa para las distintas versiones del SRRCW_CHAIN origen.


 

Partiendo de las funciones del programa de servicio SRRCW original, los métodos interfaz resultantes asociados son los siguientes:

 

 

__interface ISRRCW : IDispatch

{

 [id(1), helpstring("method NEW")] HRESULT NEW([in] BSTR bFILE, [in] LONG lDimC, [in] LONG lDimD, [out] LONG* lID);

 [id(2), helpstring("method NEWr")] HRESULT NEWr([in] BSTR bFILE, [in] LONG lDimC, [out] LONG* lID);

 [id(3), helpstring("method NEWa")] HRESULT NEWa([in] BSTR bFILE, [in] LONG lDimC, [in] LONG lDimD, [in] LONG lMaxNreg, [out] LONG* lID);

 

 [id(4), helpstring("method NOW")] HRESULT NOW([in] BSTR bFILE, [in] LONG lDimC, [in] LONG lDimD, [out] LONG* lID);

 [id(5), helpstring("method NOWr")] HRESULT NOWr([in] BSTR bFILE, [in] LONG lDimC, [out] LONG* lID);

 [id(6), helpstring("method NOWa")] HRESULT NOWa([in] BSTR bFILE, [in] LONG lDimC, [in] LONG lDimD, [in] LONG lMaxNreg, [out] LONG* lID);

 

 [id(7), helpstring("method CHAIN")] HRESULT CHAIN([in] BSTR bFILE, [in] BSTR bClav, [out] BSTR *bDato, [out] LONG *lresul);

 [id(8), helpstring("method CHAINr")] HRESULT CHAINr([in] BSTR bFILE, [in][out] BSTR *bClav, [out] LONG *lresul);

 [id(9), helpstring("method CHAINa")] HRESULT CHAINa([in] BSTR bFILE, [in] BSTR bClav, [out] BSTR *bDato, [in] LONG lLong, [out] LONG *lresul);

 

 [id(10), helpstring("method WRITE")] HRESULT WRITE([in] BSTR bFILE, [in] BSTR bClav, [in] BSTR bDato, [out] LONG *lresul);

 [id(11), helpstring("method WRITEr")] HRESULT WRITEr([in] BSTR bFILE, [in] BSTR bDato, [out] LONG *lresul);

 

 [id(12), helpstring("method READ")] HRESULT READ([in] BSTR bFILE, [in] LONG lNREG, [out] BSTR *bDato, [out] LONG *lresul);

 [id(13), helpstring("method READa")] HRESULT READa([in] BSTR bFILE, [in] LONG lNREG, [out] BSTR *bDato, [out] BSTR *bClav, [out] LONG *lresul);

 

 [id(14), helpstring("method CLOSE")] HRESULT CLOSE([out] LONG *lresul);

 

 [id(15), helpstring("method DELET")] HRESULT DELET([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 [id(16), helpstring("method DELETa")] HRESULT DELETa([in] BSTR bFILE, [in] BSTR bClav, [in] LONG lLong, [out] LONG *lresul);

 

 [id(17), helpstring("method INF")] HRESULT INF([in] BSTR bFILE, [out] LONG* lDimC, [out] LONG* lDimD, [out] LONG* lNITEM,

                                                [out] LONG* lBAJAS, [out] LONG* lNIDD, [out] LONG* lresul);

 

 [id(18), helpstring("method CLRF")] HRESULT CLRF([in] BSTR bFILE, [out] LONG* lresul);

 [id(19), helpstring("method CLRFa")] HRESULT CLRFa([in] BSTR bFILE, [out] LONG* lNBAJ, [out] LONG* lresul);

 

 [id(20), helpstring("method CPY")] HRESULT CPY([in] BSTR bORG, [in] BSTR bDES, [out] LONG *lresul);

 [id(21), helpstring("method CPYa")] HRESULT CPYa([in] BSTR bORG, [in] BSTR bDES, [in] LONG lReplace, [out] LONG *lresul);

 

 [id(22), helpstring("method CRTLF")] HRESULT CRTLF([in] BSTR bLF, [in] BSTR bPF, [in] LONG lKpos, [in] LONG lKlen, [out] LONG *lID);

 [id(23), helpstring("method DUP")] HRESULT DUP([in] BSTR bORG, [in] BSTR bDES, [out] LONG *lID);

 

 [id(24), helpstring("method ERASE")] HRESULT ERASE([in] BSTR bFILE,[out] LONG* lresul);

 

 [id(25), helpstring("method NID")] HRESULT NID([in] BSTR bFILE, [out] LONG* lNID);

 

 [id(26), helpstring("method NIDFILE")] HRESULT NIDFILE([in] LONG lNID, [out] BSTR *bFILE);

 

 [id(27), helpstring("method REORGANIZE")] HRESULT REORGANIZE([in] BSTR bFILE, [out] LONG* lresul);

 [id(28), helpstring("method REORGANIZEa")] HRESULT REORGANIZEa([in] BSTR bFILE, [out] LONG *lNBAJASDEPURADAS, [out] LONG* lresul);

 

 [id(29), helpstring("method SAVF")] HRESULT SAVF([in] BSTR bFILE, [out] LONG* lresul);

 [id(30), helpstring("method RSTF")] HRESULT RSTF([in] BSTR bFILE, [out] LONG* lresul);

 

 [id(31), helpstring("method UPDATE")] HRESULT UPDATE([in] BSTR bFILE, [in] BSTR bClav, [in] BSTR bDato, [out] LONG *lresul);

 [id(32), helpstring("method UPDATEr")] HRESULT UPDATEr([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 [id(33), helpstring("method UPDATEa")] HRESULT UPDATEa([in] BSTR bFILE, [in] BSTR bClav, [in] BSTR bDato, [in] LONG lLong, [out] LONG *lresul);

 [id(34), helpstring("method VER")] HRESULT VER([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 

 [id(35), helpstring("method RESIZE")] HRESULT RESIZE([in] BSTR bFILE, [in] LONG lMaxNreg, [out] LONG* lresul);

 

 [id(36), helpstring("method FIFO_NEW")] HRESULT FIFO_NEW([in] BSTR bFILE, [in] LONG lDimD, [out] LONG* lID);

 [id(37), helpstring("method FIFO_NEWa")] HRESULT FIFO_NEWa([in] BSTR bFILE, [in] LONG lDimD, [in] LONG lMaxNreg, [out] LONG* lID);

 [id(38), helpstring("method LIFO_NEW")] HRESULT LIFO_NEW([in] BSTR bFILE, [in] LONG lDimD, [out] LONG* lID);

 [id(39), helpstring("method LIFO_NEWa")] HRESULT LIFO_NEWa([in] BSTR bFILE, [in] LONG lDimD, [in] LONG lMaxNreg, [out] LONG* lID);

 [id(40), helpstring("method FIFO_WRITE")] HRESULT FIFO_WRITE([in] BSTR bFILE, [in] BSTR bDato, [out] LONG *lresul);

 [id(41), helpstring("method LIFO_WRITE")] HRESULT LIFO_WRITE([in] BSTR bFILE, [in] BSTR bDato, [out] LONG *lresul);

 [id(42), helpstring("method FIFO_READ")] HRESULT FIFO_READ([in] BSTR bFILE, [out] BSTR *bDato, [out] LONG *lresul);

 [id(43), helpstring("method FIFO_READa")] HRESULT FIFO_READa([in] BSTR bFILE, [out] BSTR *bDato, [in] LONG lMarcaBorrarDespues, [out] LONG *lresul);

 [id(44), helpstring("method LIFO_READ")] HRESULT LIFO_READ([in] BSTR bFILE, [out] BSTR *bDato, [out] LONG *lresul);

 [id(45), helpstring("method LIFO_READa")] HRESULT LIFO_READa([in] BSTR bFILE, [out] BSTR *bDato, [in] LONG lMarcaBorrarDespues, [out] LONG *lresul);

 

 [id(46), helpstring("method NAME")] HRESULT NAME([in] BSTR bNAMEin, [out] BSTR *bNAMEout);

 

 [id(47), helpstring("method SETEQ")] HRESULT SETEQ([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 [id(48), helpstring("method SETEQa")] HRESULT SETEQa([in] BSTR bFILE, [in] BSTR bClav, [in] LONG lLong, [out] LONG *lresul);

 

 [id(49), helpstring("method SETGT")] HRESULT SETGT([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 [id(50), helpstring("method SETGTa")] HRESULT SETGTa([in] BSTR bFILE, [in] BSTR bClav, [in] LONG lLong, [out] LONG *lresul);

 

 [id(51), helpstring("method SETGTT")] HRESULT SETGTT([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 [id(52), helpstring("method SETGTTa")] HRESULT SETGTTa([in] BSTR bFILE, [in] BSTR bClav, [in] LONG lLong, [out] LONG *lresul);

 

 [id(53), helpstring("method SETLL")] HRESULT SETLL([in] BSTR bFILE, [in] BSTR bClav, [out] LONG *lresul);

 [id(54), helpstring("method SETLLa")] HRESULT SETLLa([in] BSTR bFILE, [in] BSTR bClav, [in] LONG lLong, [out] LONG *lresul);

 

 [id(55), helpstring("method READE")] HRESULT READE([in] BSTR bFILE, [in] BSTR bCLVp, [in] LONG lLong, [out] BSTR *bDato, [out] LONG *lresul);

 [id(56), helpstring("method READEa")] HRESULT READEa([in] BSTR bFILE, [in] BSTR bCLVp, [in] LONG lLong, [out] BSTR *bDato, [out] BSTR *bClav, [out] LONG *lresul);

 

 [id(57), helpstring("method READPE")] HRESULT READPE([in] BSTR bFILE, [in] BSTR bCLVp, [in] LONG lLong, [out] BSTR *bDato, [out] LONG *lresul);

 [id(58), helpstring("method READPEa")] HRESULT READPEa([in] BSTR bFILE [in] BSTR bCLVp, [in] LONG lLong, [out] BSTR *bDato, [out] BSTR *bClav, [out] LONG *lresul);

};

 

                                                                                                              _______

 

 

B.I.2.3 La creación del componente COMw

 

Para crear el componente, primero se debe crear un proyecto y a continuación agregárselo.

 

Para ello en Visual Studio debe seleccionarse Archivo/Nuevo/Proyecto, después seleccionar Proyectos de Visual C++ y, a continuación, Proyecto ATL.

 

La hacerlo se presentará el asistente para proyectos ATL en donde se aceptarán los valores predeterminados, prefijados precisamente a la creación de una DLL.

 

El siguiente paso es agregar un componente al proyecto.

 

Se consigue haciendo clic con el botón secundario en la Vista de clases del proyecto y seleccionando Agregar/Agregar clase.

 

Dentro del nodo Visual C++ debe seleccionarse ATL y a continuación marcar la figura de Objeto simple ATL y ejecutar el botón Abrir, aceptar los valores predeterminados y finalizar.

 

Una vez creada la clase, se agregarían los métodos a la interfaz ISRRCW creada hasta llegar a la relación mostrada.

 

Para ello, bien se utiliza el asistente para agregar métodos, o bien se agregan manualmente en el propio fuente, por ejemplo porque se cometan errores y tenga que cambiarse algún método generado incorrectamente a posteriori.

 

Con el asistente, se escribiría el nombre del método, y luego se le irían añadiendo parámetros, indicando su tipo y nombre y tambien sus atributos [in] [out], aunque esta casilla debe seleccionarse al final pues sólo se activa cuando se selecciona el tipo puntero BSTR*.

 

Cuando se ha terminado de agregar parámetros se pulsaría finalizar resultando por ejemplo para el método NEW los siguientes grupos de sentencias en los fuentes SRRCW.h y SRRCW.cpp de la interfaz ISRRCW que se crea:

 

 

 

   // SRRCW.h: declaración de CSRRCW

 

   . . .

 

   __interface ISRRCW : IDispatch

   {

    [id(1), helpstring("method NEW")] HRESULT NEW([in] BSTR bFILE, [in] LONG lDimC, [in] LONG lDimD, [out] LONG* lID);

    . . .

 

   public:

    STDMETHOD(NEW) (BSTR bFILE, LONG lDimC, LONG lDimD, LONG* lID);

 

    . . .

   }

 

 

y también el grupo

 

   // SRRCW.cpp: implementación de CSRRCW

 

   #include "stdafx.h"

   #include "SRRCW.h"

   #include ".\srrcw.h"

   #include "srrcwx.h"

 

 

   // CSRRCW

 

   STDMETHODIMP CSRRCW::NEW(BSTR bFILE, LONG lDimC, LONG lDimD, LONG* lID)

   {

    // TODO: agregar aquí el código de implementación

 

 [ --------------------------------------------------------------

 

    Las siguientes sentencias son el cuerpo de implementación del procedimiento 

    y se introducen por edición tras haberse generado el "caparazón vacío" con el

    asistente

 

    USES_CONVERSION;

 

    // Convierte parámetro de nombre recibido a formato C

    char *cFile = W2A(bFILE);

 

    // Proceso

    *lID = SRRCW_NEW(cFile, lDimC, lDimD);

 

   ( Fin de sentencias añadidas )

  -------------------------------------------------------------- ]

 

    return S_OK;

   }

 

   . . .

 

 

Por tanto, en caso de necesitar un cambio o incluso una adicción posterior, puede hacerse manualmente cambiando/agregando las sentencias precisas en los dos fuentes que se muestran y en los tres puntos que se indican en negrita.

 

                                                                                                 _______

 

 

B.I.2.4 El programa interfaz PruebasV

 

El programa PruebasV está desarrollado para mostrar la forma de utilizar la clase COMw en VisualBasic.Net

 

Una imagen del mismo se presenta a continuación

 

 

 

Como su funcionamiento es prácticamente idéntico a la versión que utiliza la clase .Net vbFile, no se le dedicará aquí el detalle que se empleará con esta última versión más adelante al exponer el uso de la clase .Net

 

 

Por tanto, a continuación simplemente se va a exponer el comienzo del programa y el uso de los dos métodos mas importantes, CHAIN y WRITE:

 

 

   Public Class Form1

 

    Inherits System.Windows.Forms.Form

 

    Dim SRRCW As New COMw.CSRRCWClass ' Inclusión de la clase de soporte

    Dim lNreg As Long

    Dim lDimC As Integer

    Dim lDimD As Integer

 

 

    ' Carga del formulario

 

    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load

 

        Dim ID As Integer

        lDimC = 10

        lDimD = 80

 

 

        ' Crea ficheros virtuales soporte del proceso

 

        SRRCW.[NEW]("PRUEBASV", lDimC, lDimD, ID)

        SRRCW.[NEWr]("PRUEBASVVER", lDimC, ID)

        SRRCW.LIFO_NEW("PRUEBASVPILA", lDimD, ID)

        SRRCW.FIFO_NEW("PRUEBASVCOLA", lDimD, ID)

 

    End Sub

 

 

    ' Cierre del programa

 

    Private Sub Form1_CLose(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Closed

        Dim lresul As Long

        SRRCW.CLOSE(lresul)

    End Sub

 

 

    ' Uso del método Write

 

    Private Sub WRITE_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles WRITE.Click

 

        Dim lresul As Long

        Dim KinW As String

        Dim DinW As String

        Dim i As Integer

        Dim lKin As Integer

        Dim lDin As Integer

 

        ' Inz

        lNreg = 0

        Nchain.Text = " "

        . . .

 

 

        ' Completa clave

 

        lKin = Len(Kin.Text)

        KinW = Kin.Text

        For i = lKin To lDimC

            KinW = KinW + " "

        Next

 

 

        ' Completa datos

 

        lDin = Len(Din.Text)

        DinW = Din.Text

        For i = lDin To lDimD

            DinW = DinW + " "

        Next

 

 

        ' Graba item

 

        SRRCW.WRITE("PRUEBASV", KinW, DinW, lresul)

        Nwrite.Text = lresul.ToString

 

        ' Estadísticas

        Estadisticas_Click(sender, e)

 

    End Sub

 

 

    ' Uso del método Read

 

    Private Sub READ_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles READ.Click

 

        Dim lresul As Long

 

        ' Inz

        Kout.Text = " "

        Dout.Text = " "

        lNreg = lNreg + 1

 

 

        ' Lee ítem lNreg

 

        SRRCW.READa("PRUEBASV", lNreg, Dout.Text, Kout.Text, lresul)

        If lresul > 0 Then

            lNreg = 0

            Kout.Text = " "

            Dout.Text = " "

        End If

 

        ' Estadísticas

        Estadisticas_Click(sender, e)

 

    End Sub

 

 

    ' Uso del método Chain

 

    Private Sub CHAIN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CHAIN.Click

 

        Dim lresul As Long

        Dim KinW As String

        Dim DoutW As String

        Dim i As Integer

        Dim lKin As Integer

 

        ' Inz

        lNreg = 0

        Kout.Text = " "

        . . .

 

 

        ' Completa clave

 

        lKin = Len(Kin.Text)

        KinW = Kin.Text

        For i = lKin To lDimC

            KinW = KinW + " "

        Next

 

 

        ' Recupera item

 

        SRRCW.CHAIN("PRUEBASV", KinW, DoutW, lresul)

        Nchain.Text = lresul.ToString

 

        If lresul > 0 Then

            Kout.Text = KinW

            Dout.Text = DoutW

        End If

 

 

        ' Estadísticas

 

        Estadisticas_Click(sender, e)

 

    End Sub

    . . .

 

 

 

El resto de métodos se verá en detalle con la versión que utiliza la clase .net vbFile, ya que su funcionamiento es prácticamente idéntico en ambas versiones.

 

                                                                                                 _______




B.I.2.5 Uso de COMw en Visual Basic para Aplicaciones (VBA) de Excell


Los componentes COM también se pueden utilizar en el lenguaje Visual Basic para Aplicaciones (VBA) de Office. Aquí lo vamos a ver concretamente en Excell.

Para ello, en primer lugar, en el editor de VBA debe añadirse el componente COMw en el menú Herramientas-Referencias y utilizar la opción de examinar para localizar y añadir la "Biblioteca de tipos COMw".

Una vez agregado COMw se puede hacer referencia a sus métodos y el editor mostrará el prototipo cuando se estén introduciendo como en cualquier otra función VBA.


Construyamos ahora una hoja demo como la siguiente:

 

 

Donde hay una primera línea en que aparecen el indicador de fichero asignado, el nombre del fichero, su longitud de claves y datos y el botón de generación.

 

En las líneas siguientes aparecen los resultados de grabar, leer secuencialmente o leer por clave no secuencial.

 





El código para construirla asociado al botón DEMO es el siguiente:



 

Option Explicit         ' Se fuerza la declaración explícita de variables

Dim SRRCW As New CSRRCW ' Clase interfaz a SRRCW. Esta línea instancia el uso de COMw.CSRRCW con el nombre SRRCW

Dim Erro, ErroNum       ' Control de errores


Sub Demo()           ' Rutina que se asocia al botón DEMO para construir la hoja

 Dim File As String  ' Variable para nombre de fichero virtual
 Dim lDimC As Long   ' Variable para longitud de clave
 Dim lDimD As Long   ' Variable para longitud de datos
 Dim Nid As Long     ' Variable para el identificador del fichero virtual
 
 Dim N As Long       ' Variable limite for
 Dim i, j, k As Long ' Variable control for
 Dim Clave As String ' Variable para claves
 Dim Datos As String ' Variable para datos
 Dim Resul As Long   ' Control de resultados SRRCW
 
 Dim Rango As String ' Construcción de rangos variables
 Dim Fila As Long    ' NºFila que se utiliza
 
 
 On Error Resume Next ' En caso de error se ignora y continua el proceso en la siguiente línea

 

 

 
 ' Limpia el contenido anterior de la hoja
 
 Sheets("Hoja1").Select
 Cells.Select
 Selection.ClearContents
 
 Range("A1").Select

 

 

 

 ' Zona de generación del fichero virtual

 File = "FILE"
 lDimC = 2
 lDimD = 3
 

 

 Call SRRCW.NEW(File, lDimC, lDimD, Nid) ' Crea el fichero virtual "FILE"
 
 ErroNum = Err.Number
 Erro = Error(Err)     ' Importante: Aparecerá el error 429 "ActiveX no puede crear el objeto" si la dll COMw no estuviera registrada

                       '             en el sistema
 

 

 

 '  Construye la primera línea de la hoja

 

 Range("A1") = Nid     ' En caso de error Nid sería nulo
 
 Range("B1") = File
 Range("C1") = lDimC
 Range("D1") = lDimD
 


 ' Zona de carga de datos
 
 Range("A3") = "Write"
 

 

 N = 9 ' Nº de ítems de prueba a cargar
 
 For i = N To 1 Step -1
 
  j = N - i + 1 ' Indice inverso
 
  Clave = "1" & i
  Datos = "11" & i
 
  Call SRRCW.Write(File, Clave, Datos, Resul) ' Graba ítems en el fichero virtual
 
  ErroNum = Err.Number
  Erro = Error(Err)

 

 

  ' Duplica los datos cargados en la hoja
 
  Fila = 3 + j
 
  Rango = "A" & Fila
  Range(Rango) = Resul
   
  Rango = "B" & Fila
  Range(Rango) = Clave
 
  Rango = "C" & Fila
  Range(Rango) = Datos
 
 Next i
 

 

 

 ' Zona de lectura secuencial
 
 Range("E3") = "Read"
 
 For i = 1 To N
  
  Call SRRCW.READa(File, i, Datos, Clave, Resul) ' Lee ítems de forma secuencial

 
  ErroNum = Err.Number
  Erro = Error(Err)
 

 

  ' Vuelca los datos leídos en la hoja


  Fila = 3 + i
 
  Rango = "E" & Fila
  Range(Rango) = Resul
   
  Rango = "F" & Fila
  Range(Rango) = Clave
 
  Rango = "G" & Fila
  Range(Rango) = Datos
 
 Next i
 

 

 ' Zona de lectura por demanda "Chain"

 Range("I3") = "Chain"
 
 k = 0
 
 For i = 1 To N
  
  j = N - i + 1 ' Indice inverso
  
  k = k + 1
 
 
  ' Establece clave alternada para ver un ejemplo de acceso no secuencial
 
  If k > 1 Then
   Clave = "1" & i
   k = 0
  Else
   Clave = "1" & j
  End If
 

 

  ' Recupera los datos por clave

 

  Call SRRCW.CHAIN(File, Clave, Datos, Resul)
 
  ErroNum = Err.Number
  Erro = Error(Err)

 

 

  ' Vuelca los datos recuperados a la hoja
 
  Fila = 3 + i
 
  Rango = "I" & Fila
  Range(Rango) = Resul
   
  Rango = "J" & Fila
  Range(Rango) = Clave
 
  Rango = "K" & Fila
  Range(Rango) = Datos
 
 Next i
 

End Sub




Este sencillo ejemplo nos ha ilustrado sobre la forma de usar el modelo COM para poder aprovechar desarrollos externos desde Excell y Office.

                                                                                                _______