http://www.cnblogs.com/Jedimaster/archive/2007/02/28/660209.html
朋友的家人做生意,每日從各地分店處收集報表,然後回去彙總。由于不想用那種複雜的管理軟體,就叫他寫一個小工具。于是他找到了我,讓我想想辦法。
Python是個令人驚奇的工具,而不僅僅是一種語言。對比老牌的Perl,看似Python不是那麼的精通 —— 對比Perl超快的文本處理速度和廣泛應用于Cgi程式的編寫曆史,以及目前大紅大紫的Ruby在Web開發上的病毒式蔓延,而比起靜态語言比如C/C++,虛拟機Java和C#來說,速度又成了問題。但是Python的實力可不容小視,NASA都用Python可不是吹的,況且,Python的學習難度比Perl小多了,剛學時讓我找到了以前QBASIC的感覺。
此程式具體要求如下:每日産生副表若幹(如副表檔案)。程式先核對附表的日期和銷售點。如果銷售點不同日期相同,便把不同副表的相同産品号的 “銷售數量”欄相加,填入總表“銷售數量”欄。将副表的“總利潤”欄相加填入總表的“總利潤”欄。其他副表資訊複制到總表(備注除外,由使用者自行處理)。表頭的樣式如下:

啊哈,很簡單的表頭。其中需要操作的是“銷售數量”和“總利潤”,也就是把相同時間的報表相加。但是這樣有個嚴重問題!
必須要求,相同報表的産品名稱、貨号的順序不能出錯,各地要絕對統一,否則全部這樣照樣拷貝就會出錯!
讓我們分析一下思路:時間是關鍵。時間決定了哪些報表需要分門别類,生成哪一天的統計總表。資料結構上,用什麼呢?簡單的list?不行,我嘗試過。應該使用map容器,把日期作為key,儲存的Value是個清單。程式先掃描所有的Excel檔案擷取日期,然後把相同日期報表的COM文檔接口儲存起來,實作了分門别類。最後周遊這個map容器,計算,生成每日的統計總表。代碼如下,經過測試正常。
1
import os;
2
import sys;
3
import time;
4
import datetime;
5
# 請先安裝對應着你自己的Python版本的PythonWin32
6
import win32com.client;
7
8
9
mapper = {};
10
11
app = win32com.client.Dispatch( " Excel.Application " );
12
PipeOut = os.popen( " dir *.xls /B " );
13
FileList = PipeOut.readlines();
14
PipeOut = os.popen( " cd " );
15
CurDic = PipeOut.readline();
16
CurDic = CurDic[: - 1 ] + " // " ; # 去處末尾的/n
17
print " 目前工作目錄為 " + CurDic;
18
19
# 讀取每個檔案的時間和儲存相應的COM接口
20
21
for filename in FileList:
22
filename = CurDic + filename[: - 1 ];
23
print filename;
24
Doc = app.Workbooks.Open(filename);
25
Sheet = Doc.Sheets( 1 );
26
Time = Sheet.Cells( 2 , 5 );
27
print type(Time);
28
TimeKey = str(Time);
29
print TimeKey;
30
if mapper.has_key(TimeKey):
31
mapper[TimeKey].append(Sheet);
32
else :
33
mapper[TimeKey] = [];
34
mapper[TimeKey].append(Sheet);
35
# print mapper;
36
37
38
# 生成新的統計總表
39
40
# 開始處理mapper 每次從一個自表中讀取2x20個資料,然後和總表相加
41
print " ------------------------------------- " ;
42
Protetype = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
43
a = 0;
44
b = 0;
45
c = 0;
46
47
for k,v in mapper.items():
48
print " // "
49
a += 1 ;
50
Count = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
51
Benefit = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
52
Name = [u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ,u "" ];
53
# print Count;
54
# print Benefit;
55
# Total = app.Workbooks.Open(CurDic+"Template//TotalTemplate.xls");
56
print " How manu Sheets in this List ? " ,len(v);
57
for sht in v:
58
b += 1 ;
59
_Count = sht.Range( " C4:C23 " ).Value;
60
_Benefit = sht.Range( " F4:F23 " ).Value;
61
_Name = sht.Range( " B4:B23 " ).Value;
62
# print _Count;
63
# print _Benefit;
64
assert (len(_Count) == len(_Benefit));
65
for i in range(0,len(_Count)):
66
c += 1 ;
67
Count[i] = _Count[i][0] + Count[i];
68
Benefit[i] = _Benefit[i][0] + Benefit[i];
69
Name[i] = _Name[i][0];
70
# 以上作為儲存總表項的資料
71
Total = app.Workbooks.Open(CurDic + " Template//TotalTemplate.xls " );
72
TotalSheet = Total.Sheets( 1 );
73
_Time = k[:k.find( " " )];
74
_Time = _Time.replace( " / " , " - " );
75
print _Time;
76
print Count;
77
print Benefit;
78
# TotalSheet.Cells(2,2).Value = _Time;
79
for i in range(0,len(Count)):
80
TotalSheet.Cells( 4 + i, 3 ).Value = Count[i]; # 填充數量
81
TotalSheet.Cells( 4 + i, 6 ).Value = Benefit[i]; # 填充利潤
82
TotalSheet.Cells( 4 + i, 2 ).Value = Name[i]; # 填充貨物名稱
83
84
# 儲存總表
85
Total.SaveAs(CurDic + _Time + " 統計總表.xls " );
86
del Count,Benefit;
87
print " ++++++++++++++++++++++++++++ "
88
print a,b,c;
89
app.Quit();
90
app = None;
91
使用方法,先安裝Python 2.4和PythonWin For 2.4。然後把這個腳本拷貝到分表的檔案夾下,然後運作(調試),自動生成與日期相關的總表。效果圖如下:
最終解決思路的提示:其實這種方法隻能在規模比較小的時候,因為這種脫離于總系統的處理效率實在非常低,而且Excel二進制檔案,空表的占用就達15k,在未來有大量業務資料處理的話将是無法忍受的噩夢。是以,我建議這位商務人士分析一下他所使用的處理系統,用便宜的網絡線路建構從各地中心伺服器系統,使用XML作為資料交換得媒介,在自己的伺服器上您隻需要使用簡單的SQL處理過程就可以了,而且資料的可靠度比平面Excel文檔高得多。
資料在這裡下載下傳,為了保險起見請不要使用中文的檔案夾目錄。
0 0 0 (請您對文章做出評價)