與常見問題排查)
簡介EhLib 11.0.21 - D12是一套專為Delphi 12開發(fā)者調(diào)優(yōu)的高性能VCL界面控件庫聚焦數(shù)據(jù)網(wǎng)格、多類型圖表、數(shù)據(jù)庫綁定、打印與導(dǎo)出等高頻需求適合快速構(gòu)建報表系統(tǒng)、MIS管理界面和數(shù)據(jù)密集型桌面應(yīng)用??丶С衷O(shè)計期高度定制可調(diào)整網(wǎng)格行列、圖表配色與報表布局運行時提供排序、過濾、分頁、批量導(dǎo)出等交互能力減少重復(fù)開發(fā)工作量。資源包共收錄2000個文件壓縮包大小67.79MB文件類型覆蓋519個dfm窗體布局、293個pas核心源碼、196個dproj工程定義、170個dpk包描述以及chm幫助、docx文檔、ico圖標、png圖片等素材既可直接安裝組件也可對照示例代碼與幫助文檔快速上手。目前已有1407人學(xué)習(xí)下載適合有一定Delphi基礎(chǔ)、希望減少界面開發(fā)量并提升用戶體驗的開發(fā)者在實際項目中直接復(fù)用。 老Delphi玩家的工具箱里控件庫這東西從來不是“裝上一個包然后一直用到老”那么簡單。尤其是做數(shù)據(jù)庫應(yīng)用的人提到第三方表格控件幾乎繞不開EhLib這個名字。前陣子我把項目遷到RAD Studio 12上第一件事就是把EhLib升到11.0.21這個專門標注D12兼容的版本中間踩了不少坑也把安裝順序、路徑配置、運行期報錯都摸了一遍。這篇文章就當一份安裝與實戰(zhàn)備忘給正準備升級IDE、或者還在糾結(jié)要不要用第三方網(wǎng)格控件的朋友做個參考。1. 為什么在Delphi 12還值得配置EhLib1.1 原生DBGrid做不到的那些事Delphi自帶的TDBGrid夠輕夠快但真到做業(yè)務(wù)系統(tǒng)時你會很快發(fā)現(xiàn)它太“素”了。客戶要的表格通常長這樣點列頭能下拉篩選、底部有合計行、某些列是關(guān)聯(lián)下拉選擇、導(dǎo)出成Excel時不能亂碼甚至還要多行表頭、單元格合并、分組統(tǒng)計。這些東西用原生DBGrid做不是說做不出來而是要自己寫一堆事件、畫布繪制和臨時組件維護成本極高。EhLib 11.0.21給VCL開發(fā)者提供的就是一套開箱即用的解決方案。它的核心組件TDBGridEh在原生網(wǎng)格基礎(chǔ)上做了大量增強自動篩選行、字段匯總腳、多級表頭、下拉過濾、排序指示、樹形結(jié)構(gòu)展示、導(dǎo)入導(dǎo)出接口全都有。換句話說它把Excel里常用的那些表格交互搬進了Delphi而且是純VCL組件不額外引入重框架這對老項目遷移特別友好。1.2 版本號里的門道為什么認準D12EhLib的版本號和Delphi版本綁定得很緊。11.0.21這個版本標的D12意思是官方已經(jīng)針對RAD Studio 12的RTL、編譯器特性和包格式做過適配。這里有個容易踩的坑拿舊版EhLib硬裝到新IDE上雖然解壓、加路徑都順利但編譯時往往直接報“Unit not found”或者一連串的HPPEMIT錯誤。為什么第三方控件必須跟著IDE版本走因為Delphi的RTL頭文件、System單元、Winapi聲明在不同版本間有差異控件源碼如果調(diào)用了被廢棄的API或者引用了舊的結(jié)構(gòu)體在新編譯器下就過不去。EhLib這種大型控件庫內(nèi)部對Windows API的封裝很多官方不做適配自己改起來非常痛苦。所以我個人的建議是既然官方打了D12的適配包就老老實實用11.0.21別為了“省事”沿用老版本。1.3 安裝成本其實不高但順序錯了很折騰很多人一聽第三方控件就頭大覺得要改一堆環(huán)境變量、編譯半天。實際上EhLib 11.0.21安裝不復(fù)雜核心就三步解壓源碼包、編譯運行時包、安裝設(shè)計時包。真正煩人的是順序問題——先裝哪個包、后裝哪個包、路徑加不加對直接影響后續(xù)使用體驗。我把安裝前后需要確認的事項整理成了表格照著檢查一遍基本不會翻車階段要確認的事項安裝前IDE已關(guān)閉舊版EhLib路徑已從Library路徑移除項目源碼有備份安裝中運行時包先編譯設(shè)計時包后InstallWin32和Win64都Build安裝后組件面板出現(xiàn)EhLib頁簽Library路徑優(yōu)先級正確新建項目拖一個TDBGridEh測試2. 上手安裝從解壓到組件面板出現(xiàn)2.1 環(huán)境準備與備份開始前先把RAD Studio 12完全關(guān)掉一個實例都不要留。接著建議把當前項目里所有引用EhLib舊版本的搜索路徑刪干凈否則后面編譯新項目時編譯器可能優(yōu)先找到舊目錄里的DCU產(chǎn)生一堆莫名其妙的類型不匹配。然后是備份。因為EhLib類組件分布在很多單元里萬一你項目里同時用了舊版升級后可能會出現(xiàn)屬性變化、方法簽名不同這類問題。我曾經(jīng)因為沒有備份升級后有個自定義排序事件編譯不過改了半天才想起來OldGrid是舊版專屬寫法。所以別嫌麻煩先把整個項目目錄壓縮一份放旁邊出問題能隨時回退。源碼解壓路徑也有講究。建議放到一個純英文、無空格的固定目錄下比如D:\Components\EhLib。放在包含空格或中文的路徑里雖然現(xiàn)代IDE大多能處理但個別第三方構(gòu)建工具、腳本會在路徑解析上出幺蛾子。我見過一個同行把控件裝到桌面結(jié)果每次打開項目都要重新查找源文件就是因為路徑里帶著特殊字符。2.2 包編譯的正確順序EhLib 11.0.21安裝包里通常會配套好按Delphi版本區(qū)分的子目錄進入對應(yīng)D12的目錄后你會看到兩類包一類是運行時包不帶設(shè)計時注冊邏輯一類是設(shè)計時包帶Dcl前綴或者Install標識。我的編譯習(xí)慣是這樣的先打開運行時包項目在Project Manager里切到Win32平臺執(zhí)行Build。注意是Build不是CompileBuild會把所有引用的源碼重新編譯一遍確保當前IDE環(huán)境下的DCU是最新的。然后再切到Win64平臺同樣Build一次。之后打開設(shè)計時包右鍵執(zhí)行Install。順序為什么不能反因為設(shè)計時包要引用運行時包導(dǎo)出的符號。如果運行時包還沒編譯好Install時就會報“Cant load package”或者找不到類名更奇怪的是組件面板上可能會顯示一個灰色不可用的條目。最穩(wěn)妥的辦法就是嚴格執(zhí)行先運行時后設(shè)計時。2.3 路徑配置這步別偷懶很多人在這一步偷懶結(jié)果新建項目時從組件面板拖控件沒問題一編譯就報找不到單元“DBGridEh.pas”。這是因為拖控件時IDE加載的是BPL包里已經(jīng)編譯好的類但項目編譯時需要根據(jù)源文件重新定位這些單元。所以必須在Tools Options Language Delphi Library Library paths里把EhLib的關(guān)鍵源碼目錄加進去具體包括Common目錄、DBGridEh目錄這類包含核心單元的文件路徑。這里我強烈建議用環(huán)境變量或IDE別名的方式配置路徑而不是寫死絕對路徑。比如設(shè)置一個EHLIB_ROOT環(huán)境變量然后路徑寫成%EHLIB_ROOT%\Common。這樣以后換目錄或者升級版本只需要改環(huán)境變量不用全局搜索替換。2.4 64位項目的附加操作Delphi 12默認支持64位編譯但很多人在裝了控件后會發(fā)現(xiàn)32位編譯正常切換Win64后直接編譯失敗。原因很簡單控件的運行時包沒有編譯64位版本。雖然設(shè)計時組件是在32位IDE里運行的但你的程序在64位平臺下需要對應(yīng)64位的DCU和BPL。解決辦法就是上面說的在包項目里切到Win64平臺重新Build一遍。有的人為了方便直接讓項目只編譯32位眼不見心不煩。但現(xiàn)代業(yè)務(wù)系統(tǒng)連接第三方庫、調(diào)用系統(tǒng)API64位幾乎是大勢所趨。所以建議從安裝起就把兩個平臺都編譯好省得以后項目切平臺時被控件卡住。3. 高頻使用場景與細節(jié)拆解3.1 自動篩選讓表格自帶Excel式過濾TDBGridEh最吸引人的功能之一就是自動篩選。開啟方式很簡單在設(shè)計期把OptionsEh屬性中加上dghAutoFilterRow或者運行時通過代碼操作DBGridEh1.OptionsEh : DBGridEh1.OptionsEh [dghAutoFilterRow];開啟后表格列頭下方會出現(xiàn)一個篩選行用戶可以按鍵值精確篩選也可以通過下拉列表選擇唯一值。對于帶日期的列還能配置成區(qū)間篩選配合STFilter相關(guān)屬性體驗非常接近Excel。但這里有個坑必須提醒EhLib的自動篩選默認是基于當前數(shù)據(jù)集的過濾機制。如果數(shù)據(jù)庫端已經(jīng)有大量數(shù)據(jù)被加載到客戶端篩選時會有明顯卡頓。所以做篩選設(shè)計時最好提前在SQL層把范圍縮小或者只在必要時啟用自動篩選別每個窗體都無腦打開。3.2 多表頭、匯總行與下拉列表業(yè)務(wù)系統(tǒng)里經(jīng)常需要“產(chǎn)品名稱”、“產(chǎn)品編號”這類分組表頭。原生TDBGrid實現(xiàn)起來要重繪而TDBGridEh直接支持父子列結(jié)構(gòu)。在設(shè)計器里右鍵Columns創(chuàng)建父列后把子列拖到父列下方即可。父列作為分組標題子列綁定字段運行時還能和普通列一樣排序篩選。匯總行是我覺得最實用的功能之一。把DBGridEh1.FooterRowCount設(shè)為1然后找到對應(yīng)列的Footer屬性設(shè)置ValueType為fvtSum、fvtCount、fvtAvg底部就會自動顯示統(tǒng)計值。這一步操作比在SQL里寫ROLLUP靈活尤其是需要同時顯示明細和統(tǒng)計的時候。下拉列表對應(yīng)的是列屬性里的PickList或LookupParams。PickList適合靜態(tài)選項比如“啟用/禁用”LookupParams適合關(guān)聯(lián)主表比如從部門表中選擇部門名稱顯示名稱同時可以把部門ID回寫到字段里。這在錄入界面里非常常用等于給表格加了數(shù)據(jù)驗證避免臟數(shù)據(jù)。3.3 導(dǎo)出Excel時的中文和格式坑導(dǎo)出Excel是項目里無法回避的需求。EhLib 11.x在這塊做得很成熟TDBGridEh自帶SaveToXLSX方法一行代碼就能生成真正的xlsx文件不再依賴OLE和Excel進程DBGridEh1.SaveToXLSX(D:\temp\員工列表.xlsx);老版本里常用的TDBGridEhExportToExcel方式還可以用但新方法更簡潔而且不會出現(xiàn)“電腦沒裝Excel就導(dǎo)出失敗”的問題。不過導(dǎo)出Excel時有兩個細節(jié)要留意。第一個是中文文件名和內(nèi)容亂碼。雖然新版的XLSX格式默認走UTF-8基本不會亂碼但如果你在舊項目里沿用老導(dǎo)出組件一定要檢查字符集設(shè)置。第二個是格式。ExportExportExcel默認導(dǎo)出的格式是比較樸素的不會帶上你在網(wǎng)格里設(shè)置的列寬、字體和背景色。所以我的經(jīng)驗是先通過代碼臨時設(shè)置列寬和標題樣式導(dǎo)出完成后再還原或者在導(dǎo)出對象上設(shè)置對應(yīng)的樣式屬性。3.4 大數(shù)據(jù)量下的兩種優(yōu)化思路很多團隊在數(shù)據(jù)量上來之后抱怨EhLib卡其實網(wǎng)格渲染本身并不慢瓶頸多半在數(shù)據(jù)加載和篩選邏輯上。這里分享兩個思路。第一種是用VirtualMode。如果數(shù)據(jù)不需要編輯只是展示可以直接開啟VirtualMode配合OnGetCellParams等事件按需提供數(shù)據(jù)。這樣網(wǎng)格不會一次性創(chuàng)建大量行數(shù)據(jù)內(nèi)存占用顯著下降。第二種是使用SearchPanel替代自動篩選。SearchPanel是EhLib提供的搜索面板通過輸入關(guān)鍵詞快速定位不會觸發(fā)數(shù)據(jù)集全量掃描比自動篩選在大數(shù)據(jù)量下表現(xiàn)更好。實測下來幾十萬行的場景普通方式加載可能要兩三秒而用VirtualMode配合分頁查詢首屏呈現(xiàn)幾乎無感知。當然這兩個方案都需要調(diào)整數(shù)據(jù)獲取方式不是純靠控件一個屬性就能解決。4. 報錯實錄我踩過的坑和排查方法4.1 cannot perform this operation on an open dataset這個報錯我在論壇上見過無數(shù)次自己也踩過。它本身是數(shù)據(jù)集組件報的但經(jīng)常在EhLib相關(guān)窗體里出現(xiàn)原因是數(shù)據(jù)集已經(jīng)打開卻又執(zhí)行了Open操作。最常見的場景設(shè)計期在數(shù)據(jù)模塊里把FDQuery或ADOQuery的Active設(shè)為True然后在FormShow里又寫了一次Query.Open。設(shè)計期數(shù)據(jù)集已經(jīng)處于打開狀態(tài)運行時代碼再Open一次就會觸發(fā)這個異常。排查方法很簡單全局搜索.Open關(guān)鍵字逐個檢查是否有重復(fù)打開再看數(shù)據(jù)模塊里所有數(shù)據(jù)集的Active屬性運行期的打開操作統(tǒng)一交給代碼。如果確實需要重復(fù)執(zhí)行某個查詢先判斷狀態(tài)if not FDQuery1.Active then FDQuery1.Open;這個錯誤和EhLib本身關(guān)系不大但當頁面里有多個DbAware控件時數(shù)據(jù)集狀態(tài)變化連鎖觸發(fā)網(wǎng)格重繪報錯時機看起來就特別像控件問題。4.2 無效的授權(quán)說明這個問題大多出現(xiàn)在使用非官方渠道下載、或者從舊版機械復(fù)制文件到新環(huán)境的場景。表現(xiàn)是編譯時提示授權(quán)無效或者運行時控件進入演示模式功能受限。處理思路一般分三步第一步徹底清理舊版殘留包括項目搜索路徑、IDE Packages列表和BPL、DCP文件。第二步重新從官方完整包解壓安裝時確認使用的是對應(yīng)D12的目錄。第三步核對License文件是否存在于正確位置以及環(huán)境變量里有沒有指向舊版授權(quán)目錄的配置。這里要多說一句正規(guī)商業(yè)授權(quán)在官網(wǎng)購買后下載到的安裝包里已經(jīng)包含有效許可不需要額外破解。遇到授權(quán)問題優(yōu)先檢查自己的路徑和殘留不要繞過正規(guī)渠道。4.3 安裝了但組件面板找不到安裝過程沒報錯但打開組件面板就是看不到EhLib頁簽。出現(xiàn)這種情況先別急著重裝。首先確認設(shè)計時包真的Install成功在Component Install Packages里能查到并且勾選狀態(tài)正常。然后關(guān)閉IDE刪除AppData下對應(yīng)版本的IDE緩存目錄重啟后再看。如果還是沒有檢查是否裝到了錯誤的平臺比如IDE以管理員權(quán)限運行時組件的用戶級路徑和系統(tǒng)級路徑不一致。還有一個容易被忽略的點如果電腦上裝有多個Delphi版本安裝包默認路徑可能指向了舊版本目錄導(dǎo)致新IDE沒加載到。安裝時留意路徑選擇別讓它默認到上一個Delphi版本的組件庫里。4.4 編譯報錯與版本混用錯誤提示類似“E2201 Need imported data”或者“Unit was compiled with a different version of...”十有八九是DCU和當前IDE版本不匹配。這通常是因為Library path里殘留了舊EhLib目錄編譯器優(yōu)先索引了舊DCU。解決辦法是把新增的EhLib源碼目錄放在Library路徑列表的前面同時刪除舊目錄引用。項目級別的Search Path也要檢查一遍有些老項目會在DPR里寫死絕對路徑這個最容易漏。我的做法是全局搜索項目中所有包含“EhLib”字樣的路徑逐項確認版本確保整個項目只引用一套控件源碼。5. 一點個人心得在我最近的項目里最滿意的組合是FDQuery關(guān)聯(lián)TDBGridEh打開自動篩選配上Footer合計和SaveToXLSX導(dǎo)出。這套搭配在錄入、查詢、統(tǒng)計、導(dǎo)出幾個核心場景都不需要額外造輪子業(yè)務(wù)代碼可以專注于數(shù)據(jù)邏輯而不是表格交互細節(jié)。最后順便分享一個小習(xí)慣如果是長期維護的項目建議把TDBGridEh封裝到一個基礎(chǔ)Frame里公共屬性統(tǒng)一在Frame初始化時設(shè)置。比如自動篩選、匯總行這些默認開啟個別頁面再按需調(diào)整。這樣做能減少重復(fù)配置也能避免不同窗體之間表格行為不一致后面對接新需求時改一處就能全局生效。本文還有配套的精品資源點擊獲取