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.