-4

Below is the output I got when I use print Dumper(\%Data) in my code

{
  "" => undef,
  "123456789012:SRIRAMA" => [123456789012, "SRIRAMA", 856.06, 0, 0, 0],
  "389252737122:RAMA" => [389252737122, "RAMA", 345.76, 0, 0, 0],
}

This data I have to write to an Excel file like below

Number          Name    number        name   amt    amt2    amt3    amt4
123456789012    SRIRAMA 123456789012 SRIRAMA 856.06  0      0       0
389252737122    RAMA    389252737122 RAMA    345.76  0      0       0

The first two columns are one SQL result and rest of the columns are another SQL query result.

The first query result I have put in a map and searched based on the key in second query result and finally I got the output above.

Here, Number and Name—the first two columns—are keys for searching the data.

The code below is after getting the SQL result:

    foreach ( @Sqlresult ) {
        $rec_cntr = $rec_cntr + 1;
        my @fields = undef;
        chop;

        next if /^$/;
        next if /ERROR:/;
        next if /ORA-/;

        @fields = split( /::/, $_ );
        my $fldref = @fields;
        $ent_id = undef;
        $ent_id = $fields[0];
        $key    = undef;
        $key    = $fields[0] . ":" . $name;

        push( @{ $Data{$key} }, $fields[1] );
    }

    $rec_cntr = 0;

The below code snippet I use when the records are not there pushing as zero.

    my $kkey = undef;

    for $kkey ( sort keys %Data ) {
        next if $kkey eq '';
        my $Lent = @{ $Data{$kkey} };
        if ( $Lent < 5 ) {
            push( @{ $Data{$kkey} }, 0 );
        }
        print scalar @{ $Data{$kkey} };

    }

    print Dumper( \%Data );

The above print Dumper produces the information shown at the start of the question

Here is where the data is written into an Excel sheet

my $dt = `date +%m-%d-%Y_%\I%\M`;

chop $dt;
my $FileName = "/data_reports/AdjestedFile" . $dt . ".xls";

#my $workbook = Spreadsheet::WriteExcel->new( $FileName );
my $workbook = Excel::Writer::XLSX->new( $FileName );

# Define the format and add it to the worksheet
my $format = $workbook->add_format(
    center_across => 1,
    bold          => 1,
    size          => 10,
    color         => "black",
    bg_color      => "grey",
    border_color  => "black",
    align         => "vcenter",
);

my $formatnum = $workbook->add_format();
$formatnum->set_num_format( '00000000000' );

my $formatamt = $workbook->add_format();
$formatamt->set_num_format( '0.00' );
$formatamt->set_align( 'right' );

my $formattext = $workbook->add_format( num_format => '@' );

my $prev_feetype = "";

my $current_ws;
$current_ws = $workbook->add_worksheet();
$current_ws->keep_leading_zeros( 1 );

$current_ws->set_column( 0, 16, 17, $formattext );
$current_ws->set_column( 1, 1,  13, $formattext );
$current_ws->set_column( 2, 2,  10, $formatnum );
$current_ws->set_column( 3, 3,  10, $formattext );
$current_ws->set_column( 4, 4,  10, $formattext );
$current_ws->set_column( 5, 5,  10, $formattext );
$current_ws->set_column( 6, 6,  10, $formattext );
$current_ws->set_column( 7, 7,  10, $formattext );

my $cl = 0;
$current_ws->write_string( 0, $cl++, "Number", $format );
$current_ws->write_string( 0, $cl++, "Name",   $format );
$current_ws->write_string( 0, $cl++, "amt",    $format );
$current_ws->write_string( 0, $cl++, "NA",     $format );
$current_ws->write_string( 0, $cl++, "NA",     $format );
$current_ws->write_string( 0, $cl++, "NA",     $format );
$current_ws->write_string( 0, $cl++, "NA",     $format );
$current_ws->write_string( 0, $cl++, "NA",     $format );

my $rownum = 1;

foreach ( %Data ) {

    my @fields = undef;
    chop;

    next if /^$/;
    @fields = split( /,/, $_ );

    my $fldref = \@fields;
    my $clcntr = 0;
    my $ent_id = "";

    foreach ( @fields ) {

        if ( $clcntr == 1 ) {
            $ent_id = $_;
        }
        if ( isfloat( $_ ) ) { #and $clcntr != 9 ) {

            $current_ws->write_number( $rownum, $clcntr++, $_ );
        }
        else {
            $current_ws->write_string( $rownum, $clcntr++, $_ );
        }
    }
}
Borodin
  • 126,100
  • 9
  • 70
  • 144
