© 2015-2026. MindStreamAnalytics.com

Blog

Cómo hacer que el cuadro de diálogo de progreso de la gestión de datos sea útil para los usuarios

No me gustan los diálogos de progreso. ¿Por qué? Creo que la mayoría mienten. 3 segundos para el 98% y luego 10 minutos para el último 2%. ¡¿QUÉ?! Hagámoslo mejor. Usemos el Diálogo de Progreso de Gestión de Datos de OneStream para informar al usuario, para que sepa la verdad sobre la tarea en ejecución.

Ya que estamos, permitamos al usuario cancelar una tarea en ejecución y detenerla.

Si has creado algún proceso de Gestión de Datos de larga duración dentro de OneStream, ya sabes, de esos que se repiten durante meses o llaman a sistemas externos… Entonces probablemente hayas pensado que sería útil proporcionar retroalimentación útil mientras se ejecuta.

Aquí es donde entra en juego BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled. Permite enviar mensajes de estado al cuadro de diálogo de Gestión de Datos y, lo que es igual de importante, comprobar si el usuario ha decidido cancelar el proceso.

El patrón básico es simple: llama a este método regularmente a lo largo del código, pasa un mensaje que describa lo que estás haciendo y usa el valor de retorno verdadero/falso para decidir si salir. No me gusta escribir nombres de funciones de más de 60 caracteres que están enterrados en objetos profundos de una biblioteca. Y BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled es así de feo. Solo necesita una API. Así que escribamos una. En este caso, se trata de un método contenedor simple de una línea llamado UpdateDMDialog(message As String). La ​​función devuelve el mismo booleano que nuestra función de biblioteca de más de 60 caracteres, indicando si el usuario ha hecho clic en cancelar. Por lo tanto, si devuelve verdadero, sé que el usuario canceló el proceso y también puedo salir de mi código. Esto ofrece a los usuarios una forma de detener el proceso sin matar el servidor ni esperar a que se agote el tiempo de espera.

Consulta el código a continuación para ver un ejemplo práctico de cómo usar BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled

El verdadero valor aquí reside en los mensajes que envías. Piensa menos en "30 % completado" y más en "Obteniendo registros de mayo..." o "Esperando el trabajo de NetSuite 12734...". Cualquier cosa que muestre lo que está sucediendo y en qué punto del proceso te encuentras da a los usuarios confianza o, al menos, una idea de si deben ir a tomar un café o cancelar. Incluso puedes incluir el recuento de registros, los ID de las tareas o la latencia de la API si quieres algo más sofisticado.

Utilizo este patrón en integraciones de datos, importaciones de archivos y prácticamente en cualquier lugar donde las cosas puedan tardar o fallar a mitad del proceso. Es ligero, da control al usuario y es mucho mejor que dejarlos sentados mirando un cuadro de diálogo que gira y miente sobre el progreso real. Añade unas cuantas llamadas a UpdateDMDialog en tu bucle, ¡y listo! Usuario feliz e informado.

C#

public class DataImporter
{
    private readonly object si;
    private readonly object _args;
    private readonly string _dataType;
    private decimal _progress;

    public DataImporter(object sessionInfo, object args, string dataType)
    {
        si = sessionInfo;
        _args = args;
        _dataType = dataType;
        _progress = 0m;
    }

    private bool UpdateDMDialog(string message)
    {
        return BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled(si, _args, message, _progress);
    }

