A Velneo le cuesta ordenar

Hola.

El otro día os comenté que copiar una Lista a una Cesta implicaba perder el orden original de la Lista y había que tenerlo en cuenta en nuestro código. El equipo de desarrollo dió una explicación nada convincente.
Imaginad que queréis pasar una Lista ordenada a un Objeto mediante Añadir lista al objeto y perdiérais el orden de la Lista. Sería un desastre, pero tranquilos, que en este caso no pasa.

Al hilo de este tema se ha retomado el problema de gestionar el Orden de las Listas que son entrada de los Informes de Velneo.
Lo que en un principio parece una cuestión banal, cuando vuelves a practicar la “ancestral técnica de Prueba y Error” a la que nos tiene acostumbrados Velneo, el problema de ordenar Listas se convierte en la bestia negra del asunto.

Disponemos de 2 comandos para Ordenar:

  • El comando nativo “Ordenar lista” que solo ordena campos simples, es decir, no correspondientes a tablas maestras.
    No tiene la opción de Ordenación Ascendente/Descendente. En definitiva, un “asco” de comando.
  • La función del API RegisterList.sort(campo1, desc, campo2, desc, …). Esta función está diseñada para ordenar como dios manda, con varios campos implicados, incluso enlazados del maestro y con la opción de Ascendente/Descendente.
    La pena es que no funciona correctamente y lo más grave de todo es que Velneo no dice nada y muchos estamos perdiendo horas intentando que funcione sin resultados positivos.

Pues este es el “triste” panorama si queremos ordenar por varios campos:

  • De forma nativa solo podemos hacerlo con orden Ascendente y campos no enlazados de la tabla.
  • Con la función sort() del API podemos además ordenar por campos enlazados del maestro.
    Cuando hay varios campos, ejecutamos un sort() por cada campo, empezando por el campo menos significativo. En este caso se respeta la ordenación de un sort() a otro, aunque yo lo tuve que ver para creerlo, ya no me fio.

La ordenación ascendente/descendente independiente de cada campo no es posible, o por lo menos yo no lo he conseguido de una forma inmediata. Lógicamente cada comando “Invertir lista” afecta al último campo ordenado, pero también a la ordenación de los anteriores. Seguramente me faltan más horas de prueba y error.

¿Cómo ordenamos una lista por los campos campo1 desc, campo2 asc, campo3 desc?
¿Habrá algún algoritmo matemático que consiga obtener ese resultado combinando los comandos Ordenar/sort() e Invertir/invert().?

Si alguién puede aportar algo de conocimiento …

Saludos
Paco Satué

2 Me gusta

Buenas tardes Paco.

Seguramente me equivoco en ambas afirmaciones.

  • El comando nativo creo o por lo menos permite, ordenar por campos enlazados.
  • La ordenación invertida funciona por que, basandome en mi experiencia, hace un multipartir lista y luego las une de alguna manera. El multipartir previamente ordena para poder partir. Así a bote pronto, habría que usar el papel, digamos que coge bloques de registros.

En la Wikipedia hay un ejemplo que nos puedo orientar mejor.
(4, 1) (3, 7) (3, 1) (4, 6) (original)
(4, 1) (3, 1) (4, 6) (3, 7) (después de ser ordenado por el segundo valor)
(3, 1) (3, 7) (4, 1) (4, 6) (después de ser ordenado por el primer valor)

Como se ve, la lista queda perfectamente ordenada empezando por el orden invertido en la ordenación.

Si fuera al revés:
(3, 7) (3, 1) (4, 1) (4, 6) (después de ser ordenado por el primer valor)
(3, 1) (4, 1) (4, 6) (3, 7) (después de ser ordenando por el segundo valor, el orden por el primer valor es perturbado)

Desde soporte me comentaron que le han dado prioridad al comando sort de la API. Por lo menos, con el arreglo del otro día si podemos ordenar desde la api. Pero claro, conociendo como se hace ya que la documentación está mal.

Con eso y de manera chapuza, podríamos hacer un script genérico en javascript que reciba una lista y por parámetros los campos y orden a aplicar de devolver la lista ordenada.

¡Esto ya me dio frio, y apenas voy iniciando!

1 me gusta

Hola Manuel.

Tienes razón, el comando nativo “Ordenar lista” sí que ordena por campos enlazados de maestro, lo había confundido con el comando nativo “Multipartir lista” que no lo hace.

Vamos a ver si centramos el tema.

  • Si todas las ordenaciones son Ascendentes no hay problema, se ejecutan las ordenaciones empezando por el campo menos significativo y todo correcto.
  • El problema surge cuando mezclamos campos con ordenaciones Ascendentes y Descendentes. Con el comando Multipartir se podría solucionar, pero lamentablemente ordena previamente la Lista antes de partirla y por lo tanto deshace la Ordenación Descendente que pudiera haber.

