PARTIR ARRAY

galileogali

Well-known Member
Joined
Oct 14, 2005
Messages
748
Tengo un ARRAY por ejemplo Bidimensional:
Mimatriz ( 1 to 70536) .
Quiero dividirlo en dos; MiMatrizSh1(1 to 65536, 1 to 1) y MiMatrizSh2(65537 to 70536, 1 to 1)

¿¿Existe alguna Forma de hacer esta division sin necesidad de Loopear en un FOR NEXT, SIN PERDER LOS DATOS, desde ya???

(Tambien seria válida una división como esta:MiMatrizSh1(1 to 65536, 1 to 1) y MiMatrizSh2(1 to 5536, 1 to 1)

He probado con REDIM PRESERVE, pero no lo logro.
 

Excel Facts

Excel motto
Not everything I do at work revolves around Excel. Only the fun parts.
Usted siempre pone preguntas bien interesantes, ¿sabe?

Bueno, usted tiene razón que PRESERVE no permite a uno cortar una matriz a cierto punto; o sea que esto no da los resultados deseados:
Code:
Sub foo()
    '// no funciona como quiere
    Dim x(15) As Integer, v
    
    For i = LBound(x) To UBound(x)
        x(i) = i
        Next i
    v = x
    
    Cells.Clear
    Range("A1:P1") = v
    Range("A1:A16") = Application.WorksheetFunction.Transpose(x)
    ReDim Preserve v(5 To 10)
    Range("B3:B9") = Application.WorksheetFunction.Transpose(v)
End Sub

Pero si una usa las funciones de SPLIT y JOIN se puede evitar bucles explicitos. Note que JOIN y SPLIT no están disponibles en versiones viejas de Excel.

Code:
Sub foo2()
    Const c_UBound1 As Long = 10
    Dim x(15) As String, s(2) As String, v1(), v2()
    
    For i = LBound(x) To UBound(x)
        x(i) = i
        Next i
    'sc = x(c_UBound1)
    s(0) = Join(x, "|")
    p = InStr(1, s(0), x(c_UBound1) & "|")
    p = p + Len(x(c_UBound1))
    s(1) = Left(s(0), p)
    s(2) = Right(s(0), Len(s(0)) - p)
    'Debug.Print s(0); vbCrLf; s(1); vbCrLf; s(2)
    
    '// load array 1
    Cells.Clear
    Range("A1:A11") = Application.WorksheetFunction.Transpose(Split(s(1), "|"))
    ReDim v1(1 To 11, 1 To 2)
    v1 = Range("A1:B11")
    ReDim Preserve v1(1 To 11, 1 To 1)
    
    '// load array 2
    Cells.Clear
    Range("A1:A5") = Application.WorksheetFunction.Transpose(Split(s(2), "|"))
    ReDim v2(1 To 5, 1 To 2)
    v2 = Range("A1:B5")
    ReDim Preserve v2(1 To 5, 1 To 1)
    
End Sub

Obviamente faltan unos cambios más para hacer. Pero sé que usted es capáz hacerlos.

Saludos y feliz año nuevo,
 
Upvote 0
Gracias Greg:
Aun no he tenido el tiempo para digerir tranquilo esta OPCION de usar JOIN y SPLIT
Solo comento que anoche estuve viendo las FUNCION para ARRAYS de CHIP PEARSON particularmente CHANGEBOUNDSOFARRAY Y RESPUES DE HACER numerosas pruebas de consistencia del Objeto ARRAY propuesto inevitablemente RE ACOMODA la DATA a traves de un BUCLE.

Asi que por ahora me dedicare a analizar concienzudamente tu propuesta: fundamentalmente la idea es poder "buclear" lo menos posible.


Thanks, GREG
 
Upvote 0
Partir ARRAY

GREG:
Retorno tu MACRO con mis comentarios: la Mayoría MUY OBVIOS, solamente como para ACLARAR el PROCEDIMIENTO....

Particularmente me GUSTARIA QUE LEAS MIS COMENTARIOS EN NEGRITA (BOLD):


Sub foo2()
Const c_UBound1 As Long = 10 ' Establezco el valor de corte, para la partición
Dim x(15) As String 'Declaro Array fijo para el ejemplo, Origen a particionar.
Dim s(2) As String 'Declaro Matriz de Dimensión 3 para manipular Cadenas.
'¿es necesario que esta variable sea un Array?

Dim v1(), v2() ' Arrays dinamicas, Variant

'Cargo Array X con 0,1....15 valores para tener con qué ejemplificar.
For i = LBound(x) To UBound(x)
x(i) = i
Next i

'sc = x(c_UBound1)



s(0) = Join(x, "|") 'Construyo una string 0|1|.......|14|15

.¿Cuál es el límite de almacenamiento?

Debug.Print s(0) 'la muestro

p = InStr(1, s(0), x(c_UBound1) & "|") 'Establezco en caracteres el lugar de Corte de las Cadenas Len("0|......|9|")
p = p + Len(x(c_UBound1)) 'rectifico el valor en caracteres a fin de que la string incluya a x(c_UBound1) Len("0|....|9|")+Len("10")
s(1) = Left(s(0), p) 'Corto la primera Rama de la cadena (Hasta p) y la Almaceno. Pregunta:¿Por qué en un array?

s(2) = Right(s(0), Len(s(0)) - p) 'Corto la segunda Rama desde p.... y la almaceno
Debug.Print s(0); vbCrLf; s(1); vbCrLf; s(2) 'muestro los pedazos por separado.


'// ETAPA DE "VAYAMOS A WORKSHEET!! que hay SALE OFF...%!!!!
Hoja2.Cells.Clear 'Limpio el terreno

Range("A1:A11") = Application.WorksheetFunction.Transpose(Split(s(1), "|"))

'Siendo que SPLIT devuelve una Matriz UNIDIMENSIONAL:
'Para Ingresarla a una Range No haría FALTA REDIMENSIONARLA A A DOS DIMENSIONES ?



'Cargo un Rango de Rows.Count = 11, para eso "almaceno en un array", los valores
'DELIMITADOS por "|", antes de pasar a Range, verticalizo el array.
'Pregunta: ¿para CARGAR en RANGE no es necesario antes hacer REDIM de Split(s(1), "|"), para que tenga dos dimensiones?

'ACA ES DONDE ME PIERDO, ¿QUE ES LO QUE QUEREMOS HACER?

ReDim v1(1 To 11, 1 To 2)
'Se redimensiona el VARIANT a 11 * 2, ¿ * 2?
v1 = Range("A1:B11")

' cargo los valores en el Array del Rango de dos columnas:1) "a1:a11" (donde hay "1....11")

'y 2) "B1:B11", donde, según entiendo, no debería haber nada.¿?



ReDim Preserve v1(1 To 11, 1 To 1) 'Entonces Redimensiono Preservando la ULTIMA dimensión de V1 a: 11 * 1. Aca es como que vuelvo al Rango

'que me resulta más lógico.


'// load array 2. Mismo Esquema para la SEGUNDA Rama de la STRING s(2).Mismas Preguntas...mismas respuestas.
Cells.Clear
Range("A1:A5") = Application.WorksheetFunction.Transpose(Split(s(2), "|"))
ReDim v2(1 To 5, 1 To 2)
v2 = Range("A1:B5")
ReDim Preserve v2(1 To 5, 1 To 1)

End Sub



Nota: Estoy pensando en armar otra version de esta EXCELENTE SOLUCION TUYA, pero usando:

la Propiedad "COUNT" de SPLIT, para FRACCIONAR.
REARMAR LA SUBCADENA CON JOIN
....REPLACE de la PRIMERA SUBCADENA EN LA CADENA TOTAL
POR ""
y SPLIT de la SEGUNDA SUBCADENA....
mmmmm? tengo que probar.....

GALILEOGALI
 
Upvote 0
<ul>[*]¿es necesario que s() sea un Array?[/list]No. Bien bien podía haber usado tres variables diferentes como strAll, strFront, y strBack u otro grupo de nombres que me ocurriese.

<ul>[*]¿Cuál es el limite de almacenaje?[/list]Para hileras de largo fijo hasta 65,400 caracteres. Para hileras de largo variable hasta dos mil millones.

<ul>[*]s(1) = Left(s(0), p) 'Corto la primera Rama de la cadena (Hasta p) y la Almaceno. Pregunta:¿Por qué en un array?[/list]Porque fue un martes. :lol: O sea, vea arriba -- no importa.

<ul>[*]Siendo que SPLIT devuelve una Matriz UNIDIMENSIONAL: [*]Para Ingresarla a una Range No haría FALTA REDIMENSIONARLA A A DOS DIMENSIONES ? [/list]Vamos a tocar eso de dos dimensiones con los rangos.

<ul>[*]Se redimensiona el VARIANT a 11 * 2, ¿ * 2?[/list]Es que si empujamos un rango de una sola columna a v() nos da una matriz de una sola dimensión. Realmente para que sea más robusto, sería mejor utilizar el constante de cortar definido en la cabeza de la rutina. Es decir algo como
Code:
ReDim V1(1 to c_UBound1, 1 to 2)
Y también el rango usado debe de estar definido usando este constante:
Code:
V1=Range("A1").Resize(c_Ubound1,2)

Sobre eso de cómo cortar y rearmar. Haz lo que le conviene. Su pregunta era como mover piezas de una matriz unidimensional a dos matrices duodimensionales sin bucle. Ya que hemos encontrado un sendero útil, el color de nuestros zapatos no importa tanto mientras caminamos el sendero correcto. ¿verdad ;-)?
 