    public async Task<DataTable> GetData(string yearInput)
    {
        var response = new List<string>();
        long totalRecords = 0;

        UpdateDMDialog($"Starting {_dataType} import for year {yearInput}");

        for (int month = 1; month <= 12; month++)
        {
            string monthStr = $"{yearInput}-{month:D2}";
            UpdateDMDialog($"Starting {monthStr}...");

            string taskId = await Mock_DataRequestStart(monthStr);
            await Mock_DataRequestStatus(taskId);

            var result = await Mock_DataRequestComplete(monthStr, taskId);

            _progress = month * 8.33m;
            UpdateDMDialog($"Finished {monthStr} — {result.RecordCount} records");

            if (result.Data != null)
            {
                if (response.Count == 0)
                    response.AddRange(result.Data);
                else
                    response.AddRange(result.Data.Skip(1));

                totalRecords += result.RecordCount;
            }

            if (UpdateDMDialog($"Imported {monthStr}")) return new DataTable();
        }

        var table = Mock_ToDataTable(response);
        string preview = JsonConvert.SerializeObject(
            table.AsEnumerable().Take(5).Select(r => r.ItemArray), Formatting.Indented);

        UpdateDMDialog($"All months complete. Total records: {totalRecords}");
        BRApi.ErrorLog.LogMessage(si, $"Preview:\n{preview}");

        return table;
    }

    // Mock helpers
    private Task<string> Mock_DataRequestStart(string month)
        => Task.FromResult(Guid.NewGuid().ToString());

    private Task Mock_DataRequestStatus(string taskId)
        => Task.Delay(200);

    private Task<DataResult> Mock_DataRequestComplete(string month, string taskId)
        => Task.FromResult(new DataResult
        {
            Data = new List<string> { "header", $"data for {month}" },
            RecordCount = 1
        });

    private DataTable Mock_ToDataTable(List<string> rows)
    {
        var table = new DataTable();
        table.Columns.Add("Content", typeof(string));
        foreach (var row in rows)
            table.Rows.Add(row);
        return table;
    }

    private class DataResult
    {
        public List<string> Data { get; set; }
        public long RecordCount { get; set; }
    }
}

VB.NET

Public Class DataImporter
    Private ReadOnly si As Object
    Private ReadOnly _args As Object
    Private ReadOnly _dataType As String
    Private _progress As Decimal

    Public Sub New(sessionInfo As Object, args As Object, dataType As String)
        Me.si = sessionInfo
        Me._args = args
        Me._dataType = dataType
        Me._progress = 0D
    End Sub

    Private Function UpdateDMDialog(message As String) As Boolean
        Return BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled(si, _args, message, _progress)
    End Function

    Public Async Function GetData(yearInput As String) As Task(Of DataTable)
        Dim response As New List(Of String)()
        Dim totalRecords As Long = 0

        UpdateDMDialog($"Starting {_dataType} import for year {yearInput}")

        For month As Integer = 1 To 12
            Dim monthStr As String = $"{yearInput}-{month:D2}"
            UpdateDMDialog($"Starting {monthStr}...")

            Dim taskId As String = Await Mock_DataRequestStart(monthStr)
            Await Mock_DataRequestStatus(taskId)

            Dim result As DataResult = Await Mock_DataRequestComplete(monthStr, taskId)

            _progress = month * 8.33D
            UpdateDMDialog($"Finished {monthStr} — {result.RecordCount} records")

            If result.Data IsNot Nothing Then
                If response.Count = 0 Then
                    response.AddRange(result.Data)
                Else
                    response.AddRange(result.Data.Skip(1))
                End If

                totalRecords += result.RecordCount
            End If

            If UpdateDMDialog($"Imported {monthStr}") Then
                Return New DataTable()
            End If
        Next

        Dim table As DataTable = Mock_ToDataTable(response)
        Dim preview As String = JsonConvert.SerializeObject(
            table.AsEnumerable().Take(5).Select(Function(r) r.ItemArray),
            Formatting.Indented
        )

        UpdateDMDialog($"All months complete. Total records: {totalRecords}")
        BRApi.ErrorLog.LogMessage(si, $"Preview:{vbLf}{preview}")

        Return table
    End Function

    ' Mock helpers
    Private Function Mock_DataRequestStart(month As String) As Task(Of String)
        Return Task.FromResult(Guid.NewGuid().ToString())
    End Function

    Private Function Mock_DataRequestStatus(taskId As String) As Task
        Return Task.Delay(200)
    End Function

    Private Function Mock_DataRequestComplete(month As String, taskId As String) As Task(Of DataResult)
        Dim result As New DataResult With {
            .Data = New List(Of String) From {"header", $"data for {month}"},
            .RecordCount = 1
        }
        Return Task.FromResult(result)
    End Function

    Private Function Mock_ToDataTable(rows As List(Of String)) As DataTable
        Dim table As New DataTable()
        table.Columns.Add("Content", GetType(String))
        For Each row As String In rows
            table.Rows.Add(row)
        Next
        Return table
    End Function

    Private Class DataResult
        Public Property Data As List(Of String)
        Public Property RecordCount As Long
    End Class