En fin, tampoco será muy habitual tener que ordenar varios campos de manera Descendente.

Saludos
Paco Satué

Hola Manuel.

¡¡ Ya lo hemos conseguido !!.
La función del API multiSplit() devuelve un Array, por lo que podemos recorrer ese Array de forma Ascendente o Descendente y de esta forma respetar el Orden establecido en la ordenación anterior.

Saludos
Paco Satué

Paco, creo que me he despertado algo dormido.

¿Te refieres a recorrer toda la lista de manera invertida para obtener los registro de manera descendente?

Antes de que soporte me respondiera mi opción fue el multisplit, mi idea era precisamente esa.
De manera recursiva hacer un multisplit y un invert si el orden era descendente. Cada “sublista” retornarla para montar la lista resultante.

De todas formas quizás es más fácil montar una función y usar los comandos sort de manera invertida al orden.

Hola Manuel.

Te vuelvo a repetir que ejecutar los comandos Sort() de forma encadenada no funciona porque un Sort() deshará el Orden de un anterior Sort().

Efectívamente, el truco está en la función MultiSplit() que nos permite respetar la Ordenación establecida previamente.

Prueba el siguiente código:


// Uso de la función multiSplit() para ordenar Listas por múltiples campos y Ordenaciones
// Recibe una Lista (theRegisterListIn) con campos a ordenar
// Devuelve la misma Lista ordenada (theRegisterListOut)

// Supongamos que queremos ordenar por los campos PREFIJO -> NAME (desc) -> IMPORTE (desc)
// PREFIJO Ascendente
// NAME Descendente
// IMPORTE Descendente

var oLista 
var aListas1 = []  // sublistas de PREFIJO
var aListas2 = []  // sublistas de NAME

// Ordenamos y multipartimos por el campo PREFIJO
aListas1 = theRegisterListIn.multiSplit("PREFIJO")

// Recorremos en orden Ascendente las subListas del PREFIJO
for (i=0; i<aListas1.length; i++) {
	// Ordenamos  por el NAME y Descendente
	aListas1[i].sort("NAME")
	aListas1[i].invert()

	// Multipartimos por el campo NAME. 
	aListas2 = aListas1[i].multiSplit("NAME")

	// Recorremos en orden Descendente las subListas del NAME
	for (j=aListas2.length-1; j>-1; j--) {
		// Ordenamos  por el IMPORTE y Descendente
		aListas2[j].sort("IMPORTE")
		aListas2[j].invert()

		// ¡¡OJO!! Sacamos registro a registro porque si lo hacemos por la Lista entera se pierde el Orden
		// Ver http://velneo.es/foros/topic/agregar-lista-a-la-cesta-y-orden-de-lista/#post-45214
		for (k=0; k<aListas2.length; k++) {
			theRegisterListOut.append(aListas2[j].readAt(k))
		}
	}
}

Habría que generalizarlo para N-CAMPOS con N-Ordenaciones.

Saludos
Paco Satué

Hola a todos,

otro jarro de agua fría… me parece bastante grave que algo tan habitual como esto no se pueda hacer de forma nativa en velneo.

1 me gusta

Hola.

Por fin tenemos una función que sustituye a la inoperante función VRegisterList.sort(campo1, desc, …) del API.

Haciendo un gran esfuerzo intelectual, que a estas alturas cada día me cuesta más, he creado un script que mediante recursividad nos servirá para cualquier número de campos y ordenaciones.

Ejemplo de uso


Rem ( Queremos ordenar por el Nombre de Comunidad, Nombre de Provincia (Desc) y por Importes (Desc) )
Set ( CCAMPOS_ORDEN, "COMUNIDADES.NAME, 0, PROVINCIAS.NAME, 1, PROVINCIAS.IMPORTE, 1")
Rem (Ejecutamos el proceso javascript con entrada y salida de la lista que vamos a ordenar)
Crear manejador de objeto ( oOrdenar, Proceso PRO_ORDENAR_PROV_COMUNIDADES_JS@0PS__Soporte_app )
Set variable local de objeto ( oOrdenar, CCAMPOS_ORDEN, CCAMPOS_ORDEN )
Cargar lista ( PROV_COMUNIDADES@<proyecto_dat>, ID, , , , )
   Añadir lista al objeto ( oOrdenar )
Disparar objeto ( oOrdenar, 1º plano: Local (síncrono), )
   If ( sysListSize > 0 )
      Rem ( Mostramos el resultado en la Rejilla)
      Crear manejador de objeto ( oLista, Rejilla GRD_PROV_COMUNIDADES@proyecto_app )
      Añadir lista al objeto ( oLista )
      Disparar objeto ( oLista, No aplicable, )

