
簡介FastReport 2.53 是面向 Delphi 5、6、7 開發(fā)者的經(jīng)典報(bào)表控件包專為需要在傳統(tǒng) VCL 項(xiàng)目中快速實(shí)現(xiàn)數(shù)據(jù)打印、報(bào)表設(shè)計(jì)與導(dǎo)出功能的程序員準(zhǔn)備。該版本重點(diǎn)改進(jìn)了與 FastReport 3 的兼容性修復(fù)了 Excel XML 導(dǎo)出邊距錯(cuò)誤并更新了捷克語、羅馬尼亞語等語言資源同時(shí)修正了導(dǎo)出模塊與報(bào)表引擎的若干小問題適合仍在使用舊版 Delphi 維護(hù)遺留系統(tǒng)、或希望低成本搭建報(bào)表模塊的中級開發(fā)者。壓縮包為 rar 格式體積約 4.1MB內(nèi)含控件源碼、運(yùn)行時(shí)庫及示例工程等文件便于直接集成到現(xiàn)有項(xiàng)目中調(diào)試。目前已有 164 人學(xué)習(xí)下載可作為舊版 Delphi 報(bào)表開發(fā)的參考資料幫助讀者理解報(bào)表引擎的導(dǎo)出機(jī)制、語言資源組織方式以及版本兼容性處理思路減少在打印與導(dǎo)出環(huán)節(jié)的排錯(cuò)時(shí)間。1. 老 Delphi 項(xiàng)目里翻出一套 FastReport 2.53它到底能干什么接手過 Delphi 5、6、7 時(shí)代遺留系統(tǒng)的人大概都有體會(huì)代碼能跑數(shù)據(jù)庫能連唯獨(dú)報(bào)表模塊一碰就出問題。要么是當(dāng)年用的第三方報(bào)表控件找不到安裝包要么是源碼里引用的單元文件在現(xiàn)在的機(jī)器上根本編譯不過。最近整理一套老項(xiàng)目的歸檔資料時(shí)翻出了一份 FastReport 2.53 的完整安裝包專門針對 Delphi 5、6、7 三個(gè)版本。這東西放到今天看確實(shí)老但對于還在維護(hù)那批老系統(tǒng)的團(tuán)隊(duì)來說它解決的是一個(gè)很具體的問題——讓原本已經(jīng)無法編譯的報(bào)表模塊重新跑起來。FastReport 在 Delphi 圈子里算是老牌報(bào)表控件2.53 這個(gè)版本對應(yīng)的是 Delphi 5 到 7 的黃金時(shí)期。它的核心能力就三塊可視化報(bào)表設(shè)計(jì)器、運(yùn)行時(shí)報(bào)表引擎、以及和 Delphi 數(shù)據(jù)集的綁定。和后來那些動(dòng)輒幾十兆的報(bào)表工具比它體積小、依賴少編譯出來的可執(zhí)行文件不會(huì)突然膨脹。適合的人群也很明確手里有 Delphi 5/6/7 老項(xiàng)目需要維護(hù)的開發(fā)者或者需要從舊系統(tǒng)里導(dǎo)出報(bào)表邏輯做遷移參考的人。如果你用的是 Delphi 10 以后的版本這套東西基本用不上別浪費(fèi)時(shí)間。2. 拆開安裝包文件結(jié)構(gòu)與版本對應(yīng)關(guān)系拿到一個(gè)老安裝包第一步不是急著裝而是先看清楚里面有什么。FastReport 2.53 的包結(jié)構(gòu)比較典型分成了幾個(gè)獨(dú)立目錄對應(yīng)不同的 Delphi 版本和功能模塊。2.1 目錄布局與關(guān)鍵文件識(shí)別解壓之后通常能看到這樣的結(jié)構(gòu)FastReport2.53/ ├── Delphi5/ │ ├── FastReport_D5.dpk │ ├── frxClass.pas │ ├── frxDBSet.pas │ └── ... ├── Delphi6/ │ ├── FastReport_D6.dpk │ └── ... ├── Delphi7/ │ ├── FastReport_D7.dpk │ └── ... ├── Source/ │ ├── frxClass.pas │ ├── frxReport.pas │ ├── frxPreview.pas │ └── ... ├── Design/ │ ├── frxDesgn.pas │ └── ... └── Help/ └── FastReport.chm這里有幾個(gè)關(guān)鍵點(diǎn)。Delphi5、Delphi6、Delphi7三個(gè)目錄里放的是對應(yīng)版本的包文件.dpk包文件里引用的單元路徑指向Source和Design目錄。也就是說安裝的時(shí)候不能只把某個(gè)版本目錄拷進(jìn)去Source和Design是共享的。我見過有人只復(fù)制了Delphi7目錄結(jié)果編譯時(shí)報(bào)找不到frxClass.pas這就是沒搞清楚目錄之間的引用關(guān)系。Source目錄里是運(yùn)行期單元Design目錄里是設(shè)計(jì)期單元。運(yùn)行期單元是報(bào)表引擎的核心設(shè)計(jì)期單元負(fù)責(zé)在設(shè)計(jì)器里拖拽控件、編輯報(bào)表模板。如果你只是想在運(yùn)行時(shí)動(dòng)態(tài)生成報(bào)表理論上只需要Source里的文件但要在 IDE 里可視化設(shè)計(jì)報(bào)表Design目錄不能少。2.2 版本匹配D5、D6、D7 的包文件差異三個(gè)版本的包文件名字不同內(nèi)容也有細(xì)微差別。Delphi 5 的包文件里引用的單元路徑和 Delphi 7 的不完全一樣主要是因?yàn)?IDE 的包管理機(jī)制在這幾個(gè)版本之間有變化。具體來說版本包文件名運(yùn)行期包設(shè)計(jì)期包Delphi 5FastReport_D5.dpkfrxR5.dpkfrxD5.dpkDelphi 6FastReport_D6.dpkfrxR6.dpkfrxD6.dpkDelphi 7FastReport_D7.dpkfrxR7.dpkfrxD7.dpk運(yùn)行期包和設(shè)計(jì)期包要分開安裝。運(yùn)行期包提供報(bào)表引擎的類設(shè)計(jì)期包提供 IDE 里的控件面板注冊和屬性編輯器。如果只裝運(yùn)行期包代碼里能uses frxClass但控件面板上找不到 FastReport 的組件如果只裝設(shè)計(jì)期包編譯時(shí)又會(huì)報(bào)運(yùn)行期單元找不到。常見做法是先裝運(yùn)行期包再裝設(shè)計(jì)期包順序反了有時(shí)候 IDE 會(huì)提示依賴缺失。提示安裝前先確認(rèn) Delphi 的 Library Path 里沒有舊版本的 FastReport 路徑。如果有先清理掉否則新裝的包可能引用到舊單元編譯出一堆莫名其妙的錯(cuò)誤。2.3 安裝前的環(huán)境檢查清單在動(dòng)手之前有幾項(xiàng)檢查建議走一遍確認(rèn) Delphi 版本號(hào)不要憑感覺。Delphi 5 和 Delphi 6 的包格式雖然相似但混用會(huì)出問題。檢查系統(tǒng)里是否已經(jīng)裝了其他版本的 FastReport。如果有先卸載或至少把路徑從 Library Path 里移除。備份當(dāng)前的 Library Path 設(shè)置。老 IDE 的路徑管理比較脆弱改亂了恢復(fù)起來很麻煩。確認(rèn)安裝包里的.dpk文件沒有被殺毒軟件誤刪。老安裝包里的某些文件偶爾會(huì)被誤報(bào)。這些檢查看起來瑣碎但老工具鏈的坑往往就藏在這些地方。我遇到過有人直接雙擊.dpk文件IDE 打開了但編譯報(bào)錯(cuò)最后發(fā)現(xiàn)是 Library Path 里有一個(gè)指向舊版本的空路徑導(dǎo)致編譯器找錯(cuò)了單元。3. 在 Delphi 5/6/7 里編譯安裝從 .dpk 到控件面板安裝過程本身不復(fù)雜但老 IDE 的包管理界面和現(xiàn)在的版本差別很大步驟上容易卡住。下面按 Delphi 7 的界面走一遍Delphi 5 和 6 的操作邏輯類似只是菜單項(xiàng)位置略有不同。3.1 編譯運(yùn)行期包打開 Delphi選擇File→Open定位到Delphi7目錄下的frxR7.dpk。打開后在項(xiàng)目管理器里右鍵點(diǎn)擊包節(jié)點(diǎn)選擇Compile。如果一切正常編譯輸出會(huì)顯示沒有錯(cuò)誤。這一步可能遇到的問題報(bào)錯(cuò)File not found: frxClass.pas。原因是 Library Path 里沒有包含Source目錄。解決方法是打開Tools→Environment Options→Library在Library Path里加上Source目錄的完整路徑。報(bào)錯(cuò)Unit frxDBSet is not found。檢查Source目錄下是否有這個(gè)文件如果沒有說明安裝包不完整。編譯通過但提示Package compiled with warnings。老代碼里有一些過時(shí)的語法警告可以忽略只要沒有 Error 就行。編譯成功后點(diǎn)擊Install按鈕。IDE 會(huì)把運(yùn)行期包注冊到系統(tǒng)里。這一步不會(huì)在控件面板上添加任何東西因?yàn)檫\(yùn)行期包只提供類庫。3.2 編譯設(shè)計(jì)期包并注冊控件接下來打開frxD7.dpk同樣先Compile再Install。設(shè)計(jì)期包安裝成功后控件面板上會(huì)出現(xiàn)一個(gè)FastReport標(biāo)簽頁里面有TfrxReport、TfrxDBDataset、TfrxDesigner等組件。如果控件面板上沒有出現(xiàn)新標(biāo)簽頁檢查這幾項(xiàng)設(shè)計(jì)期包是否真的編譯并安裝成功了。在Component→Install Packages里能看到已安裝的包列表。IDE 是否需要重啟。老版本的 Delphi 有時(shí)候安裝完包之后需要重啟才能刷新控件面板。包文件的Contains列表里是否包含了設(shè)計(jì)期單元。打開.dpk文件在Contains節(jié)點(diǎn)下應(yīng)該能看到frxDesgn等單元。3.3 驗(yàn)證安裝一個(gè)最小報(bào)表的編譯與預(yù)覽裝完之后建一個(gè)新的 VCL 應(yīng)用在窗體上放一個(gè)TfrxReport、一個(gè)TfrxDBDataset和一個(gè)TButton。TfrxDBDataset的DataSet屬性指向一個(gè)TADOQuery或TTableTfrxReport的DataSet屬性指向TfrxDBDataset。procedure TForm1.Button1Click(Sender: TObject); begin // 打開數(shù)據(jù)集 ADOQuery1.Open; // 加載報(bào)表模板文件 frxReport1.LoadFromFile(report.fr3); // 顯示預(yù)覽窗口 frxReport1.ShowPreparedReport; end;這段代碼的邏輯很直接先讓數(shù)據(jù)集處于打開狀態(tài)然后從磁盤加載報(bào)表模板最后調(diào)用預(yù)覽。LoadFromFile的參數(shù)是報(bào)表模板文件的路徑.fr3是 FastReport 2.x 的模板格式。ShowPreparedReport會(huì)直接顯示已經(jīng)生成好的報(bào)表如果模板里沒有數(shù)據(jù)預(yù)覽窗口會(huì)是空的。如果編譯時(shí)報(bào)Undeclared identifier: TfrxReport說明運(yùn)行期包沒有正確安裝或者uses子句里沒有加frxClass。如果運(yùn)行時(shí)預(yù)覽窗口彈不出來檢查DataSet屬性是否設(shè)置正確以及數(shù)據(jù)集是否真的打開了。注意FastReport 2.53 的模板文件擴(kuò)展名是.fr3不是后來版本的.frx。如果你手頭有.frx模板需要確認(rèn)版本兼容性直接加載可能會(huì)報(bào)格式錯(cuò)誤。4. 避坑與排查老版本 Delphi 報(bào)表模塊的五個(gè)血淚經(jīng)驗(yàn)老工具鏈的問題往往不是功能本身而是環(huán)境、路徑、版本這些外圍因素。下面這幾條是我在實(shí)際維護(hù)中反復(fù)遇到的按「現(xiàn)象 → 原因 → 解決」整理出來。4.1 編譯報(bào)錯(cuò)「找不到 frxClass.pas」現(xiàn)象打開.dpk文件后編譯IDE 提示File not found: frxClass.pas。原因Delphi 的 Library Path 里沒有包含Source目錄。老版本的 Delphi 不會(huì)自動(dòng)把包文件所在目錄的上級目錄加入搜索路徑需要手動(dòng)配置。解決打開Tools→Environment Options→Library在Library Path末尾加上Source目錄的完整路徑。注意路徑之間用分號(hào)隔開路徑末尾不要多加反斜杠。改完之后重新編譯包文件。4.2 控件面板上找不到 FastReport 標(biāo)簽頁現(xiàn)象設(shè)計(jì)期包編譯安裝成功但控件面板上沒有出現(xiàn)FastReport標(biāo)簽頁。原因設(shè)計(jì)期包的Register過程沒有執(zhí)行或者 IDE 的控件面板緩存沒有刷新。老版本 Delphi 有時(shí)候安裝完包之后不會(huì)立即刷新面板。解決先確認(rèn)Component→Install Packages列表里有FastReport相關(guān)的包并且勾選狀態(tài)是啟用的。然后關(guān)閉 Delphi重新打開。如果還是沒有檢查.dpk文件的Contains列表里是否有frxDesgn單元沒有的話手動(dòng)添加進(jìn)去再編譯安裝。4.3 運(yùn)行時(shí)預(yù)覽窗口一閃而過現(xiàn)象點(diǎn)擊按鈕后預(yù)覽窗口閃一下就消失了或者根本沒有出現(xiàn)。原因TfrxReport的DataSet屬性沒有設(shè)置或者數(shù)據(jù)集沒有打開。FastReport 在生成報(bào)表時(shí)如果發(fā)現(xiàn)數(shù)據(jù)集是關(guān)閉的會(huì)直接跳過數(shù)據(jù)綁定預(yù)覽窗口里沒有內(nèi)容有時(shí)候窗口會(huì)立即關(guān)閉。解決在調(diào)用ShowPreparedReport之前確保數(shù)據(jù)集已經(jīng)Open并且TfrxDBDataset的DataSet屬性指向了正確的數(shù)據(jù)集組件??梢栽诖a里加一句if not ADOQuery1.Active then ADOQuery1.Open;做保護(hù)。4.4 模板文件加載失敗現(xiàn)象LoadFromFile報(bào)錯(cuò)提示文件格式不正確或版本不兼容。原因FastReport 2.53 的模板格式是.fr3和后續(xù)版本的.frx不兼容。如果手頭的模板是從新版本導(dǎo)出的直接加載會(huì)失敗。解決確認(rèn)模板文件的擴(kuò)展名和來源版本。如果是.frx文件需要用對應(yīng)版本的 FastReport 重新導(dǎo)出為.fr3或者直接在 2.53 的設(shè)計(jì)器里重新畫一遍。老版本的模板結(jié)構(gòu)比較簡單重畫的成本通常比找轉(zhuǎn)換工具低。4.5 編譯出來的程序在其他機(jī)器上報(bào)錯(cuò)現(xiàn)象在本機(jī)編譯運(yùn)行正??降狡渌麢C(jī)器上提示缺少 DLL 或包文件。原因Delphi 的包編譯模式分兩種使用運(yùn)行期包動(dòng)態(tài)鏈接和不用運(yùn)行期包靜態(tài)鏈接。如果編譯時(shí)勾選了Build with runtime packages生成的可執(zhí)行文件依賴frxR7.bpl等包文件目標(biāo)機(jī)器上沒有這些文件就會(huì)報(bào)錯(cuò)。解決在項(xiàng)目選項(xiàng)里取消Build with runtime packages或者把對應(yīng)的.bpl文件一起拷過去。對于老項(xiàng)目的部署我一般建議靜態(tài)鏈接雖然可執(zhí)行文件大一點(diǎn)但部署時(shí)少很多麻煩。5. 從 2.53 遷移到新版本模板轉(zhuǎn)換與代碼兼容的實(shí)操技巧FastReport 2.53 能解決老項(xiàng)目的燃眉之急但如果項(xiàng)目有升級計(jì)劃遲早要面對遷移問題。從 2.53 到后續(xù)版本變化最大的兩塊是模板格式和部分類名。下面說幾個(gè)實(shí)際遷移中驗(yàn)證過的做法。5.1 模板文件的批量轉(zhuǎn)換思路2.53 的.fr3模板和后續(xù)版本的.frx模板在結(jié)構(gòu)上差異不小官方?jīng)]有提供直接的轉(zhuǎn)換工具。常見的做法是分兩步走先在 2.53 的設(shè)計(jì)器里把模板導(dǎo)出為 XML 格式如果版本支持然后用腳本把 XML 里的節(jié)點(diǎn)名映射到新版本的格式。如果版本不支持 XML 導(dǎo)出就只能在新版本的設(shè)計(jì)器里重新畫。對于模板數(shù)量不多的情況重畫其實(shí)更快。我經(jīng)手過一個(gè)項(xiàng)目大概二十張報(bào)表兩個(gè)人花了一天半重畫完比寫轉(zhuǎn)換腳本再調(diào)試的時(shí)間還短。模板數(shù)量超過五十張的時(shí)候才值得考慮寫轉(zhuǎn)換工具。5.2 代碼層面的兼容處理2.53 里的一些類名和屬性名在后續(xù)版本里改了。比如TfrxReport的ShowPreparedReport方法在新版本里仍然存在但LoadFromFile的參數(shù)格式可能有變化。更常見的是TfrxDBDataset的DataSet屬性在新版本里改成了DataSet加UserName的組合。遷移代碼時(shí)我一般會(huì)先在新版本的 IDE 里編譯一遍讓編譯器把不兼容的地方全部報(bào)出來然后逐個(gè)改。不要憑記憶改老版本的很多屬性名和現(xiàn)在看起來像但實(shí)際不一樣。編譯器的報(bào)錯(cuò)信息雖然有時(shí)候不太準(zhǔn)確但至少能定位到行。5.3 一個(gè)驗(yàn)證遷移是否成功的檢查清單遷移完成后用這幾項(xiàng)做驗(yàn)證所有報(bào)表模板都能在新版本的設(shè)計(jì)器里打開沒有格式報(bào)錯(cuò)。運(yùn)行時(shí)生成的報(bào)表數(shù)據(jù)和舊版本一致特別是分組、匯總這些邏輯。打印預(yù)覽的分頁和舊版本一致沒有多出空白頁或內(nèi)容截?cái)?。編譯后的可執(zhí)行文件在目標(biāo)機(jī)器上能正常運(yùn)行不缺少依賴文件。最后說一個(gè)習(xí)慣每次遷移完我都會(huì)把新舊兩個(gè)版本生成的報(bào)表各打印一份逐頁對比??雌饋肀康馨l(fā)現(xiàn)很多肉眼看不出來、只有打印出來才暴露的問題比如字體替換導(dǎo)致的排版偏移。從那以后我每次做版本遷移都強(qiáng)制走一遍這個(gè)對比流程希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取