I am new to perl.
i have an excel sheet with lot of data.. I need to update it and create a graph based on the data..using perl.
i am succeded in updating an existing excel..
now adding chart to it is not happening
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::SaveParser;
use Spreadsheet::WriteExcel;
# Open an existing file with SaveParser
my $parser = Spreadsheet::ParseExcel::SaveParser->new();
my $template = $parser->Parse('MyExcel.xls');
my $worksheet = $template->worksheet('Firstsheet');
my $chart = $template->add_chart( type => 'line' );
$chart->add_series(
categories => '=URV!$A$17:$A$442',
values => '=URV!$D$17:$D$442',
name => 'pended graph',
);
This is not working.
Can't call method "add_chart" on an undefined value at charts4.ps line 20
Please help me with a sample working code..
Want to know whats the problem here.
add_chart() is one of the WORKBOOK METHODS. Try code like this:
use Spreadsheet::WriteExcel;
my $workbook = Spreadsheet::WriteExcel->new('perl.xls');
$worksheet = $workbook->add_worksheet();
$worksheet->write('A1', 'Hi Chart!');
my $chart = $workbook->add_chart( type => 'line', embedded => 1, name => 'pended graph' );
# Insert the chart into the a worksheet.
$worksheet->insert_chart( 'E2', $chart );
Update
The problem is that excel is very hard to update with perl.
An Excel file is a binary file within a binary file. It contains
several interlinked checksums and changing even one byte can cause it
to become corrupted.
As such you cannot simply append or update an Excel file. The only way
to achieve this is to read the entire file into memory, make the
required changes or additions and then write the file out again.
Spreadsheet::ParseExcel will read in existing excel files:
my $parser = Spreadsheet::ParseExcel->new();
# $workbook is a Spreadsheet::ParseExcel::Workbook object
my $workbook = $parser->Parse('blablabla.xls');
What you really want is Spreadsheet::ParseExcel::SaveParser, which is a combination of Spreadsheet::ParseExcel and Spreadsheet::WriteExcel.
Here is an example.
Summing it up, I would suggest you to read the excel data in and then try either of the following:
Create another xls file and use the Spreadsheet::WriteExcel::Chart
library.
Create a xlsx file and use the Excel::Writer::XLSX::Chart library.
Another close option would be to read the excel in with
Spreadsheet::ParseExcel::SaveParser and then add the chart and save
it, but with this module all original charts are lost.
If you are on a Windows machine you may try to use Win32::OLE.
Here is the example from Win32::OLE's own documentation:
use Win32::OLE;
# use existing instance if Excel is already running
eval {$ex = Win32::OLE->GetActiveObject('Excel.Application')};
die "Excel not installed" if $#;
unless (defined $ex) {
$ex = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;})
or die "Oops, cannot start Excel";
}
# get a new workbook
$book = $ex->Workbooks->Add;
# write to a particular cell
$sheet = $book->Worksheets(1);
$sheet->Cells(1,1)->{Value} = "foo";
# write a 2 rows by 3 columns range
$sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ],
[ 42, 'Perl', 3.1415 ]];
# print "XyzzyPerl"
$array = $sheet->Range("A8:C9")->{Value};
for (#$array) {
for (#$_) {
print defined($_) ? "$_|" : "<undef>|";
}
print "\n";
}
# save and exit
$book->SaveAs( 'test.xls' );
undef $book;
undef $ex;
UPDATE#2
Here is an example code:
use strict;
use Spreadsheet::WriteExcel;
my $workbook = Spreadsheet::WriteExcel->new( 'chart_column.xls' );
my $worksheet = $workbook->add_worksheet();
my $bold = $workbook->add_format( bold => 1 );
# Add the worksheet data that the charts will refer to.
my $headings = [ 'Category', 'Values 1', 'Values 2' ];
my $data = [
[ 2, 3, 4, 5, 6, 7 ],
[ 1, 4, 5, 2, 1, 5 ],
[ 3, 6, 7, 5, 4, 3 ],
];
$worksheet->write( 'A1', $headings, $bold );
$worksheet->write( 'A2', $data );
###############################################################################
#
# Example 1. A minimal chart.
#
my $chart1 = $workbook->add_chart( type => 'column', embedded => 1 );
# Add values only. Use the default categories.
$chart1->add_series( values => '=Sheet1!$B$2:$B$7' );
# Insert the chart into the main worksheet.
$worksheet->insert_chart( 'E2', $chart1 );
###############################################################################
#
# Example 2. One more chart
#
my $chart2 = $workbook->add_chart( type => 'column', embedded => 1 );
# Configure the chart. # change the categories if required change the values as required
$chart2->add_series(
categories => '=Sheet1!$A$4:$A$7',
values => '=Sheet1!$B$4:$B$7',
);
$worksheet->insert_chart( 'N1', $chart2, 3, 3 );
Also,
If you don't mind xlsx over xls, you may use Excel::Writer::XLSX. It is more actively maintained.
The trick to be able to parse and use at the same time the functions inside the WriteExcel module is to use the the use Spreadsheet::ParseExcel::SaveParser; module.
Below i have an example. The example will not use the chart functions but the problem you have is not on how to use the chart functions of WriteExcel module but on how to parse an existing excel file and then use that parsed information with the WriteExcel modul (which is originally thought only for NEW excel files).
if ( ( -f $excel_file_name ) && ( ( stat $excel_file_name )[7] > 0 ) ) {
#PARSE EXCEL
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::SaveParser;
# Open the template with SaveParser
my $parser = new Spreadsheet::ParseExcel::SaveParser;
my $template = $parser->Parse("$excel_file_name");
my $sheet = 0;
my $row = 0;
my $col = 0;
if ( !defined $template ) {
die $parser->error(), " Perlline:", __LINE__, " \n "; #probably the file is already open by your GUI
}
# Get the format from specific cell
my $format = $template->{Worksheet}[$sheet]->{Cells}[$row][$col]->{FormatNo};
# Add a new worksheet
#for my $worksheet ( $template->worksheets() ) {
my $worksheet_parser = $template->worksheet("$metrict_data_worksheet_name");
my ( $row_min, $row_max ) = $worksheet_parser->row_range();
my ( $col_min, $col_max ) = $worksheet_parser->col_range();
my #row_array_value;
for my $row ( 1 .. $row_max ) { #avoid header start from 1
for my $col ( $col_min .. $col_max ) {
my $cell = $worksheet_parser->get_cell( $row, $col );
next unless $cell;
#print "Row, Col = ($row, $col)\n";
#print "Value = ", $cell->value(), "\n";
#print "Unformatted = ", $cell->unformatted(), "\n";
#print "\n";
push( #row_array_value, $cell->value() );
} #end header column loops for one regression
} #end row loop all lines
#}
# The SaveParser SaveAs() method returns a reference to a
# Spreadsheet::WriteExcel object. If you wish you can then
# use this to access any of the methods that aren't
# available from the SaveParser object. If you don't need
# to do this just use SaveAs().
#
my $workbook;
{
# SaveAs generates a lot of harmless warnings about unset
# Worksheet properties. You can ignore them if you wish.
local $^W = 0;
# Rewrite the file or save as a new file
my $check_if_possible2write = Spreadsheet::WriteExcel->new($excel_file_name);
if ( defined $check_if_possible2write ) { #if not possible it will be undef
$workbook = $template->SaveAs("$excel_file_name");#IMPORTANT this is of type WriteExcel and not ParseExcel
}
else {
print "Not possible to write the Excel file :$excel_file_name, another user may have the file open. Aborting... ", __LINE__, " \n ";
exit;
}
}
#####################FROM HERE YOU CAN USE AGAIN use Spreadsheet::WriteExcel; ####################
use Spreadsheet::WriteExcel;
my $worksheet = $workbook->sheets("$metrict_data_worksheet_name");
my $column_header_count = 0;
foreach my $name ( sort { lc $a cmp lc $b } keys %merged_all_metrics ) {
$worksheet->write( $row_max + 1, $column_header_count, "$merged_all_metrics{$name}" ); #row,col start
$column_header_count++;
}
$worksheet->set_column( 'A:L', 50, undef, 0, 1, 0 ); #grouping #comp_src group
$worksheet->set_column( 'N:R', 50, undef, 0, 1, 0 ); #grouping
$workbook->close() or die "Error closing file: $!"; #CLOSE
}
The important part of the code is what happens after the comment line:
#####################FROM HERE YOU CAN USE AGAIN use Spreadsheet::WriteExcel; ####################
After that point you will see that you have a $workbook handler. This variable has all the information parsed and more important is that it is from type WriteExcel Object so you will have all the methods of this module available.
Important Notice. The parser is not able to parse charts and formulas (only values), therefore you will have to write then again on each parse->write loop.
Related
I am trying to read an existing Excel spreadsheet and write it into a new Excel document with all the same format options.
I am able to read the cell contents and write them into the new Excel sheet, but I cannot get the background color of the cell.
If I use the $cell->get_format->{Fill}[2] method it gives me numbers like either 64 or 65 if the cell has a background color.
How can I get the actual color of a cell and apply the same background color to the cell in new Excel sheet?
I am doing all these things as there is no method available in the Spreadsheet::ParseExcel module to set the background color for a cell after appending data to an existing Excel sheet.
Here is my code
use Spreadsheet::WriteExcel;
use Spreadsheet::ParseExcel;
my $parser = Spreadsheet::ParseExcel->new();
my $workbook_parse = $parser->Parse( 'Report.xls' );
my $worksheet_parse = $workbook_parse->Worksheet( "Health_Report" );
my ( $col_min, $col_max ) = $worksheet_parse->col_range();
my ( $row_min, $row_max ) = $worksheet_parse->row_range();
my $workbook = Spreadsheet::WriteExcel->new( "Report_new.xls" );
my $worksheet = $workbook->addworksheet( "Health_Report" );
my $bkgd_color = $workbook->addformat();
for my $col ( $col_min .. $col_max ) {
for my $row ( $row_min .. $row_max ) {
# Return the cell object at $row and $col
my $cell = $worksheet_parse->get_cell( $row, $col );
next unless $cell;
my $value = $cell->value();
my $format = $cell->get_format();
my $backgroundcolor = $format->{Fill}->[2];
print "Row, Col = ($row, $col) ";
print "Value = $value\n";
print "Format = $backgroundcolor\n";
$bkgd_color->set_bg_color( $backgroundcolor );
### Here trying to rewrite into Excel and apply the
### same background color which the cell had previously
$worksheet->write( $row, $col, $value, $bkgd_color );
}
}
Part of my output from print statements:
Format = 65
Row, Col = (25, 4) Value = -115966
Format = 65
Row, Col = (10, 5) Value = 20170417
Format = 65
Row, Col = (11, 5) Value = 0
Format = 64
Row, Col = (16, 5) Value = 0
Format = 64
Update
It appears that the documentation is wrong. The name of the workbook object method is different from that of the class method, and you need to call
$workbook->color_idx_to_rgb($color_index)
instead
The documentation for Spreadsheet::ParseExcel says this
$font->{Color}
Returns the color index for the font. The mapping to an RGB color is defined by each workbook.
The index can be converted to a RGB string using the $workbook->ColorIdxToRGB() Parser method.
(Older versions of Spreadsheet::ParseExcel provided the ColorIdxToRGB class method, which is deprecated.)
I expect that the colour indexes in the $format->{Fill} array can be translated similarly
Hello Venkatesh k,
Try the set_color() method from (Spreadsheet::WriteExcel).
From the documentation:
Default state: Excels default color, usually black
Default action: Set the default color
Valid args: Integers from 8..63 or the following strings:
'black'
'blue'
'brown'
'cyan'
'gray'
'green'
'lime'
'magenta'
'navy'
'orange'
'pink'
'purple'
'red'
'silver'
'white'
'yellow'
Update: try this, it seems to be working for my example spread sheet.
#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::WriteExcel;
use Spreadsheet::ParseExcel;
sub create_new_worksheet {
my ($row, $col, $value, $backgroundcolor) = #_;
# Create a new Excel workbook
my $workbook = Spreadsheet::WriteExcel->new('perl.xls');
# Add a worksheet
my $worksheet = $workbook->add_worksheet();
# Add and define a format
my $format = $workbook->add_format(bg_color => $backgroundcolor);
$format->set_align('center');
# Write a formatted and unformatted string, row and column notation.
$worksheet->write($row, $col, $value, $format);
}
my $parser = Spreadsheet::ParseExcel->new();
my $workbook_parse = $parser->Parse( 'Report.xls' );
my $worksheet_parse = $workbook_parse->Worksheet("Sheet1");
my ( $col_min, $col_max ) = $worksheet_parse->col_range();
my ( $row_min, $row_max ) = $worksheet_parse->row_range();
for my $col ( $col_min .. $col_max ) {
for my $row ( $row_min .. $row_max ) {
# Return the cell object at $row and $col
my $cell = $worksheet_parse->get_cell( $row, $col );
next unless $cell;
my $value = $cell->value();
my $format = $cell->get_format();
my $backgroundcolor = $format->{Fill}->[2];
print "Row, Col = ($row, $col) ";
print "Value = $value\n";
print "Format = $backgroundcolor\n";
create_new_worksheet($row, $col, $value, $backgroundcolor);
}
}
I have a .xlsx file (only one sheet) with 15 columns. I want to read some specific columns, let's say columns 3, 5, 11, 14 and write it to a new Excel sheet. In this case some cells of input files are empty means don't have any value.
Here what I am trying:
use warnings;
use strict;
use Spreadsheet::ParseXLSX;
use Excel::Writer::XLSX;
my $parser = Spreadsheet::ParseXLSX->new;
my $workbook = $parser->parse("test.xlsx");
if ( !defined $workbook ) {
die $parser->error(), ".\n";
}
my $worksheet = $workbook->worksheet('Sheet1');
# but from here I don't know how to define row and column range to get specific column data.
# I am trying to get all data in an array, so I can write it in new .xlsx file.
# function to write data in new file
sub writetoexcel
{
my #fields = #_;
my $workbook = Excel::Writer::XLSX->new( 'report.xlsx' );
$worksheet = $workbook->add_worksheet();
my $row = 0;
my $col = 0;
for my $token ( #fields )
{
$worksheet->write( $row, $col, $token );
$col++;
}
$row++;
}
I also followed this Question, but no luck.
How can I read specific columns from .xlsx file and write it into new .xlsx file?
Have you never copied a subset of columns from an array of arrays to another?
Here is the input sheet I used for this:
and, this is what I get in the output file after the code is run:
#!/usr/bin/env perl
use strict;
use warnings;
use Excel::Writer::XLSX;
use Spreadsheet::ParseXLSX;
my #cols = (1, 3);
my $reader = Spreadsheet::ParseXLSX->new;
my $bookin = $reader->parse($ARGV[0]);
my $sheetin = $bookin->worksheet('Sheet1');
my $writer = Excel::Writer::XLSX->new($ARGV[1]);
my $sheetout = $writer->add_worksheet('Extract');
my ($top, $bot) = $sheetin->row_range;
for my $r ($top .. $bot) {
$sheetout->write_row(
$r,
0,
# of course, you need to do more work if you want
# to preserve formulas, formats etc. That is left
# to you, as you left that part of the problem
# unspecified.
[ map $sheetin->get_cell($r, $_)->value, #cols ],
);
}
$writer->close;
i wanted to parse a csv file in perl and want to generate an excel sheet.
As of now i am able to parse CSV file and converted into xls.This code is working properly, which is giving some 6 rows and 3 colums according to CSV.which is correct.After parsing it i want to do some formating also.let say any row or colum which has "Pass" as a string that should be of green color and fail then that should be of Red color.How can i do that please help..
#!/run/pkg/TWW-perl-/5.8.8/bin/perl -w
use strict;
use warnings;
use Spreadsheet::WriteExcel;
use Text::CSV::Simple;
use Spreadsheet::ParseExcel::Format
my $infile = "/project/ls1socdft_nobackup/rev2.0/user/Shah- B53654/dft/dfta/perl/pattern_qa/output_0/xls_info.csv";
#usage() unless defined $infile && -f $infile;
my $parser = Text::CSV::Simple->new;
my #data = $parser->read_file($infile);
my $headers = shift #data;
my $outfile = shift || "/project/ls1socdft_nobackup/rev2.0/user/Shah-B53654/dft/dfta/perl/pattern_qa/output_0/xls_info.xls";
my $subject = shift || 'worksheet';
my $workbook = Spreadsheet::WriteExcel->new($outfile);
my $bold = $workbook->add_format();
$bold->set_bold(1) ;
my $color =$workbook->add_format();
$color->set_bg_color('green');
my $color1=$workbook->add_format();
$color1->set_bg_color('red');
import_data($workbook, $subject, $headers, \#data);
# Add a worksheet
sub import_data {
my $workbook = shift;
my $base_name = shift ;
my $colums = shift;
my $data = shift;
my $limit = shift || 50_000;
my $start_row = shift ||1;
my $worksheet = $workbook->add_worksheet($base_name);
$worksheet->add_write_handler(qr[\w], \&store_string_widths);
my $w = 1;
$worksheet->write('A' . $start_row, $colums,$bold);
my $i = $start_row;
my $qty = 0;
for my $row (#$data) {
$qty++;
if ($i > $limit) {
$i = $start_row;
$w++;
$worksheet = $workbook->add_worksheet("$base_name - $w");
$worksheet->write('A1', $colums);
}
$worksheet->write(1+$i++,0, $row);}
autofit_columns($worksheet);
warn "Convereted $qty rows.";
return $worksheet;
}
sub store_string_widths {
my $worksheet = shift;
my $col = $_[1];
my $token = $_[2];
# Ignore some tokens that we aren't interested in.
return if not defined $token; # Ignore undefs.
return if $token eq ''; # Ignore blank cells.
return if ref $token eq 'ARRAY'; # Ignore array refs.
return if $token =~ /^=/; # Ignore formula
# Ignore numbers
#return if $token =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d++))?$/;
# Ignore various internal and external hyperlinks. In a real scena+rio
# you may wish to track the length of the optional strings used wi+th
# urls.
return if $token =~ m{^[fh]tt?ps?://};
return if $token =~ m{^mailto:};
return if $token =~ m{^(?:in|ex)ternal:};
# We store the string width as data in the Worksheet object. We us+e
# a double underscore key name to avoid conflicts with future name +s.
#
my $old_width = $worksheet->{__col_widths}->[$col];
my $string_width = string_width($token);
if (not defined $old_width or $string_width > $old_width) {
# You may wish to set a minimum column width as follows.
#return undef if $string_width < 10;
$worksheet->{__col_widths}->[$col] = $string_width;
}
# Return control to write();
return undef;
}
sub string_width {
return length $_[0];
}
sub autofit_columns {
my $worksheet = shift;
my $col = 0;
for my $width (#{$worksheet->{__col_widths}}) {
$worksheet->set_column($col, $col, $width) if $width;
$col++;
}
}
There are two ways you can get the individual cell formatted the way you're expecting.
1: Instead of passing an array of data into the $worksheet->write() method, loop through each row and column and write each cell individually.
EX:
change
$worksheet->write('A1', $colums);
to
for (my $r=0;$r<#$colums;$r++) {
for (my $c=0;$c<#{$colums->[$r]}) {
$worksheet->write($r,$c,$colums->[$r]->[$c]);
}
Now, you can test each value being written for your criteria. If it matches, just include the format you want to use.
$worksheet->write($r,$c,$columns->[$r]->[$c],$color1);
}
2: The other option is to use Excel::Writer::XLSX
Spreadsheet::WriteExcel is in maintenance only mode and has
effectively been superseded by Excel::Writer::XLSX.
This module is more up to date and includes functions for conditional formatting, which can be added after writing your data.
Also, there should be no change in your excel generation code except for when you include the module and when you initialize it.
Then, you just specify the rules for the conditional formatting.
$worksheet->conditional_formatting( 'A1:J10',
{
type => 'text',
criteria => 'containing',
value => 'Pass',
format => $color,
}
);
$worksheet->conditional_formatting( 'A1:J10',
{
type => 'text',
criteria => 'containing',
value => 'Fail',
format => $color1,
}
);
I get 2 errors when compiling the following code:
#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseExcel;
my $xlsparser = Spreadsheet::ParseExcel->new();
my $xlsbook = $parser->parse('xsl_test.xls');
my $xls = $xls->worksheet(0);
my ( $row_first, $row_last ) = $xls->row_range();
my ( $col_first, $col_last ) = $xls->col_range();
my $csv = '';
for my $row ( $row_first .. $row_last ) { #Step through each row
for my $col ( $col_first .. $col_last ) { #Step through each column
my $cell = $xls->get_cell( $row, $col ); #Get the current cell
next unless $cell;
$csv .= $cell->unformatted(); #Get the cell's raw data -- no border colors or anything like that
if ( $col == $col_last ) {
$csv .= "\n"; #Make a new line at the end of the row
} else {
$csv .= ",";
}
}
}
Errors:
global symbol "$parser" requires explicit package name at line 8
global symbol "$xls" requires explicit package name at line 9
I get the above code from http://www.ehow.com/how_7352636_convert-xls-csv-perl.html, and installed the excel module using: cpan Spreadsheet::ParseExcel Spreadsheet::XLSX Spreadsheet::Read
What's causing the error?
Those errors mean that you are using strict, but you didn't declare some variables with my. For example, you declared $xmlprser, but then you tried to use $parser, which was not declared. The code you copied has errors.
A better place to get code is the source itself: Spreadsheet::ParseExcel
Try:
my $parser = Spreadsheet::ParseExcel->new();
my $xlsbook = $parser->parse('xsl_test.xls');
my $xls = $xlsbook->worksheet(0);
I have a Perl program using Spreadsheet::ParseExcel. However, there are two difficulties that have arisen that I have been unable to figure out how to solve. The script for the program is as follows:
#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseExcel;
use WordNet::Similarity::lesk;
use WordNet::QueryData;
my $wn = WordNet::QueryData->new();
my $lesk = WordNet::Similarity::lesk->new($wn);
my $parser = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse ( 'input.xls' );
if ( !defined $workbook ) {
die $parser->error(), ".\n";
}
WORKSHEET:
for my $worksheet ( $workbook->worksheets() ) {
my $sheetname = $worksheet->get_name();
my ( $row_min, $row_max ) = $worksheet->row_range();
my ( $col_min, $col_max ) = $worksheet->col_range();
my $target_col;
my $response_col;
# Skip worksheet if it doesn't contain data
if ( $row_min > $row_max ) {
warn "\tWorksheet $sheetname doesn't contain data. \n";
next WORKSHEET;
}
# Check for column headers
COLUMN:
for my $col ( $col_min .. $col_max ) {
my $cell = $worksheet->get_cell( $row_min, $col );
next COLUMN unless $cell;
$target_col = $col if $cell->value() eq 'Target';
$response_col = $col if $cell->value() eq 'Response';
}
if ( defined $target_col && defined $response_col ) {
ROW:
for my $row ( $row_min + 1 .. $row_max ) {
my $target_cell = $worksheet->get_cell( $row, $target_col);
my $response_cell = $worksheet->get_cell( $row, $response_col);
if ( defined $target_cell && defined $response_cell ) {
my $target = $target_cell->value();
my $response = $response_cell->value();
my $value = $lesk->getRelatedness( $target, $response );
print "Worksheet = $sheetname\n";
print "Row = $row\n";
print "Target = $target\n";
print "Response = $response\n";
print "Relatedness = $value\n";
}
else {
warn "\tWroksheet $sheetname, Row = $row doesn't contain target and response data.\n";
next ROW;
}
}
}
else {
warn "\tWorksheet $sheetname: Didn't find Target and Response headings.\n";
next WORKSHEET;
}
}
So, my two problems:
First of all, sometimes the program returns the error "No Excel data found in file," even though the data is there. Each Excel file is formatted the same way. There is only one sheet, with the A and B columns labelled 'Target' and 'Response,' respectively, with a list of words beneath them. However, it does not ALWAYS return this error. It works for one Excel file, but it does not work for a different one, even though both are formatted the exact same way (and yes, they are both the same file type, as well). I cannot find any reason for it to not read the second file, because it is identical to the first. The only difference is that the second file was created using an Excel macro; however, why would that matter? The file types and format are exactly the same.
Second, the variables '$target' and '$response' need to be formatted as strings in order for the 'my $value' expression to work. How do I convert them into string format? The value assigned to each variable is a word from the appropriate cell of the Excel spreadsheet. I don't know what format that is (and there is no apparent way in Perl for me to check).
Any suggestions?
In relation to your first question, the "no data found" error indicates some problem with the file format. I've seen this error with pseudo-Excel files such as Html or CSV files that have an xls extension. I've also seen this error with mal-formed files generated by third party apps.
You could do an initial verification of the files by doing a hexdump/xxd dump of a working and non working file and seeing if the overall structure is approximately the same (for example if it has similar magic numbers at the start and isn't Html).
It could also be an issue with Spreadsheet::ParseExcel. I am the maintainer of that module. If you like you could send me on a "good" and "bad" file, at the email address in the docs, and I will have a look at them.
First of all, if you are getting "no data found" you can thank proprietary Excel data file formats and the inability of even a good Perl library to extract information from them.
I strongly suggest that you export the Excel data in something easily parsed like CSV especially given the simple nature of the data layout you described. There may be a way to get Excel to process a batch but I have no idea. A quick search yielded a tool to use OpenOffice to do batch conversion.
The rest of your question is rather moot once you accept that Excel data files will not play nicely.
I wrote this code after a client couldn't decide whether the XLS he was sending every week was really in XLS format or just CSV.... HTH!
sub testForXLS ()
{
my ( $FileName ) = #_;
my $signature = '';
my $XLSsignature = 'D0CF11E0A1B11AE10000';
open(FILE, "<$FileName")||die;
read(FILE, $buffer, 10, 0);
close(FILE);
foreach (split(//, $buffer))
{ $signature .= sprintf("%02x", ord($_)); }
$signature =~ tr/a-z/A-Z/;
if ( $signature eq $XLSsignature )
{ return 1; } else { return 0; }
}