Upvote 0
Greg: Muy claro y con buen humor: ambas cosas se agradecen.
Gracias a tus aclaraciones y a la idea de SALTAR de STRINGS A ARRAYS y de ARRAYS a STRINGS y a esa propiedad de SPLIT (...,...,COUNT) (que, inicialmente, no terminaba de entender que deja la "COLA" de la STRING en mtrzSPLITICA(uBOUND))....

esta es la idea que te mencionaba de usar el COUNT de SPLIT......


Option Base 1
Sub recortarARRAY()
Dim v() As String, i As Long, ParseArr() As String, Parse1() As String, Parse2() As String

Dim strSecond As String, strFirst As String, stALL As String



Const TOPE1 As Long = 44000
Const TOPEend As Long = 56000


ReDim v(TOPEend)


For i = 1 To TOPEend
v(i) = i * 2
Next i



stALL = Join(v, "|")

ParseArr = Split(stALL, "|", TOPE1, 1)
strSecond = ParseArr(UBound(ParseArr))
ParseArr(UBound(ParseArr)) = ""

strFirst = Join(ParseArr, "|")
Parse1 = Split(strFirst, "|")
Parse2 = Split(strSecond, "|")

Hoja1.Cells.Clear

Range("a1:a" & TOPE1).Value = Application.WorksheetFunction.Transpose(Parse1)
Range("b1:b" & (TOPEend - TOPE1 + 1)).Value = Application.WorksheetFunction.Transpose(Parse2)