End Class

Socio Destacado

OneStream se alinea con las necesidades de su negocio y cambia más rápida y fácilmente que cualquier otro producto al ofrecer una plataforma y un modelo para todas las soluciones financieras de CPM. OneStream emplea guiado Flujos de trabajo, validaciones y mapeo flexible para brindar confianza en la calidad de los datos para todas las recopilaciones y análisis al tiempo que se reduce el riesgo a lo largo de todo el proceso financiero auditable.

OneStream

Nuestra compañía

El personal senior de MindStream Analytics estuvo presente en el nacimiento de Business Intelligence. Hemos sido parte de la construcción de Business Intelligence a nivel nacional desde su humilde estado de producto de nicho hasta el ubicuo herramienta analítica que es hoy. Los consultores de MindStream están bien versados ​​en informes y gestión de información y están listos para ayudarlo a aprovechar el poder de múltiples proveedores de nivel 1. Desde Oracle Hyperion a IBM Cognos, podemos ayudarlo a seleccionar e integrar las herramientas adecuadas para comprender mejor su información. MindStream Analytics tiene experiencia en una amplia variedad de industrias: servicios comerciales, Productos de Consumo, Energía, Servicios Financieros, Salud, Manufactura, Transporte y Telecomunicaciones. Tenemos la profundidad y la amplitud de la experiencia para ayudarlo a brindar información procesable a los usuarios

Ya sea que necesite una implementación de Oracle BI Enterprise Edition (OBIEE) para toda la empresa, una implementación de Oracle BI Apps o una implementación de IBM Cognos ReportNet, MindStream Analytics está aquí para ayudarlo a tener éxito.

Estudios de caso

Accumen

Gracias a la intervención de MindStream Analytics, el departamento de Finanzas de Accumen ahora puede modelar su negocio con una estructura nueva y más organizada que no está disponible convencionalmente en NetSuite.

Acme Brick

Acme Brick recurrió a MindStream Analytics en busca de ayuda para implementar OneStream para reemplazar su obsoleta solución TM1.

Alterra

Alterra buscó la experiencia de MindStream para abordar los desafíos que enfrentaron en su proceso de planificación de capital.

ATCO Group

El conglomerado energético ATCO opera en todo el mundo en servicios públicos, generación de energía y servicios relacionados.

Avalon

Al trabajar con MindStream Analytics, Avalon Healthcare Solutions adopta NetSuite Planning and Budgeting para acelerar los procesos de presupuestación y previsión.

Bayer Health Care

Bayer Healthcare implementó Hyperion Planning y Workforce Planning en 10 semanas para optimizar drásticamente su presupuesto de declaración de ingresos y su proceso de planificación de la fuerza laboral.

BluEarth

La asociación de MindStream Analytics con BluEarth Renewables personifica el poder de la tecnología y la colaboración.

Celgene

Una actualización de planificación de Oracle Hyperion proporciona optimización y estabilización de la aplicación Hyperion de organizaciones multinacionales.

Cleaver Brooks

Se eligió OneStream XF como la plataforma que transformaría los procesos financieros de Cleaver-Brooks.

CoorsTek

