Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

perl/postscript csv label maker

29 views
Skip to first unread message

luser-ex-troll

unread,
Mar 5, 2009, 1:15:59 AM3/5/09
to
Has this already been done better?
Surely this idea isn't new?
This is a project for my mom, for whom
MSWord and Excel no longer play nicely together.
-- luser-ex-troll

#!/usr/bin/perl
# labels.pl reads csv records in the form:
# "Name","123 Street","Apt","City, ST ZIP"
# from a file named "addr.csv" and
# produces a postscript program on stdout
# suitable for piping into ps2pdf or
# even distiller, maybe
# CAVEATS: prototype produces at most
# one page. label and sheet sizes are hard-coded
# at 3 3-inch-width labels which are 4*17 points
# high. I don't have any real ones on hand
# to measure.

$IN = "addr.csv";
open IN or die "Can't open input: $!";

print <<PROLOG;
%!
/in{72 mul}def
/LEAD 17 def
/LM 10 def
/count 0 def
/TM 11 in LEAD sub def
/Palatino-Roman 15 selectfont

[
PROLOG

while(<IN>) {
s/\n$//;
s/^"/\[\(/;
s/","/\)\(/g;
s/"$/\)\]/;
s/$/\n/;
print;
}

print <<PSPROGRAM;
]

{ %each record
LM TM moveto
{ %each address line
dup () eq { pop } { % skip empties
show % paint the string
%currentpoint exch = = = % diagnostic
LM currentpoint exch pop LEAD sub moveto % reposition
} ifelse
} forall
/LM LM 3 in add store % move over
/count count 1 add store
count 3 mod 0 eq { % back to left after each 3
/LM 10 store /TM TM LEAD 4 mul sub store
} if
} forall

showpage

PSPROGRAM

macropod

unread,
Mar 7, 2009, 5:46:20 AM3/7/09
to
You could, of course, fix the MS Office installation instead of giving your mom something sp arcane to play with.

--
Cheers,
macropod


"luser-ex-troll" <mij...@yahoo.com> wrote in message news:e8e73e53-016c-4362...@r34g2000vbp.googlegroups.com...

luser-ex-troll

unread,
Mar 7, 2009, 9:41:23 AM3/7/09
to
On Mar 7, 4:46 am, "macropod" <macro...@invalid.invalid> wrote:
> You could, of course, fix the MS Office installation instead of giving your mom something sp arcane to play with.
>
> --
> Cheers,
> macropod

Agreed. But I wanted to have a plan B ready, and I
thought two mutually-embracing languages was interesting.
Besides she's never been happy with the Word+Excel
solution, particularly the word side. When it stopped
working entirely, I thought a different tactic might
be more effective. This way would retain the part she
likes (maintaining the database in excel), and replace
the part she don't (which already required another
program).

Since she already has distiller, she won't need
ghostscript, just perl. everybody needs perl.


luxexterol

luser-ex-troll

unread,
Mar 16, 2009, 8:26:52 PM3/16/09
to
Mommy likes it!
Double-clicking a shortcut is ultimately easier
than any Wizard M$Word can concoct.
Wait till I show her how to edit the file with
a text-editor instead of Excel!

Version 0.2beta:

#!/usr/bin/perl
# labels.pl reads csv records in the form:
# "Name","123 Street","Apt","City, ST ZIP"

# from files named on the command line or
# "addr.csv", if none are specified, and


# produces a postscript program on stdout

# containing records in the form:
# [(Name)(123 Street)(Apt)(City, ST ZIP)]
# suitable for piping into ps2pdf or distiller.
# eg.$ labels|ps2pdf - out.pdf
# CAVEATS:
# coded for Avery 5160 2.5935" x 1"
# letter-sheet labels 3 x 10 / page

