package Querylet::Output::Excel::OLE; use base qw(Querylet::Output); use strict; use warnings; =head1 NAME Querylet::Output::Excel::OLE - output query results to Excel via OLE =head1 VERSION version 0.142 $Id: /my/cs/projects/q/excel/trunk/lib/Querylet/Output/Excel/OLE.pm 28050 2006-11-14T23:40:46.906717Z rjbs $ =cut our $VERSION = '0.142'; use Carp; =head1 SYNOPSIS use Querylet::Output::Excel::OLE; use Querylet; database: bogosity query: SELECT detector_id, measurement FROM bogon_detections output format: excel =head1 DESCRIPTION Querylet::Output::Excel::OLE provides an output handler for Querylet that will create a new instance of Microsoft Excel using Win32::OLE and populate a worksheet with the query results. =head1 METHODS This module isa Querylet::Output, and implements the interface described by that module. =over 4 =item C<< default_type >> The Excel::OLE handler is by default registered for the 'excel' type. =cut sub default_type { 'excel' } =item C<< handler >> The Querylet::Output::Excel::OLE handler returns a coderef that, when called, will create an Excel.Application object, then create a workbook, and then populate its worksheet with the querylet's results. If the "excel_workbook" and "excel_worksheet" options are set, it will attempt to open the named workbook file and put its results into the named worksheet, creating it if necessary. If the workbook, but not worksheet, is set, it will create a new worksheet in the named workbook. If the "excel_postprocessing_callback" option is set, the handler will try to evaluate it into a code reference, the code reference will be called after all other processing is done. It will be passed a hash reference with the following keys: query - the Querylet::Query object being output excel - the Excel.Application object workbook - the Workbook object worksheet - the Worksheet object =cut sub handler { \&_to_excel } sub _to_excel { my $q = shift; my $workbook = $q->option('excel_workbook'); my $worksheet = $q->option('excel_worksheet'); my $postproc = $q->option('excel_postprocessing_callback'); $postproc &&= eval $postproc; warn "couldn't eval postprocessing callback: $@" if $@; my $range = [[ map { $q->header($_) } @{$q->columns} ]]; foreach my $row (@{$q->results}) { push @$range, [ @$row{@{$q->columns}} ]; } my $rows = @$range; my $column = column_name(scalar @{$range->[0]}); return sub { require Win32::OLE; require Win32::OLE::Const; Win32::OLE::Const->import('Microsoft Excel'); my $xl = Win32::OLE->new("Excel.Application") or croak "can't create a new Excel application"; $xl->{Visible} = 1; my ($xlb,$xls); if ($workbook) { $xlb = $xl->Workbooks->Open($workbook) or croak "can't open workbook $workbook"; } else { $xlb = $xl->Workbooks->Add; } $xls = $xlb->Worksheets(defined $worksheet ? $worksheet : 1); unless ($xls) { $xls = $xlb->Worksheets->Add; $xls->{Name} = $worksheet if $worksheet; } unless ($xls) { croak "can't find worksheet $worksheet" } $xls->Range("A1:$column$rows")->{Formula} = $range; $xls->Range("A1:${column}1")->{Font}->{Bold} = 1; $xls->Range("A1:${column}1")->AutoFit(); $postproc->( { excel => $xl, workbook => $xlb, worksheet=> $xls, query => $q } ) if (ref($postproc)||'' eq 'CODE'); } } =back =head1 FUNCTIONS =over 4 =item C<< column_name($column_number) >> This converts a column number to a column name, Excel style. In other words: 1 -> A 26 -> Z 27 -> AA 2600 -> CUZ =cut sub column_name { my ($number) = @_; return unless $number > 0; my $name = ''; my $zero = ord('A') - 1; while ($number) { $name = chr($zero + (my $digit = ($number % 26) || 26)) . $name; ($number -= $digit) /= 26; } return $name; } =back =head1 AUTHOR Ricardo SIGNES, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 COPYRIGHT Copyright 2004-2006, Ricardo SIGNES, All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;