Hi Monks:

I'm starting to learn Perl and trying to use it in my first real life project. This is my first post on perlmonks.org.

The purpose of the program is to read 2 files and write a CSV batch file to print price labels with glabels (the program is unfinished).

The files to read are:

1) An EDI purchase order. This is a file with fields separated by * and end of lines separated by ~

2) A CSV file with three columns: Store number, type of store (there are 2 types that require different graphics on the label), and store location.

So far I've managed to extract the information I need from the EDI file (probably in a very long-winded way). I wrote a subroutine to read the CSV file (last sub in the code: &separate_stores) and it worked fine when I ran it by itself.

PROBLEM:

Seeing that &separate_stores worked as I wanted, I included it in my main program. When I run it with the other subroutines, &separate_stores seems to never go into the while loop and the two store number arrays return empty. I thought this might be due to the fact that I've read the other file (EDI) earlier in the program and it is somehow interfering with the second read, but I'm not sure and cannot find a way to fix this. Any help is much appreciated. Thank you!

EDI file structure:

The EDI file is a standard EDI purchase order. The program deletes all information before the first line starting with PO1. It then reads the product code from each PO1 line (i.e. *THSB01*). The next line is unecessary. The following line gives store numbers and quantities to be supplied for that product (i.e. *00001*12*00002*10*etc*), then another PO1 line, etc.
ISA*00* *00* *ZZ*EXAMPLE *ZZ*EDISUPPLIER + *130315*0332*U*00304*000001345*0*P*:~GS*PO*EXAMPLE*EDISUPPLIER*13031 +5*0332*993*X*003040~ST*850*000003696~BEG*00*SA*20202020**130315~REF*D +P*0155~DTM*011*130312~DTM*001*130318~N1*SU**92*123456~N1*ST**92*00090 +~PO1**17*EA*42*CA*EN*1234567890123*SK*1234567890*IZ*v*CL*v*ST*THSB10* +BC*LIMPIEZA*BL*005~CTP**RTL*11~SDQ*UN*92*00021*15*00072*2~PO1**6*EA*4 +2*CA*EN*1234567890123*SK*1234567890*IZ*v*CL*v*ST*THSB11*BC*LIMPIEZA*B +L*005~CTP**RTL*11~SDQ*UN*92*00012*2*00134*4~PO1**4*EA*46*CA*EN*123456 +7890123*SK*1234567890*IZ*v*CL*v*ST*THSB12*BC*LIMPIEZA*BL*005~CTP**RTL +*11~SDQ*UN*92*00016*2*00113*1*00165*1~PO1**2*EA*103*CA*EN*12345678901 +23*SK*1234567890*IZ*v*CL*v*ST*THSB01*BC*LIMPIEZA*BL*005~CTP**RTL*20~S +DQ*UN*92*00012*2~PO1**1*EA*52*CA*EN*1234567890123*SK*1234567890*IZ*v* +CL*v*ST*THSB03*BC*LIMPIEZA*BL*005~CTP**RTL*11~SDQ*UN*92*00065*1~PO1** +5*EA*27*CA*EN*1234567890123*SK*1234567890*IZ*v*CL*v*ST*THSB09*BC*LIMP +IEZA*BL*005~CTP**RTL*6~SDQ*UN*92*00031*1*00080*3*00165*1~CTT*6*35~SE* +27*000003696~GE*1*993~IEA*1*000001345~

CSV example file:
# de tienda, tipo, ubicacion 00001,li,location1 00002,li,location2 00003,li,location3 00004,li,location4 00005,li,location5 00006,li,location6 00007,li,location7 00010,ff,location8 00011,ff,location9 00012,ff,location10 00014,li,location11 00015,ff,location12 00016,ff,location13 00017,ff,location14 00019,ff,location15 00021,li,location16 00022,li,location17 00025,ff,location18 00026,ff,location19 00027,ff,location20 00028,ff,location21 00029,li,location22 00031,li,location23 00034,ff,location24 00035,ff,location25 00036,ff,location26 00037,ff,location27

(the file consists of close to 100 locations. The preceeding is a smaller version)

CODE:
#!/usr/bin/perl use strict; use warnings; use File::HomeDir; use List::Util 'first'; use List::MoreUtils 'first_index'; use Text::CSV; my @po = &open_po; #my @po_no_headings = &erase_headings(@po); #my @po_separated = &make_product_store_quantity(@po_no_headings); #print "@po_separated\n"; my ($li_stores_ref, $ff_stores_ref) = &separate_stores; my @liv_stores = @$li_stores_ref; my @ffr_stores = @$ff_stores_ref; print "Li stores: @liv_stores\n"; print "FF Stores: @ffr_stores\n"; # **************************************** # 1) open .EDI file # 2) split into lines through "~" line separator # 3) Place .EDI file contents into @po_array sub open_po { my (edi_file, $po_data, @po_array); edi_file = File::HomeDir->my_home . "/example/po//example.EDI" or di +e ".EDI file not found\n"; open ($po_data, '<', edi_file) or die "Could not open the file 'edi_ +file' $!\n"; undef $/; @po_array = split (/\~/, <$po_data>); close $po_data; return @po_array; } # **************************************** # Erase all information from purchase order before first PO1 line sub erase_headings { my ($delete_point); $delete_point = (first_index {/PO1/} @_) - 1; # Find first PO1 line # Shift array up to first PO1 line for (0..$delete_point) { shift @_; } @_; } # **************************************** # Return array with product, store, quantity # (i.e. THSB01 00021 3 00043 1 THSB02...etc.) sub make_product_store_quantity { my (@line, @product_stores, $product, $product_index); while(scalar (@_) !=0) { @line = split (/\*/, $_[0]); # Split line into fields # Find product code (i.e. THSB01) and shift array twice if ($line[0] eq "PO1") { $product_index = (first_index {/ST/} @line) + 1; $product = $line[$product_index]; shift; shift; } # Find stores & quantity for each store. # Write product code followed by stores & quantity to array @product_s +tores if ($line[0] eq "SDQ") { shift (@line); shift (@line); shift (@line); unshift (@line, $product); push (@product_stores, @line); shift; # Exit when PO line starts with CTT, meaning end of PO1 details } elsif ($line[0] eq "CTT") { undef (@_); } } @product_stores; } # **************************************** # 1) Open and read stores.csv # 2) Place all "li" type store numbers in @li_store array # 3) Place all "ff" type store numbers in @ff_store array # 4) Return array references sub separate_stores { my (@li_stores, @ff_stores); my $stores_file = File::HomeDir->my_home . "/example/data/example.cs +v"; open my $fh, "<", $stores_file or die "$stores_file: $!"; my $csv = Text::CSV->new ({ binary => 1, auto_diag => 1, }); my $count_li = 0; my $count_ff = 0; $csv ->getline ($fh); while (my $row = $csv->getline ($fh)) { if ($row->[1] eq "li") { $li_stores[$count_li] = $row->[0]; $count_li ++; } else { $ff_stores[$count_ff] = $row->[0]; $count_ff ++; } } close $fh; return (\@li_stores, \@ff_stores); }

########################

***PROBLEM SOLVED***

SUMMARY:

1) A subroutine to open and read a CSV file worked fine in isolation but stopped working when integrated into larger script.

2) The problem stemmed from an earlier subroutine (open_po) which globally modified the input record separator ($/) through: undef $/;

3) The problem code was modified to change the state locally, according to sn1987a's post to: local ($/);

4) This modification solved the problem.

Thank you all for your help!

In reply to Cannot work on second file after reading first file. by 1straw

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.