Proceso javascript PRO_ORDENAR_PROV_COMUNIDADES_JS con entrada y salida de la lista que vamos a ordenar
Tendrá una Variable local CCAMPOS_ORDEN


#include "proyecto.vca/Listas_gestion/ListasOrdenar.js"	// FuncionesComunes_app

Script ListasOrdenar.js
Necesita una Variable local como una cadena “campo1, desc, campo2, desc, …” igual que lo hace la función sort().


// Uso de la función multiSplit() para ordenar Listas por múltiples campos y Ordenaciones Asc/Desc
// ---------------------------------------------------
// Parámetros:
// Recibe una Lista en theRegisterListIn y la devuelve ordenada en theRegisterListOut
// Variable local CCAMPOS_ORDEN. String con las pares "campo, orden"
//   campo: es el nombre del campo por el que queremos ordenar. Acepta campos del puntero a maestro.
//   orden:  es 1 o true cuando el orden es Descendente
//   Ejem.- "PREFIJO, 0, PROV.NAME, 1, PROV.IMPORTE, 1"  o   "PREFIJO, false, PROV.NAME, true, PROV.IMPORTE, true" 

var aListaOrdenacion = theRoot.varToString("CCAMPOS_ORDEN").split(",")
var aCampos = [], aDesc  = [], lOK = true
// Construimos los Arrays de parámetros aCampos y aDesc
try {
   for (i in aListaOrdenacion) {
      if (i%2 == 0) aCampos.push(aListaOrdenacion[i].trim())
      else {aDesc.push(eval(aListaOrdenacion[i].trim()))}
    }
}
catch (oError) {
   alert("Parámetros incorrectos")
   lOK = false
}

if (lOK) {
   // Número de Niveles o columnas a ordenar
   var nNumNiveles = aCampos.length
   // Primer Nivel de Ordenación
   var n = 0
   var campo = aCampos[n]
   // Multipartimos por el primer campo según el parámetro aCampos[0]
   var aListasIni = theRegisterListIn.multiSplit(campo)
   // Ejecuta la función de ordenación de forma recursiva
   recorrer(aListasIni, n)
}
	
function recorrer(aListas, nivel) {
   // Reordenamos el Array de Listas según el parámetro aDesc[nivel]
   if (aDesc[nivel]) aListas.reverse()
   // Incrementamos un Nivel
   nivel++
   if (nivel<nNumNiveles) {
      // Recorremos el Array de Listas
      for (i in aListas) {
         // Multipartimos por el campo según el parámetro aCampos[nivel]
         campo = aCampos[nivel]
         var aListas_t = aListas[i].multiSplit(campo)
         // Por recursión se vuelve a Reordenar y Multipartir
         recorrer(aListas_t, nivel)
      }
   }
   else {
      // En el último Nivel enviamos el array de Listas a la Salida
      for (i in aListas) {
         theRegisterListOut.append(aListas[i])
      }
   }	
}

Entiendo que pocas veces tendremos la necesidad de ordenar listas porque podremos hacerlo con Índices.
Se me ocurren 2 casos en que sí será útil, ordenar el resultado de un objeto Búsqueda en el que no podemos predecir el orden de dicho resultado y en la necesidad expuesta recientemente en el foro de ordenar la Lista según los agrupaminetos definidos en el Informe.

Espero os sirva.
Saludos
Paco Satué

Necesitamos escuchar la voz de velneo, en comandos como estos que deberian ser mas lifeissoft?

alguien de Velneo, que al menos nos de la esperanza de que esta considerado en el RoadMap, el poder de velneo contra otras bases de datos, es su modelo de base de datos “real”, lo cual de entrada ya es una ventaja, queda completamente mermada con problematicas como las se que presentan en este hilo, que queda de mano del programador hacer maroma y teatro para poder lograr X cosa,

por otro lado seguimos aun con las limitantes vReports, graficas, por mencionar solo algunas,

¿es tan dificil para el equipo de Velneo que nos apoye con estos requerimientos basicos de la plataforma?

los clientes finales no piensan ni les interesan las maravillas de las actualizaciones, triggers, herencia y DataEditCacher?, <- este ultimo no le encuentro pies ni cabeza… un completo desatino a mi parecer,

debemos ir en la misma direccion, y que es lo que le interesa al cliente, es tal ves resolver su problema, tener su informacion disponible su informacion online-offline, desde cualquier plataforma, y lo mas importante es poder explotarla al maximo con el minimo esfuerzo para ambas partes (desarrollador-cliente) , cubos Olap <- esto ni siquiera existe en la filosofia de velneo,

