2012-07-16 34 views
6

Así que estoy trabajando en un proyecto de Excel que va a cargar un dll de C++ usando VBA. Lo que me gustaría hacer es poder pasar un rango de Excel sin un tipo específico (los datos pueden ser numéricos o categóricos) al dll de C++ (la mejor manera en que puedo describir mi rango de Excel es del tipo variant).Pasa datos de tipo arbitrario entre VBA y dll

Así que los pasos probablemente implican:

  1. cargar la DLL en VBA
  2. Enviar el rango de Excel para DLL (El rango puede contener columnas de números y/o columnas de cuerdas)
  3. manipular el datos de excel en el archivo dll

Estoy pensando en usar la variante de Excel y la variante de C++. Pero no está claro para mí cómo usar la variante C++ ya que no pude encontrar ninguna buena documentación sobre ella.

Otra sugerencia que recibí fue para la programación de COM.

Mis preguntas:

  • Podría un alma amable posiblemente proporcionen indicadores para mí sobre cómo proceder? (por ejemplo, al proporcionar el prototipo de C++ y un ejemplo simple de cómo manejar la variante)
  • ¿Alguien conoce alguna documentación/tutorial sobre el uso de variantes de C++ (y quizás junto con VBA)?
  • ¿Es preferible usar COMs para usar VARIANTES si la velocidad es un problema?
  • ¿Está utilizando la API C una opción?

ACTUALIZACIÓN:

  • El tamaño de los rangos que necesito para manipular puede ser de gran tamaño (~ 500.000 filas).
  • La velocidad es un factor, por lo tanto, me gustaría evitar la copia innecesaria tanto como sea posible.

Respuesta

2

a que usted solamente quiere pasar los datos a la DLL (y no punteros a objetos reales Excel como Range), tiene dos opciones fundamentales:

  1. Usted tiene enormes conjuntos de datos y desea evitar copiar tanto como sea posible.
    En este caso, es posible que desee pasar la misma matriz Variant que obtiene al llamar al Range.Value. Para hacer eso, tendrá que escribir un pequeño TLB para referenciar desde VB, en el que describiría su función C++ exportada esperando un SAFEARRAY(VARIANT)*. Esto se debe a que el operador Declare no le permitirá aprobar un SAFEARRAY *.
    La función se verá así:

    LONG __stdcall ReturnArrLowerBound(SAFEARRAY** ppArr) 
    { 
        if (ppArr == NULL) return -1; 
        SAFEARRAY* pArr = (*ppArr); 
    
        LONG res = 0; 
        SafeArrayGetLBound(pArr, 1, &res); 
    
        return res; 
    } 
    

    Y el descripion TLB se parecerá a lo siguiente:

    [ 
        uuid(A686B138-D8CE-462e-AEF2-75DA4DBF1C75) 
    ] 
    library foo 
    { 
        [ 
         dllname("TestSafearray.dll") 
        ] 
        module vb 
        { 
         [entry("ReturnArrLowerBound")] 
         LONG __stdcall ReturnArrLowerBound(SAFEARRAY(VARIANT)* ppArr); 
        } 
    } 
    

    Y su proyecto C++, obviamente, incluirá un archivo de definición:

    LIBRARY "TestSafearray" 
    
    EXPORTS 
        ReturnArrLowerBound 
    
  2. Sus conjuntos de datos son de un tamaño razonable y no le importa un poco copiar.
    Luego haga que su función C++ acepte un simple int[] y Declare en VB como aceptando arr() as Long. En el lado VB, asigne una matriz en Long sy copie los elementos en ella desde la matriz Range.Value.

+0

Gracias! Si no me equivoco, escribir el TLB implica una programación COM, ¿verdad? ¿Y eso limita la portabilidad de la aplicación (particularmente en máquinas Linux)? – SMir

+1

@SMir No, no incluye programación COM per se. Solo escribe TLB para que VB comprenda la firma de su función C++. Aparte de eso, la función es una función exportada de estilo clásico que no es COM. – GSerg

+0

Gracias por la pronta respuesta. ¿El uso de 'Variant' me permite pasar tipos mixtos a la DLL? O solo permite tener un solo tipo (ya sean cadenas o números, etc.). – SMir

Cuestiones relacionadas