Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doing math with auto_format: true #154

Open
Nickduino opened this issue Nov 23, 2024 · 9 comments
Open

Doing math with auto_format: true #154

Nickduino opened this issue Nov 23, 2024 · 9 comments

Comments

@Nickduino
Copy link

I’d like column 5 to be column 4 multiplied by 43 (the price of a liter multiplied by the capacity = the price of a full tank).

It works if I don’t use auto_format :

image

Not with it true:

image

Just in case, I tried :

image

I’m sure some of you will tell me it works exactly as expected but I can assure you, as a user (and not a Javascript developer or a computer wizard of some sort), it’s extremely disconcerting. Should I turn auto_format off and then apply a modify: to each column to replace the . with a , and add the unit?

@daringer
Copy link
Collaborator

daringer commented Nov 27, 2024

auto_format happens very early - in fact the data is already received formatted from HA. This means inside modify you'll have a string already - doing arithmetic on strings is not liked by JS:

a = "3 hdf"
"3 hdf"
>> a*4
NaN 

So under the line this boils down to the order of operations done on the data.
Maybe you should take a look into suffix (which is appended after modify):
https://github.com/custom-cards/flex-table-card/blob/master/docs/example-cfg-simple-cell-formatting.md

It feels like we should document these orders to avoid this confusion...

@EdLeckert
Copy link
Contributor

I'd like to fix this problem by grabbing both unformatted and formatted versions and making the unformatted version available for cross-cell math, sorting, footers, etc. The need for unformatted data keeps popping up in issues.

Haven't looked at it in detail yet but I will.

@Nickduino
Copy link
Author

I'd like to fix this problem by grabbing both unformatted and formatted versions and making the unformatted version available for cross-cell math, sorting, footers, etc. The need for unformatted data keeps popping up in issues.

Haven't looked at it in detail yet but I will.

But then the cell in which you did cross-cell math won't be formatted, right?

Could the card do the formatting itself (grab the locale from HA and format the data once it's been modified, suffixed and everything)?

@EdLeckert
Copy link
Contributor

But then the cell in which you did cross-cell math won't be formatted, right?

The card can grab both formatted and unformatted values from HA and provide one or the other as appropriate.

In the meantime, you can use parseFloat:

let x = "1.682 €";
console.log (((parseFloat(x)) * 43).toFixed(1));
> "72.3"

The reason this works in this case is:

parseFloat() is more lenient than Number() because it ignores trailing invalid characters, which would cause Number() to return NaN.

parseFloat

@Nickduino
Copy link
Author

But then the cell in which you did cross-cell math won't be formatted, right?

The card can grab both formatted and unformatted values from HA and provide one or the other as appropriate.

Some cells will be formatted (the ones without math), the others won't.

In the meantime, you can use parseFloat:

let x = "1.682 €";
console.log (((parseFloat(x)) * 43).toFixed(1));
> "72.3"

The reason this works in this case is:

parseFloat() is more lenient than Number() because it ignores trailing invalid characters, which would cause Number() to return NaN.

I tried:

image

It doesn't work at all:

  1. It doesn't do the math, I get 55 instead of 55*1,8 (or whatever the price per liter is);
  2. the second column loses its format anyway.

image

@EdLeckert
Copy link
Contributor

EdLeckert commented Nov 29, 2024

Apparently parseFloat doesn't support commas as a decimal separator.

The characters accepted by parseFloat() are plus sign (+), minus sign (- U+002D HYPHEN-MINUS), decimal digits (0 – 9), decimal point (.), exponent indicator (e or E), and the "Infinity" literal.

So, you'll have to convert the comma to a period, and then you would have to reformat it:

let x = "1,682 €";
let result =  new Intl.NumberFormat('fr',).format((((parseFloat(x.replace(',', '.'))) * 43).toFixed(1))) + ' €';
console.log(result);
> "72,3 €"

It's not pretty, but it works.

@Nickduino
Copy link
Author

Thank you for spending time on my problem!

We're getting somewhere:

image

It's already really good but I'd like to force the number of decimals to 3 on the first column and 2 on the second one.

I tried modify: (new Intl.NumberFormat('fr',).format(parseFloat(x))).toFixed(3), modify: new Intl.NumberFormat('fr', { minimumFractionDigits: 3 } ).format(parseFloat(x)) to no avail

@EdLeckert
Copy link
Contributor

As I said, you're not going to get anywhere trying to parseFloat a number with a comma as a decimal separator.

BTW, I used "fr" to force the locale to French for the example, since my environment is set to "en-US".

let x = "1,8";
let y = 55;
console.log(new Intl.NumberFormat('fr',{minimumFractionDigits:3}).format(parseFloat(x.replace(',', '.'))) + "€/l");
console.log(new Intl.NumberFormat('fr',{minimumFractionDigits:2}).format((parseFloat(x.replace(',', '.') * y))) + "€");
> "1,800€/l"
> "99,00€"

@Nickduino
Copy link
Author

As I said, you're not going to get anywhere trying to parseFloat a number with a comma as a decimal separator.

I know, so I had not set auto_format: to true. So I didn't need x.replace(',', '.') since x was already using a decimal point. My mistake (and I thank you for allowing me to realize it) was the space in minimumFractionDigits: 3

So, with modify: Intl.NumberFormat('fr',{ minimumFractionDigits:3 }).format(parseFloat(x)), I get:
image

Thanks again!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants