I have a excel document that I am editing with perl OLE automation and I have run into a problem. I need to enter an empty row in between two rows that already contain data, kind of like appending it to the file but not at the end of the file. I don't want to have to rewrite the entire file using perl either. How would I go about doing this?
Thanks
One thing that always helps me when I am automating Excel with Perl & Win32::OLE is to create a macro in Excel capturing exactly what I am trying to accomplish first. From there I can view the VB code and usually convert that to Perl relatively easily.
For example, in an open Excel 2010 file:
View -> Macros -> Record New Macro
Click OK
Right click somewhere on the sheet to insert a new row
View -> Macros -> Stop Recording
View -> Macros -> View Macros, click edit
From this, I could write code, for example:
#!c:/perl/bin/perl.exe
use strict;
use warnings;
use Win32::OLE;
my $excel = Win32::OLE->new( 'Excel.Application' )
or die "Could Not Start Excel.\n";
$excel->{ 'Visible' } = 1;
$excel->{ DisplayAlerts } = 0;
$excel->{ SheetsInNewWorkBook } = 1;
my $workbook = $excel->Workbooks->Add;
my $sheet = $workbook->Sheets( 1 );
$sheet->Range( 'A1' )->{ Value } = 'Data 1';
$sheet->Range( 'A2' )->{ Value } = 'Data 2';
$sheet->Range( '2:2' )->Select(); #Select Entire 2nd Row
$sheet->Range( '2:2' )->Insert( {
'Shift' => -4121, #xlDown
'CopyOrigin' => 0, #xlFormatFromLeftOrAbove
} );
__END__
Also, here is a list of a bunch of the Excel enumerations: http://www.datapigtechnologies.com/downloads/Excel_Enumerations.txt
Hope this helps!
Related
I'm still learing Perl, and am trying to perform the following task -- and am miserably stuck.
Currently I have the following.
Open the necessary Excel file
Store Workbooks info under var $workbook1
Store Worksheets info under var $worksheets1
my $excel = Win32::OLE -> new("Excel.Application");
$excel->{Visible} = 0;
$excel->{DisplayAlerts}=0;
$excel->{SheetsInNewWorkbook} = 1;
my $workbook1 = $excel->Workbooks->Open($OutFileName);
my $worksheet1 = $workbook1->Worksheets(1);
I later take this info and have Perl to write in the cells of the Excel file (the necessary $Row and $Col are initialized accordingly).
$worksheet1->Cells($Row, $Col)->{'Value'} = $var1;
$worksheet1->Cells($Row, $Col+1)->{'Value'} = $var2;
$worksheet1->Cells($Row, $Col+2)->{'Value'} = $var3;
$worksheet1->Cells($Row, $Col+3)->{'Value'} = $var4;
So far this works fine.
What I intend to do is operate on multiple worksheets instead of just one.
Open the necessary Excel file
Store Workbooks info under var $workbook1
Store Wortsheets info under var(s) $worksheets1, $worksheets2, $worksheets3, $worksheets4, $worksheets5 (or store it into an array if it's possible?)
I have a total of 5 worksheets I need to operate on in the Excel file.
I'm trying to for loop the latter process (where I write in the cells) for each worksheet, but I'm trying to find an easier way to recall the $worksheet1, $worksheet2, ..., $worksheet5 variables. Cuz, for now without the proper array variable -- which I yet learned how to in Perl -- I need to do an if statement for each every for loop and write the according code, which is very ineffective.. Is there a way to perform this with an array or something else for the worksheet variable?
I'm more familiar with how Matlab works.. and here's what I would like Perl to do if it were a Matlab script with arrays.
for i = 1:num_worksheets
# write in worksheet[i] cell (j,k) with variable var1
end
I am not entirely sure I get what you mean, but I think what you want to do is not repeat code. At least that is how I understand your Matlab code.
You can put all the worksheets into one array in Perl like this.
my $worksheet1 = $workbook1->Worksheets(1);
my $worksheet2 = $workbook1->Worksheets(2);
my $worksheet3 = $workbook1->Worksheets(3);
Or shorter:
my #worksheets (
$workbook1->Worksheets(1),
$workbook1->Worksheets(2),
$workbook1->Worksheets(3),
);
Or even shorter:
my #worksheets = map { $workbook1->Worksheets($_) } 1 .. 3;
Then you can iterate that array. The $worksheet variables are all objects, and objects in Perl are references. That means that if you put them into an array, you are not making copies of the objects.
foreach my $sheet ( #worksheets ) {
$sheet->Cells($row, $col)->{'Value'} = $var1;
$sheet->Cells($row, $col + 1)->{'Value'} = $var2;
}
That code will write $var1 and $var2 into the $row/$col cells in all three worksheets 1, 2 and 3.
You don't even have to create an array. You can just supply a list of the workbooks if that's the only place where you use all of them together in that order.
foreach my $sheet ($worksheet1, $worksheet2, $worksheet3) {
$sheet->Cells($row, $col)->{'Value'} = $var1;
}
I do have the following code in perl that open an excel file and read row:column, what I want to get is the content of the cell not formula, the get_cell (0,1) and (1,1) and (2,1) has some formula, and value, I'm not interested in formula just the content of the cell or value that has been return by formula say if row:1:0 is 200 then I need to read the 200 not the formula behind the cell! can a few good people get back to me on this..thanks in advance..
some code above
use Spreadsheet::ParseExcel
$workbook = $parser->parse("$dir/$file");
$worksheet = $workbook->worksheet('Sheet1');
$total = $worksheet->get_cell(0,1);
$pass = $worksheet->get_cell(1,1);
$fail = $worksheet->get_cell(2,1);
# Print the cell value when not blank
$total = $total->value();
$pass = $pass->value();
$fail = $fail->value();
The value() method returns as desired the result of a formula, not the formula itself. I've just tested it myself with a simple =1+1 formula in a cell and the value() returns 2.
If the Excel file you are reading is previously created by Spreadsheet::WriteExcel, then there is a known issue: This module cannot read the values of formulas from files created with Spreadsheet::WriteExcel unless the user specified the values when creating the file (which is generally not the case). The reason for this is that Spreadsheet::WriteExcel writes the formula but not the formula result since it isn't in a position to calculate arbitrary Excel formulas without access to Excel's formula engine.
I found it using
use Spreadsheet::XLSX;
my $excel = Spreadsheet::XLSX->new("$filename");
my ($sheet) = #{ $excel->{Worksheet} };
print $sheet->{Cells}[0][1]{Val}, "\n";
I am trying to find exact string in excel sheet using Find command.
I was successful to find the cell having the string, here the problem is
i am not able to find cell matching given exact string.
Scenario is explained below:
Scenario:
Excel sheet having below values.
C1(value): ABCD
D1(value): ABCDEFABCD
Input search string: ABCD
Expected value: 3 (C)
Output: 4 (D)
Below is the code which i was using:
use Win32::OLE;
use Win32::OLE qw(in with);
use Win32::OLE::Variant;
use Win32::OLE::Const 'Microsoft Excel';
$Excel = Win32::OLE->new('Excel.Application');
$Excel->{'Visible'} = 0; #0 is hidden, 1 is visible
$Excel->{DisplayAlerts}=0; #0 is hide alerts
# Open File and Worksheet
my $Book = $Excel->Workbooks->Open ('D:\\all_files.csv'); # open Excel file
$Sheet = $Book->Worksheets(1);
# Find Last Column and Row
$search_string = "ABCD";
my $Row_index = $Sheet->UsedRange->Find({What=>$search_string,
SearchDirection=>xlPrevious,
SearchOrder=>xlByRows})->{Row};
$Book->Close();
$Excel->Quit();
Please help me out to overcome this difficluty. Thanks in advance.
Add the flag LookAt => xlWhole , as it matches the whole string.
Also, Why did you decide to use xlPrevious?
Last thing - for sanity check - also use LookIn => xlValues , becuase you're not looking for formulas.
I have a Perl script, the relevant bits of which are posted below.
# Pull values from cells
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();
# Determine relatedness
my $value = $lesk->getRelatedness($target, $response);
# Copy output to new Excel spreadhseet, 'data.xls'
my $workbook1 = Spreadsheet::WriteExcel->new('data.xls');
my $worksheet1 = $workbook1->add_worksheet();
$worksheet1->set_column(0, 3, 18);
my $row = 0;
foreach ($target) {
$row++;
$worksheet1->write( $row, 0, "Target = $target\n");
$worksheet1->write( $row, 1, "Response = $response\n");
$worksheet1->write( $row, 2, "Relatedness = $value\n");
}
}
}
This script uses the Perl modules ParseExcel and WriteExcel. The input data spreadsheet is a list of words under two columns, one labelled 'Target' and the other labelled 'Response.' The script takes each target word and each response word and computes a value of relatedness between them (that's what the
$lesk->getRelatedness
section of code is doing. It is calling a perl module called WordNet::Similarity that computes a measure of relatedness between words).
All of this works perfectly fine. The problem is I am trying to write the output (the measure of similarity, or $value in this script) into a new Excel file. No matter what I do with the code, the only output it will give me is the relatedness between the LAST target and response words. It ignores all of the rest.
However, this only occurs when I am trying to write to an Excel file. If I use the 'print' function instead, I can see all of the outputs in the command window. I can always just copy and paste this into Excel, but it would be much easier if I could automate this. Any idea what the problem is?
You're resetting the value of $row each time to 0.
Problem is solved. I just needed to move the
my $workbook1 = Spreadsheet::WriteExcel->new('data.xls');
my $worksheet1 = $workbook1->add_worksheet();
lines to another part of the script. Since they were in the 'for' statement, the program kept overwriting the 'data.xls' file every time it ran through the loop.
I have a perl script read Excel file and parse using a perl module "Spreadsheet::ParseExcel::Simple; what I want is my script to read only one tab instead of reading all tabs on the spread sheet. here what looks like the portion of the script.
# ### Use a Spreadsheet CPAN module for parsing Excel spreadsheet
require Spreadsheet::ParseExcel::Simple;
my $xls = Spreadsheet::ParseExcel::Simple->read('/opt/test.xls');
$Output_Circuit_file = "/opt/result.text";
############################################################################
$err_idx = 0;
$out_idx = 0;
#date_var = localtime;
$date = sprintf("%02d",($date_var[4] + 1)) . '/' . sprintf("%02d",$date_var[3]) . '/' . ($date_var[5] + 1900);
## #############
foreach my $sheet ($xls->sheets) {
while ($sheet->has_data) {
my #words = $sheet ->next_row;
$ctr++;
anyone can help, where I can modify to read my script read only tab "A" and ignore everything else.
foreach my $sheet ($xls->sheets) this loop is causing you to read all sheets (worksheets), which is another word for the tabs in excel. Just read the first of the $xls->sheets and you've got it
#sheets = $xls->sheets;
$sheet = $sheets[0];
if($sheet->has_data) {
....
}
add the following lines and read specific worksheet name
$sheetname= $sheet->{sheet}->{Name};
if ($sheetname !~ 'Test') { next; }
Thanks all for your effort to help me!!