摘要:該文介紹了在GAE編程環(huán)境下用pyExcelerator導(dǎo)出Excel報(bào)表文件的方法,著重介紹了pyExcelerator產(chǎn)生帶格式的Excel文件的實(shí)現(xiàn)細(xì)節(jié),并給出了向?yàn)g覽器返回Excel二進(jìn)制流的方法。
關(guān)鍵詞:Python;GAE;pyExcelerator;Excel
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2009)26-7513-03
Exporting Excel Files in GAE
PANG Sheng-li1, LI Peng2
(1.Graduate School of Xidian University, Xi’an 710071, China; 2.Shaanxi Telecommunications Planning and Designing Institute CO. LTD, Xi'an 710065, China)
Abstract: This paper describes how to export Excel files using pyExcelerator library in GAE programming environment and focuses on gererating formatted Excel files with the implementation details and the mothod of returning Excel binary stream to browser.
Key words: Python; GAE; pyExcelerator; Excel
GAE(Google App Engine)是Google推出的一個(gè)互聯(lián)網(wǎng)應(yīng)用服務(wù)引擎,是Google云計(jì)算的一部分,開發(fā)人員可以使用GAE的API開發(fā)互聯(lián)網(wǎng)應(yīng)用,而不用擔(dān)心帶寬、主機(jī)、數(shù)據(jù)庫、安全等資源配置、維護(hù)。開發(fā)人員可以很方便的利用其API快速開發(fā)應(yīng)用。在GAE開發(fā)過程中,很多情況都需要導(dǎo)出Excel報(bào)表,而GAE沒有提供導(dǎo)出Excel報(bào)表的API,本文給出了在GAE提供的Python環(huán)境下導(dǎo)出Excel報(bào)表的實(shí)現(xiàn)。
1 GAE應(yīng)用開發(fā)
GAE的應(yīng)用非常容易建立和維護(hù),GAE起初只支持Python語言,后來逐漸支持多種編程語言。GAE提供了Java運(yùn)行環(huán)境,可以使用標(biāo)準(zhǔn)的Java技術(shù),包括JVM、Java Servlet、Java語言或者任何其他基于JVM的解釋語言或編譯器,如Javascript或Ruby。GAE提供了一個(gè)受限的Python運(yùn)行環(huán)境,包括一個(gè)Python解釋器和Python標(biāo)準(zhǔn)庫。GAE提供的Java和Python環(huán)境保證應(yīng)用運(yùn)行的快速、安全,不受其他應(yīng)用的影響。
不同于傳統(tǒng)的虛擬主機(jī),GAE提供的是整套構(gòu)建應(yīng)用的基礎(chǔ)架構(gòu)平臺(tái),可以幫助開發(fā)人員獲取網(wǎng)絡(luò)數(shù)據(jù)、發(fā)送郵件、數(shù)據(jù)存儲(chǔ)、圖片操作、緩存數(shù)據(jù)等,以后還會(huì)有更多的API推出。開發(fā)人員在GAE的框架內(nèi)開發(fā),不用再考慮CPU、內(nèi)存、分布等復(fù)雜和難以控制的問題,初級(jí)的程序員按照GAE的規(guī)范也可以寫出高性能的應(yīng)用。但是為了安全考慮,GAE不能直接使用socket、進(jìn)行文件操作。總之,GAE提供的開發(fā)環(huán)境,可以讓開發(fā)更加簡(jiǎn)單,更關(guān)注于業(yè)務(wù)。
在GAE環(huán)境下,可以免費(fèi)使用500M的存儲(chǔ)空間和每月500萬次頁面刷新,如果想使用更多的資源,可以按需支付費(fèi)用。
2 生成Excel文件
GAE提供的是受限的Python環(huán)境,在此環(huán)境下生成Excel文件只能依靠第三方庫。pyExcelerator是一個(gè)主要用于產(chǎn)生Excel文件的庫,能夠靈活產(chǎn)生各種帶格式的Excel文件,也能夠讀取已經(jīng)存在的Excel文件,只是美中不足只能讀取Excel單元格的值,而不能讀取各個(gè)單元格的格式。pyExcelerator完全支持UNICODE,并且支持各種格式設(shè)置。最重要的是pyExcelerator是一個(gè)跨平臺(tái)的組件,并不需要Windows平臺(tái)和COM服務(wù)器也能正常使用,這非常符合GAE環(huán)境的要求。
pyExcelerator中有多個(gè)類用于產(chǎn)生Excel文件,其中常用的有三個(gè):Workbook,Worksheet,XFStyle。Workbook代表一個(gè)Excel文件,Worksheet代表一個(gè)Excel文件中的一頁,XFStyle用于確定產(chǎn)生單元格的格式。
2.1 生成最簡(jiǎn)單的Excel文件
生成最簡(jiǎn)單Excel文件的代碼如下:
#coding=utf-8
from pyExcelerator import *
w = Workbook()#生成Workbook對(duì)象
ws = w.add_sheet('Hey, Dude')#生成Worksheet對(duì)象
ws.write(0, 0, 'The first cell')#向Worksheet對(duì)象的A1單元寫入數(shù)據(jù)‘The first cell’
w.save('mini.xls')#將Workbook對(duì)象存盤
可以看出主要是用Worksheet對(duì)象的write方法寫入數(shù)據(jù)的,此函數(shù)定義:write(r, c, label=\"\", style=Style.XFStyle())。r、c是要寫入數(shù)據(jù)的單元格的行、列坐標(biāo),從0開始,如A1單元就是(0,0),B2單元就是(1,1)。Label參數(shù)是要寫入的具體內(nèi)容。最后的style參數(shù)指定寫入時(shí)的格式,這在下面討論。
2.2 設(shè)置單元格字體
設(shè)置單元格的字體格式就要使用Font對(duì)象,代碼如下:
font0 = Font()
font0.name = 'Arial'#字體的名稱
font0.bold = True#是否加粗
font0.italic = True#是否斜體
font0.height = 200 # 字體的高度,200:相當(dāng)于10點(diǎn)高
font0.struck_out = True#是否在字之間劃刪除線
font0.outline = False#是否采用outline字體
font0.shadow = False#是否加陰影
font0.colour_index = 2#字體顏色的索引
font0.escapement = font0.ESCAPEMENT_SUBSCRIPT#指定字體的上、下標(biāo)
font0.underline = font0.UNDERLINE_SINGLE_ACC#是否使用下劃線
font0.family = font0.FAMILY_NONE#指定字體集
font0.charset = font0.CHARSET_ANSI_CYRILLIC#指定字符集
style0 = XFStyle()
style0.font = font0
wb = Workbook()
ws0 = wb.add_sheet('Sheet1')
ws0.write(1, 1, 'Test', style0)
wb.save('font.xls')
可以看到通過Font對(duì)象可以設(shè)置各種字體格式,大部分使用方法都在注釋中給出,其中比較特殊的兩個(gè):escapement用于設(shè)置字體的上下標(biāo),ESCAPEMENT_NONE不使用上下標(biāo),ESCAPEMENT_SUPERSCRIPT使用上標(biāo),ESCAPEMENT_SUBSCRIPT使用下標(biāo)。underline用于設(shè)置字體的下劃線,UNDERLINE_NONE不使用下劃線,UNDERLINE_SINGLE使用單下劃線,UNDERLINE_SINGLE_ACC使用會(huì)計(jì)用單下劃線,UNDERLINE_DOUBLE使用雙下劃線,UNDERLINE_DOUBLE_ACC使用會(huì)計(jì)用雙下劃線。另外,通過設(shè)置一行上某個(gè)單元格字體的高度(height)就可以間接的設(shè)置此行的行高。
2.3 設(shè)置列寬
w = Workbook()
ws = w.add_sheet('Sheet1')
ws.write(1, 1, 'Test')
ws.col(1).width = 8000#8000:400點(diǎn)
w.save('col_width.xls')
ws.col(colnum)函數(shù)返回代表第colnum列的列對(duì)象,可以設(shè)置它的width屬性來設(shè)置此列的寬度。
2.4 設(shè)置單元格邊框
每個(gè)單元格都可以設(shè)置其邊框,這要通過Borders對(duì)象。
borders = Borders()
borders.left = borders.DOUBLE#設(shè)置左邊框
borders.right= borders.DOUBLE#設(shè)置右邊框
borders.top= borders.NO_LINE#設(shè)置上邊框
borders.bottom = borders.NO_LINE#設(shè)置下邊框
borders.diag = borders.DOUBLE#設(shè)置對(duì)角線
borders.left_colour = 0x40#設(shè)置左邊框顏色
borders.right_colour= 0x40#設(shè)置右邊框顏色
borders.top_colour= 0x40#設(shè)置上邊框顏色
borders.bottom_colour = 0x40#設(shè)置下邊框顏色
borders.diag_colour = 0x40#設(shè)置對(duì)角線顏色
borders.need_diag1 = borders.NEED_DIAG1#設(shè)置是否顯示左上->右下對(duì)角線
borders.need_diag2 = borders.NO_NEED_DIAG2#設(shè)置是否顯示左下->右上對(duì)角線
style0 = XFStyle()
style0.borders = borders
wb = Workbook()
ws0 = wb.add_sheet('Sheet1')
ws0.write(1, 1, 'Test borders!', style0)
wb.save('borders.xls')
可以看出Borders是格式(XFStyle)的一種,它的left、right、top、bottom、diag屬性分別設(shè)置左、右、上、下、對(duì)角五條線的類型,類型共有14種:NO_LINE、THIN、MEDIUM、DASHED、DOTTED、THICK、DOUBLE、HAIR、MEDIUM_DASHED、THIN_DASH_DOTTED、MEDIUM_DASH_DOTTED、THIN_DASH_DOT_DOTTED、MEDIUM_DASH_DOT_DOTTED、SLANTED_MEDIUM_DASH_DOTTED。其中NO_LINE為不顯示相應(yīng)的邊框,其它值顯示對(duì)應(yīng)線形樣式的邊框,但diag除外。它的left_colour等以_colour結(jié)尾的屬性是對(duì)應(yīng)的線的顏色的索引。need_diag1、need_diag2設(shè)置是否需要對(duì)角線:NEED_DIAG1(或2)需要、NO_NEED_DIAG1(或2)不需要。上面的diag屬性只是設(shè)置對(duì)角線的線形,只有設(shè)置need_diag屬性為NEED才真正顯示對(duì)角線。
2.5 設(shè)置單元格底紋
設(shè)置單元格的底紋要通過Pattern對(duì)象。
pattern = Pattern()
pattern.pattern = 2#設(shè)置底紋的圖案索引
pattern.pattern_fore_colour = 20#設(shè)置底紋的前景色
pattern.pattern_back_colour = 10#設(shè)置底紋的背景色
style0 = XFStyle()
style0.pattern = pattern
wb = Workbook()
ws0 = wb.add_sheet('Sheet1')
ws0.write(1, 1, 'Test pattern!', style0)
wb.save('pattern.xls')
Pattern的pattern屬性指示底紋的圖案索引,0為實(shí)心,1為75%灰色,2為50%灰色,依次類推,可以參考Excel的幫助文檔。pattern_fore_colour、pattern_back_colour指示底紋前景色、背景色的顏色索引。
2.6 生成合并的單元格
生成合并的單元格要通過Worksheet的write_merge、merge方法,write_merge的定義:write_merge( r1, r2, c1, c2, label=\"\", style),merge的定義:merge(r1, r2, c1, c2, style),其中r1,r2指示要合并單元格的起始行、終止行(0為第一行);c1、c2指示要合并單元格的起始列、終止列(0為第一列);label是寫入的數(shù)據(jù)內(nèi)容;style指示合并后單元格的格式。可以看出merge是write_merge的特殊情況,merge只能執(zhí)行寫入內(nèi)容為空的合并操作。示例代碼如下:
wb = Workbook()
ws0 = wb.add_sheet('Sheet1')
ws0.write_merge(3, 3, 1, 5, 'test1')#合并第4行,第2列到6列,并寫入test1。
ws0.write_merge(4, 10, 1, 5, 'test2')#合并第5行到11行,第2列到6列,并寫入test2。
ws0.merge(12, 15, 1, 5)#合并第13行到16行,第2列到6列,并寫入空白。
wb.save('merged.xls')
2.7 其他操作
pyExcelerator還有其他操作,包括設(shè)置數(shù)字單元格的格式、插入圖片等,可以參考pyExcelerator的例子和文檔,這里不做詳細(xì)介紹。
3 GAE返回Excel報(bào)表
3.1 得到Excel二進(jìn)制流
pyExcelerator庫可以方便的生成Excel文件,但GAE環(huán)境卻不允許文件操作,也就是說,Workbook的save方法是不允許執(zhí)行的。如果要返回Excel報(bào)表文件,可以參照GAE返回圖片的方法,直接將Excel的二進(jìn)制流返回給瀏覽器。這就需要修改Workbook和CompoundDoc.XlsDoc的代碼,仿照save函數(shù)加入返回二進(jìn)制流的函數(shù):savestream。
Workbook的savestream:
def savestream(self):
import CompoundDoc
doc = CompoundDoc.XlsDoc()
return doc.savestream(self.get_biff_data())
CompoundDoc.XlsDoc的savestream方法:
def savestream(self, stream):
# 1. Align stream on 0x1000 boundary (and therefore on sector boundary)
padding = '\\x00' * (0x1000 - (len(stream) % 0x1000))
self.book_stream_len = len(stream) + len(padding)
self.__build_directory()
self.__build_sat()
self.__build_header()
s = \"\"
s = s + str(self.header)
s = s + str(self.packed_MSAT_1st)
s = s + str(stream)
s = s + str(padding)
s = s + str(self.packed_MSAT_2nd)
s = s + str(self.packed_SAT)
s = s + str(self.dir_stream)
return s
這樣可以通過Workbook的savestream函數(shù)最終得到了Excel文件的二進(jìn)制流。
3.2 返回Excel流
用戶在請(qǐng)求Excel報(bào)表的時(shí)候就可以將上面生成的Excel二進(jìn)制流返回了,如同請(qǐng)求一個(gè)Excel文件一樣。但返回流的時(shí)候,還要通過設(shè)置HTTP報(bào)文頭,通知瀏覽器這是個(gè)Excel文件。具體代碼如下:
class Main(webapp.RequestHandler):
def get(self):
if self.request.get('export') == 'excel':
#生成Excel文件
wb = Workbook()
ws = wb.add_sheet(u'統(tǒng)計(jì)報(bào)表')
ws.write(2, 0, u\"日期\")
ws.write(2, 1, u\"資金流向\")
#寫入其他數(shù)據(jù)
#...
#設(shè)置報(bào)文頭,返回Excel報(bào)表
self.response.headers['Content-Type'] = \"application/vnd.ms-execl\"
self.response.headers['Content-Disposition'] = str(\"attachment; filename=report.xls\")
self.response.headers['Pragma'] = \"no-cache\"
self.response.headers['Expires'] = \"0\"
self.response.out.write(wb.savestream())
return
4 結(jié)束語
本文給出了GAE編程環(huán)境下用pyExcelerator庫生成Excel報(bào)表的方法,著重介紹了產(chǎn)生帶格式Excel文件的方法和將生成的Excel二進(jìn)制流返回給瀏覽器的方法。由于GAE是新興的一種網(wǎng)絡(luò)應(yīng)用服務(wù)架構(gòu),在其上開發(fā)的應(yīng)用越來越多,不論是企業(yè)信息產(chǎn)品還是網(wǎng)絡(luò)服務(wù)網(wǎng)站,大多都需要產(chǎn)生Excel報(bào)表,因此本文給出的方法具有較強(qiáng)的實(shí)用價(jià)值。
參考文獻(xiàn):
[1]魯茲,阿舍爾.Python語言入門[M].陳革,馮大輝,譯.北京:中國電力出版社,2001.