End Sub

Excuse me: podrías explicarme que se considera una "Hilera de longitud fija" y una de longitud variable? (o citarme algun Link donde esto este claro) o tal vez un ejemplo.
Desde ya GRACIAS GREG
 
Upvote 0
Gali,

Corras el siguiente y verás ;-) ==>
Code:
Sub SillyStrings()
    Dim strVar As String, strFix As String * 20
    
    strVar = "Hola"
    Debug.Print "|" & strVar & "|"
    
    strFix = "Adios"
    Debug.Print "|" & strFix & "|"
    
    RSet strFix = "Hello"
    Debug.Print "|" & strFix & "|"
    
End Sub

Saludos,
 
Upvote 0
Muy claro GREG. Tenía el concepto pero me faltaba identificarlo con su "denominaciòn".
De paso me hiciste aprender RSet y LSet que no las conocía.

Gracias y hasta pronto.
 
Upvote 0
Continuando con el tema me plantee hacer una Funcion que dado un X ARRAY y j (as long), con Lbound(x)<= j <= Ubound(x), devuelva otro ARRAY, donde x(j) ya no exista y la dimensión del ARRAY haya disminuido en 1.
La SUB listar es simplemente un recurso para ver cómo funcionaba la Function. Cuando tengas/n tiempo me gustaría una miradita a la Function.
Me gustaría (aunque me cueste reconocerlo) que me muestren otra forma más simple de hacer esto (aunque me frustre, no importará).
Function EliminarItem(x() As String, n As Long) As Variant

