許多商業(yè)最終用戶更喜歡使用目前流行的電子數(shù)據(jù)表格程序(如Microsoft Excel),而不是數(shù)據(jù)庫功能或應(yīng)用程序。盡管Excel可以用ODBC及相關(guān)技術(shù)來提取儲(chǔ)存在Oracle數(shù)據(jù)庫當(dāng)中的數(shù)據(jù),但想讓用戶建立一個(gè)環(huán)境來直接訪問數(shù)據(jù)或是通過安裝腳本來安裝數(shù)據(jù)資源可能會(huì)不大合理。
因此,對(duì)于程序開發(fā)人員來說,從儲(chǔ)存在數(shù)據(jù)庫中的數(shù)據(jù)生成一個(gè)電子數(shù)據(jù)表格,并通過e-mail或網(wǎng)站將其文檔傳回用戶手中,是一個(gè)非?;镜囊话阋?。
關(guān)于如何生成Excel電子數(shù)據(jù)表格,一個(gè)典型回答是,生成一個(gè)CSV(comma-separated values)文件,在這里每一個(gè)字段都用一個(gè)Text屬性來說明,可能包含在引號(hào)里。這種情況下,這個(gè)文件作為原始數(shù)據(jù)被終端用戶接受,終端用戶在Excel下打開它,通過一個(gè)對(duì)話將數(shù)據(jù)正確的分解成電子數(shù)據(jù)表格中的單元格。
也可能僅僅通過傳送作為一個(gè)電子數(shù)據(jù)表格屬性的公式(如“=A1+B1”),將這些公式寫進(jìn)電子數(shù)據(jù)表格,而這個(gè)公式只有在字段被準(zhǔn)確讀取到正確位置時(shí)才會(huì)有用。在這種情況下,沒有格式化控制,當(dāng)數(shù)據(jù)讀入時(shí),最終用戶只能手工將一個(gè)電子數(shù)據(jù)表格重新格式化。
一個(gè)Perl替代品
現(xiàn)在有了一個(gè)非常有用的CSV文件的替代品。John McNamara創(chuàng)建了一個(gè)Perl模塊,叫做SPReadsheet::WriteExcel,它能動(dòng)態(tài)生成一個(gè)真正的、二進(jìn)制的、Excel的電子數(shù)據(jù)表格文件。
在這個(gè)模塊中,你可以創(chuàng)建一個(gè)工作手冊(cè),并在其中加入工作表,然后直接寫入工作表單元格。有許多格式化選項(xiàng)答應(yīng)你改變字段數(shù)據(jù)的格式、黑體、對(duì)齊方式、字體、前景和背景顏色、填充圖案以及邊框。
另外,Spreadsheet::WriteExcel可以改變字體,文字變形和旋轉(zhuǎn)文字,插入位圖,設(shè)置密碼保護(hù)工作表,以及建立能用鼠標(biāo)擴(kuò)展的數(shù)據(jù)集合。當(dāng)然還能夠設(shè)置打印選項(xiàng)和頁面暫停的功能。
該模塊還可以寫標(biāo)準(zhǔn)輸出數(shù)據(jù),因此它可以在cgi-bin程序中使用。其他程序語言可以通過HTTP URL參照cgi-bin,來請(qǐng)求Excel電子數(shù)據(jù)表格電子數(shù)據(jù)表格。
下面是一個(gè)例子,它用DBI從EMP表中提取數(shù)據(jù)并用公式和格式化生成一個(gè)Excel電子數(shù)據(jù)表格電子數(shù)據(jù)表格。
use DBI;
use Spreadsheet::WriteExcel;
# connect to the local database
my $dbh = DBI->connect('dbi:Oracle:','scott','tiger') die $DBI::errstr;
print "Generating Excel Spreadsheet/n";
my $workbook = new Spreadsheet::WriteExcel "emp.xls";
my $worksheet = $workbook->add_worksheet();
my $fmt = {
HEADER => $workbook->add_format(bold=>1,align=>'center',
bottom=>2,bg_color=>'silver'),
ENAME => $workbook->add_format(bold=>1,color=>'blue'),
MONEY => $workbook->add_format(
num_format=>'$#,##0.00',align=>'right'),
TOTAL => $workbook->add_format(
num_format=>'$#,##0.00',align=>'right',bold=>1,
top=>2),
};
print "Querying Employees/n";
my $sth = $dbh->prepare('select * from emp') die $DBI::errstr;
my $rc = $sth->execute;
my $r = 1;
$worksheet->write($r-1,0,'Employee',$fmt->{HEADER});
$worksheet->write($r-1,1,'Salary',$fmt->{HEADER});
$worksheet->write($r-1,2,'Commission',$fmt->{HEADER});
$worksheet->write($r-1,3,'Total',$fmt->{HEADER});
$r++;
while (my $row = $sth->fetchrow_hashref)
{
$worksheet->write($r-1,0,$row->{ENAME},$fmt->{ENAME});
$worksheet->write($r-1,1,$row->{SAL},$fmt->{MONEY});
$worksheet->write($r-1,2,$row->{COMM},$fmt->{MONEY});
$worksheet->write($r-1,3,"=B$r+C$r",$fmt->{MONEY});
$r++;
}
$worksheet->write($r-1,0,'',$fmt->{TOTAL});
$worksheet->write($r-1,1,'=SUM(B2:B'.($r-1).')',$fmt->{TOTAL});
$worksheet->write($r-1,2,'=SUM(C2:C'.($r-1).')',$fmt->{TOTAL});
$worksheet->write($r-1,3,"=B$r+C$r",$fmt->{TOTAL});
print "Processed " . ($r-2) ." rows/n";
$sth->finish;