La colaboración entre CoorsTek y MindStream dio como resultado mejoras significativas en los procesos de informes y consolidación financiera de CoorsTek.

Elite Body Sculpture

La colaboración de MindStream Analytics con Elite Body Sculpture resume el potencial transformador de las soluciones tecnológicas específicas para agilizar los procesos administrativos.

Enlyte

Enlyte, una fusión de Mitchell, Genex y Coventry, enfrentó desafíos con soluciones financieras dispares y la necesidad de informes combinados.

Flanders

MindStream Analytics colaboró ​​con Flanders para implementar la solución OneStream Consolidation and Reporting.

Productos Foley

Foley Products se enfrentaba a un desafío importante con su sistema de informes de gestión real basado en Excel.

Harte Hanks

La colaboración entre MindStream Analytics y Harte Hanks culminó en una implementación de NetSuite altamente personalizada y fácil de usar.

Interface

La interfaz utilizó un proceso de FP&A complejo, manual y basado en Excel para la revisión mensual, y los datos resumidos se cargaron en OneStream.

Kymera Internacional

Gracias a la asistencia de Mindstream Analytics, Kymera pudo cargar todos sus datos en OneStream y validarlos exitosamente.

MacLean Fogg

MacLean-Fogg se asoció con MindStream, un implementador líder que se especializa en modernizar y optimizar sistemas empresariales.

MEPPI

Se buscaron los conocimientos y la experiencia de MindStream para llevar a cabo una iniciativa de selección de proveedores centrada en el proceso de planificación F2023 de MEPPI.

OUAI

La colaboración de MindStream Analytics y OUAI muestra el poder transformador de la intervención tecnológica estratégica.

Plaskolite

Al migrar a OneStream, Plaskolite logró una reducción sustancial en el tiempo de consolidación y el ciclo general de cierre financiero, eliminó las horas dedicadas a compilar y verificar datos en Excel, agilizó su modelo de planificación, presupuestación y previsión y entregó informes flexibles y oportunos que permiten un análisis más estratégico de sus datos financieros.

Redwire

Al comprender los matices de los desafíos de Redwire, MindStream Analytics ideó un enfoque holístico para superarlos. La implementación de NetSuite fue sólo el comienzo.

Simon

La aplicación de producción corporativa Hyperion Financial Management (HFM) existente de Simon se estaba consolidando a un ritmo de siete horas, un problema de rendimiento que causaba un gran dolor de cabeza a la contabilidad corporativa.

Source Code

La transición exitosa a OneStream revolucionó los informes financieros de Source Code.

Subway

Subway colaboró ​​con MindStream Analytics para la implementación de NetSuite Analytics Warehouse.

UPenn

Los miembros del equipo de MindStream Consulting y AppCare están orgullosos de trabajar codo con codo con la Universidad de UPenn para lograr esta implementación y continuar con nuestros servicios de AppCare después de su puesta en marcha.

USG

USG era un cliente de Oracle Hyperion y se dio cuenta de que necesitaba soporte más especializado para sus diversas aplicaciones de Oracle Hyperion.

Vantiv

¿Dividir una aplicación de planificación de Hyperion y ampliar la huella de Hyperion para pronosticar el negocio? Categorías de clientes.

Versant Health

Versant Health contrató a MindStream para ayudar a resolver los desafíos que estaban experimentando con sus procesos de consolidación, cierre e informes financieros.

Virginia Space Authority

El equipo de MindStream implementó Standard + Workforce NetSuite Planning & Budgeting.

WeWork

MindStream Analytics determinó que la mejor solución era implementar Oracle Essbase Cloud como parte de la plataforma como servicio Oracle Analytics Cloud (OAC).

WindStream

Uso innovador de essbase para optimizar y conectar la gestión financiera de Hyperion para mejorar el análisis financiero.

XY Planning

MindStream Analytics, experto en abordar estos desafíos, presentó una solución integral de Netsuite para XY Planning.

Enlaces Relacionados