Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Perl formatting beginner

by Anonymous Monk
on Apr 15, 2014 at 15:23 UTC ( [id://1082353]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi all i am new to perl just trying to figure out how I would format my output to look a certain way if possible. I want it be in 3 columns 10 rows Avery 5160 format, but without the use of PostScript. but right now it only show all in one column all the way down.

#!/usr/bin/perl # Program name: perlReadAndFormat.pl # Purpose: Open disk file. Read and display the records in # the file. Count the number of records in the file. format LABEL = @<<<<<<<<<<<<<<<< $CUSTID @<<<<<<<<<<<<<<<< $fname @<<<<<<<<<<<<<<<< $lname @<<<<<<<<<<<<<<<< $phone @<<<<<<<<<<<<<<<< $address @<<<<<<<<<<<<<<<< $city @<<<<<<<<<<<<<<<< $state @<<<<<<<<<<<<<<<< $zip @<<<<<<<<<<<<<<<< $email . #$topmargin = 0.60; #$poleft = 0.4; $pomiddle = 3.20; $poright = 5.95; $lheight = 1; $row = int($opt{r}) || 1; # chop off any fractional parts and $col = int($opt{c}) || 1; if ($col == 1) { $po = $poleft; } elsif ($col == 2) { $po = $pomiddle; } else { $po = $poright; } # $sp = ($topmargin + ($row - 1)*$lheight); # required terminator for format definition open (FILEIN, "cust.txt") || warn "Could not open passwd file\n"; open (LABEL, ">labels-to-print") || warn "Can't create labels file\n"; while (<FILEIN>) { #print "$_"; ($CUSTID,$fname,$lname,$phone,$address,$city,$state,$zip,$email) += split(/,/,$_); # Or use array: @fields = split(/,/,$_); write(LABEL); # send to output ++$line_count; } print ("File \"passwd\" has $line_count lines. \n"); close (FILEIN); close (LABEL);

Replies are listed 'Best First'.
Re: Perl formatting beginner
by ww (Archbishop) on Apr 15, 2014 at 16:06 UTC
    1. Perl is indeed wonderfully capable... but do you really need to do it the hard way? After all, a standard Perl remark is 'don't reinvent the wheel:' http://office.microsoft.com/en-us/templates/avery-5160-mailing-labels-featuring-avery-app-for-word-2013-anniversary-design-30-per-page-TC103749911.aspx
    2. But if you're still going to do it in Perl, it looks as though you have a comma-delimited source file, AKA, CSV. So use one of the csv modules to drag in your data (not that what you were doing is terribly wrong).
    3. And if you're still going to do it your way -- minus the formatting:
    #!/usr/bin/perl use strict; use warning; #mandatory inclusions until you know enough to know +when you can skip these helpers use 5.016; # Program name: perlReadAndFormat.pl # Purpose: Open disk file. Read and display the records in # the file. Count the number of records in the file. # open (FILEIN, "cust.txt") || warn "Could not open source file\n"; open (LABEL, ">","labels-to-print.txt") || warn "Can't create labels f +ile\n"; # while (<FILEIN>) while (<DATA>){ #print "$_"; ($CUSTID,$fname,$lname,$phone,$address,$city,$state,$zip,$email) += split(/,/,$_); # Or use array: @fields = split(/,/,$_); # write(LABEL); # send to output print LABEL "$CUSTID,$fname,$lname\n$address,$city,$state,$zip\n$ +phone,$email\n"; ++$line_count; } print ("File \"passwd\" has $line_count lines. \n"); close (FILEIN); close (LABEL); __DATA__ $CUSTID,$fname,$lname,$phone,$address,$city,$state,$zip,$email 1,fred,jones,555-1212,123 Main St.,Boston, MA,00001,test@test.com 2,mary,smith,222-1515,321 Least St.,Hanover,NH,02022,testmary@test.com 3,jack,least,122-5511,231 Last St.,Franklin,CT,06001,nomail@test.com

    Output:

    1,fred,jones 123 Main St.,Boston, MA,00001 555-1212,test@test.com 2,mary,smith 321 Least St.,Hanover,NH,02022 222-1515,testmary@test.com 3,jack,least 231 Last St.,Franklin,CT,06001 122-5511,nomail@test.com

    Obviously, this ignores your desire to spread them over the page; that's left as an exercise...
    BUT IT WOULD HAVE BEEN NICE IF YOU'D SHOWN US THE DESIRED OUTPUT!


    Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
    1. code
    2. verbatim error and/or warning messages
    3. a coherent explanation of what "doesn't work actually means.

    check Ln42!

      It also ignores nested comma-characters, which IIRC are quite common in addresses. It also disables addresses so complicated they need embedded newlines.

      I like the approach, but please advice the use of Text::CSV_XS and/or Text::CSV.


      Enjoy, Have FUN! H.Merijn

        ... but please advice the use of Text::CSV_XS and/or Text::CSV..

        I think ww did "advise" that on the second point, though he didn't mention one.

        ..But if you're still going to do it in Perl, it looks as though you have a comma-delimited source file, AKA, CSV. So use one of the csv modules to drag in your data (not that what you were doing is terribly wrong).

        If you tell me, I'll forget.
        If you show me, I'll remember.
        if you involve me, I'll understand.
        --- Author unknown to me
Re: Perl formatting beginner
by Not_a_Number (Prior) on Apr 15, 2014 at 20:56 UTC

    First:

    #$topmargin = 0.60; #$poleft = 0.4; $pomiddle = 3.20; $poright = 5.95; $lheight = 1; $row = int($opt{r}) || 1; # chop off any fractional parts and $col = int($opt{c}) || 1; if ($col == 1) { $po = $poleft; } elsif ($col == 2) { $po = $pomiddle; } else { $po = $poright; } # $sp = ($topmargin + ($row - 1)*$lheight);

    I have no idea what these 16 lines are meant to do. I doubt that you have, either, since none of the variables defined are actually used...

    Second:

    I can only agree with ww that:

    IT WOULD HAVE BEEN NICE IF YOU'D SHOWN US THE DESIRED OUTPUT!

    However, for the sake of argument, let's presume that you'd like the following output from ww's __DATA__ section:

    1 fred jones 555-1212 123 Main St. Boston MA 00001 test@test.com 2 mary smith 222-1515 321 Least St. Hanover NH 02022 testmary@test.com 3 jack least 122-5511 231 Last St. Franklin CT 06001 nomail@test.com

    In that case, you need to change your format definition to something like:

    @<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<< $CUSTID,$fname,$lname @<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<< $phone,$address,$city @<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<< $state,$zip,$email

    Proof of concept:

    Third:

    Don't use format. It's just too clunky. Learn how to use printf/sprintf:

    use strict; use warnings; while ( <DATA> ) { my @fields = split /,/; while ( my @chunk = splice @fields, 0, 3 ) { printf "%-17s", $_ for @chunk; print "\n"; } } __DATA__ 1,fred,jones,555-1212,123 Main St.,Boston,MA,00001,test@test.com 2,mary,smith,222-1515,321 Least St.,Hanover,NH,02022,testmary@test.com 3,jack,least,122-5511,231 Last St.,Franklin,CT,06001,nomail@test.com

    Fourth:

    Other respondents are right: use Text::CSV rather than naïvely splitting the lines from your input file on commas.

    Update:

    Combined internet connection/brainfart problems have necessitated several unlisted alterations to the original version of this post. My apologies.

Re: Perl formatting beginner
by DrHyde (Prior) on Apr 16, 2014 at 10:30 UTC
    Why not use PostScript? When the problem is to carefully control the position of text on a page, PostScript is the right tool for the job. I've had great success using PostScript::Simple in the past.
Re: Perl formatting beginner
by RonW (Parson) on Apr 16, 2014 at 17:18 UTC
    Hello,

    Yes, I do recommend using a CSV module ro read your data. And yes, I recommend against format, but it is an easy (though very tedious), visual way to lay out "page oriented" output.

    Caveat: When using format, you need to use a monospaced font for your output.

    Caveat: This is really ugly. (Because format is really clunky)

    My example, below, is very simple. Even with format, it can be done better.

    (Also, I'm very probably forgetting something, here. It has been years since I last used format.)

    I am guessing you intend to print labels. Depending on print size and line spacing, you can usually fit 3 or 4 lines of 30 to 40 characters. You will have to determine this yourself.

    First, use sprintf to format the lines of each label:

    my $adr01 = sprintf("%16.16s, %10.10s %1.1s\r",$last,$first,$mi); $adr01 .= sprintf("%30.30s\r%30.30s\r",$adr1,$adr2); $adr01 .= sprintf("%16.16s %2.2s %10.10s",$city,$state,$zip);

    Then you can place the labels on the page using format:

    format LABEL_PAGE = ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr01,$adr02,$adr03 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr01,$adr02,$adr03 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr01,$adr02,$adr03 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr01,$adr02,$adr03 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr04,$adr05,$adr06 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr04,$adr05,$adr06 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr04,$adr05,$adr06 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< +<<<<<<<<<<<<<<<<<<<<<<<< $adr04,$adr05,$adr06 Insert additional rows to fill page. .

    You will need to test the spacing and probably adjust the output character size and line spacing. You will need to use a monospaced font for printing.

    As I said, this is really clunky, so is really ugly.

Re: Perl formatting beginner
by Not_a_Number (Prior) on Apr 15, 2014 at 20:51 UTC

    Oh dear, sorry.

    Dupe, please delete.

      I cant post a picture of it but the output should look like the avery 5160 label 3 columns and 10 rows filled with the data. Like the image on the link http://office.microsoft.com/en-us/templates/mailing-labels-30-per-sheet-TC001183278.aspx

        But note that the data in the M$ sample is NOT spaced out to center the second item on three item lines nor to make the last item on each label flush_right.

        But that extra code you gave us -- despite the commenting (which means we won't be interested anyway, since it's not part of your problem statement) -- appears to have, at some point, been attempting the set some spacing in that general vein.


        Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
        1. code
        2. verbatim error and/or warning messages
        3. a coherent explanation of what "doesn't work actually means.

        check Ln42!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1082353]
Approved by davido
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2024-04-24 14:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found