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);
}
}
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
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);
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)" };