2011-07-21 43 views
19

Sé que puede tomar fácilmente un rango de celdas y pegarlas en una Variant Array, pero quiero trabajar con una matriz de cadenas (porque es unidimensional y requiere menos memoria que una matriz Variant).Excel VBA: Rango a String Array en 1 paso

¿Hay alguna forma de convertir automáticamente un rango en una matriz de cadenas?

En este momento estoy usando una función que tomará el rango y guardará los valores en una matriz variante, luego convierta la matriz variante a una matriz de cadenas. Funciona bien, pero estoy buscando una forma de ir directamente del rango a la matriz de cadenas. Cualquier ayuda sería muy apreciada.

Function RangeToArray(ByVal my_range As Range) As String() 

Dim vArray As Variant 
Dim sArray() As String 
Dim i As Long 

vArray = my_range.Value 
ReDim sArray(1 To UBound(vArray)) 

For i = 1 To UBound(vArray) 
    sArray(i) = vArray(i, 1) 
Next 

RangeToArray = sArray() 

End Function 

ACTUALIZACIÓN: es que parece que no hay manera de saltarse el paso de tirar los datos en una matriz de variables primero antes de convertirlo en una matriz de cadenas unidimensional. Una pena si es verdad (incluso si no requiere mucho esfuerzo, me gusta optimizar al máximo, así que esperaba que hubiera una forma de saltear ese paso). Cerraré la pregunta en unos días si no se presenta ninguna solución. Gracias por los útiles comentarios, chicos!

ACTUALIZACIÓN2: La respuesta es para Simon, quien hizo un gran esfuerzo (al igual que todos los demás) y puntualizó que de hecho es imposible pasar del rango a la matriz de cuerdas en una sola toma. Gracias a todos.

+0

Hay rutinas de manipulación de memoria directos se puede acceder en VBA para crear una función muy eficiente para convertir la matriz. No tengo el tiempo y las habilidades para montar uno, aunque tengo un código de mapeo de memoria en mi aplicación principal, por lo que está disponible y te ayudará a crear un programa de copia de matriz extremadamente eficiente. –

+1

El enlace a una respuesta que di con algunas de las funciones de memoria es [aquí] (http://superuser.com/questions/196565/how-to-merge-data-from-two-differently-structured-excel -files/196577 # 196577). –

+0

Aunque no pude aplicar la información en sus enlaces a este problema en particular, fue una buena lectura e interesante. Gracias por el enlace. – aevanko

Respuesta

10

¿Qué tal ...

Public Function RangeToStringArray(theRange As Excel.Range) As String() 

    ' Get values into a variant array 
    Dim variantValues As Variant 
    variantValues = theRange.Value 

    ' Set up a string array for them 
    Dim stringValues() As String 
    ReDim stringValues(1 To UBound(variantValues, 1), 1 To UBound(variantValues, 2)) 

    ' Put them in there! 
    Dim columnCounter As Long, rowCounter As Long 
    For rowCounter = UBound(variantValues, 1) To 1 Step -1 
     For columnCounter = UBound(variantValues, 2) To 1 Step -1 
      stringValues(rowCounter, columnCounter) = CStr(variantValues(rowCounter, columnCounter)) 
     Next columnCounter 
    Next rowCounter 

    ' Return the string array 
    RangeToStringArray = stringValues 

End Function 
+1

Ya tengo una función que toma una matriz variante y la convierte en una matriz de cadenas (publicada en cuestión). ¡Buscando una manera de saltearse ese paso! – aevanko

+1

Ah ... mi mal. Realmente no hay forma de saltear este paso, aunque ¿cuál es el problema de tener que simplemente llamar a una función para convertir? Solo hay 10 caracteres extra de código después de todo ... –

+0

@SimonCowen pero hay cientos de caracteres en su función, aún así funciona – iliketocode

2
Function RangeToStringArray(myRange as range) as String() 

    ReDim strArray(myRange.Cells.Count - 1) As String 
    Dim idx As Long 
    Dim c As Range 
    For Each c In myRange 
     Set strArray(idx) = c.Text 
     idx = idx + 1 
    Next c 

    RangeToStringArray = strArray 
End sub 
1

Si no le importa alterar el contenido del portapapeles a continuación:

  1. copiar el rango en el portapapeles con el método de copia :

    MyTargetRange.Copy 
    
  2. Copie los contenidos del portapapeles a una variable de cadena (busque en este sitio o en otro lugar para transferir cadenas al portapapeles).

  3. dividir la cadena en una matriz de variante:

    MyStringArray = Split(MyClipboardText, vbCrLf) 
    
  4. OPCIONAL: La matriz tiene un elemento adicional en blanco, porque siempre hay un retorno adicional (vbCrLf) al final del texto que acaba de copiar al portapapeles. Para quitar simplemente cambiar el tamaño de la matriz:

    Redim Preserve MyStringArray(Ubound(MyStringArray) - 1) 
    

muy simple y rápida !!!

Los inconvenientes son que el portapapeles puede cambiar cuando menos lo esperas (durante un recálculo) y que solo produce matrices de cadenas (no Dobles ni otros tipos de valores numéricos).

Esto sería MUY ÚTIL si está trabajando con muchas funciones repetitivas (miles) que usan los mismos datos (miles de puntos de datos). La primera vez que se llama a su función, haga todos los cálculos intermedios en los rangos de datos que necesita, pero guarde los resultados en variables estáticas. Guarde también una copia de cadena de sus rangos de entrada a través del portapapeles. Con cada llamada posterior a su función, convierta los rangos de entrada a texto, nuevamente a través del portapapeles, y compare con la copia guardada.Si son iguales, es posible que pueda eludir todos los cálculos preliminares.

+0

Tal vez alguien pueda agregar a esto sobre cómo copiar al portapapeles y recuperarlo nuevamente sin alterar los datos del portapapeles superior. Tal vez a través de la API? –

3

En realidad, puede ir directamente de un rango a una matriz utilizando las funciones Dividir, Unir y un delimitador no en el texto.

Asumiendo que ya tiene asignado un rango de valores de 1D como SrcRange

Dim Array() As String: Array = Split(Join(Application.Transpose(SrcRange), "#"), "#") 
+1

Esta es la única respuesta a la pregunta completa, "Range to String Array ** in 1 step **". Desde Office 2010 en adelante, se accede al método de transposición a través del objeto WorksheetFunction. 'WorksheetFunction.Transpose (SrcRange)' – lonestorm

+0

Cuando trato de hacer esto en Excel 2016 obtengo 'Llamada o argumento de procedimiento inválido'. – nhinkle

0

rangos con nombre utilizados en VBA ya son matrices. Por lo tanto, primero haga que el rango pase a un rango con nombre, luego refiérase a él y elimine el rango con nombre. Por ejemplo:

ThisWorkbook.Names.Add Name:="test_array", RefersTo:=Sheet1.Range("A4:B10") 
a = Sheet1.Range("test_array") 
ThisWorkbook.Names("test_array").Delete