简体   繁体   中英

Missing headers using Perl module Text::CSV::Slurp

I am using Text::CSV::Slurp to create a CSV file from an array of hashes. It works great except some headers are missing.

hash1    
    header1 header2
    1          2

hash2
    header1 header2 header3
    11        22       33

I want the final output to be a CSV file:

header1 header2 header3
1          2
11         22      33

not the slurp output

header1 header2
1          2
11         22

Any suggestions?

code:

sub entry_capture_csv {
my ($stores_folder, $cmdstr, $header_field, $entrycmdstr, $entryfilename) = @_;

print "\t\tOSSI-" . $cmdstr . " for " . $entryfilename . " entry detail\n";
$node->pbx_command($cmdstr);
if ( $node->last_command_succeeded() ) {
    my @ossi_output = $node->get_ossi_objects();
    my $i = 0;
    my @ext_array;
    foreach my $hash_ref(@ossi_output) {
        $i++;
        #print "output result $i\n";
        for my $field ( sort keys %$hash_ref ) {
            my $value = $hash_ref->{$field};
            #print "\t$field => $value\n";
        }
        my $entryNumber = trim($hash_ref->{$header_field});
        unless( defined $entryNumber ) { $entryNumber = '' };
        if ($entryNumber eq "") {
            #empty string
        } else {
            push(@ext_array, $entryNumber);
        }
    }

    # Issue = failed sometimes there is extra header
    #
    my @result_array;

    foreach (@ext_array) {
        my $entrycmd =  $entrycmdstr . " " . $_;
        $node->pbx_command($entrycmd);

        if ( $node->last_command_succeeded() ) {
            print "\t\t\t" . $entrycmd . "\n";

            my @ossi_output = $node->get_ossi_objects();
            push(@result_array, @ossi_output);

            #my $csv = Text::CSV::Slurp->create( input => \@ossi_output );
            #open (OUTFILE, ">$stores_folder/$store-" . $entryfilename . "-" . "$_" . ".csv") || die "Can't open output file.\n";
            #print OUTFILE $csv;
            #close(OUTFILE);

        } else {
            print "Failed\t\t\t" . $entrycmd . "\n";
        }
    }

    my $csv = Text::CSV::Slurp->create( input => \@result_array );
    open (OUTFILE, ">$stores_folder/$store-" . $entryfilename . ".csv") || die "Can't open output file.\n";
    print OUTFILE $csv;
    close(OUTFILE);
}

}

The Text::CSV::Slurp->create constructor method takes a field_order option which defines the keys of the hash elements to be used and their order in the CSV record.

Take a look at this code, which I think is self-explanatory.

use strict;
use warnings;

use Text::CSV::Slurp;

my @data = (
  {
    header1 => 1,
    header2 => 2,
  },
  {
    header1 => 11,
    header2 => 22,
    header3 => 33,
  },
);

my $csv = Text::CSV::Slurp->create(
    input => \@data,
    field_order => [qw/ header1 header2 header3 /]);

print $csv;

output

header1,header2,header3
1,2,
11,22,33

Update

To automate getting a list of headers from the data, you could write something like this. The output is identical to that from the previous program.

Note that there is no way of knowing how best to sort the list of headers so I have used a simple lexical sort. It produces the desired effect with this trivial data.

use strict;
use warnings;

use Text::CSV::Slurp;

my @data = (
  {
    header1 => 1,
    header2 => 2,
  },
  {
    header1 => 11,
    header2 => 22,
    header3 => 33,
  },
);

my @headers = do {
  my %headers;
  $headers{$_}++ for map { keys %$_ } @data;
  sort keys %headers;
};

my $csv = Text::CSV::Slurp->create(
    input => \@data,
    field_order => \@headers);

print $csv;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM