Búsqueda eficiente en Control «matrix»

Entre mis pruebas usando el SDK de SAP Business One, he estado intentando averiguar la forma más eficiente para buscar y seleccionar dentro de un control “matrix” (cargado usando dbdatasources) una fila que cumple un criterio específico.

La idea era replicar el formulario de Listas de precios del estándar añadiendo dos columnas para vincular a los artículos, además de los precios, dos descuentos que se usarán a nivel de línea en los documentos.

Imagen de Belen Hernández

Belen Hernández

Es decir, tenemos una matriz con información de precios de artículos (replicando el formulario del estándar para las listas de precios), tenemos un edittext para hacer búsquedas en la matriz (al igual que el estándar), introducimos un código de artículo en el edittext y pulsamos en un botón de buscar para realizar una búsqueda del código de artículo en la matriz de forma eficiente.

En mi caso estaba tratando con cerca de 2400 registros que se cargan velozmente usando el método del control Matrix: ”loadfromdatasource”. A continuación expongo mis experiencias:

  • El óptimo sería usar el dbdatasource de la columna por la que queremos buscar para hacer un query(conditions) con el valor que tenemos y seleccionar en la matriz la fila que se corresponde con el valor seleccionado en el dbdatasource. Pude comprobar que el query(conditions) tarda un tiempo despreciable para encontrar cuál es la línea del dbdatasource adecuada.

    El problema es que una vez encontrada la línea del dbdatasource que se está buscando no hay forma de saber con qué línea del control Matrix se corresponde. Por lo tanto, para poder saber la línea de la matrix que debía marcar, me dispuse a cargar en el dbdatasource la información de índice de cada fila. Esto lo hice de dos maneras:

    • Con un datatable de los de ado .net: Tardaba 44 segundos en cargar el formulario después de haber ejecutado el loadfromdatasource.
    • Usar arraylist cargado en el momento del form también retrasa la carga demasiado (en comparación con loadfromdatasource):

Código usado:

Form f = kernel.cargarForm("XML\ITOP_PRECIOS.xml", "ITOP_PRECIOS" + FormUID);
   inicializarFormItopDtos(f, lista);
   DateTime antes = DateTime.Now;
   ArrayList listaAux = new ArrayList();
   for (int i = 0; i < f.DataSources.DBDataSources.Item("ITM1").Size; i++) {
      listaAux.Add(i);
   }
   TimeSpan tarda = DateTime.Now - antes;
   kernel.Application.MessageBox("Tarda: " + tarda.TotalSeconds.ToString(), 0, "", "", "");

Resultado carga form rellenando arraylist:

Rellenando un userdatasoure y usando mtx.addRow() en lugar de loadfromdatasource: Tardaba 74 segundos en cargar el formulario.

  • Después de los resultados anteriores (Carga de formulario demasiado lenta) me planteé desechar la búsqueda con Query(conditions), por lo que llegué a estas dos alternativas:
    • Búsqueda por ui api en la matrix…. Opción demasiado lenta.
    • Búsqueda en los datasources: Lo mejor que he encontrado. Haciendo una búsqueda secuencial en la columna que corresponda del dabdatasource adecuado se obtienen unos resultados muy buenos con los 2400 registros:
      • Último registro (empieza por f)
      • Registro no existente
      • Registro intermedio.

El código usado es el siguiente:

private void seleccionarFila(Matrix mtx, DBDataSource dbds, string columna, string codigoABuscar, string celdaFocoDestino) {
   int i = 0;
   DateTime antes = DateTime.Now;
   while ((i < dbds.Size) && (!dbds.GetValue(columna, i).Trim().StartsWith(codigoABuscar)))
   i++;
   if (i < dbds.Size) {
      mtx.SelectRow(i + 1, true, false);
      mtx.Columns.Item(celdaFocoDestino).Cells.Item(i + 1).Click(BoCellClickType.ct_Regular, 0);
   }
   else
   kernel.Application.MessageBox("Código: " + codigoABuscar + " no encontrado", 1, "", "", "");
   TimeSpan tarda = DateTime.Now - antes;
   kernel.Application.MessageBox("Tarda: " + tarda.TotalSeconds.ToString(), 0, "", "", "");
}
Compartir

¿Quieres ponerte en contacto con nosotros?

Si necesitas ayuda, más información o te gustaría realizar alguna consulta.

Suscríbete a nuestra newsletter

Si nos indicas tu dirección de correo electrónico, declaras que has leído y que comprendes nuestra Política de Privacidad.