Reading XLS file using Perl - perl

This is my Perl script
#!/usr/bin/perl -w
use strict;
use warnings;
use Spreadsheet::WriteExcel;
use Spreadsheet::ParseExcel;
my $workbook = Spreadsheet::ParseExcel->new("/home/Admin/Desktop/RP_processed_Address_withsubscriptionID (1).xls");
my $workbook1 = Spreadsheet::WriteExcel->new("/home/Admin/Desktop/new.xls");
open(my$old, '<', "$workbook") or die "oops!";
open(my$new, '>', "$workbook1") or die "ooops!";
while (my$line = <$workbook>) {
print $workbook1 $line
}
When I run this Script I'm getting following error
Odd number of elements in hash assignment at /usr/local/share/perl5/Spreadsheet/ParseExcel.pm line 167.
oops! at sample.pl line 9.
I'm not getting any idea where is script is going wrong . Please help me how to resolve this error
your suggestions will be appreciable.

You are not reading any docs again. You copy and paste code and don't understand the basics of what you do. Why are you opening files using open when you already open them using the two modules? Why do you write a line manually? This is not how excel data works, this is not how the modules work. Stop guessing. Learn what you're doing. This will never work.

Take a look at CPAN for Spreadsheet::ParseExcel
You need to access the worksheets within the workbook object you've created and determine which you would like to parse data from. From here you can access cells using the column/width coordinate system. You don't need to use 'open' as the ParseExcel and WriteExcel already do this.
my $sheet = $workbook1->worksheet('Sheet1');
my $cell = $sheet->get_cell( 0, 0 );
my $cell_value = $cell->value();
Is it a bit more clear on what you need to do?

Related

how to read data from spreadsheet with .xlsm format in perl?

I want read data from spreadsheet ,which is .xlsm format.I am unable to access it.its showing blank while access the data .so i want how to access .xlsm format in perl.
Here is what I have tried:
#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::Read;
use Spreadsheet::read qw(ReadData);
my $book = ReadData ('C:\Perl64\bin\sample.xlsm');
foreach my $line(1..1000) {
my #rows =Spreadsheet::Read::cellrow($book->[0],"$line");
print "#rows";
}
seems the module you used doesn't work on xlsm files
consider using Spreadsheet::Reader::ExcelXML instead ;)
http://search.cpan.org/~jandrew/Spreadsheet-Reader-ExcelXML/lib/Spreadsheet/Reader/ExcelXML.pm
also beware, you should use push instead of #rows = ..., this way, you won't overwrite #rows at each for iteration
when you try to open a file you should add or die "error message"; at the end of the open, this way you will see if the file opened correctly
my $book = ReadData ('C:\Perl64\bin\sample.xlsm') or die "error while opening the file"; triggers the error with your example code

Getstore to Buffer, not using temporary files

