ComBoBox動態清單 |
答題得分者是:herbert2
|
superrakce
一般會員 發表:24 回覆:35 積分:11 註冊:2006-10-09 發送簡訊給我 |
我想作的功能是,使用者輸入文字後,會去資料庫搜尋類似的記錄,填到combobox 的選項裡,以供選擇,加快資料輸入的效率
但是每載入完一次清單,游標就會跑到text 的最前面,造成每次輸入都要將游標移到最後面 經測試是ComboBox1.Items.Clear;影響 有什麼解決方案嗎? [code delphi] procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char); var j:integer; // i 為全域變數 ComboBox1.Items.Clear; for j:=i to i 5 do ComboBox1.Items.Add(inttostr(j)); i:=i 5; ComboBox1.DroppedDown := true; end; [/code] 原來只有這行就可以解決 ComboBox1.SelStart := length(combobox1.Text); 編輯記錄
|
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
Hello, 我不建議這樣做,因為每按一個鍵去讀資料庫一次,會是惡夢一場。
正確的做法是,改用 TEDit 或 TDBEdit,輸入文字後之後,按 Function Key(例如 F4,F5,F8,F9),或滑鼠點兩下,跳出一個查詢視窗,排序好,並用 Locate() 自動指符合的第一筆,開頭文字相同的會排在一起,按確定,或按兩下 DBGrid 就送回。 ===================引 用 superrakce 文 章=================== 我想作的功能是,使用者輸入文字後,會去資料庫搜尋類似的記錄,填到combobox 的選項裡,以供選擇,加快資料輸入的效率 但是每載入完一次清單,游標就會跑到text 的最前面,造成每次輸入都要將游標移到最後面 經測試是ComboBox1.Items.Clear;影響 有什麼解決方案嗎? [code delphi] procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char); var j:integer; // i 為全域變數 ComboBox1.Items.Clear; for j:=i to i 5 do ComboBox1.Items.Add(inttostr(j)); i:=i 5; ComboBox1.DroppedDown := true; end; [/code] 原來只有這行就可以解決 ComboBox1.SelStart := length(combobox1.Text); |
herbert2
尊榮會員 發表:58 回覆:640 積分:894 註冊:2004-04-16 發送簡訊給我 |
|
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
|
Victor4022
中階會員 發表:0 回覆:76 積分:90 註冊:2011-02-20 發送簡訊給我 |
您好, 如果資料量是維持最新/ 或常用 n 筆 (例如 10 筆), 也可以用下面方法:
1. 將 ComboBox.Style := csSimple; 2. 初始化時, 將 top n 筆資料放入 ComboBox1.Items 3. 由於 Style 已設成 csSimple, 試打幾個字看看, 比對上的會自動帶入 4. 視您的需求, 將使用者目前輸入的資料 4.1 如果資料不存在, Insert 至第 1 筆 4.2 如果資料存在, 則不異動資料庫 當然, 不一定要限用最新 n 筆情形, 您可以任意變化資料內容的新舊順序, 我的使用經驗通常只保留"最後被使用的 top 10" |
superrakce
一般會員 發表:24 回覆:35 積分:11 註冊:2006-10-09 發送簡訊給我 |
「最後被使用的 top 10]」 <-這東西是記錄在資料庫裡嗎?(新增一個資料表記專門記錄這東西)
還是其它方法? 短短一行幾個字,感覺很奧妙 ===================引 用 Victor4022 文 章=================== 您好, 如果資料量是維持最新/ 或常用n 筆 (例如 10 筆), 也可以用下面方法: 1. 將 ComboBox.Style := csSimple; 2. 初始化時, 將 top n 筆資料放入 ComboBox1.Items 3. 由於 Style 已設成 csSimple, 試打幾個字看看, 比對上的會自動帶入 4. 視您的需求, 將使用者目前輸入的資料 4.1 如果資料不存在, Insert 至第 1 筆 4.2 如果資料存在,則不異動資料庫 當然, 不一定要限用最新 n 筆情形, 您可以任意變化資料內容的新舊順序, 我的使用經驗通常只保留"最後被使用的 top 10" |
Victor4022
中階會員 發表:0 回覆:76 積分:90 註冊:2011-02-20 發送簡訊給我 |
抱歉,小弟未說明清楚!
這邊指的是任意的常用資料,例如: 假設某公司使用的帳號系統(ex: Windows AD)內含有5000 個 account 與 5000 個 group 分散在 5000個 OU內, 這種大 site 類型的 AD Tree 展開會很驚人, MIS 想在 AD Tree 裡面尋找指定的account 可能會非常費時, 此時,如果我們提供的 Application 有提供"搜尋使用者"功能,就可以進行底下的設計: 設計A. 每次進入搜尋使用者對話框時,自動載入前次最新查詢 10 次的使用者關鍵字清單。 設計B. 每次離開該對話框時,將本次搜尋的關鍵字加入清單,並將清單儲存起來。 記錄的方式不外乎: 1. 寫入資料庫 2. 本地端寫入至 .ini內或自訂的檔案格式內(例如 %temp%\search_history.ini) 在設計A 與 設計B 的查詢對話框場景,就適合放入 ComboBox 讓使用者 keyin 或挑選(例如最多 10 筆)。 雖然上述假設資料庫內已知有 5000 筆使用者帳號, 但如果您想要,也可以將其加入 ComboBox 內,如果考量處理效能, 不確定您是透過何種 VCL 進行資料庫存取,小弟習慣是使用 TADOQuery, 小弟的使用經驗是不要直接使用 TADOQuery.FieldByName(field name).AsXXX 之類的方式從 TADOQuery 讀出資料, 會建議使用 TADOQuery.Recordest 進行資料操作,7萬筆的資料處理速度是 12 秒 vs 0.5秒的差距。 小弟工作上開發的產品,使用者通常是管理者/MIS 或文管人員,一般企業組織內部使用產品的人也佔少數, 在沒效能瓶頸與 Database engine throughput 壓力下,通常一次載入數百筆或數千筆資料到 ComboBox 並不算奢侈, 除非您的產品是兩岸三地用有頻寬考量。 希望這麼解說有比較清楚,但可能也不適合您的需求,僅供您參考:) ===================引 用 superrakce 文 章=================== 「最後被使用的 top 10]」 <-這東西是記錄在資料庫裡嗎?(新增一個資料表記專門記錄這東西) 還是其它方法? 短短一行幾個字,感覺很奧妙 |
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
Victor 大,請教一下,不直接用 FieldByName(...).As..,改用 RecordSet 的話,效率的提昇是指資料讀取還是迴圈處理?看起來應該不是資料讀取,迴圈處理的速度提昇比較有可能。用 RecordSet 怎麼取出特定欄位內容?
一直都有一個未解問題,客戶要求在 DBGrid 打資料時,離開某個欄位 OnCellExit 後,馬上要檢查有沒有重複輸入相同的內容,有的話要馬上 ShowMessage() 提示,例如打到第十筆,OnCellExit 中用迴圈,從第一筆開始比對到第九筆,看有沒有跟第十筆有重複內容,因為 DataSet 還沒有存至資料庫,不能用 select 指令來檢查,這個時候只能 DataSet.DisableControls, 迴圈檢查,DataSet.EnableControls,但我覺得打字的過程中移動 DataSet 的 Record 指標不是一種好的寫作方式,如果能有另一種內部迴圈處理可以不用動到 Record 指標,那是最好不過的,而速度一定會比較快。 |
Victor4022
中階會員 發表:0 回覆:76 積分:90 註冊:2011-02-20 發送簡訊給我 |
您好:)
其實操作 RecordSet 跟操作 TADOxxx.FieldByName一樣, VCL 實作中最後也是呼叫 OLE COM 裡面的 interface, 雖然 FieldByName(...) As... 雖然方便使用, 但是資料量一大, 欄位數一多, 效能就變的比較糟糕, 因為 FieldByName 至少要以下動作: 1. 將輸入的 Field Name 從所有 TFields 中由第一筆找出最後一筆 -> 假設我們的 T-SQL query 出來 100 個欄位, 使用 FieldByName(...) As... 的欄位剛好又是第100筆的話, DataSet 假設有1000筆資料, 那麼這段 FieldByName(最後一個欄位).As.... 會被執行 1000 * 100次. 2. FieldByName(...) As... 是操作 OleVariant 進行轉型, 同樣以上為例, 1000 筆資料就轉型 1000 次(視資料型別而定) . 由於 T-SQL query 能經由設計師控制, 回傳資料型別也能自己控制, 所以後期手上維護的產品, 大概都是秉持這方向 (操作 RecordSet, 自己將 Variant 轉型適當資料並取出使用), 效能比使用 VCL 封裝好的存取方式快很多 不過, 您提到的DBGrid.OnCellExit 要檢查當前 DataSet 有無重覆, 小弟想到2作法: 1. 如您所說的, 先DisableControls 再迴圈檢查 -> 此處目前已知的有2種處理方式, FieldByName(..) As... 或直接操作 Recordest 2. 使用一 TStringList, 設定 Sorted 為 True, 每當DBGrid.OnCellExit 就先使用 TStringList.Find 進行 Binary search, 若: a. 使用者輸入資料不在 TStringList 內則將該字串 Add 進去(此時由於 Sorted property 為 True 會自動排序) b. 存在則 ShowMessage(); 最後, 小弟不知道是否有內部迴圈可以處理您的問題, 但是如果資料未 commit 又想檢查 DataSet 內的資料, 可以考慮上面作法之外, 另外一個就是一次存取 2個 DataSet, 一個是與 DBGrid 連結用, 另一個專門檢查用, 這樣就不用管 DBGrid 目前使用者操作狀態, 也不用檢查完後再跳回使用者輸入的該筆位置. 副作用是浪費一塊記憶體 :P 希望對您有幫忙:) ===================引 用 cancer 文 章=================== Victor 大,請教一下,不直接用 FieldByName(...).As..,改用 RecordSet 的話,效率的提昇是指資料讀取還是迴圈處理?看起來應該不是資料讀取,迴圈處理的速度提昇比較有可能。用 RecordSet 怎麼取出特定欄位內容? 一直都有一個未解問題,客戶要求在 DBGrid 打資料時,離開某個欄位 OnCellExit 後,馬上要檢查有沒有重複輸入相同的內容,有的話要馬上 ShowMessage() 提示,例如打到第十筆,OnCellExit 中用迴圈,從第一筆開始比對到第九筆,看有沒有跟第十筆有重複內容,因為 DataSet 還沒有存至資料庫,不能用 select 指令來檢查,這個時候只能 DataSet.DisableControls, 迴圈檢查,DataSet.EnableControls,但我覺得打字的過程中移動 DataSet 的 Record 指標不是一種好的寫作方式,如果能有另一種內部迴圈處理可以不用動到 Record 指標,那是最好不過的,而速度一定會比較快。 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |