Jspdf: Strange formatting of number fields

Created on 28 Jul 2020  路  8Comments  路  Source: MrRio/jsPDF

In case where a number field follows a format such as "100 000,00" (space after every 3 digits, comma for decimal point) the output file replaces the space with a slash (/) and places a space between every digit, like so:

image

I followed the creation of the PDF file in our project all the way down until the code got to jsPDF, this is what the model looks like before it exits our code and gets sent to the JsPdfAutotable.save() method:

Screenshot 2020-07-28 at 17 38 16

The highlighted values will always come out in the format "1 / 0 0 0 , 0 0" for some reason. This is doubly confusing since the number is given as a string, like any other value.

I'm using Angular 9. This might be an Autotable issue, in which case I will move it to that project.

Thanks

All 8 comments

That's interesting. Could you share a minimal repro for debugging?

@HackbrettXXX
I've been trying to set up a Stackblitz but it's a nightmare trying to get it to work with autotable, and it keeps giving me the doc.autoTable is not a function error.
I have zeroed in on the source of the issue though (more or less). It's angular's built in formatNumber function.

If you format a number using the French localization ('fr-FR'), it will be exported like the picture I posted above.
Here's some basic code to try it out. Maybe you have an empty jsPDF project locally that you can plug this into?

import { formatNumber } from '@angular/common';

public exportPdf() {
    const doc = new jsPDF('portrait', 'pt', 'a4');
    const options = {
      columns: [
        {
          header: 'Name',
          dataKey: 'name'
        },
        {
          header: 'Amount',
          dataKey: 'amount'
        }
      ],
      body: [
        {
          name: 'Balance 1',
          amount: formatNumber(3.0012, 'fr-FR')
        },
        {
          name: 'Balance 2',
          amount: formatNumber(40001010, 'fr-FR')
        },
        {
          name: 'Balance 3',
          amount: formatNumber(3000.10, 'fr-FR')
        }
      ]
    };

    doc.autoTable(options);
    doc.save('sample.pdf');
  }

Don't forget to register the locale in your AppModule:

import { NgModule, LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
registerLocaleData(localeFr);

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ],
  providers: [
    { provide: LOCALE_ID, useValue: 'fr-FR'},
  ]
})
export class AppModule { }

If I set up a project without Angular I can't reproduce the issue. This is my code:

  const doc = new jsPDF('portrait', 'pt', 'a4');
  const options = {
    columns: [
      {
        header: 'Name',
        dataKey: 'name'
      },
      {
        header: 'Amount',
        dataKey: 'amount'
      }
    ],
    body: [
      {
        name: 'Balance 1',
        amount: "3,0012"//formatNumber(3.0012, 'fr-FR')
      },
      {
        name: 'Balance 2',
        amount: "40 001 010" //formatNumber(40001010, 'fr-FR')
      },
      {
        name: 'Balance 3',
        amount: "3 000,10"//formatNumber(3000.10, 'fr-FR')
      }
    ]
  };

  doc.autoTable(options);
  doc.save('sample.pdf');

I replaced the formatNumbers with strings matching your screenshot above. Here is the PDF:
sample.pdf

What is the exact result of formatNumber in your example?

Yep, without Angular everything is fine. If you simply provide a string in the style of "4 444,0000" then it will export properly. For some reason the formatNumber method corrupts it, despite returning what seems to be the exact same string.

The exact result of formatNumber is always just a string that looks like all the other strings.

Maybe it uses a different space character or something like that? Please check the char codes of the strings.

You were correct, it was giving back U+202F instead of U+0020. A string.replace(' ', ' ') was enough to fix it. Thanks!

Alternatively you could add a TTF Unicode font that supports this character. Replacing it is probably, the better option, though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yankeeBrit picture yankeeBrit  路  3Comments

arulmb0136 picture arulmb0136  路  4Comments

mellisa0109 picture mellisa0109  路  3Comments

NoFootDancer picture NoFootDancer  路  3Comments

sajesh1985 picture sajesh1985  路  5Comments