http://www.perlmonks.org?node_id=235862

John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

A long time ago, in an operating system far, far away, I could print stuff simply by opening a file handle to a reserved name and write data to it. Effects that the printer could do, like bold face, were done by sending control codes. Every printer had their own codes, so programs had to handle every printer they planned to support.

I find myself longing for that simple time, because I want to print a fancy directory listing on a label. Perl can do its report stuff (a feature I've never used before, actually) but I'd have to load the resulting text file into some application using a monospaced font and print it from there.

To print in Windows, a program uses a device context and draws, just like on the screen. Perl doesn't do that naturally. I do want to use some simple formatting like large centered text for caption, and wrapping long lines (with a proportional font).

One idea is to drive Word through OLE Automation. But I'm wondering if there is something simpler that's Perl-like and works on ActiveState? Barring that, any other ideas on how to print from Perl?

—John

Replies are listed 'Best First'.
Re:(Win32::OLE) Printing from Perl in Windows
by tachyon (Chancellor) on Feb 17, 2003 at 05:14 UTC

    KISS I reckon. If Word can do it then why not save yourself the pain and just script it....

    use Win32::OLE; # start Word program die if unable to $word = Win32::OLE->new('Word.Application', sub { $_[0]->Quit; } ) or die 'Cannot start Word'; # let's watch $word->{'Visible'} = 1; # Create new document my $d = $word->Documents->Add; # define selection my $s = $word->Selection; my @lines = ( "This is test line 1", "This is test line 2", "This is test line 3", ); # $c is the color # $start is the start of Range # $end is the end of Range # $r is the Range object my ($c, $start, $end, $r) = (2, 0, 0, ); for my $line (@lines) { $end += length($line) + 1; $s->TypeText($line); # define the Range $r = $d->Range($start, $end); # Set font properties $r->Font->{Size} = 18; $r->Font->{ColorIndex} = $c++; $r->Font->{Name} = 'Courier New'; $s->TypeText("\n"); $start = $end; } # TIMTOWTDI but this will overwrite the above #my $r = $doc->{Content}; #$r->{Text} = 'Hello World!'; #$r->InsertParagraphAfter(); #$r->InsertParagraphAfter(); #$r->InsertAfter('Bye!'); # here is how to print a document $word->ActiveDocument->PrintOut({ Background => 0, Append => 0, Range => wdPrintAllDocument, Item => wdPrintDocumentContent, Copies => 1, PageType => wdPrintAllPages, }); # save the file without a prompt $word->WordBasic->FileSaveAs("c:\\test.doc"); # have a quick look at the objects and properties # don't try to Dumper the whole thing unless you have time and memory+ ++ print "Range: $_ => $r->{$_}\n" for sort keys %$r; print "Doc: $_ => $d->{$_}\n" for sort keys %$d; # house keeping, clean up our instances $d->Close(); $word->Quit(); undef $word;

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Very nice—that's most of what I need in your sample.

      I did some Word scripting before, for my C++ Color Pretty Printer. But it has a problem: if I insert too much, it gets in a bad mood. I don't remember the details, but it basically doesn't work any more. The work-around is to Save every few lines of inserting, which doesn't do wonders for its already slow speed.

      It's probably the simplest thing for a directory-listing label, though. I think I'll start with your code.

      Though the Excel idea is also pretty nice, since the data is tabular.

      —John

        Just a (possibly irrelvant) thought: Please don't make WinWord/Office a requirement if you're going to distribute this script.

        C.

      Perhaps an even simpler approach would be to output HTML/CSS to a file and then automate IE to open and print the file. Word could be used with HTML too, but the results should be more accurate using IE.

Re: Printing from Perl in Windows
by toma (Vicar) on Feb 17, 2003 at 04:33 UTC
    You can write Postscript directly, but these days PDF is more popular. There are some nice modules to work with PDF. For example, PDF::Report looks like it might do what you want. ActiveState has a few PDF modules including PDF::Labels.

    It should work perfectly the first time! - toma

      okay - i guess that makes my first post obsolete.
      these modules (seem to) rock!
      is there any easy way to print the generated .pdfs without having to open them in a browser or Acrobat Reader?
      beacause if there is, i have some serious re-coding to to do!
Re: Printing from Perl in Windows
by schweini (Friar) on Feb 17, 2003 at 04:28 UTC
    just some (untested) brainstormed ideas:
    - you can still open printers in windows through open(PRN, ">LPT1") or open(PRN, '>\\printserver\printershare') (watch out for the single-quotes to avoid interpolation of the backslashes), and IMHO perl's formating abilities are quite fun to use - so if you don't NEED any special formatting (bold, etc) that option is still open.
    you may want to look at Tk::Canvas' postscript() function. I've never used it, but it's supposed to generate postscript that you could (some way or another) send to your printer, convert to .pdf, etc.
    another (weird) option would be to genrate HTML, pipe that to html2ps, or let a browser print it - even though printer-formating via CSS is still in its infancy.
    i've never done Word-automation, but i think it's quite hard, and not worth the extra effort just to get that special word bold.
    another fun option would be to create an Excel .xls file using Spreadsheet::WriteExcel formatting capabilities, and then tell Excel to print it via Win32::OLE .
    hope these thoughts help you find a better way,

    -schweini
Re: Printing from Perl in Windows
by grantm (Parson) on Feb 17, 2003 at 20:44 UTC

    Further to my HTML suggestion (above), I've poked around in the windows explorer 'File Types' dialog and discovered that you can print an HTML document from the command line using this command:

    "C:\Program Files\Microsoft Office\Office\msohtmed.exe" /p filename.html

    When you run that, an MS Word window appears, opens the file, prints it and exits. So obviously this option assumes you have Word.

    On a machine without MS Office installed, I found this command associated with the HTML Print action:

    rundll32.exe C:\WINNT\System32\mshtml.dll,PrintHTML filename.html

    I found that this command only worked if the filename was an absolute pathname (perhaps a URL would work too). It had the advantage of using the fonts defined in the HTML/CSS, which the Word command did not. It had the disadvantage of popping up a print dialog which you have to click OK on - there may be some way to automate that.

      Hmm, very nice. HTML is easy to generate, but I'd need to figure out enough style stuff to get the sizes right.