How can I suppress Excel's password prompt in Perl? - perl

Please tell me a solution to suppress passsword prompting of an excel file.
use Win32::OLE;
my $xlApp = Win32::OLE->new('Excel.Application');
$xlApp->{Visible} = 0;
$xlApp->{DisplayAlerts} = 0;
# Open excel file.
my $xlBook = $xlApp->Workbooks->Open("C:\\Documents and Settings\\username\\Desktop\\testfile.xls");
my $Sheet1 = $xlBook->Worksheets(1);
my $row = 1;
my $col = 1;
$Sheet1->Cells($row,$col)->{'Value'} = 5;
if (Win32::OLE->LastError)
{
print "File protected";
}
$xlBook ->Close();
undef $xlBook;

If you know the passwords, you can supply them in the password and/or writerespassword arguments of the open command. Excel will not prompt for the passwords if they are supplied this way.
If you don't know the passwords but want to prevent the dialog box from appearing, you can supply dummy passwords in these parameters ("ThisIsNotAPassword", for instance). I have not found this in the documentation, but tested it in Excel 2003:
If the Excel file does not have passwords, it is opened.
If it does have passwords (other than those supplied), it will not ask the user for a password, but fail with an error you can detect.

You may convert the following vb code to perl and give a try,
Please note that this code is for vbproject, similary you can check for the worksheets, cells, or entire sheet, the same way.
' returns TRUE if the VB project in the active document is protected
' Please not
Function ProtectedVBProject(ByVal wb As Workbook) As Boolean
Dim VBC As Integer
VBC = -1
On Error Resume Next
VBC = wb.VBProject.VBComponents.Count
On Error GoTo 0
If VBC = -1 Then
ProtectedVBProject = True
Else
ProtectedVBProject = False
End If
End Function
Example:
If ProtectedVBProject(ActiveWorkbook) Then Exit Sub
For Worksheet
If ActiveWorkbook.ProtectStructure=True Then Exit Sub
For active work book windows
If ActiveWorkbook.ProtectWindows= True Then Exit sub
and so on..
Or You can open excel sheet with password
The Open method for the Workbook
object, takes 12 arguments. To open a workbook with password protection, you would need to write the following code:
Workbooks.Open "Book1.xls", , , ,"pswd"
You can also check with perl the same with empty arguments. I am not sure how to give...

Working off of lakshmanaraj's idea, and unknown's response:
use Win32::OLE;
sub is_protected_vb_project {
my $work_book = shift;
eval {
my $count = $work_book->{VBProject}{VBComponents}{Count};
};
Carp::carp $# if $#;
return $# ? 1 : 0;
}
my $work_book = Win32::OLE->GetObject( 'd:/some/path/somewhere.xls' );
printf "is_protected_vb_project( \$work_book )=%s\n"
, is_protected_vb_project( $work_book )
;

Related

ksh perl script.. if condition

