guys,
Iam trying to delete used rows in already existing excel file
i tried with below code
use strict;
use warnings;
use Win32::OLE;
my $xl = Win32::OLE->new('Excel.Application');
$xl->{Visible} = 0;
my $nShtsOld = $xl->{SheetsInOldWorkbook};
$xl->{SheetsInOldWorkbook} = 1;
my $wb = $xl->Workbooks->Open('C:\Users\u304079\Desktop\Test_S1_Legacy_US.xlsx');
$xl->{SheetsInOldWorkbook} = $nShtsOld;
my $sht = $wb->Sheets(o);
my $end = $sht->Usedrange->Row->Count;
print $end;
for (my $count = $end; 0 < $count; $count--)
{
my $cell = $sht->{Cells};
if (!defined $cell->{Value})
{
$cell->entireRow->delete;
}
}
# save and exit
$xl->SaveAs('C:\Users\u304079\Desktop\Test_S1_Legacy_US.xlsx');
$xl->close();
but iam unable to do with following code getting error message as
Can't call method "Usedrange" on an undefined value"
It looks like my $sht = $wb->Sheets(o); may be a typo. Should that be a zero 0 instead?
Related
I try to insert a formula =IF(D2="";"";COUNTIF(D:D;D2)) in an Excel worksheet.
Here is the code I'm trying:
$WorkSheet->Cells($Row2Use,'L')->{Formula} = "=IF(D".$Row2Use."=\"\",\"\",COUNTIF(D:D,D".$Row2Use.")"; # =IF(D2="";"";COUNTIF(D:D;D2))
I also tried using {Value} instead of {Formula} without success!
What did I wrong
This following works for me. Code taken and modified from the link given by xxfelixxx.
use Cwd 'abs_path';
use Win32::OLE;
use Win32::OLE qw(in with);
use Win32::OLE::Const "Microsoft Excel";
$Win32::OLE::Warn = 3;
my $Excel = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit');
$Excel->{Visible} = 1;
my $Book = $Excel->Workbooks->Add;
my $Sheet = $Book->Activesheet;
$Sheet->Range("A1")->{Value} = 1;
$Sheet->Range("A2")->{Value} = 1;
$Sheet->Range("A3")->{Formula} = "=SUMA(R[-2]C:R[-1]C)";
I was using Spreadsheet::WriteExcel to create xls file using perl. When the range of spreadsheet increased, the Microsoft excel shows an alert before opening the file "File Error: Data may have been lost".
Please help me to solve this.
Here is the code
my $row = 2;
foreach my $sid(array of students objects)
{
my $s = $students->{$sid};
my $cc = 0;
my $wall = f1($x, $y, $z);#f1 is a method returns hash of arrays that have to write on excel having keys #key_array
foreach my $key (#key_array) {
my $t_row = $row;
my $i_c = 0;
my $t_col = 0;
my $m_row = $max_row;
while($m_row > 0){
$t_col = 3+($cc*7);
if($cc == 0){
$ws->write($t_row, 0,
[$s->{first_name}, $s->{last_name}, $s->{l_name}], $fmt_wrap
);
}
if(defined $wall->{$key}->[$i_c] ){
$ws->write($t_row, $t_col, $wall->{$key}->[$i_c], $fmt_wrap);
} else {
$ws->write($t_row, (3+$cc*7),["","","","","","",""], $fmt_wrap);
}
$t_row++;
$i_c++;
$m_row--;
}#while loop
$ws->write($t_row-1, 3+$company_format*$max_step,
[ (scalar keys %{$s->{videos}}), $s->{total_pageviews} ], $fmt
);
$cc++;
$t_row = 2;
}#foreach loop
$row+=$max_row;
}#foreach student array
I have found answer. In the code there was a line which write data into a cell multiple times. So i found that multiple write attempt to a particular cell can cause file corruption.
I converted multiple csv files into a excel spreadsheet using the perl script below which is basically a modified version of the code in the link, but i cannot open the output excel file, it gives a pop up message "The file is corrupted."
#!/usr/intel/bin/perl -W
use strict;
use Spreadsheet::WriteExcel::Big;
use Text::CSV_XS;
# Check for valid number of arguments
if (($#ARGV < 1) || ($#ARGV > 2)) {
die("Usage: csv2xls csvfile_dir xlsfile\n");
};
my $csvdir = $ARGV[0];
my $outfile = $ARGV[1];
# Create a new Excel workbook
my $workbook = Spreadsheet::WriteExcel::Big->new($outfile);
my $csvfile = "";
my $tab_title = "";
foreach $csvfile (glob("$csvdir/*.csv")) {
print "$csvfile\n";
# Open the Comma Separated Variable file
open (CSVFILE, $csvfile) or die "$csvfile: $!";
$csvfile =~ s/.*\///;
$tab_title = (split(/\./,$csvfile))[0];
print "-D- $tab_title\n";
# Create a new Excel worksheet
my $worksheet = $workbook->add_worksheet($tab_title);
# Create a new CSV parsing object
my $csv = Text::CSV_XS->new;
# Row and column are zero indexed
my $row = 0;
while (<CSVFILE>) {
if ($csv->parse($_)) {
my #Fld = $csv->fields;
print "-D- #Fld\n";
my $col = 0;
foreach my $token (#Fld) {
$worksheet->write($row, $col, $token);
$col++;
}
$row++;
} else {
my $err = $csv->error_input;
print "Text::CSV_XS parse() failed on argument: ", $err, "\n";
}
}
}
How can i fix it?
You need to close your workbook.
$workbook->close();
Also upgrade your Excel module to the latest version, I also faced the similar issue of corrupted excel files which was solved on updating Spreadsheet::WriteExcel.
Also from docs
Note about the requirement for binmode(). An Excel file is comprised
of binary data. Therefore, if you are using a filehandle you should
ensure that you binmode() it prior to passing it to new().You should
do this regardless of whether you are on a Windows platform or not.
This applies especially to users of perl 5.8 on systems where UTF-8 is
likely to be in operation such as RedHat Linux 9. If your program,
either intentionally or not, writes UTF-8 data to a filehandle that is
passed to new() it will corrupt the Excel file that is created.
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'm new to perl. I have two excel files containing huge no of rows and just two columns. I want to get each cell from one of the excel files and search whether its there in another excel file or not. if its not then print that cell.
I believe that if I get each cell from one of the excel and search it in another and then run a for loop for all the rows it will be done.
I reached upto getting the cell from first excel but how to search whether it is there in the another excel and printing it is the issue.
can anybody help. ??
I'm not entirely sure what you want, but this might give you some ideas. It's completely untested, though.
use strict;
use Spreadsheet::ParseExcel;
my $parser = Spreadsheet::ParseExcel->new();
my $workbook1 = $parser->parse('Book1.xls');
if (!defined $workbook1) { die $parser->error(), ".\n"; }
my $workbook2 = $parser->parse('Book2.xls');
if (!defined $workbook2) { die $parser->error(), ".\n"; }
$worksheet1 = $workbook1->worksheet('Sheet1');
$worksheet2 = $workbook2->worksheet('Sheet1');
my ($row_min1, $row_max1) = $worksheet1->row_range();
my ($col_min1, $col_max1) = $worksheet1->col_range();
for my $row1 ($row_min1 .. $row_max1) {
for my $col1 ($col_min1 .. $col_max1) {
my $cell1 = $worksheet1->get_cell($row1, $col1);
my ($row_min2, $row_max2) = $worksheet2->row_range();
my ($col_min2, $col_max2) = $worksheet2->col_range();
my $found_match = 0;
for my $row2 ($row_min2 .. $row_max2) {
for my $col2 ($col_min2 .. $col_max2) {
my $cell2 = $worksheet2->get_cell($row2, $col2);
if ($cell1->value() eq $cell2->value()) { # or == ?
$found_match = 1;
break;
}
}
break if $found_match;
}
if (!$found_match) {
print $cell1->value, "\n";
}
}
}
This is mostly from here: http://search.cpan.org/dist/Spreadsheet-ParseExcel/lib/Spreadsheet/ParseExcel.pm