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);
Re: Perl formatting beginner
by ww (Archbishop) on Apr 15, 2014 at 16:06 UTC
|
#!/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:
- code
- verbatim error and/or warning messages
- a coherent explanation of what "doesn't work actually means.
check Ln42!
| [reply] [d/l] [select] |
|
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
| [reply] |
|
... 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
| [reply] |
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. | [reply] [d/l] [select] |
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. | [reply] |
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.
| [reply] [d/l] [select] |
Re: Perl formatting beginner
by Not_a_Number (Prior) on Apr 15, 2014 at 20:51 UTC
|
Oh dear, sorry.
Dupe, please delete.
| [reply] |
|
| [reply] |
|
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:
- code
- verbatim error and/or warning messages
- a coherent explanation of what "doesn't work actually means.
check Ln42!
| [reply] |
|
|