ya por ultimo aclarar que NO es una queja, simplemente Velneo, escuchen la demanda de la comunidad, y lo mas importante tomen acciones en marcha al respecto

saludos a todos, y disculpen si casi no participo y cuando lo hago sea por algo similar a una queja…

Buenas, según el último soporte que mande, han dejado nota a desarrollo para solventar el comando sort.

Hola arturomiranda.

Entiendo perfectamente tu punto de vista.
Yo soy de los que adquirí Velneo pensando en disponer de una Herramienta de muy alto Nivel a la hora de desarrollar, es decir, de olvidarme de los pequeños detalles que se suponen que están resueltos y centrarme únicamente en seleccionar módulos, ensamblarlos y ejecutar el resultado.
Evidentemente esto es una utopía y Velneo no es una excepción.
Toca currarse los detalles como este de ordenar por múltiples columnas. Quién me lo iba a decir después de trabajar con SQL.

Es cierto que hay un alto porcentaje de éxito entre los usuarios estandar que usan Velneo para lo que fue diseñado, aplicaciones puramente de gestión sin grandes pretensiones en cuanto a prestaciones multiplataforma, minería de datos o capacidades gráficas.

De momento, si pretendes construir otro tipo de aplicaciones, necesitarás conocer javascript, QML, HTML, XML, JSON, REST, … y un sin fin de tecnologías dispares. En este caso ya no eres un usuario estandar sino un desarrollador avanzado.

Desde mi punto de vista, el problema es que los que queremos avanzar y explorar esas nuevas tecnologías dentro de Velneo nos vemos fustrados al no disponer de Herramientas avanzadas de edición y depuración, y las que hay muy mal adaptadas a Velneo nativo.

Mi ideal sería disponer de un nuevo Framework que englobara editores/depuradores avanzados de Velneo, Javascript, HTML, QML y multiplataforma.

En resumen, tenemos 2 productos objetivo:

  • Un Velneo de altísimo nivel y super asistido: usted solo ensamble módulos y ejecute. Este es mi deseo todavía incumplido.
  • Un Velneo más dinámico y personalizable con motores javascript y QML con editores avanzados para desarrolladores avanzados.

El problema es que a dia de hoy Velneo no es ni una cosa ni la otra, así que de momento habrá que esperar a que se defina.

Desde luego Velneo es el que mejor conoce lo que demanda la comunidad y en cualquier caso, siendo justos, Velneo es un gran producto si encaja en tus aplicaciones de negocio.

Saludos
Paco Satué

Hola Manuel.

Suena a broma decir que han dejado nota a desarrollo para solventar el comando sort.

¿Son funcionalidades sin importancia?

No disponemos del vBugman hace tiempo. ¡¡Algo pasa con desarrollo!!

Saludos
Paco Satué

1 me gusta

Muchas gracias Paco por la aportación. Lo guardaré porque seguramente la utilice en el proyecto que estoy desarrollando.

Entre tu y Wilkan le estáis haciendo el “trabajo sucio” a Velneo.

Algo pasa con desarrollo no, ¡algo pasa con Velneo! ( lifeissoft2016 es un ejemplo). Últimamente parece un pollo sin cabeza.

Un saludo

+1

+1

+1

Todavía no lo he probado pero parece que han arreglado el sort

VELNEO-396 - Nueva función sort de la clase VRegisterList que permite la ordenación de una lista de registros por varios campos indicados por su identificador compuesto con el fin de facilitar la ordenación compleja de listas en el API de Velneo para Javascript

https://velneo.es/info_v7_719_es/velneo_vdevelop/scripts/clases/core/vregisterlist/#sort

Aunque parece que la posibilidad de descendente ha desaparecido :frowning:

Hola Infortic.

Pues sí, a Velneo le va a seguir siendo dificil ordenar por más de un campo cuando lo queramos hacer arbitrariamente de forma ascendente/descendente.

Seguramente es una limitación de la Base de datos Real porque en realidad nunca ha existido el parámetro ASC/DESC (a nivel de índice) en los comandos Cargar lista o Búsqueda. Existe un simple Invertir lista de la lista resultado, claramente insuficiente.

Bueno, siempre nos quedará el API.

Saludos
Paco Satué

Definición del Velneo por la empresa propietaria del producto: Velneo, herramienta para desarrollo de aplicaciones de gestión empresarial.

Partiendo de esta definición algunos comentarios aquí vertidos no encajan con la realidad y aspiramos a que como es tan bueno y fácil dentro de su ámbito siga siendo tan bueno y fácil fuera del entorno para el que fue creado