Dim r As String

tope = UBound(x) - 1

r = Join(x, "|")

If tope + 2 = n Then


r = Left(r, InStrRev(r, "|", -1) - 1)

Else

End If

x = Split(r, "|", n + 1, vbTextCompare)

ReDim Preserve x(LBound(x) To UBound(x))

If tope + 2 = n Then
Else
x(UBound(x) - 1) = Empty
End If

r = Replace(Join(x, "|"), "||", "|")
If Left(r, 1) = "|" Then r = Right(r, Len(r) - 1)

ReDim x(0 To tope)

x = Split(r, "|")
EliminarItem = x


End Function

Sub listarsin()
Dim f As Long
Dim x() As String

x = Split([a1], " ")

Range("h1:h9") = Application.Transpose(EliminarItem(x, 6))


End Sub

Galileogali
 
Upvote 0
Estuve cambiando un poco el código de ayer a hoy, para ver si logor algo más ductil en la funcion EliminaItem.

Escribiendo en A1 de la hoja1, una cadena de palabras separadas por espacios

Function EliminaItem(x() As String, n As Long) As Variant

Dim strR As String

'Contemplar caso en que el ARRAY x() tiene un solo elemento

If UBound(x) = 0 Then
EliminaItem = Nothing
Exit Function
End If

Select Case n - 1
Case LBound(x) 'el item a eliminar es el primero
x(LBound(x)) = Empty ' Vacío el Primer Item

strR = Join(x, "|") 'Rearmo la CADENA

strR = Right(strR, Len(strR) - 1) 'Elimino el Primer "|"

EliminaItem = Split(strR, "|") 'Rearmo el ARRAY con la cadena disminuida

Exit Function

Case UBound(x) ' Caseo el ítem a eliminar es el último

x(UBound(x)) = Empty ' Vacío el Ultimo Item

strR = Join(x, "|") 'Rearmo la CADENA

strR = Left(strR, Len(strR) - 1) ' elimino el último "|"

EliminaItem = Split(strR, "|") ' Rearmo el ARRAY con la cadena disminuida

Exit Function

Case Else

x(n - 1) = Empty 'vacío el Item

strR = Join(x, "|") 'rearmo la cadena

strR = Replace(strR, "||", "|") 'elimino el espacio vacío
EliminaItem = Split(strR, "|") 'rearmo el ARRAY con la cadena disminuida
End Select

End Function

Sub listarprueba()
Dim Arrx() As String, cad As String
Dim n As Long

cad = Trim([a1])
If Len(cad) = Len(Replace(cad, " ", "")) Then

Arrx = Split(cad)
Else

Arrx = Split(Trim([a1]), " ")
ReDim Preserve Arrx(LBound(Arrx) To UBound(Arrx))

n = Application.InputBox("Elija un elemento entre: " & (LBound(Arrx) + 1) & " y " & (UBound(Arrx) + 1))

Arrx = EliminaItem(Arrx, n)
End If

[g:g].Clear


Range("g1:g" & (UBound(Arrx) + 1)).Value = Application.Transpose(Arrx)


End Sub

Haciendo correr la macro se puede obtener la eliminacion del Item ubicado en el n.esimo lugar.
 
Upvote 0

Forum statistics

Threads
1,223,958
Messages
6,175,636
Members
452,662
Latest member
Aman1997

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top