Page 1 of 2

StiReport Custom function is not working properly

Posted: Thu Nov 23, 2023 2:17 pm
by PeterQuill
I have a datatable where the column that I have to sort contains both numeric values and string. I've implemented a custom sorting logic to put all numeric values on top and sort them ascendingly, then non-numeric values to bottom as sort them alphabetically. My function worked just fine as I tried to debug it and could get the expected result.

Here is my custom function:

Code: Select all

        public static IOrderedEnumerable<TSource> ExtendedNumberSort<TSource>(this IEnumerable<TSource> source, Func<TSource, string> keySelector)
        {
            var comparer = new CustomStringComparer();
            return source.OrderBy(keySelector, comparer);
        }
        
            public class CustomStringComparer : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            (bool isNumberX, object parsedValueX) = ParseValue(x);
            (bool isNumberY, object parsedValueY) = ParseValue(y);

            if (isNumberX && isNumberY)
            {
                // Both are numeric, sort them numerically
                return Comparer<double>.Default.Compare((double)parsedValueX, (double)parsedValueY);
            }
            else if (!isNumberX && !isNumberY)
            {
                // Both are non-numeric, sort them alphabetically
                return StringComparer.CurrentCultureIgnoreCase.Compare(x, y);
            }
            else if (isNumberX)
            {
                // Numbers come before strings
                return -1;
            }
            else
            {
                // Numbers come after strings
                return 1;
            }
        }

        private static (bool isNumber, object parsedValue) ParseValue(string value)
        {
            // Check if the value is a valid number (contains only digits)
            bool isNumber = double.TryParse(value, out double numberValue);

            // Trim leading zeros only if the value is a valid number
            string trimmedValue = isNumber ? numberValue.ToString() : value;

            // Parse the value accordingly (as number or string)
            object parsedValue = isNumber ? (object)numberValue : (object)trimmedValue;

            return (isNumber, parsedValue);
        }
    }
        
Here is how I register the custom function

Code: Select all

StiFunctions.AddFunction(
                customFunctionsCategoryName,             // Category
                "ExtendedNumberSort",                    // Name of function
                "Sort a list of Project Number",         // Description
                typeof(StiCustomFunctions),              // Static class where function lives
                typeof(IEnumerable<object>),             // Return type (changed from IOrderedEnumerable<object> to IEnumerable<object>)
                "Ordered list of Project Numbers",       // Return type description (adjusted to match the actual return type)
                new Type[2] { typeof(IEnumerable<object>), typeof(Func<object, string>) },    // Array of types for each argument
                new string[2] { "source", "keySelector" }); // Array of names for each argument
My code to run the function directly in .net with some real data, I get the expected result here

Code: Select all

string[] data = new string[]
        {
            "NEW JOB",
            "CW1000",
            "CW11",
            "18",
            "19",
            "WEBINAR",
            "MH",
            "45"
        };
            StiCustomFunctions.ShuffleArray(data);

            // Sort the array using ExtendedNumberSort function
            var sortedData = StiCustomFunctions.ExtendedNumberSort(data, x => x);
Here is how I add the custom sort expression.
Image

When I ran the report, there was no error. However, the sort result is not as expected as the numeric values and non-numeric values get intermingled. Also the result is not the same as there is not sorting. So the custom sort function has probably worked but I just don't get the expected result. I tried a different approach that is adding the sorting expression through StiDataBand in .NET and still got the same unexpected result.

Code: Select all

            var databand = report.GetComponentByName("DataBand1") as StiDataBand;
            databand.Sort = new string[1] { "ExtendedNumberSort(project.projectNumber)" };
Can anyone let me know what am I missing here?

Re: StiReport Custom function is not working properly

Posted: Fri Nov 24, 2023 12:19 am
by Lech Kulikowski
Hello,

Please send us a sample that reproduces the issue for analysis.

Thank you.

Re: StiReport Custom function is not working properly

Posted: Mon Nov 27, 2023 8:04 am
by PeterQuill
Lech Kulikowski wrote: Fri Nov 24, 2023 12:19 am Hello,

Please send us a sample that reproduces the issue for analysis.

Thank you.
Hi, here is the sample report. The way that I invoke the custom sort function is the same as my real report. Let me know if you need more information.

Re: StiReport Custom function is not working properly

Posted: Wed Nov 29, 2023 12:54 am
by Lech Kulikowski
Hello,

We need some time to investigate the issue. We will let you know about the result.

Thank you.

Re: StiReport Custom function is not working properly

Posted: Thu Nov 30, 2023 9:16 am
by MatthiasU
I don't think, you can use a function for sorting this way. Sort picks the current value for each datarow and your function(method) is called for each instance and the results of each instance will be compared.
So I would propose to create a custom class/struct containing the numeric and non-numeric values and implement the comparer for this class. Further, create a calculated column (of type object) on your datasource returning an instance of your new class. Then, sort over the new calculated column.

Re: StiReport Custom function is not working properly

Posted: Fri Dec 01, 2023 10:23 am
by Lech Kulikowski
Hello,

Your function returns the full data result set. But for Sotring, only one value is needed.

In your case, you can sort your data source and provide to report with the RegData() method.

Thank you.

Re: StiReport Custom function is not working properly

Posted: Mon Dec 04, 2023 9:07 am
by PeterQuill
Lech Kulikowski wrote: Fri Dec 01, 2023 10:23 am Hello,

Your function returns the full data result set. But for Sotring, only one value is needed.

In your case, you can sort your data source and provide to report with the RegData() method.

Thank you.
Hi, thank you for answering.

I'm still new to Stimulsoft. So might I ask, is it possible to do the sorting using the custom function? That would be the most preferable method in this case of mine, since the code for RegData() is being used for multiple reports, I would avoid modifying
the general code for a specific report as much as possible.
Your function returns the full data result set. But for Sotring, only one value is needed.
If it's possible to the sorting with custom function. Then how would I modify the arguments being passed into ExtendedNumberSort to match with the parameters being passed into the expression? Or how should I modify the expression to match with the custom function? I'm not the one who built the project, so I couldn't find a way to debug the custom method when the Stimulsoft report is being run.

Thank you.

Re: StiReport Custom function is not working properly

Posted: Mon Dec 04, 2023 11:45 pm
by Lech Kulikowski
Hello,

Unfortunately, it is not possible to add sorting with a custom function. You can sort your data source and provide it to the report.

Thank you.

Re: StiReport Custom function is not working properly

Posted: Tue Dec 05, 2023 11:12 am
by PeterQuill
Lech Kulikowski wrote: Mon Dec 04, 2023 11:45 pm Hello,

Unfortunately, it is not possible to add sorting with a custom function. You can sort your data source and provide it to the report.

Thank you.
Thank you, I appreciate your responses.

Re: StiReport Custom function is not working properly

Posted: Tue Dec 05, 2023 11:14 am
by PeterQuill
MatthiasU wrote: Thu Nov 30, 2023 9:16 am I don't think, you can use a function for sorting this way. Sort picks the current value for each datarow and your function(method) is called for each instance and the results of each instance will be compared.
So I would propose to create a custom class/struct containing the numeric and non-numeric values and implement the comparer for this class. Further, create a calculated column (of type object) on your datasource returning an instance of your new class. Then, sort over the new calculated column.
Hi Matthias, am I able to add the custom Comparer Class into the report and interactively sort it? When clicking in the column header, I'm able to sort it ascendingly and descendingly with my custom sort logic. Or is it only possible for me to run sorting on the column before the report got rendered?