Rama
  • 1
  • 3
  • 2
    You will need to show your program before we can help you to fix it. – Borodin May 27 '17 at 15:30
  • Hello Borodin, thanks replying. For me getting the result and pushing into a map working correctly, but not sure how to write it into an excel sheet. – Rama May 27 '17 at 16:28
  • 1
    Thank you. You may answer you own question, but what you've written isn't an answer. You should edit your question to add the information there. There's an `edit` link just below your question. I've added it for you, so please delete your answer. – Borodin May 27 '17 at 17:59

1 Answers1

2

There's a lot to read there, but these ideas may help

  • Always use strict and use warnings at the top of every Perl program you write. It is invaluable for locating the more obvious bugs

  • Don't initialise arrays with @data = undef. If you want to empty an existing array then write @data = (). If you are declaring a new array then my @data will create a new empty array

    The exact same advice applies to hashes, and that will be the reason for the "" => undef at the start of your %Data hash

  • Don't use my $dt = `date +%m-%d-%Y_%\I%\M`. You are starting a whole new shell process just to ask it the time. You should

    use Time::Piece;
    

    and

    my $dt = localtime->strftime('%m-%d-%Y_%I%M');
    

    The result from this won't need chomping

    But are you sure you want %I? That gives you the 12-hour time, so the value will reset to zero at midday. %H gives you 24-hour time, and is much more likely to be useful

  • chomp is preferable to chop unless you're doing something unusual. chop will just remove the last character from a string, whatever it is, while chomp will remove the last character if it is a newline

  • for ( %Data ) { ... } will loop over the hash setting $_ to key1, val1, key2, val2 etc. That isn't what you want

    In this case, since the information in the key is duplicated in the value, you probably want for ( values %Data ) { ... }. But that value is an array reference so no splitting is required

This is probably closer to what you need

my $rownum = 0;

for my $values ( values %Data ) {

    my $colnum = 0;

    for my $val ( @$values ) {

        if ( isfloat($_) ) {
            $current_ws->write_number( $rownum, $colnum++, $val );
        }
        else {
            $current_ws->write_string( $rownum, $colnum++, $val );
        }
    }
}
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thank you so much for your explanation, some how i make it work what i need, will paste the code once i complete. – Rama May 27 '17 at 18:49
  • I'm getting an error always when a ran the perl program sh: line 15: warning: here-document at line 0 delimited by end-of-file (wanted `!') but in line 15 i have the code: sub isfloat{ my $val = shift; return $val =~ m/^\d+.\d+$/; } – Rama May 27 '17 at 18:50
  • @Rama: You're running your program with sh instead of perl. Did you write this code? How did you run it when you got `Dumper` output? – Borodin May 27 '17 at 19:02
  • I didn't understand the terminology that you are asking, i ran the script like ./program.pl – Rama May 27 '17 at 19:41
  • @Rama: It sounds like you're using the Bourne shell `sh` and you're passing your program to that shell for execution as a shell script, which doesn't understand Perl. I would guess that you have no shebang `#!` line at the start of your program. You can run it anyway with `perl program.pl` – Borodin May 27 '17 at 20:54
  • I'm using #!/usr/bin/perl at the beginning and also i ran like perl program.pl but getting the same error sh: line 9: warning: here-document at line 0 delimited by end-of-file (wanted `!') – Rama May 28 '17 at 06:00
  • It looks like issue is not with shell or #! when i'm generating the report as excel it is getting the warning my $dt=`date +%m-%d-%Y_%\I%\M`; chop $dt; my $FileName = "/reports/RamFile".$dt.".xls"; my $workbook = Excel::Writer::XLSX->new($FileName); – Rama May 28 '17 at 10:29
  • @Rama: I don't see much point in asking for help if you are going to ignore the answers you get. Please correct *all* of the issues I have listed, including fetching the date-time string from a call to `date`. – Borodin May 28 '17 at 13:54
  • @Rama: Since this is a completely different problem from your original question you should open a new question. Perhaps you have accidentally removed the closing backtick from your call to `date`? – Borodin May 28 '17 at 14:02
  • :Thanks for all your suggestions which was helped a lot to me and this Warning issue i had a space after my sql query (Before ending with !) – Rama May 31 '17 at 11:54