How to force Text::CSV to store number as text?

Viewed 833

I am writing some perl code to create a .csv file from records in the database, using the Text::CSV module. Occasionally, one or more of the fields in my table will contain multiple repeating 0s, which will write to the CSV as a single 0. I'm trying to find out how to force the number as text format, so that all of the 0s from those fields will remain in tact.

    use Text::CSV_XS;

    sub write_file {
       my ($self, %params) = @_;

       my $fh = $params{fh};

       .. do stuff
       .. get database rows

       my $csv = Text::CSV_XS->new({ sep_char => ',' });
    
       for my $row (@$rows) {
           my @fields = (
              $row->{name},
              $row->{address},
              $row->{code}
           );

           $csv->combine(@fields);

           print $fh $csv->string . "\r\n"
               or die 'Write error.';
       }

With this approach, everything looks good most of the time. But, when code comes through as "00000", it is truncated and written as "0" in my CSV.

I've investigated $csv->types, but this only allows the type to be defined when decoding during a parse.

I've also tried wrapping the fields in quotes using $csv->quote(@fields), with no luck.

2 Answers

Refer to always_quote() to force the the combined fields to be quoted

use Text::CSV_XS;
my $csv = Text::CSV_XS->new( { sep_char => ',' } );

my @fields = ( "0", "00", "000" );

$csv->combine(@fields);
print $csv->string . "\n";

$csv->always_quote(1);
$csv->combine(@fields);
print $csv->string . "\n";

which results in

0,00,000
"0","00","000"

Normalize your data

If the problem is that

  • You want leading 0s,
  • The leading zeros in your input are NOT significant (ie, scientific notation)

Then you can simply normalize the data with sprintf

$x = 5;
print sprintf("%05d", $x)

You can choose how many leading zeros you want in your output, and make all colums read the same.

Related