Friends...
I have got bash script which calls perl script and emails logfile result everytime.
I want to change my bash script such that it should only email if there is value in perl subroutine row counter (rcounter++) and not all time.
any tips on how to change .ksh file?
.ksh
#!/bin/ksh
d=`date +%Y%m%d`
log_dir=$HOME
output_file=log.list
if ! list_tables -login /#testdb -outputFile $output_file
then
mailx -s "list report : $d" test#mail < $output_file
fi
=======Below if condition also works for me=============================
list_tables -login /#testdb -outputFile $output_file
if ["$?" -ne "0"];
then
mailx -s "list report : $d" test#mail < $output_file
fi
========================================================================
Perl Script: list_tables
use strict;
use Getopt::Long;
use DBI;
use DBD::Oracle qw(:ora_types);
my $exitStatus = 0;
my %options = ()
my $oracleLogin;
my $outputFile;
my $runDate;
my $logFile;
my $rcounter;
($oracleLogin, $outputFile) = &validateCommandLine();
my $db = &attemptconnect($oracleLogin);
&reportListTables($outputFile);
$db->$disconnect;
exit($rcounter);
#---------------------------
sub reportListTables {
my $outputFile = shift;
if ( ! open (OUT,">" . $outputfile)) {
&logMessage("Error opening $outputFile");
}
print OUT &putTitle;
my $oldDB="DEFAULT";
my $dbcounter = 0;
my $i;
print OUT &putHeader();
#iterate over results
for (my $i=0; $i<=$lstSessions; $i++) {
# print result row
print OUT &putRow($i);
$dbCounter++;
}
print OUT &putFooter($dbCounter);
print OUT " *** Report End \n";
closeOUT;
}
#------------------------------
sub putTitle {
my $title = qq{
List Tables: Yesterday
--------------
};
#------------------------------
sub putHeader {
my $header = qq{
TESTDB
==============
OWNER Table Created
};
#------------------------------
sub putRow {
my $indx = shift;
my $ln = sprintf "%-19s %-30s %-19s",
$lstSessions[$indx]{owner},
$lstSessions[$indx]{object_name},
$lstSessions[$indx]{created};
return "$ln\n";
}
#------------------------------
sub getListTables {
my $runDt = shift;
$rcounter = 0;
my $SQL = qq{
selct owner, object_name, to_char(created,'MM-DD-YYYY') from dba_objects
};
my $sth = $db->prepare ($SQL) or die $db->errstr;
$sth->execute() or die $db->errstr;;
while (my #row = $sth->fethcrow_array) {
$lstSessions[$rcounter] {owner} =$row[0];
$lstSessions[$rcounter] {object_name} =$row[1];
$lstSessions[$rcounter] {created} =$row[2];
&logMessage(" Owner: $lstSessions[$rcounter]{owner}");
&logMessage(" Table: $lstSessions[$rcounter]{object_name}");
&logMessage(" created: $lstSessions[$rcounter]{created}");
$rcounter++;
}
&logMessage("$rcounter records found...");
}
thanks..
also happy to include mail-x part in perl if that makes life more easy..
I am not sure I understood your question correctly. Also, your code is incomplete. So there's some guessing involved.
You cannot check the value of a local Perl variable from the caller's side.
But if your question is if the Perl code added anything to the logfile, the solution is simple: Delete the "rcounter records found..." line (which doesn't make sense anyway since it is always executed, whether the query returned results or not). Then, let the shell script backup the logfile before the call to Perl, and make a diff afterwards, sending the mail only if diff tells you there has been output added to the logfile.
If this doesn't help you, please clarify the question.
EDIT (from comments below):
Shell scripting isn't that difficult. Right now, your Perl script ends with:
$db->($exitStatus);
That is your exit code. You don't check that in your shell script anyway, so you could change it to something more useful, like the number of data rows written. A primitive solution would be to make $rcounter global (instead of local to getListTables()), by declaring it at the top of the Perl script (e.g. after my $logFile;). Then you could replace the "exitStatus" line above with simply:
$rcounter;
Voila, your Perl script now returns the number of data rows written.
In Perl, a return code of 0 is considered a failure, any other value is a success. In shell, it's the other way around - but luckily you don't have to worry about that as Perl knows that and "inverts" (negates) the return code of a script when returning to the calling shell.
So all you need is making the mailing depend on a non-zero return of Perl:
if list_tables -login /#testdb -outputFile $output_file
then
mailx -s "list report : $d" test#mail < $output_file
fi
A comment on the side: It looks to me as if your programming skill isn't up to par with the scope of the problem you are trying to solve. If returning a value from Perl to bash gives you that much trouble, you should probably spend your time with tutorials, not with getting input from a database and sending emails around. Learn to walk before you try to fly...

Perl Script Prompts for Input before Printing Information

I'm having an issue with a Perl script relating to the Weather Research Forecast (WRF) model configuration. The script in question is a part of the download located here (login required, simple signup). If you download the most recent WRF-NMM core, in the unzipped directory is arch/Config_new.pl. The error that I'm having lies somewhere within lines 262-303:
until ( $validresponse ) {
print "------------------------------------------------------------------------\n" ;
print "Please select from among the following supported platforms.\n\n" ;
$opt = 1 ;
open CONFIGURE_DEFAULTS, "< ./arch/configure_new.defaults"
or die "Cannot open ./arch/configure_new.defaults for reading" ;
while ( <CONFIGURE_DEFAULTS> )
{
for $paropt ( #platforms )
{
if ( substr( $_, 0, 5 ) eq "#ARCH"
&& ( index( $_, $sw_os ) >= 0 ) && ( index( $_, $sw_mach ) >= 0 )
&& ( index($_, $paropt) >= 0 ) )
{
$optstr[$opt] = substr($_,6) ;
$optstr[$opt] =~ s/^[ ]*// ;
$optstr[$opt] =~ s/#.*$//g ;
chomp($optstr[$opt]) ;
$optstr[$opt] = $optstr[$opt]." (".$paropt.")" ;
if ( substr( $optstr[$opt], 0,4 ) ne "NULL" )
{
print " %2d. %s\n",$opt,$optstr[$opt] ;
$opt++ ;
}
}
}
}
close CONFIGURE_DEFAULTS ;
$opt -- ;
print "\nEnter selection [%d-%d] : ",1,$opt ;
$response = <STDIN> ;
if ( $response == -1 ) { exit ; }
if ( $response >= 1 && $response <= $opt )
{ $validresponse = 1 ; }
else
{ print("\nInvalid response (%d)\n",$response);}
}
Specifically, I am sent to an input line without any kind of prompting or list of what my options are. Only after I select a valid choice am I presented with the previous options. This is repeated a second time with another chunk of code further down (lines 478-528). What's got me confused is that, when I entered debugging mode, I inserted a break before the start of this portion of code. I ran p $validresponse and got the following:
0
If you REALLY want Grib2 output from WRF, modify the arch/Config_new.pl script.
Right now you are not getting the Jasper lib, from the environment, compiled into WRF.
This intrigues me, as the paragraph is from a printf from several lines before. In this particular script, it is the only printf that has run so far, but why the output was saved to the next created variable is beyond me. Any suggestions?
EDIT: After looking at choroba's suggestion, the same problem occurs with any type of redirection, whether piping, using tee, or stderr/stdout redirection. As such, I'm thinking it may be a problem with bash? That is, the only way I can run it is without any kind of logging (at least to my knowledge, which is admittedly quite limited).
You want to enable autoflushing, so that the Perl print buffer is flushed automatically after something is printed.
This is the default behavior when a Perl script outputs to a terminal window, but when the output is redirected in any way, the default is to buffer the output. Enabling autoflushing disables the buffering.
You can enable autoflushing by adding the following two lines to the top of the Perl script (below the Perl hashbang line, of course):
use IO::Handle qw();
STDOUT->autoflush(1);
When you redirect with pipes or similar you are (normally) redirecting STDOUT. All of the print statements go to STDOUT, so when redirecting the will be sent to whatever process you are piping to. Without seeing the full command you are using I can't say exactly why you aren't seeing the STDOUT messages, but they are obviously being swallowed by the redirection. Whether or not that is actually a problem if for you to decide.
the line
$response = <STDIN> ;
causes the script to wait for input from STDIN which is why you see the prompt. You are not piping anything in to STDIN so it waits.

perl ftp not working

Script works fine, but ftp code uploading the xls but uploading with 0 byte, but if ftp code present in before of the following snippet, FTP Works Fine,
What is the error in code,
my $workbook = Spreadsheet::WriteExcel->new('TestRPT.xls');
my $worksheet = $workbook->add_worksheet('TestRPT Report');
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Spreadsheet::WriteExcel;
use POSIX qw(strftime);
my $CurTimeStamp=time;
my $LastSunTimestamp=($CurTimeStamp - 168*60*60);
my $row;
my $PinNumber;
my $PinAmount;
my $get_date;
my $get_time;
my $get_time_stamp;
my $DoFTPFlg = "yes";
# Create a new workbook and add a worksheet.
my $workbook = Spreadsheet::WriteExcel->new('TestRPT.xls');
my $worksheet = $workbook->add_worksheet('TestRPT Report');
# Write some text. in write function First Argument for ROW, Second Argument for COLUMN, Third Argument for Title/Text to display
$worksheet->write(0, 0, 'val1');
$worksheet->write(0, 1, 'val2');
$worksheet->write(0, 2, 'val3');
$worksheet->write(0, 3, 'val4');
my $cnt = 1;
$get_time_stamp = time;
$get_date = strftime("%m/%d/%y",localtime($get_time_stamp));
$get_time = strftime("%H:%M",localtime($get_time_stamp));
# Write some numbers.
$worksheet->write($cnt, 0, "val1");
$worksheet->write($cnt, 1, "val2");
$worksheet->write($cnt, 2, "val3");
$worksheet->write($cnt, 3, "val4");
if ($DoFTPFlg eq "yes") {
print "DO FTP";
use Net::FTP;
my $ftp;
$ftp = Net::FTP->new("mysite.in", Debug => 0);
$ftp->login("user",'pass');
$ftp->cwd("/www/");
$ftp->put("TestRPT.xls");
$ftp->quit;
}
You should close your $workbook object before trying to do anything with the file.
From the documentation:
An explicit close() is required if the file must be closed prior to performing some external action on it such as copying it, reading its size or attaching it to an email.
Try a slight modification on your code. Instead of
$ftp->put("TestRPT.xls");
Create another file in the www directory and try to ftp that file. If that file is called test.txt, change your line to:
$ftp->put("TestRPT.xls");
Thus, the only change in your code is the name of the file being FTP'd. If your FTP works, the problem isn't with the FTP, but with the Spreadsheet::WriteExcel module. As Mat has already stated, you need to do an explicit close on your object.
If your FTP doesn't work, it probably is an issue with the FTP call (although it looks fine to me).

Perl Loop Output to Excel Spreadsheet

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.

Read one worksheet from Excel workbook in Perl

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!!