As Brian pointed out there is the Spreadsheet::ParseExcel module.
Below is a snippet form a script I use to extract data (dates and text for a newsticker) from an Excel workbook. Hopefully not too confusing, but it might get you some ideas how to use that module.
Ekkehard
use Spreadsheet::ParseExcel;
my $oExcel = new Spreadsheet::ParseExcel;
my $oBook = $oExcel->Parse('G:/BusUnits/PH-RES/cta/COMMON/CT_HomePage/CT_News.xls') or die "No News sheet";
$newsSheet = $oBook->{Worksheet}[0];
[snip]
for (my $iR = 1 ;
defined $newsSheet->{MaxRow} && $iR <= $newsSheet->{MaxRow} ;
$iR++)
{
my %news=();
$news{dispstart} = $newsSheet->{Cells}[$iR][$displayStartCol]->Value if $newsSheet->{Cells}[$iR][$displayStartCol];
$news{dispend} = $newsSheet->{Cells}[$iR][$displayEndCol]->Value if $newsSheet->{Cells}[$iR][$displayEndCol];
$news{startdate} = $newsSheet->{Cells}[$iR][$startDateCol]->{Val};
$news{enddate} = $newsSheet->{Cells}[$iR][$endDateCol]->Value if $newsSheet->{Cells}[$iR][$endDateCol];
$news{title} = $newsSheet->{Cells}[$iR][$titleCol]->{Val};
(my $text = $newsSheet->{Cells}[$iR][$textCol]->{Val}) =~ s/\n/<br>/g;
$news{text} = $text;
my $unit = $newsSheet->{Cells}[$iR][$unitCol]->{Val};
push @{$ctnews{$unit}}, \%news;
}