if ($#ARGV == -1) { $ARGV[0] = "addr.csv"; } #default argument

print <<PROLOG;
%!
% persuade acrobat reader to obey the numbers
[ {Catalog} << /ViewerPreferences << /PrintScaling /None >> >> /PUT
pdfmark
/in{72 mul}def % tom thumb's shoe size

% measurements
/H 1 in def % how big
/W 2.5935 in def % they are
/Palatino-Roman 16 selectfont % set text 16/
/LEAD H 4 div def % 18
/LM 0.1875 10 add def % edge + padding
/TM 11 in 0.5 in sub LEAD sub def % top - margin - line

% control
/count 0 def
/perLINE 3 def
/perPAGE perLINE 10 mul def

{ %make array as executable to avoid stackoverflow
PROLOG

$\ = $/;
while(<>) {
chop;


s/^"/\{\(/;
s/","/\)\(/g;
s/"$/\)\}/;

print;
}

print <<PSPROGRAM;
} cvlit

{ % each record
cvlit LM TM moveto
{ % each address line


dup () eq { pop } { % skip empties

%dup currentpoint exch = = = % diagnostic


show % paint the string

LM currentpoint exch pop LEAD sub moveto % reposition
} ifelse
} forall

/LM LM W add store % move over


/count count 1 add store

count perLINE mod 0 eq { % back to left after each 3
/LM 10 store
/TM TM H sub store
} if
count perPAGE mod 0 eq { % print a page when it's full
showpage
/LM 10 store
/TM 11 in LEAD sub store
} if
} forall

count perPAGE mod 0 ne { showpage } if
%the end
PSPROGRAM

#eof labels


sample input (addr.csv):
"M. Joshua Ryan","1234 Streetname","","City, ST 12345"
"M. Joshua Ryan","4567 Streetname","","City, ST 23456"
"M. Joshua Ryan","7890 Streetname","","City, ST 34567"
"M. Joshua Ryan","1234 Streetname","","City, ST 45678"
"M. Joshua Ryan","4567 Streetname","","City, ST 56789"
"M. Joshua Ryan","7890 Streetname","","City, ST 67890"
"M. Joshua Ryan","7890 Streetname","","City, ST 67890"
"","","",""


sample output:
%!
% persuade acrobat reader to obey the numbers
[ {Catalog} << /ViewerPreferences << /PrintScaling /None >> >> /PUT
pdfmark
/in{72 mul}def % tom thumb's shoe size

% measurements
/H 1 in def % how big
/W 2.5935 in def % they are
/Palatino-Roman 16 selectfont % set text 16/
/LEAD H 4 div def % 18
/LM 0.1875 10 add def % edge + padding
/TM 11 in 0.5 in sub LEAD sub def % top - margin - line

% control
/count 0 def
/perLINE 3 def
/perPAGE perLINE 10 mul def

{ %make array as executable to avoid stackoverflow
{(M. Joshua Ryan)(1234 Streetname)()(City, ST 12345)}
{(M. Joshua Ryan)(4567 Streetname)()(City, ST 23456)}
{(M. Joshua Ryan)(7890 Streetname)()(City, ST 34567)}
{(M. Joshua Ryan)(1234 Streetname)()(City, ST 45678)}
{(M. Joshua Ryan)(4567 Streetname)()(City, ST 56789)}
{(M. Joshua Ryan)(7890 Streetname)()(City, ST 67890)}
{(M. Joshua Ryan)(7890 Streetname)()(City, ST 67890)}
{()()()()}
} cvlit

{ % each record
cvlit LM TM moveto
{ % each address line


dup () eq { pop } { % skip empties

%dup currentpoint exch = = = % diagnostic


show % paint the string

LM currentpoint exch pop LEAD sub moveto % reposition
} ifelse
} forall

/LM LM W add store % move over


/count count 1 add store

count perLINE mod 0 eq { % back to left after each 3
/LM 10 store
/TM TM H sub store
} if
count perPAGE mod 0 eq { % print a page when it's full
showpage
/LM 10 store
/TM 11 in LEAD sub store
} if
} forall

count perPAGE mod 0 ne { showpage } if
%the end

lxt
(yes, that's my real name, mostly)

Tad J McClellan

unread,
Mar 16, 2009, 10:35:59 PM3/16/09
to

["Followup-To:" header set to comp.lang.perl.misc.]


luser-ex-troll <mij...@yahoo.com> wrote:

> #!/usr/bin/perl

Ask for all the help you can get:

use strict;
use warnings;


> if ($#ARGV == -1) { $ARGV[0] = "addr.csv"; } #default argument


$ARGV[0] = "addr.csv" unless defined $ARGV[0]; # default argument


> while(<>) {
> chop;


chop() was how we removed newlines in the mid-90s.

chomp() is how we remove newlines nowadays.


> s/^"/\{\(/;
> s/","/\)\(/g;
> s/"$/\)\}/;


The replacement part of s/PATTERN/REPLACEMENT/ is a string.

None of those backslashed characters are special in strings,
so none of those backslashes are needed.

s/^"/{(/;
s/","/)(/g;
s/"$/)}/;


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"

Ilya Zakharevich

unread,
Mar 17, 2009, 2:00:00 AM3/17/09
to
On 2009-03-17, Tad J McClellan <ta...@seesig.invalid> wrote:
>> #!/usr/bin/perl
>
> Ask for all the help you can get:
>
> use strict;
> use warnings;

Or, better, add -w ot the #!-line...

>> if ($#ARGV == -1) { $ARGV[0] = "addr.csv"; } #default argument

> $ARGV[0] = "addr.csv" unless defined $ARGV[0]; # default argument

I would write

@ARGV = "addr.csv" unless @ARGV;

[ Unfortunately, the most logical @ARGV ||= "addr.csv" does not
compile... If it would, the scalar/list context determination
might get in the way, too... ]

>> s/^"/\{\(/;
>> s/","/\)\(/g;
>> s/"$/\)\}/;

> The replacement part of s/PATTERN/REPLACEMENT/ is a string.

Still, one should keep in mind that backslashes may help with "less
capable" editors... ;-)

Ilya

luser-ex-troll

unread,
Mar 17, 2009, 2:03:29 AM3/17/09
to
On Mar 16, 9:35 pm, Tad J McClellan <ta...@seesig.invalid> wrote:
> ["Followup-To:" header set to comp.lang.perl.misc.]
>

Excellent. Thank you.
I was transcribing my memory of vi substitutions
while simultaneously relearning perl. It went though
some very ugly stages.

lxt

Tim McDaniel

unread,
Mar 17, 2009, 12:16:17 PM3/17/09
to
In article <slrngruf30.5s...@chorin.math.berkeley.edu>,

Ilya Zakharevich <nospam...@ilyaz.org> wrote:
>On 2009-03-17, Tad J McClellan <ta...@seesig.invalid> wrote:
>>> #!/usr/bin/perl
>>
>> Ask for all the help you can get:
>>
>> use strict;
>> use warnings;
>
>Or, better, add -w ot the #!-line...
>
>>> if ($#ARGV == -1) { $ARGV[0] = "addr.csv"; } #default argument
>
>> $ARGV[0] = "addr.csv" unless defined $ARGV[0]; # default argument
>
>I would write
>
> @ARGV = "addr.csv" unless @ARGV;

I would write

@ARGV = ('addr.csv') if @ARGV == 0;

The parens don't actually cause a list context, but they're visually
reminiscent. In C, where {...} was allowed but not required around
one statement, I used {...} anyway.

I use '...' unless I need variable interpolation.

--
Tim McDaniel, tm...@panix.com

Peter J. Holzer

unread,
Mar 17, 2009, 12:47:39 PM3/17/09
to
On 2009-03-17 06:00, Ilya Zakharevich <nospam...@ilyaz.org> wrote:
> On 2009-03-17, Tad J McClellan <ta...@seesig.invalid> wrote:
>>> #!/usr/bin/perl
>>
>> Ask for all the help you can get:
>>
>> use strict;
>> use warnings;
>
> Or, better, add -w ot the #!-line...

Ok, I'll bite: How is -w better than "use warnings"?

hp

A. Sinan Unur

unread,
Mar 17, 2009, 12:59:03 PM3/17/09
to
tm...@panix.com (Tim McDaniel) wrote in
news:gpoich$ft1$1...@reader1.panix.com:

> In article <slrngruf30.5s...@chorin.math.berkeley.edu>,
> Ilya Zakharevich <nospam...@ilyaz.org> wrote:
>>On 2009-03-17, Tad J McClellan <ta...@seesig.invalid> wrote:
>>>> #!/usr/bin/perl
>>>
>>> Ask for all the help you can get:
>>>
>>> use strict;
>>> use warnings;
>>
>>Or, better, add -w ot the #!-line...
>>
>>>> if ($#ARGV == -1) { $ARGV[0] = "addr.csv"; } #default argument
>>
>>> $ARGV[0] = "addr.csv" unless defined $ARGV[0]; # default
>>> argument
>>
>>I would write
>>
>> @ARGV = "addr.csv" unless @ARGV;
>
> I would write
>
> @ARGV = ('addr.csv') if @ARGV == 0;


I would write:

@ARGV = qw( addr.csv ) unless @ARGV;

Sinan

--
A. Sinan Unur <1u...@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/

Ilya Zakharevich

unread,
Mar 17, 2009, 4:30:40 PM3/17/09
to

IMO, `no warnings' is quite use()ful, but `use warnings' is absolutely
use()less.

Just try removing -w from

perl -we "sub a{print shift}" -e "use warnings; a my $x"

(I pretend I forgot to initialize $x, and pass it to a function in a
different module.)

Hope this helps,
Ilya

John W. Krahn

unread,
Mar 17, 2009, 5:32:39 PM3/17/09
to
Ilya Zakharevich wrote:
> On 2009-03-17, Peter J. Holzer <hjp-u...@hjp.at> wrote:
>> On 2009-03-17 06:00, Ilya Zakharevich <nospam...@ilyaz.org> wrote:
>>> On 2009-03-17, Tad J McClellan <ta...@seesig.invalid> wrote:
>>>>> #!/usr/bin/perl
>>>> Ask for all the help you can get:
>>>>
>>>> use strict;
>>>> use warnings;
>>> Or, better, add -w ot the #!-line...
>> Ok, I'll bite: How is -w better than "use warnings"?
>
> IMO, `no warnings' is quite use()ful, but `use warnings' is absolutely
> use()less.
>
> Just try removing -w from
>
> perl -we "sub a{print shift}" -e "use warnings; a my $x"

perl -e "sub a{print shift}" -e "use warnings; a my $x"

Or is that not what you meant?

John
--
Those people who think they know everything are a great
annoyance to those of us who do. -- Isaac Asimov

Peter J. Holzer

unread,
Mar 17, 2009, 6:02:17 PM3/17/09
to
On 2009-03-17 20:30, Ilya Zakharevich <nospam...@ilyaz.org> wrote:
> On 2009-03-17, Peter J. Holzer <hjp-u...@hjp.at> wrote:
>> On 2009-03-17 06:00, Ilya Zakharevich <nospam...@ilyaz.org> wrote:
>>> On 2009-03-17, Tad J McClellan <ta...@seesig.invalid> wrote:
>>>>> #!/usr/bin/perl
>>>>
>>>> Ask for all the help you can get:
>>>>
>>>> use strict;
>>>> use warnings;
>>>
>>> Or, better, add -w ot the #!-line...
>>
>> Ok, I'll bite: How is -w better than "use warnings"?
>
> IMO, `no warnings' is quite use()ful, but `use warnings' is absolutely
> use()less.
>
> Just try removing -w from
>
> perl -we "sub a{print shift}" -e "use warnings; a my $x"

% perl -e 'use warnings; sub a{print shift}' -e 'use warnings; a my $x'
Use of uninitialized value within @_ in print at -e line 1.

Yes, "use warnings" needs to be in every module. It usually is, which
means that you get warnings even if you don't use -w.

hp

Ilya Zakharevich

unread,
Mar 18, 2009, 1:27:15 AM3/18/09
to
On 2009-03-17, Peter J. Holzer <hjp-u...@hjp.at> wrote:
>>> Ok, I'll bite: How is -w better than "use warnings"?

>> IMO, `no warnings' is quite use()ful, but `use warnings' is absolutely
>> use()less.

>> Just try removing -w from

>> perl -we "sub a{print shift}" -e "use warnings; a my $x"

> % perl -e 'use warnings; sub a{print shift}' -e 'use warnings; a my $x'
> Use of uninitialized value within @_ in print at -e line 1.

Not applicable - you do not have control over "the first -e". It is
one of hundreds somebody else's modules your script is using...

> Yes, "use warnings" needs to be in every module.

No. Just use -w. It would just work.

And cannot be in ANY portable enough module - this would break
compatibility with pre-5.6.0...

Hope this helps,
Ilya

0 new messages