I've started Perl recently and mixed quite a bit of things to get what I want.
My script gets the content of a webpage, writes it to a file.
Then I open a filehandler, plug the file report.html in (sorry i'm not english, i don't know how to say it better) and parse it.
I write every line i encounter to a new file, except lines containing a specific color.
It works, but I'd like to try another way which doesn't require me to create a "report.html" temporary file.
Furthermore, I'd like to print my result directly in a file, I don't want to have to use a system redirection '>'. That'd mean my script has to be called by another .sh script, and I don't want that.
use strict;
use warnings;
use LWP::Simple;
my $report = "report.html";
getstore('http://test/report.php', 'report.html') or d\
ie 'Unable to get page\n';
open my $fh2, "<$report" or die("could not open report file : $!\n");
while (<$fh2>)
{
print if (!(/<td style="background-color:#71B53A;"/ .. //));
}
close($fh2);
Thanks for your help
If you have got the html content into a variable, you can use a open call on this variable. Like:
my $var = "your html content\ncomes here\nstored into this variable";
open my $fh, '<', \$var;
# .. just do the things you like to $fh
You can try get function in LWP::Simple Module ;)
To your sencond question, use open like open $fh, '<', $filepath. you can use perldoc -f open to see more info.

How to read a line into an array using perl

I am using perl for the first time. I am trying to read a line from input file and store it in an array. Note that the the input file contains a single line with a bunch of words.
I tried using the following code:
open input, "query";
my #context = <input>;
But this gives a syntax error. How could i fix this?
It doesn't give a syntax error. IT even works fine if there's only one line. The following will only get the first line even if there are more than one:
my #context = scalar( <input> );
But why wouldn't you just do
my $context = <input>;
What is the syntax error? IMHO it writes none. But I would suggest some improvements
Always use use strict; use warnings; as a first line! It helps to detect a lot of possible problems.
Code has no error handling.
Use variables for file handlers. Using bareword is deprecated.
Open file for read if you need to only read from a file.
Maybe the ending newlines would be removed form the array.
If the file not needed to be kept opened it worth to close it. Here is not needed as exit will automatically close it implicitly, but it is a good practice to close the files explicitly.
So it could be:
#!/usr/bin/perl
use strict;
use warnings;
open my $input, "<infile" or die "$!";
my #context = map { chomp; $_;} <$input>;
close $input;

Open Excel file in perl and print row count

I am using Win32::OLE module to open an excel file and get row count. The problem is when i hard code excel file path it works fine but when i dynamically pass path it throw an error saying that "cant call method workbooks on unblessed reference". Please find the below sample code.
use OLE;
use Win32::OLE::Const 'Microsoft Excel';
my $xapp= Win32::OLE->GetActiveObject('Excel.Application')
or do { Win32::OLE->new('Excel.Application', 'Quit')};
$xapp->{'Visible'} = 0;
my $file='excel.xlsx';
my $fileName="c:/users/mujeeb/desktop/".$file;
print $fileName;
my $wkb = $xapp->Workbooks->Open($fileName); //here i am getting error coz i am passing dynamic fileName;
my $wks = $wkb->Worksheets('Sheet1');
my $Tot_Rows=$wks->UsedRange->Rows->{'Count'};
print $Tot_Rows."\n";
$xapp->close;
Use backslashes in the filename.
The filename is given to excel and excel won't understand forward slashes. Perl does not convert them because Perl doesn't know the string is a file.
Are you sure that there exists a method named as Open? Because I don't see it in the documentation of Win32::OLE. Also you must add use Win32::OLE; in your code.
You could use this line of code to change the path into readable path for OLE:
my $file='excel.xlsx';
my $fileName="c:/users/mujeeb/desktop/".$file;
$fileName=~s/[\/]/\\/g;
print $fileName;
outputs:
c:\\users\\mujeeb\\desktop\\excel.xlsx

Print Archive::Zip zip file to Apache2::RequestIO object

I have a website using mod_perl.
I'm creating a zip file in memory (using Archive::Zip), and I want to serve that file without having to write it to disk.
Archive::Zip will only output to a specified file handle, and I don't think Apache2::RequestIO provides me with one.
At the moment I just print the Zip file to *STDOUT and that works. But I'm sure there's a better way to do it. I'm printing everything else through the RequestRec object, e.g. $r->print(...)
Something like this should help...
use Archive::Zip;
my $zip = Archive::Zip->new();
#create your zip here
use IO::Scalar;
my $memory_file = ''; #scalar as a file
my $memfile_fh = IO::Scalar->new(\$memory_file); #filehandle to the scalar
# write to the scalar $memory_file
my $status = $zip->writeToFileHandle($memfile_fh);
$memfile_fh->close;
#print with apache
#$r->content_type(".......");
$r->print($memory_file); #the content of a file-in-a-scalar
EDIT:
The above is obsoloted.
from the Archive::Zip docs:
Try to avoid IO::Scalar
One of the most common ways to use Archive::Zip is to generate Zip
files in-memory. Most people have use IO::Scalar for this purpose.
Unfortunately, as of 1.11 this module no longer works with IO::Scalar
as it incorrectly implements seeking.
Anybody using IO::Scalar should consider porting to IO::String, which
is smaller, lighter, and is implemented to be perfectly compatible
with regular seekable filehandles.
Support for IO::Scalar most likely will not be restored in the future,
as IO::Scalar itself cannot change the way it is implemented due to
back-compatibility issues.
In versions of Perl 5.8+, it seems like you can skip IO::Scalar and IO::String all together.
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
my $zip = Archive::Zip->new();
my $memory_file = ''; #scalar as a file
open(my $fh, '>', \$memory_file) || die "Couldn't open memory file: $!";
my $status = $zip->writeToFileHandle($fh);
$fh->close;
$r->print($memory_file);
I think there is probably a more optimal way of doing this, but it works...