Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
1059
Dynamic measures
posted

Is it possible to add a measure dynamically bypassing th data source altogether.

For example, If an Excel file is loaded in the cube and displayed in the grid. Is it possilble to have the user create a new measure and added into the collection of measure. This measure will be essentialy a sum and a product of two other measure. Also, we want to display it right next to other measure in the grid.

Thanks.

Parents
  • 8831
    posted

    Hello,

    Yes you can do that using your own aggregator. Here is the sample code:

     

    1.       Create and add a cube metadata to the flat data source

     

        CubeMetadata cubeMetadata = new CubeMetadata { DataTypeFullName = "ExcelData", DisplayName = "My excel cube" };

        flatDataSource.CubesSettings.Add(cubeMetadata);

     

    2.       Create and add a dimension metadata to the cube metadata

     

        DimensionMetadata calcMeasureMetadata = new DimensionMetadata

            {

                SourcePropertyName = "Cost",

                DimensionType = DimensionType.Measure,

                DisplayName = "Final Price",

                Aggregator = new CustomMeasureAggregator()

            };

     

         cubeMetadata.DimensionSettings.Add(calcMeasureMetadata);

     

    3.       Define your own aggregator:

     

        public class CustomMeasureAggregator : Aggregator<double>

        {

            public override IAggregationResult<double, double> Evaluate(IAggregationResult<double, double> oldResult, IAggregateable aggregateable, IEnumerable items)

            {

                double result = 0;

                IList<object> dataItems = items.Cast<DataRowMetadata>().Select(drm => drm.DataObject).ToList();

     

                if (dataItems.Count > 0)

                {

                    Type itemsType = dataItems[0].GetType();

                    PropertyInfo unitsPropertyInfo = itemsType.GetProperty("Cost");

                    Func<object, object> func = ReflectionHelper.CreatePropertyGetMethod(unitsPropertyInfo);

     

                    foreach (object dataItem in dataItems)

                    {

                        // you can use IAggregateable.GetValue(object) instead

                        // but it operates only over the property specified into DimensionMetadata.SourcePropertyName

                        /*result += (double)aggregateable.GetValue(dataItem);*/

     

                        result += (double)func(dataItem);

                    }

                }

     

                return new SingleResult<double>(result * 1.05);

            }

     

            public override IAggregationResult<double, double> Evaluate(IAggregationResult<double, double> oldResult, double value)

            {

                // you don't need this one

                throw new NotImplementedException();

            }

        }

     

    Because of the usage of excel file the items’ type is type which is dynamically generated. That’s why you need to use reflection in order to extract the values from DataRowMetadata.DataObject property. If your calculations are based over a single property you can use IAggregateable.GetValue(object). It has the same Func<object, object> defined internally and it returns the value of the property you have set as source property of DimensionMetadata.

     

    Best regards.

    PPilev.

Reply Children