Inquiry Regarding Currency, Number, and Percent Display Settings in SpreadJS

Posted by: kei.takemura on 20 March 2024, 1:57 pm EST

    • Post Options:
    • Link

    Posted 20 March 2024, 1:57 pm EST - Updated 20 March 2024, 5:19 pm EST

    Hello,

    I am developing a program to display Excel sheets using SpreadJS. I am trying to modify the settings for currency, numbers, and percentages without changing the DecimalSeparator and GroupSeparator settings of the current culture. I executed the following code:

    // "culture-nm" is current culture name
    var cultureInfo = GC.Spread.Common.CultureManager.getCultureInfo(angular.element("#culture-nm").val());
    var numberFormat: any = cultureInfo.NumberFormat;
    // data.Separator contain separators I want to set
    numberFormat.currencyGroupSeparator = data.Separator.CurrencyGroup;
    numberFormat.currencyDecimalSeparator = data.Separator.CurrencyDecimal;
    numberFormat.numberGroupSeparator = data.Separator.NumberGroup;
    numberFormat.numberDecimalSeparator = data.Separator.NumberDecimal;
    numberFormat.percentGroupSeparator = data.Separator.PercentGroup;
    numberFormat.percentDecimalSeparator = data.Separator.PercentDecimal;
    cultureInfo.NumberFormat = numberFormat;
    // set edited culture
    GC.Spread.Common.CultureManager.addCultureInfo("lo-cl", cultureInfo);
    GC.Spread.Common.CultureManager.culture("lo-cl");

    Although DecimalSeparator and GroupSeparator have been changed, the display of decimals is different from what I expected. Specifically, the display is as follows:

    Example: When DecimalSeparator is “.”, and GroupSeparator is “'”:

    • Input: “111222333.4445”
    • Expected display: “111’222’333.4445
    • Actual display: “111’222’333.444’5

    Could you please advise on how to correctly configure this to achieve the expected display? Thank you.

  • Posted 20 March 2024, 3:12 pm EST

    Sorry, there was mistakes in this part of the above text. (cause I used DeepL).

    I am trying to modify the settings for currency, numbers, and percentages without changing the DecimalSeparator and GroupSeparator settings of the current culture.

    The correct is :

    I am trying to change the settings of the DecimalSeparator and GroupSeparator for currency, number, and percent in the current culture.

    I do not want to change any other settings than those for DecimalSeparator and GroupSeparator.

    Thank you.

  • Posted 21 March 2024, 10:28 pm EST

    Hi,

    I attempted to reproduce the issue on my end using the available information, but I was unsuccessful. Refer attached sample.

    To better assist you, could you share a sample along with the steps to replicate the behavior you have observed, or modify the existing sample to replicate the behavior? This will enable me to investigate the problem more thoroughly. And It would be helpful if you could provide a GIF or video illustrating the issue.

    Sample: https://jscodemine.mescius.io/share/ITbUiEvfxUCB-hNxFI2c4Q/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fapp.component.ts"%2C"%2Fpackage.json"%2C"%2Fsrc%2Fapp.component.html"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.component.ts"}

    Regards,

    Priyam

  • Posted 24 March 2024, 6:15 pm EST

    Thank you for providing the information.

    I tried editing the sample, but I couldn’t reproduce the issue.

    As stated in the sample, specifying characters like “'” and “.” directly worked correctly as separators.

    However, when trying to specify characters stored in variables, such as:

    numberFormat.numberDecimalSeparator = data.Separator.NumberDecimal;

    I encountered the following error at my program:

    angular.js:12520 numberDecimalSeparator, listSeparator and arrayListSeparator should be different in cluture info.

    Here,

    data.Separator.NumberDecimal
    and other properties are of type Object.

    The version of SpreadJS we are using in our program is “9.20171.0”.

    Would you like to try reproducing the issue with this version?

    Thank you.

  • Posted 24 March 2024, 7:49 pm EST

    I’m sorry, the above error was due to my lack of familiarity with the NumberFormat property.

    To avoid this error, I’d like to input appropriate values for listSeparator, arrayListSeparator, and arrayGroupSeparator.

    Is there a way to retrieve these pieces of information in C#?

    It’s because the requests from users are being parsed in a controller written in C#, and the server is maintaining the user’s CultureInfo.

    I’ve confirmed that ListSeparator exists in System.Globalization.CultureInfo.TextInfo. If you know how to retrieve arrayListSeparator and arrayGroupSeparator, please let me know.

    Thank you.

  • Posted 25 March 2024, 8:18 pm EST

    Hi,

    The error you were getting “angular.js:12520 numberDecimalSeparator, listSeparator and arrayListSeparator should be different in cluture info.” occurs when numberDecialSeparator, listSeparator, and arrayListSeparator are not different. This is expected behavior as the mentioned separator should be different to correctly parse the data in the cell.

    We are not certain about the exact issue that you are facing. Could you please confirm if you are using SpreadJS or Spread.NET? SpreadJS is a web component that is used at the front end and Spread.NET is used in .NET/C#. As you have mentioned about the controller in C# and System.Globalization.CultureInfo.TextInfo class that are available in C#/.NET.

    Could you please explain your use case in more detail along with a sample? So that we can have clarity on the issue and resolve it as soon as possible.

    Regards

  • Posted 26 March 2024, 1:40 pm EST - Updated 26 March 2024, 4:18 pm EST

    Thank you for the information.

    Sorry for the unclear use case.

    I’m developing a web application using TypeScript (& SpreadJS) on the front end and C# on the server side.

    When accessing the application, the following method created in C# is called:

    public ActionResult Index(string returnUrl) {
        var context = GetContext();
    
        //
        // some processes
        //
    
        var userLangs = Request.UserLanguages;
        CultureInfo userCultureInfo = userLangs != null && userLangs.Length > 0
        ? new CultureInfo(userLangs[0])
        : CultureInfo.CurrentCulture;
    
        context.Separator = new MyContext.SeparateCharacterContainer
        {
            CurrencyGroupSeparator = userCultureInfo.NumberFormat.CurrencyGroupSeparator,
            CurrencyDecimalSeparator = userCultureInfo.NumberFormat.CurrencyDecimalSeparator,
            NumberGroupSeparator = userCultureInfo.NumberFormat.NumberGroupSeparator,
            NumberDecimalSeparator = userCultureInfo.NumberFormat.NumberDecimalSeparator,
            PercentGroupSeparator = userCultureInfo.NumberFormat.PercentGroupSeparator,
            PercentDecimalSeparator = userCultureInfo.NumberFormat.PercentDecimalSeparator,
            ListSeparator = userCultureInfo.TextInfo.ListSeparator
        };
    
        //
        // some processes
        //
    }

    “context” is an object that holds settings and is common in the program.

    In this process, separators are stored on the server side.

    When the Spread screen is displayed, the method created in C# is called by the following TypeScript function:

    protected loadSpreadData(lockCancel: boolean) {
        var me = this;
        me.myHttp.doPost('GetSpreadData', { bookDataId: me.id, lockCancel: lockCancel }, function (data) {
            me.loadSpread(data);
        });
    }

    The C# method looks like this:

    [HttpPost]
    public ActionResult GetSpreadData(decimal bookDataId, bool lockCancel) {
        //
        // some processes
        //
    
        Dictionary<string, object> dto = new Dictionary<string, object>();
        var separator = new Dictionary<string, string>
        {
            { "CurrencyGroup", context.Separator.CurrencyGroupSeparator },
            { "CurrencyDecimal", context.Separator.CurrencyDecimalSeparator },
            { "NumberGroup", context.Separator.NumberGroupSeparator },
            { "NumberDecimal", context.Separator.NumberDecimalSeparator },
            { "PercentGroup", context.Separator.PercentGroupSeparator },
            { "PercentDecimal", context.Separator.PercentDecimalSeparator },
            { "List", context.Separator.ListSeparator },
            { "UICurrencyGroup", context.UISeparator.CurrencyGroupSeparator },
            { "UICurrencyDecimal", context.UISeparator.CurrencyDecimalSeparator },
            { "UINumberGroup", context.UISeparator.NumberGroupSeparator },
            { "UINumberDecimal", context.UISeparator.NumberDecimalSeparator },
            { "UIPercentGroup", context.UISeparator.PercentGroupSeparator },
            { "UIPercentDecimal", context.UISeparator.PercentDecimalSeparator },
            { "UIList", context.UISeparator.ListSeparator }
        };
        dto["Separator"] = separator;
    
        //
        // some processes
        //
    
        return this.Json(dto);
    }

    With this method, separators stored on the server side are returned as a JsonResult.

    The returned value is processed by the following function:

    protected loadSpread(data: any) {
        //
        // some processes
        //
    
        // set separator to current culture
        // "culture-nm" is current culture name
        var cultureInfo = GC.Spread.Common.CultureManager.getCultureInfo(angular.element("#culture-nm").val());
        var numberFormat: any = cultureInfo.NumberFormat;
        // data.Separator contain separators I want to set
        numberFormat.currencyGroupSeparator = data.Separator.CurrencyGroup;
        numberFormat.currencyDecimalSeparator = data.Separator.CurrencyDecimal;
        numberFormat.numberGroupSeparator = data.Separator.NumberGroup;
        numberFormat.numberDecimalSeparator = data.Separator.NumberDecimal;
        numberFormat.percentGroupSeparator = data.Separator.PercentGroup;
        numberFormat.percentDecimalSeparator = data.Separator.PercentDecimal;
        cultureInfo.NumberFormat = numberFormat;
        // set edited culture
        GC.Spread.Common.CultureManager.addCultureInfo("lo-cl", cultureInfo);
        GC.Spread.Common.CultureManager.culture("lo-cl");
    
        //
        // some processes
        //
    }

    In this “loadSpread” function, the returned value is used to set data in the Spread.

    Before setting data in the Spread, I tried to change current culture separators using the above process.

    Is this information sufficient?

    Thank you.

  • Posted 27 March 2024, 12:41 am EST

    Hi,

    Thanks for the detailed explanation of your use case. It was of immense help to understand the issue.

    As per my understanding, you are fetching the culture-related (separators, etc) data/settings from the C# project at the backend and then using that data in SpreadJS to modify the culture settings. However, you are not able to find the arrayGroupSeparator and arrayListSeparator properties in C# to map them accordingly in SpreadJS and because of that you were getting the error “angular.js:12520 numberDecimalSeparator, listSeparator and arrayListSeparator should be different in cluture info.” which occurs due to same separator in numberDecimalSeparator, listSeparator, and arrayListSeparator.

    After investigating the issue, it seems that arrayGroupSeparator and arrayListSeparator properties are specific in SpreadJS INumberFormat. So, after fetching the culture settings from the backend, you need to process the culture settings at the front end to make sure that numberDecimalSeparator, listSeparator and arrayListSeparator are not same.

    Please let us know if you face any difficulties.

    Regards

  • Posted 27 March 2024, 12:33 pm EST

    Thank you for the information.

    I understand that arrayGroupSeparator and arrayListSeparator are specific to SpreadJS.

    Moreover, by manually setting listSeparator, arrayListSeparator, and numberDecimalSeparator to different values, I was able to avoid the error “angular.js:12520 numberDecimalSeparator, listSeparator, arrayListSeparator should be different in culture info.”

    Thank you for that.

    However, I was unable to resolve the issue of incorrect formatting of decimals when displaying the spread.

    The example of the display is the same as shown earlier in this thread.

    Is there a way to correct this display behavior as well?

    Thank you.

  • Posted 27 March 2024, 11:50 pm EST

    Hi,

    Could you please provide us with a sample that replicates the issue? It would be difficult to find the root cause of the issue without replicating it at our end.

    Regards

  • Posted 28 March 2024, 6:30 pm EST - Updated 28 March 2024, 6:36 pm EST

    Hello,

    Let me demonstrate an example that I was able to reproduce.

    Below is the code that modifies the current culture’s separators based on the browser’s language.

    var cultureInfo = GC.Spread.Common.CultureManager.getCultureInfo(GC.Spread.Common.CultureManager.culture());
    var usrCulture: GC.Spread.Common.CultureInfo = JSON.parse(JSON.stringify(cultureInfo));
    var numberFormat: any = usrCulture.NumberFormat;
    
    numberFormat.currencyGroupSeparator = data.Separator.CurrencyGroup;
    numberFormat.currencyDecimalSeparator = data.Separator.CurrencyDecimal;
    numberFormat.numberGroupSeparator = data.Separator.NumberGroup;
    numberFormat.numberDecimalSeparator = data.Separator.NumberDecimal;
    numberFormat.percentGroupSeparator = data.Separator.PercentGroup;
    numberFormat.percentDecimalSeparator = data.Separator.PercentDecimal;
    numberFormat.listSeparator = data.Separator.List;
    numberFormat.arrayListSeparator = data.Separator.ArrayList;

    The method to retrieve separators in the backend C# is the same as previously shown.

      1. When the browser’s language is Japanese, English, Korean, etc., it displays correctly as follows:

      1. However, when the browser’s language is German, Italian, etc., the display of decimals is incorrect.

    I believe these differences lie in the separators of number and currency.

      1. GroupSeparator: “,”, DecimalSeparator: “.”
      1. GroupSeparator: “.”, DecimalSeparator: “,”

    To replicate this behavior, I experimented with the sample you provided earlier.

    I set GroupSeparator and DecimalSeparator to pattern 2., and ensured other properties were appropriately configured. However, I was unable to reproduce it in the sample.

    Based on this, I suspect that this behavior may not be due to the version of SpreadJS.

    The version of SpreadJS used in the program is “9.20171.0”.

    Could you please check if this issue can be reproduced in this version?

    Thank you.

  • Posted 31 March 2024, 12:16 pm EST

    Hello,

    Here is an example I was able to reproduce.

    Below is the code that modifies the current culture’s separators based on the browser’s language.

    var cultureInfo = GC.Spread.Common.CultureManager.getCultureInfo(GC.Spread.Common.CultureManager.culture());
    var usrCulture: GC.Spread.Common.CultureInfo = JSON.parse(JSON.stringify(cultureInfo));
    var numberFormat: any = usrCulture.NumberFormat;
    
    numberFormat.currencyGroupSeparator = data.Separator.CurrencyGroup;
    numberFormat.currencyDecimalSeparator = data.Separator.CurrencyDecimal;
    numberFormat.numberGroupSeparator = data.Separator.NumberGroup;
    numberFormat.numberDecimalSeparator = data.Separator.NumberDecimal;
    numberFormat.percentGroupSeparator = data.Separator.PercentGroup;
    numberFormat.percentDecimalSeparator = data.Separator.PercentDecimal;
    numberFormat.listSeparator = data.Separator.List;
    numberFormat.arrayListSeparator = data.Separator.ArrayList;

    The method to retrieve separators in the backend C# is the same as previously shown.

      1. When the browser’s language is Japanese, English, Korean, etc., it displays correctly as follows:

      1. However, when the browser’s language is German, Italian, etc., the display of decimals is incorrect.

    I believe these differences lie in the separators of number and currency.

      1. GroupSeparator: “,”, DecimalSeparator: “.”
      1. GroupSeparator: “.”, DecimalSeparator: “,”

    To replicate this behavior, I experimented with the sample you provided earlier.

    I set GroupSeparator and DecimalSeparator to pattern 2., and ensured other properties were appropriately configured. However, I was unable to reproduce it in the sample.

    Based on this, I suspect that this behavior may not be due to the version of SpreadJS.

    The version of SpreadJS used in the program is “9.20171.0”.

    Could you please check if this issue can be reproduced in this version?

    Thank you.

  • Posted 31 March 2024, 12:21 pm EST

    The duplicate replies above are my failed attempts to edit the content. I hope you don’t mind.

  • Posted 31 March 2024, 9:36 pm EST

    Hi,

    Thanks for explaining the issue and sharing your understanding with us.

    Sorry, however, we are not able to find the specific version(9.20171.0) of SpreadJS that you mentioned. Could you please check if this is the correct version that you are using? Kindly share the SpreadJS build(version) with us.

    Also, as you mentioned that the issue was not replicable in the sample that we shared with you, so the issue be specific to the SpreadJS version that you are using(as you have mentioned) or it might be related to your specific implementation. Hence, please provide us with a sample that replicates the issue using the specific SpreadJS version that you are using. You can simply remove the parts where there is interaction with the backend and use static data to reproduce the issue.

    Thanks for your understanding.

    Regards

  • Posted 31 March 2024, 9:48 pm EST - Updated 1 April 2024, 3:02 pm EST

    Thank you for the information.

    The correct version is SpreadJS 9J SP2 (Ver. 9.20171.0).

    I have also confirmed that this version is listed in the following thread.

    https://dev.mescius.jp/support/kb/detail.asp?id=40130

    Here is the sample without the backend(and using static data).

    var cultureInfo = GC.Spread.Common.CultureManager.getCultureInfo(GC.Spread.Common.CultureManager.culture());
    var usrCulture: GC.Spread.Common.CultureInfo = JSON.parse(JSON.stringify(cultureInfo));
    var numberFormat: any = usrCulture.NumberFormat;
    
    numberFormat.currencyGroupSeparator = ".";
    numberFormat.currencyDecimalSeparator = ",";
    numberFormat.numberGroupSeparator = ".";
    numberFormat.numberDecimalSeparator = ",";
    numberFormat.percentGroupSeparator = ".";
    numberFormat.percentDecimalSeparator = ",";
    numberFormat.listSeparator = ";";
    numberFormat.arrayGroupSeparator = ";";
    numberFormat.arrayListSeparator = "\\";
    
    usrCulture.NumberFormat = numberFormat;
    GC.Spread.Common.CultureManager.addCultureInfo("lo-cl", usrCulture);
    GC.Spread.Common.CultureManager.culture("lo-cl");

    Thank you.

  • Posted 1 April 2024, 6:09 pm EST - Updated 1 April 2024, 6:14 pm EST

    Hi,

    Thanks for providing us with the code snippet.

    We are able to replicate the issue at our end with SpreadJS 9J SP2 (Ver. 9.20171.0). We replicated the issue with GroupSeparator: “.”, DecimalSeparator: “,” for Number and Currency. Please refer to the attached sample

    SpreadJS_9.20171.0.zip.

    However, please note that the mentioned issue has been already fixed in SpreadJS v13.0.5 and later versions including the latest version of SpreadJS(v17.0.5). Kindly refer to the attached sample “SpreadJS_17.0.5.zip” and the image.

    SpreadJS_17.0.5.zip

    We recommend you to upgrade your SpreadJS version to resolve the issue. The later versions of SpreadJS include new features, bug fixes, and performance enhancement.

    Regards,

    Chandan

  • Posted 1 April 2024, 11:31 pm EST

    Thank you for the information.

    I understood the issue has been already fixed.

    I will consider to upgrade SpreadJS versions.

    Thank you for your support!

    I will mark this thread as resolved.

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels