I am finding that MS-Excel does not shut down if I read my entire =
spreadsheet of 4550 rows with Win32::OLE. But if I read 500 rows and then =
close Excel and reopen it and read the next 500 rows (keeping track of =
where I left off) and continue this way to the end, then Excel closes down =
fine. Not sure why so I made a workaround as explained above. Must be a =
big memory overhead to read more than 500 rows without shutting down Excel =
when using Win32::OLE. It could be something to do with running in =
conjunction with Win32::GUI. Anybody had similar problems with OLE alone, =
or OLE and GUI combined applications?
Thanks,
Eric
Garland, Texas USA
# This application transfers data from an Excel spreadsheet straight into =
an Access database. Excel is shutdown
# after each read of 500 rows from the spreadsheet and restarted to read =
the next 500 rows and continued
# till all rows are read. The program keeps track of last record read in =
spreadsheet so knows where to begin
# reading of next 500 rows.
use Win32;
use Win32::GUI;
use Win32::ODBC;
use Win32::OLE;
use File::Copy;
$PWD=3DWin32::GetCwd(); # save application directory so ODBC knows where =
to look for MSAccess FILEDSN=20
$FILEDSN=3D"FILEDSN=3D$PWD\\MyAccessDB.dsn";
$M =3D new Win32::GUI::Menu(
"&File" =3D> "File",
" > &Port" =3D> "Port",
" > E&xit" =3D> "Exit",
"&Help" =3D> "Help",
" > &About - Excel port to Access" =3D> "About",
);
$W =3D new Win32::GUI::Window(
-title =3D> "Excel port to Access",
-left =3D> 100,=20
-top =3D> 100,=20
-width =3D> 500,=20
-height =3D> 200,
-menu =3D> $M,
-style =3D> ws_sysmenu,
-name =3D> "Window",
);
$B =3D new Win32::GUI::Bitmap("$PWD\\Logo.bmp");=20
$BITMAP =3D $W->AddLabel(
-left =3D> 0,=20
-top =3D> 0,
-style =3D> 14 | WS_VISIBLE,
-name =3D> "Bitmap",
);
$BITMAP->SetImage($B);
$SFont =3D new Win32::GUI::Font(
-name =3D> "Courier New",
-size =3D> 8,
-weight =3D> 700,
-height =3D> -11,
);
$Status =3D $W->AddStatusBar(
-name =3D> "Status",
-text =3D> "Select menu option File->Port to begin.",
-font =3D> $SFont,
);
$W->Show();
$W->BringWindowToTop();
#-------------------------------#
# Event Handler=20
#-------------------------------#
Win32::GUI::Dialog();
END {
$db->Close;
undef $db;
$sheet->Close;
undef $sheet;
$book->Close;
undef $book;
$Excel->Quit;
undef $Excel;
}
#------------------------------------#
# Event Subroutines
#------------------------------------#
sub Exit_Click {
return -1; # exits the Win32 GUI Event Handler Win32::GUI::Dialog();
}
sub About_Click {
$msg=3D"";
$msg=3D$msg . "Program: Excel port to Access\n";
$msg=3D$msg . " Version: 1.0\n";
$msg=3D$msg . " Date: June 2002\n";
$msg=3D$msg . " By: Eric Hansen\n";
Win32::GUI::MessageBox($W,"$msg",
"About - Excel port to Access",64,);
}
sub Port_Click {
=20
# Open File DialogBox showing files with=20
# *.xls extension starting in application directory
$file =3D "*.xls\0" . " " x 256;
$file =3D Win32::GUI::GetOpenFileName(
-owner =3D> $W,
-directory =3D> $PWD,
-title =3D> "Select MS-Excel file to port to MS-Access",=20
-file =3D> $file,
);
# if file is not valid, or contains no data, then return
if (! -s $file) {
Win32::GUI::MessageBox($W,"Microsoft Excel file notfound or is =
empty",
"Excel port to Access - Error & Abort",16,);
return -1;
}
=20
$M->{'Exit'}->Enabled(0); #-- Disable menu option
$M->{'Port'}->Enabled(0); #-- Disable menu option
$Status->Text("Connecting. Please wait...");
$Status->Update(); =20
=20
$stat=3Dcopy("$PWD\\CopyOfMyAccessDB.mdb","$PWD\\MyAccessDB.mdb"); =
#-- File::Copy=20
if ($stat !=3D 1) {
$msg=3D"Cannot COPY empty database file:\n" .
"$PWD\\CopyOfMyAccessDB.mdb\n" .
"to file:\n" .
"$PWD\\MyAccessDB.mdb\n";=20
Win32::GUI::MessageBox($W,$msg,
"Excel port to Access - Error & Abort",16,);
return -1;
} =20
=20
# connect to the MS-Access database =20
$db =3D new Win32::ODBC($FILEDSN); =20
if (! $db) {
$error=3DWin32::ODBC::Error();
Win32::GUI::MessageBox($W,
"Can't Establish Database Connection using file DSN:\n$FILEDSN\n$=
error",=20
"Excel port to Access - Error & Abort",16,);
return -1;
}
=20
$exitwhileloop=3D"N"; =20
$cnt=3D0;=20
$j=3D1;
=20
# 500 times 130 =3D 65,000 which is max rows in an Excel spreadsheet =
worksheet.
# We have to close Excel after each read of 500 records and restart =
Excel
# otherwise Excel won't shutdown. Some kind of memory problem =
develops.=20
=20
while ($j <=3D 130) {
=20
if ($j > 1) {
$sheet->Close;
undef $sheet;=20
$book->Close;
undef $book;
$Excel->Quit;
undef $Excel;
$Excel =3D Win32::OLE->new('Excel.Application');
$book =3D $Excel->Workbooks->Open($file);
$sheet =3D $book->Worksheets(1);
$start=3D($stop + 1);
$i=3D$start;
$stop=3D($start + 499);
} else {
$Excel =3D Win32::OLE->new('Excel.Application');
$book =3D $Excel->Workbooks->Open($file);
$sheet =3D $book->Worksheets(1);
$i=3D2;
$start=3D2;
$stop=3D500;
}
=20
for ($i=3D$start;$i<=3D$stop;$i++) {
=20
# build the sql insert statement
$sqltxt=3D"INSERT INTO MyAccessTBL VALUES ("; =20
=20
$cell=3D"A" . $i;
$market=3D$sheet->Range($cell)->{Value};
$market=3D~s/\'/\"/g;
$sqltxt=3D$sqltxt . "'" . $market . "'";
=20
$cell=3D"B" . $i;
$custnbr=3D$sheet->Range($cell)->{Value};
$custnbr=3D~s/\'/\"/g;
$sqltxt=3D$sqltxt . ",'" . $custnbr . "'";
=20
$cell=3D"C" . $i;
$custname=3D$sheet->Range($cell)->{Value};
$custname=3D~s/\'/\"/g;
$sqltxt=3D$sqltxt . ",'" . $custname . "'";
=20
$cell=3D"F" . $i;
$current=3Dsprintf("%9.2f",($sheet->Range($cell)->{Value}));
$sqltxt=3D$sqltxt . "," . $balance;
if ($market eq "" || $market eq " ") {
# this check tells us when we are at the end of our data =
since we know in this case
# that market field should not be blank. Otherwise we would =
continue reading to the
# 65,000th row in the spreadsheet which is a waste of time. =
=20
$exitwhileloop=3D"Y";
last;
}
=20
####################################################### =20
# execute the insert statement and get return status
#######################################################
$ret=3D$db->Sql($sqltxt); =20
if ($ret) {
$error=3D$db->Error; # capture the sql error message
=20
Win32::GUI::MessageBox($W,"$error\n$sqltxt",
"Excel port to Access - SQL Error($ret)",16,);
return -1; =20
}
$cnt++;
=20
$Status->Text($cnt);
$Status->Update();
=20
Win32::GUI::DoEvents(); # keep screen refreshed
=20
} # end of for loop
=20
if ($exitwhileloop eq "Y") {
last;
}
=20
$j++;
=20
} # end of while loop
=20
=20
Win32::GUI::MessageBox($W,"There were $cnt records ported to MS-Access.=
",=20
"Excel port to Access - Process Complete.",64,);
=20
$Status->Text("Exiting Program - Please wait ...");
$Status->Update();
sleep 3;
=20
return -1; =20
=20
} # Port_Click event
# End Script
|