Reading Dates from Excel-file

B

bruno

I have a script that reads an excel file.
Since I upgraded to activeperl 5.8 the date-fields are read as:

Win32::OLE::Variant=SCALAR(0x20d341c)

before I got real date-values (although I do not remember what
perl-version I had before).
Platform: win2000

thanks for any hints,
Bruno
 
B

Bob Walton

bruno said:
I have a script that reads an excel file.
Since I upgraded to activeperl 5.8 the date-fields are read as:

Win32::OLE::Variant=SCALAR(0x20d341c)

before I got real date-values (although I do not remember what
perl-version I had before).
Platform: win2000
....


Please boil your problem down to the shortest possible complete sample
code segment that illustrates your problem, set it up so anyone can
copy/paste/execute it, and post that. We can't comment on code we can't
see and run. Also include your Excel version.

In addition, I'm a bit confused: you say you are reading an Excel file;
but it appears that you are using Win32::OLE, which interfaces with a
running instance of Excel, and does not read an Excel file. Which is it?
 
B

bruno

As I was told to provide a code sample, here it is:
This function returns an array of lines, where every line
contains the cells of the excel spreadsheet seperated by tabs.

Cells that contain simple text or numbers are exported as expected,
cells that contain date values are exported as:
Win32::OLE::Variant=SCALAR(0x20d341c)

eg:

number text date
491 Stammdaten Win32::OLE::Variant=SCALAR(0x20d341c)
487 Abrechnung Win32::OLE::Variant=SCALAR(0x20d25e0)
482 Audiometrie Win32::OLE::Variant=SCALAR(0x20d1274)


#############################################################
# start of sample
# just paste and provide valid filename

use Win32::OLE::Const 'Microsoft Excel';
use strict;

my $excelfile = "test.xls";

sub readexcelfile {
my $source = $_[0];

my @all;
my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
|| Win32::OLE->new('Excel.Application', 'Quit');
my $Book = $Excel->Workbooks->Open("$source");
my $Sheet = $Book->Worksheets(1);

my $rows = $Sheet->UsedRange->Rows->Count;
my $blatt = $Sheet->Range("A1:K$rows")->{'Value'};
$Book->Close(0);

foreach my $ref_zeile (@$blatt) {
my $line = "";
for my $item (@$ref_zeile) {
$line.=$item."\t";
}
push(@all,$line);
}
#@all = reverse sort buildvgl @all;
return @all;
}


#dummy main to read the file and dump the lines:
{
my @lines = readexcelfile($excelfile);
foreach(@lines) {
print "$_\n";
}
}

# end of sample
#############################################################

If there is a better way, or an easy way to directly access the file
(without excel needed to be installed on that particular workstation)
please let me know.

thanks, Bruno
 
W

William Herrera

use Win32::OLE::Const 'Microsoft Excel';
use strict;

my $excelfile = "test.xls";

