|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Список фильтруется по мере ввода данных. Удобно использовать на более менее длинных списках. Класс взят как есть из рабочего проекта. Делалось под свои задачи, но пока особых проблем за ним не замечал. Последний раз дорабатывалось когда понадобилось расширить функционал на простые списки. Во время написания поста нашел похожую тему: https://www.sql.ru/forum/277809/filtraciya-combobox-po-mere-vneseniya-dannyh-ado?mid=2510813#2510813 В общем,- может кому пригодится и моя поделка на эту тему.. Конструктивная критика приветствуется. Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 12:38 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Пример использования во вложении. Не заметил - в классе в качестве SQL инструкций используются имена констант из глобального модуля. В принципе несложно заменить. В образце приложил модуль с соотв константами. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 13:09 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRus, вы бы хоть написали, чем ваше решение на 100 строчек лучше, чем на 10 строчек в похожей теме. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 14:03 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRus, я так понял что Вы хотите осуществлять поиск Может так?(значительно проще) ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 14:05 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Не ставил себе задачу сравнивать. Сделал - решил что удобно (сейчас втыкаю везде где использую подходящие списки) - решил поделиться. Потом увидел другое решение на эту тему - дал ссылку. Но на вскидку - потенциально - большей универсальностью. - не проверял смежное, но это должно лучше вести себя при входе выходе из поля - возможностью работы со списками заданными строкой с разделителями - инициализация для последующего полноценного использования с любым комбобоксом - одной строчкой. но да - более громоздко, возможно больше памяти (для списка например создается дополнительный массив, хотя с другой стороны я не храню в классе запрос, а работаю с его текстом), ну, - пожалуй - медленнее. Есть кривизна с выходом по табу когда выбор еще не завершен. Обновил пример: + добавил в пример комбу с простым списком с разделителями. - поправил ошибку во вспомогательном модуле не имеющем отношения к основному классу (при бэкапе исходников, при отсутствии папки SRC вылетала ошибка). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 14:49 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
sdku, Посмотрел - проще, - но не всегда удобнее. У меня в оригинальной задаче может быть много очень похожих вариантов выбора, а вспомогательных данных которые надо выводить после выбора много поэтому селектор нужен во-первых компактный, а во-вторых чтобы список вариантов можно было охватить глазом - когда список сокращается пользователю понятней какой именно ему нужен. Ну и у меня поиск по подстроке Например длинные ничего не говорящие вещи в начале текста типа "Оббщество с ограниченной ответственностью.." не мешают быстро находить нужное по значимой части текста. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 14:56 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRus, можете сделать форму, по которой ищите, ленточной (в ней поместится столько же записей сколько и в списке, без прокрутки) ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 17:57 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
sdku, вы не поняли - я не прошу совета как сделать. когда мне удобнее ленточную форму я делаю ленточную форму или табличную или поле поиска или разделенную форму или еще что-нибудь. я предложил решение именно для фильтрующегося комбобокса и только его готов здесь обсуждать. если оно вам удобно - пользуйтесь пожалуйста, если у вас есть идеи по развитию - буду благодарен если для ваших задач удобнее что-то другое - это просто значит что это решение вам не пригодилось. И - спасибо за советы. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2019, 18:24 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Изменения в основном модуле: - добавил задержку перед применением фильтра, чтобы дать пользователю возможность завершить ввод. Ранее фильтр ставился сразу после ввода очередного символа. Сейчас перед применением фильтра производится проверка сколько прошло с момента ввода последнего символа и если время превышает пороговое - применяется фильтр списка. Это необходимо для уменьшения тормозов на действительно больших списках. Cпособ имитации события таймера отсюда: https://excelvba.ru/code/timer/htmlfile Наверняка есть решение лучше, но пока и это выглядит вполне удовлетворительным. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.05.2019, 14:45 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Идея с задержкой обработки ввода себя не оправдала. Сама по себе идея правильная, но реализация оказалась крайне неудачная. Периодически происходит отваливание объекта mCombo в классе что приводит к полной неработоспособности решения и необходимости переинициализации контрола. События таймера в классе продолжают срабатывать, но из-за потери объекта, получить данные фильтра и передать на обработку становится невозможным. Место и причину отваливания пока отловить не удалось. Поэтому от этого решения пришлось отказаться и вернуться прямой фильтрации после ввода каждого символа. Если у кого есть предложения по организации задержки обработки ввода был бы признателен. Текущая версия класса во вложении. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2019, 11:00 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRus, отказался от этой порнографии "поля со списком" в плане поиска. делаю 1-й список из 1-х букв (на самом деле 2 - 1-с кириллицей, 2-й с латиницей, но сути это не меняет) и 1/2 списка подчиненных - не надо искать клаву при поиске, все быстро. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2019, 11:25 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Еще несколько правок - некорректно обрабатывались изменения в поле, в частности в результате изменения поля при перемещении по списку стрелками ... |
|||
:
Нравится:
Не нравится:
|
|||
06.06.2019, 14:07 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRusСписок фильтруется по мере ввода данных....добавил в [таблицу].[поле0] записи:"абв","авб" и "вгд" -открываю форму "главная" -ввожу в Combo символ "а" (предлагается вариант "абв"),раскрываю список и вижу в нем ВСЕ значения из таблицы с выделенным значением "абв",аналогично если введу символ "в",выделенное значение "вгд"-стандартное поведение поляСоСписком -стесняюсь спросить:что же делает Ваш код-его назначение и зачем пытаться (причем неудачно) изобретать велосипед? (штатное поведение Combo сделано вполне нормально,а сокращение значений в списке достигается использованием зависимых Combo) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.06.2019, 15:25 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
sdku, напрасно стесняетесь - если бы вы не спросили - я, вероятно, не скоро бы обратил бы внимание на эту особенность. В реальной задаче, где я его использую элементы списка у меня начинаются с цифрового кода, а потом уже идет текстовой идентификатор. поэтому у меня он выглядит как корректно работающий и при вводе сначала (по коду) и по текстовой подстроке. Это искусственное ограничение введенное в строке 178 модуля clsAutoFilteredCombo (v.1.2.4) для исключения срабатывания фильтрации при перемещении в открытом списке стрелками. благодаря тому что вы обратили мое внимание на некорректное поведение фильтра я, вероятно, пересмотрю это условие (но позже, - пока ему надо работать). так что реально - Спасибо! и в ответ на ваши вопросы: - класс делает ровно то для чего предназначен - выполняет автофильтрацию списка при вводе. это было бы заметно если в вашем случае вы начали ввод не с "а" (сработал встроенный автовыбор комбы и условие в строке 178 не дало отфильтровать список по автоматически предложенному списком комбы содержимому поля - полной строке "абв"), а попытались бы начать с "б" (встроенный автовыбор комбобокса по первым символам не сработал - содержимое поля не совпадает с элементом списка, условие 178 не срабатывает, - фильтрация списка происходит). удаление данного условия устранит напрягший вас эффект, но создаст большее неудобство при срабатывании автовыбора списка. поэтому думаю строки 178-181 надо пересмотреть. до этого были попытки SelStart SelLength брать только введенный кусок без предложенного автовыбором "хвоста", но там будет беда если вы попытаетесь корректировать введенное (SelStart будет не в конце) это условие мне показалось более удачным. - велосипед по моему следует изобретать хотя бы для того чтобы понять как он работает и научиться создавать свои (если получится - даже лучше.)) в данном случае это попытка сделать сокращающийся список по подобию адресных строк в браузерах. в моей задаче мне это реально уменьшает количество необходимых манипуляций для выбора необходимой записи примерно на 1,5-2 секунды на запись - при массовом вводе это много. ПыСы - позже подумаю как корректно переписать условие. Еще раз спасибо за замечание. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.06.2019, 21:30 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Кстати, - по горячим следам, пока свежа мысль: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
такое условие должно устранить эту проблему. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.06.2019, 22:36 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRus, Trim удаляет пробелы в начале и в конце СТРОКИ (RowSourse всегда был набором) и чему, по Вашему, должно равняться? Код: vbnet 1.
(это одно,далеко не единственное, "интересное" место Вашего кода) ... |
|||
:
Нравится:
Не нравится:
|
|||
07.06.2019, 10:49 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
sdkuRowSourse всегда был наборомой! ... |
|||
:
Нравится:
Не нравится:
|
|||
07.06.2019, 10:56 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
sdku, не уверен что понял что вы имели ввиду - RowSource м.б. текстом SQL запроса или именем таблицы/запроса при RowSourceType="Table/Query", либо списком значений с разделителями при RowSourceType="Value List", "Field List" пользоваться не приходилось - там не знаю. Я не в курсе как Acc обрабатывает передаваемую RowSource строку, - может это и не нужно, но привычка - пуще неволи, а я привык обрезать строки от мусора. Не вижу почему это неверно - максимум избыточно. Интересные места это хорошо)) Если что-то вызывает у вас сомнения - спрашивайте: смогу - поясню, если окажется косяк - подумаю как исправить - затем и выложил) ... |
|||
:
Нравится:
Не нравится:
|
|||
07.06.2019, 12:25 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
iKaRusСписок фильтруется по мере ввода данных.... А этот пример не делает это? Код: vbnet 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
07.06.2019, 13:56 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
sdku, примерно с такого оно когда-то и начиналось), только я бы добавил в маску ещё одну звёздочку - перед введённым текстом. а дальше начинаются улучшалочки для сокращения колчества движений: при выходе из поля надо что-бы выбралось первое отфильтрованное (если нет прямого выбора в списке), при входе в поле надо выделить все введенное чтобы при новом вводе текст замещал старый а не дополнял его и т.п. потом выясняется что при перемещении по списку срабатывает Change и прочие подобные мелочи и начинаются костыли и разрастание кода.. Как выяснилось последняя версия условия тоже не всегда ведет себя адекватно - иногда ListIndex выдает значение не соответствующее автоматически выбранному в поле что вызывает неправильное поведение фильтра. Надо искать дальше, - но по большому счёту это мелочь - здесь хоть понятно куда копать - на самом деле, в контексте задачи, меня больше интересует как получше организовать задержку применения фильтра после ввода. Способ который я пытался приспсообить к случаю (создание внешнего таймера в HTML объекте) ведет себя не стабильно. Иногда (редко, но непонятно) отваливается объектная переменная в классе, иногда - выдает ошибку скрипта (было один раз). ... |
|||
:
Нравится:
Не нравится:
|
|||
07.06.2019, 17:30 |
|
Автофильтрующийся комбобокс
|
|||
---|---|---|---|
#18+
Update. ввиду продолжающегося на ходу отлова и исправления багов выглядит несколько сумбурно (уже требует зачистки от лишнего кода и устаревших комментариев), но вполне работоспособно. Тестировался преимущественно на списках с RowSourceType="Table/Query" заданных через RecordSource. текущий текст модуля под спойлером clsAutoFilteredCombo Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391. 392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419. 420. 421. 422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433. 434. 435. 436. 437. 438. 439. 440. 441. 442. 443. 444. 445. 446. 447. 448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460. 461. 462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475. 476. 477.
Попытался исправить известные мне ошибки связанные со срывом выбора в списке. Выяснилось следующее: ListIndex, который я использовал для идентификации выбранного в списке значения, после применения фильтра (замены источника списка) остается прежним, в то время как остальные параметры списка в т.ч. ListCount меняются. т.о. получается что в поле, как бы выбрано нужное значение (.Text после применения сохранилось), список сократился, искомый элемент в списке по фильтру отобран, но - индекс выбора (ListIndex) указывает на позицию, которую этот элемент занимал в списке ДО применения фильтра, т.е. он может соответствовать/не соответствовать или вообще выходить за границы списка. Отсюда естественно возникала ошибка. Не знаю чего я от него ожидал - вероятно просто ситуация, что раз в text выбор сохранился, то и в списке тоже должен мне показалась само собой разумеющейся, хотя если подумать - логичным поведением Combobox в подобной ситуации д.б. сброс индекса (например в 0 или -1) поскольку фактически изменен источник данных. тем не менее исходим из того что есть. Поскольку проблема в неправильном индексе несоответствующем текущему выбору сходу видны три возможных варианта устранения проблемы: 1. в лоб - просмотреть список и найти значение соответствующее правильному выбору и вернуть его (плюсы - простота, минусы - полный перебор списка) 2. вариант предыдущего. тоже, но поиск осуществлять не в списке, а в источнике списка (плюсы - относительная простота, минусы - придется создавать объект - запрос соотв тексту источника и производить поиск в нем - показалось лишним так как запрос уже был однажды вызван - когда мы подменили источник и если он содержит сложные формулы то работа с ним может оказаться заметно медленнее чем работа с уже годовым списком полученным из этого запроса). отказался т.к. нет очевидных преимуществ. 3. доверить выбор нужного значения встроенному автовыбору Combы сымитировав ввод значения (плюсы - поиск перекладывается на встроенные алгоритмы Combы, а значит он будет наверняка быстрее тупого перебора, минусы - здесь чтобы не нарваться на каскад событий Change придется заметно усложнять код (возможно ввести флаг для пропуска основного обработчика при искусственном вызове события). после пары экспериментов отказался из-за плохо контролируемого риска сваливания в мертвый цикл. т.о. был реализован первый вариант пока он себя неплохо показывает в том числе в варианте с задержкой применения фильтра (#USEDELAY=True) В процессе обнаружил интересный факт - вопреки Help свойство ListIndex у Access.Combobox Read/Write а не ReadOnly. При попытке записи значения в ListIndex выбор в списке меняется, но возникает ошибка 7777, т.е. если ее обработать можно использовать ListInex для управления выбором в списке. Тут можно поэкспериментировать. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.06.2019, 22:36 |
|
|
start [/forum/topic.php?desktop=1&fid=45&tid=1610635]: |
0ms |
get settings: |
9ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
30ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 144ms |
0 / 0 |