1. Esta comunidad utiliza cookies. Si continuas utilizando nuestra comunidad estás aceptando la utilización de nuestras cookies. Más información.

Solucionado Macro para ordenar matriz

Tema publicado en 'Soporte - Ayuda Excel' iniciado por Aitor, 10 Jul 2013.

Estado del tema:
Cerrado para nuevas respuestas
  1. Aitor

    Aitor Usuari@

    Registrado:
    10 Jul 2013
    Mensajes:
    5
    Me Gusta recibidos:
    0
    Trofeos:
    1
    Género:
    Masculino
    Versión Excel:
    2010
    Buenos días,
    Me estoy volviendo loco a la hora de ordenar los valores de 3 columnas con un orden determinado. Encontré una macro por la red que funciona, pero a la hora de la verdad, cuando hay más datos es muy lenta. Me explico:

    En un excel tengo 3 columnas con datos: Modo, Frecuencia, Origen. Estos valores los paso a una matriz, y ahora quiero ordenar esta matriz de menor a mayor modo y frecuencia. Es decir, si tengo

    Modo Frecuencia Origen
    8 1560 Direct
    7 1560 Direct
    8 1560 Direct
    8 1560 WEH
    -2 1560 WEH
    3 720 Direct
    4 720 Direct
    3 720 WEH

    Que me los ordene:
    Modo Frecuencia Origen
    3 720 Direct
    3 720 WEH
    4 720 Direct
    -2 1560 WEH
    7 1560 Direct
    8 1560 Direct
    8 1560 Direct
    8 1560 WEH

    Es decir, que ordene las frecuencias de menor a mayor y dentro de cada frecuencia que ordene el modo de menor a mayor. Y lo que es importante, si dentro del mismo modo y frecuencia se repiten "direct" o "weh" que los ordene "ordenados" es decir,
    8 1560 Direct
    8 1560 Direct
    8 1560 WEH

    y que no haga por ejemplo

    8 1560 Direct
    8 1560 WEH
    8 1560 DIRECT

    Os adjunto la macro que utilizo yo para hacerlo, pero como ya os he dicho si hay muchos datos es muy lenta (lo que os mando es un ejemplo simplificado, pero realmente tengo 25 columnas)


    Si me podeis ayudar os lo agradecería

    Saludos

    Adjuntos:

  2. logroastur

    logroastur Staff

    Registrado:
    11 May 2011
    Mensajes:
    1.791
    Me Gusta recibidos:
    490
    Trofeos:
    83
    Género:
    Masculino
    Versión Excel:
    2007, 2010
    Colaboración:
    Donación vía Paypal
    Buenas ubica el siguiente código
    CÓDIGO:
    Sub Ordenalo()
        Dim i As Long
        i = Range("A50000").End(xlUp).Row
        If i < 2 Then
            MsgBox "No existen datos a ordenar", vbExclamation, Application.OrganizationName
            Exit Sub
        End If
        Range("A2:C" & i).Sort key1:=Range("B2"), order1:=xlAscending, _
                               key2:=Range("A2"), order2:=xlAscending, _
                               key3:=Range("C2"), order3:=xlAscending
    End Sub
    
    Un saludo
  3. Aitor

    Aitor Usuari@

    Registrado:
    10 Jul 2013
    Mensajes:
    5
    Me Gusta recibidos:
    0
    Trofeos:
    1
    Género:
    Masculino
    Versión Excel:
    2010
    Muchas gracias logroastur

    El problema es que necesito que se me ordene dentro del vector, es decir, los datos los tendre metidos en un vector PresionRadial(2000,3) y se me tiene que ordenar aqui, mi idea es no tener que sacarlos por pantalla desordenados para luego ordenados. QUiero que se me ordenen en el vector
    Muchas gracias

    Saludos[DOUBLEPOST=1373461119,1373460276][/DOUBLEPOST]He leido que la función quicksort es más rápida. y yo tengo hecho:
    CÓDIGO:
    Sub QuickSortmodo(arr, Lo As Integer, Hi As Integer)
    Dim varPivot As Variant
    Dim varTmp As Variant
    Dim tmpLow As Integer
    Dim tmpHi As Integer
    tmpLow = Lo
    tmpHi = Hi
    varPivot = arr((Lo + Hi) \ 2, 1)
    Do While tmpLow <= tmpHi
    Do While arr(tmpLow, 1) < varPivot And tmpLow < Hi
    tmpLow = tmpLow + 1
    Loop
    Do While varPivot < arr(tmpHi, 1) And tmpHi > Lo
    tmpHi = tmpHi - 1
    Loop
    If tmpLow <= tmpHi Then
    For K = 1 To 3
    varTmp = arr(tmpLow, K)
    arr(tmpLow, K) = arr(tmpHi, K)
    arr(tmpHi, K) = varTmp
    Next K
    tmpLow = tmpLow + 1
    tmpHi = tmpHi - 1
    End If
    Loop
    If Lo < tmpHi Then QuickSortmodo arr, Lo, tmpHi
    If tmpLow < Hi Then QuickSortmodo arr, tmpLow, Hi
    End Sub
     
    Sub quicksortfrecuencia(arr, Lo As Integer, Hi As Integer)
    Dim varPivot As Variant
    Dim varTmp As Variant
    Dim tmpLow As Integer
    Dim tmpHi As Integer
    tmpLow = Lo
    tmpHi = Hi
    varPivot = arr((Lo + Hi) \ 2, 2)
    Do While tmpLow <= tmpHi
    Do While arr(tmpLow, 2) < varPivot And tmpLow < Hi
    tmpLow = tmpLow + 1
    Loop
    Do While varPivot < arr(tmpHi, 2) And tmpHi > Lo
    tmpHi = tmpHi - 1
    Loop
    If tmpLow <= tmpHi Then
    For K = 1 To 3
    varTmp = arr(tmpLow, K)
    arr(tmpLow, K) = arr(tmpHi, K)
    arr(tmpHi, K) = varTmp
    Next K
    tmpLow = tmpLow + 1
    tmpHi = tmpHi - 1
    End If
    Loop
    If Lo < tmpHi Then quicksortfrecuencia arr, Lo, tmpHi
    If tmpLow < Hi Then quicksortfrecuencia arr, tmpLow, Hi
    End Sub
    


    Esto me ordena bien el modo y frecuencia, pero no me pone bien la columna origen, es decir me lo deja:
    8 1560 Direct
    8 1560 WEH
    8 1560 DIRECT


    y yo quiero que sea
    8 1560 Direct
    8 1560 Direct
    8 1560 WEH


    es decir, dentro de cada mismo modo y frecuencia que todos esten ordenados primero los direct y luego los weh (o viceversa)

    He intendado crear otra funcion quicksortorigen, pero lo único que me hace es desordenar las otras dos columnas
  4. logroastur

    logroastur Staff

    Registrado:
    11 May 2011
    Mensajes:
    1.791
    Me Gusta recibidos:
    490
    Trofeos:
    83
    Género:
    Masculino
    Versión Excel:
    2007, 2010
    Colaboración:
    Donación vía Paypal
    Buenas la verdad es que en ocasiones (más de las que uno desea) intentamos reinventar la rueda.

    Bien comentas

    me pregunto por que y para que precisas tener que cargar una Array, realizar el ordenamiento de este y descargar dicho Array en la hoja.
    Si los datos son tomados de otra hoja y lo que deseas es que no se vean los datos desordenados bien utiliza la parada de refresco de pantalla y no se verían los datos hasta finalizado el código con lo cual se verían de forma ordenada, consumiendo menos recursos y de una forma rápida.
    Por ejemplo basado en el archivo de ejemplo sería

    CÓDIGO:
    Sub TraeloyOrdenalo()
        Dim i As Long
        With Hoja1
        i = .Range("A50000").End(xlUp).Row
        If i < 2 Then
            MsgBox "No existen datos a Traer", vbExclamation, Application.OrganizationName
            Exit Sub
        End If
        Application.ScreenUpdating = False
        .Range("A1:C" & i).Copy
        End With
        With Hoja3
            .Range("A1").PasteSpecial xlPasteValues
            Application.CutCopyMode = False
            .Range("A2:C" & i).Sort key1:=.Range("B2"), order1:=xlAscending, _
                                    key2:=.Range("A2"), order2:=xlAscending, _
                                    key3:=.Range("C2"), order3:=xlAscending
        End With
     
    End Sub
    
    Bien si lo ejecutas mostrara los datos de la Sin Ordenar en la hoja3 de forma ordenada
    Un saludo
  5. Aitor

    Aitor Usuari@

    Registrado:
    10 Jul 2013
    Mensajes:
    5
    Me Gusta recibidos:
    0
    Trofeos:
    1
    Género:
    Masculino
    Versión Excel:
    2010
    El asunto es que lo que os he mandado en el excel es un ejemplo. En mi macro realmente yo no tengo los valores copiados en una hoja excel: yo he ido haciendo unas operaciones y los resultados los he ido guardando en un vector, y ahora quiero ordenar ese vector antes de seguir haciendo otras operaciones, en ningun momento estoy escribiendo nada en la hoja excel.

    Por eso quería saber si había alguna forma de ordenarlo sin tener que escribirlo en excel, ordenar, y luego volver a copiarlo

    Saludos
  6. logroastur

    logroastur Staff

    Registrado:
    11 May 2011
    Mensajes:
    1.791
    Me Gusta recibidos:
    490
    Trofeos:
    83
    Género:
    Masculino
    Versión Excel:
    2007, 2010
    Colaboración:
    Donación vía Paypal
    Bien pues si es asi lo que debes de realizar es ordenar directamente en la carga del array y de esa forma ahorrar un proceso.
    Ahora yo personalmente usaría una hoja temporal tanto pata la toma de los datos y ordenamiento puesto que si el array es bastante grande consumirá más recursos y tiempo.

    Un saludo
  7. Aitor

    Aitor Usuari@

    Registrado:
    10 Jul 2013
    Mensajes:
    5
    Me Gusta recibidos:
    0
    Trofeos:
    1
    Género:
    Masculino
    Versión Excel:
    2010
    Es que ordenar en el array como lo tengo hecho ahora con la función bubble sort tarda bastante, el tamaño del array es normalmente de a(2000,25). Pero es que si lo hago con la función quick sort, la columna "origen no me la ordena bien"

    Entonces tendré que hacer lo de copiar a una hoja temporal, ordenarlo alli y luego volver a copiarlo en el array

    Me podeis ayudar con estos pasos? Es que yo para copiar en la hoja excel lo hago con
    for i=1 to X
    for j=1 to 25
    next j
    next i

    Y esto tarda bastante, hay alguna forma más rápida de hacerlo?
  8. logroastur

    logroastur Staff

    Registrado:
    11 May 2011
    Mensajes:
    1.791
    Me Gusta recibidos:
    490
    Trofeos:
    83
    Género:
    Masculino
    Versión Excel:
    2007, 2010
    Colaboración:
    Donación vía Paypal
    Buenas para poder darte un código optimizado de pasar los datos a una hoja temporal es preciso que indiques de donde tomas los datos.
    Por ejemplo si los datos son de un rango lógico es decir que o se debe de evaluar ninguna condición condicional puedes usar
    por ejemplo para el rango A1:Z50000 de la Hoja1 y llevarlos ordenados a la Hoja3
    CÓDIGO:
    Sub TraeloyOrdenalo()
        Dim i As Long
        Sheets.Add After:=Sheets(Sheets.Count)
        With Hoja1
            i = .Range("A50000").End(xlUp).Row
            If i < 2 Then
                MsgBox "No existen datos a Traer", vbExclamation, Application.OrganizationName
                Exit Sub
            End If
            Application.ScreenUpdating = False
            .Range("A1:Z" & i).Copy
        End With
        With Sheets(Sheets.Count)
            .Range("A1").PasteSpecial xlPasteValues
            Application.CutCopyMode = False
            .Range("A2:Z" & i).Sort key1:=.Range("B2"), order1:=xlAscending, _
                                    key2:=.Range("A2"), order2:=xlAscending, _
                                    key3:=.Range("C2"), order3:=xlAscending
            .Range("A1:Z" & i).Copy
        End With
        With Hoja3
            .Range("A1").PasteSpecial xlPasteValues
            Application.CutCopyMode = False
        End With
        Application.DisplayAlerts = False
        Sheets(Sheets.Count).Delete
     
    End Sub
    
    Bien esto si se deben de usar solamente 3 niveles de ordenamiento si por el contrario precisas más niveles se debería de usar por medio de creación de una tabla dinámica
    Un saludo
  9. Aitor

    Aitor Usuari@

    Registrado:
    10 Jul 2013
    Mensajes:
    5
    Me Gusta recibidos:
    0
    Trofeos:
    1
    Género:
    Masculino
    Versión Excel:
    2010
    Yo los datos sin ordenar los tengo en un array de normalmente 2000 filas y 25 columnas(las columnas son fijas) que lo he ido llenando mediante fórmulas utilizando valores de distintas pestañas. Es decir, yo quiro hacer una macro en la que el punto de partida sea

    1. Tengo un array Presion radial(2000,25) lleno de valores
    2.Las primeras 3 columnas son las columnas modo, frecuencia y origen. Tengo que ordenar por modo primero y luego por frecuencia. Yo creo que no tengo que ordenar por "origen" porque tal y como están los datos metidos en el array antes de ordenar siempre están los valores "Direct" primero y luego los Weh" .Lo digo porque cuando he ordenado los datos de las dos primeras columnas en una hoja excel a traves de pestañas excel de ordenar siempre me las ha ordenado bien, es decir me ha puesto el orden que quiero, los "direct" con los "direct" y los "weh" con los "weh"
    Modo Frecuencia Origen ...
    8 1560 Direct ....
    8 1560 Direct .....
    8 1560 WEH ....

    3. Por lo que me decis, lo primero que tengo que hacer es copiar estos datos en una hoja auxiliar excel
    4. Luego los ordeno
    5.Vuelvo a copiar los datos ordenados en mi array
    6.Borro la hoja temporal
    7. Sigo trabajando


    No se si me he explicado bien, te mando un excel de lo que tengo que ordenar (ordenando por modo y frecuencia), y cómo quedaría ordenado. Solo que estos valores en vez de estar en una hoja excel están en un array y serían más filas

    Y estoy buscando la manera de que dure poco haciendolo[DOUBLEPOST=1373550128,1373550057][/DOUBLEPOST]vaya, no lo he subido...
    Ahora sí

    Adjuntos:

Estado del tema:
Cerrado para nuevas respuestas