sub readexcelfile {
my $source = $_[0];

my @all;
my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
|| Win32::OLE->new('Excel.Application', 'Quit');
my $Book = $Excel->Workbooks->Open("$source");
my $Sheet = $Book->Worksheets(1);

my $rows = $Sheet->UsedRange->Rows->Count;
my $blatt = $Sheet->Range("A1:K$rows")->{'Value'};
$Book->Close(0);

foreach my $ref_zeile (@$blatt) {
my $line = "";
for my $item (@$ref_zeile) {
$line.=$item."\t";
}

#########

I think that here is the problem, I think. You are assuming that $item is a
simple scalar. But sometimes it is a reference to a date object, an array, etc:

see docs for Win32::OLE::Variant -- you may need to use that module BTW:

my $v = Variant(VT_DATE, "April 1 99");
print $v->Date(DATE_LONGDATE), "\n";
print $v->Date("ddd',' MMM dd yy"), "\n";will print:

Thursday, April 01, 1999
Thu, Apr 01 99

###########
 
B

Bob Walton

bruno said:
As I was told to provide a code sample, here it is:
This function returns an array of lines, where every line
contains the cells of the excel spreadsheet seperated by tabs.

Cells that contain simple text or numbers are exported as expected,
cells that contain date values are exported as:
Win32::OLE::Variant=SCALAR(0x20d341c)

eg:

number text date
491 Stammdaten Win32::OLE::Variant=SCALAR(0x20d341c)
487 Abrechnung Win32::OLE::Variant=SCALAR(0x20d25e0)
482 Audiometrie Win32::OLE::Variant=SCALAR(0x20d1274)


#############################################################
# start of sample
# just paste and provide valid filename

use Win32::OLE::Const 'Microsoft Excel';
use strict;


use warnings; # ***always*** use warnings when debugging!!!

my $excelfile = "test.xls";

sub readexcelfile {
my $source = $_[0];

my @all;
my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
|| Win32::OLE->new('Excel.Application', 'Quit');
my $Book = $Excel->Workbooks->Open("$source");
my $Sheet = $Book->Worksheets(1);

my $rows = $Sheet->UsedRange->Rows->Count;
my $blatt = $Sheet->Range("A1:K$rows")->{'Value'};
$Book->Close(0);

foreach my $ref_zeile (@$blatt) {
my $line = "";
for my $item (@$ref_zeile) {


Here, $item is not necessarily a string. It could be a
Win32::OLE::Variant object, which could be a variety of things, one of
which is a reference to a scalar. You get the message you got because
$item was a blessed reference to a scalar. A "quick fix" is to test to
see if $item is a reference, and, if it is, assume it is a reference to
a Win32::OLE::Variant Date object, and stringify the date. This can be
done with:

use Win32::OLE::NLS qw:)LOCALE :DATE); #to get the constant
$line.=(ref($item)?$item->Date(DATE_LONGDATE):$item)."\t";

That will stringify an Excel date to something that prints useful info.
But if the $item is a Variant which is not a Date, this will mess up.

To treat the full range of possible $item's will involve testing the
item to see if it is a Win32::OLE::Variant object (hint: ref() ), and,
if it is, using a couple of methods from Win32::OLE::Variant, such as
the ->Type method to figure out what type of Variant it is, and then
calling an appropriate method to convert it according to an appropriate
format. I leave that as an exercise for the reader.

$line.=$item."\t";
}
push(@all,$line);
}
#@all = reverse sort buildvgl @all;
return @all;
}


#dummy main to read the file and dump the lines:
{
my @lines = readexcelfile($excelfile);
foreach(@lines) {
print "$_\n";
}
}

# end of sample
#############################################################

If there is a better way, or an easy way to directly access the file
(without excel needed to be installed on that particular workstation)
please let me know.


There are many ways to go, most of which are a lot less hassle than
using Win32::OLE with all the foibles of OLE. One would be to look on
CPAN for Excel-related modules. Spreadsheet::parseExcel might do the
trick, and shouldn't require the presence of Excel (so you can use it on
any OS, even one for which Excel is not available). I know nothing
about this module other than that is exists.

Another would be to treat your spreadsheet as a database and use the DBI
module with DBD::Excel to access it. That is probably the easiest.

HTH.
 
B

bruno

A "quick fix" is to test to
see if $item is a reference, and, if it is, assume it is a reference to
a Win32::OLE::Variant Date object, and stringify the date. This can be
done with:

use Win32::OLE::NLS qw:)LOCALE :DATE); #to get the constant
$line.=(ref($item)?$item->Date(DATE_LONGDATE):$item)."\t";


Thanks, got it.

BTW, for some reason I get the answers via mail hours before they
appear on the board. That's the reason why I had not referred to your
first posting, because I thought, that you had written me an e-mail.

thanks, bruno.
 
C

Chris Mattern

bruno said:
Thanks, got it.

BTW, for some reason I get the answers via mail hours before they
appear on the board.

Scarcely surprising. Mail gets sent directly to your service's SMTP
server, while news has to get passed from server to server along the
NNTP backbone until it gets to your news server. It's the difference
between point-to-point and scalable broadcast.

Chris Mattern
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,142
Messages
2,570,820
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top