| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C++ Builder > Посчитать одинаковые записи |
| Автор: Лена 16.4.2007, 18:15 |
| При помощи этого кода я могу найти нужную запись: Variant Rez = ADOQueryKey->Lookup("code", Form1->DBGrid1->Fields[0]->AsString, "code"); if(!Rez.IsNull())... Если запись найдена, подскажите, как можно посчитать сколько раз она встречается в колонке грида? |
| Автор: Anikmar 16.4.2007, 18:47 |
| Может быть быстрее отдельным запросом? SELECT Count(Поле) AS Result FROM Table WHERE условие |
| Автор: Лена 16.4.2007, 19:24 | ||
Мне надо не много по другому. Пользователь вводит запись в колонку грида номер 1 и затем щелчком мыши переходит на другую строку в колонку например номер 3. Я хочу убедиться, что пользователь ввел запись, которой гарантировано, нет в колонке номер 1. Сейчас это реализовано так:
Этот код прекрасно работает, если пользователь сразу после ввода значения перейдет на другую строку в гриде. Если же пользователь продолжит редактировать эту же запись в соседней колонке, то при попытке post возникнет исключение, потому что в первой колонке записи должны быть разные. Для пояснения рисунок. |
| Автор: Anikmar 16.4.2007, 19:47 |
| Я для решения таких задач применял 2 метода: 1. Вводил ограничение Unique в саму БД и ловил исключение 2. (Более гуммано с точки зрения сбережения нервов пользователю) выводил редактирование строки в отдельную форму, где все проверки проводил при нажатии ок и по-русски объснял пользователю в каком месте он дурак |
| Автор: Лена 17.4.2007, 10:49 |
| В этом поле есть ограничение Unique. Подскажите, как правильно его обработать? Связь: ADOConnection1->ADOQuery->DataSetProvider->ClientDataSet->DataSource->Грид. В моем случае, который представлен на рисунке, происходит исключение. В каком событии правильно обработать эту ситуацию? Думала просто простым циклом: если одинаковых записей больше двух, сделать отмену редактирования. |
| Автор: Anikmar 17.4.2007, 11:21 |
| Думаю самым простым в вашей ситуации будет обработчик BeforePost. В нем отдельным запросом проводить проверку и запрещать запись, если поля неподходят. Таким образом вы отсечете ситуацию ДО ее возникновения, а не после, как в случае с исключением. |
| Автор: Лена 17.4.2007, 11:49 |
| У меня как раз в обработчике ClientDataSetBeforePost, код который я приводила выше в своем втором сообщении. Как его правильно переделать? |
| Автор: Anikmar 17.4.2007, 12:04 |
| Я с этим компонентом никогда не работал, но общая логика такая: Проверяете записываемые поля на допустимость их значений и в случае невозможности записи выдаете сообщение об ошибке и прерываете запись функцией Abort() |
| Автор: Лена 17.4.2007, 12:21 |
Сообственно это и есть моя проблема. |
| Автор: Vyacheslav 17.4.2007, 12:35 | ||||||
Лена. Вся проблема у Вас возникла потому, что Вы не контролируете момент начала редактирования и его конца. Под контролем я понимаю наличие в коде команд Edit и Post при устаноленном AutoEdit в false. Наиболее правильным был бы подход, когда пользователю явно обозначен момент начала редактирования и его конца. То есть, если он хочет отредактировать конкретную строку, он должен нажать кнопку Редактировать, получить окно для редактирования, набрать все данные, визуально проверитиь их правильность и завершить редактирование, сохранив изменения или отказавшись от них. В этом случае у Вас есть всегда место, где перед сохранением, Вы можете проверить все данные на валидность В Вашем случае скорее всего придется написать обработчик
Добавлено @ 12:37
Обычно никто не занимается проверкой того, что БД сделает за Вас. Она (БД) должна сообщить (exception), а Вы выдать информацию в понятном вмде пользователю и предложить ему сценарий дальнейших действий |
| Автор: Лена 17.4.2007, 12:46 | ||
Да, теперь понимаю, что такой подход с окном для редактирования самый оптимальный. Я буду так реализовывать в следующих проектах. Просто этот проект надо уже отдать. Не готова вносить серьезные изменения. Скорость моего кодирования не впечатляет, могу не успеть. Вроде все работает. Вот только случайно наткнулась на ситуации описанную выше. Для своего случая попробую, согласно вашего совета, ClientDataSet1PostError. |
| Автор: Лена 17.4.2007, 13:06 | ||
| Всем хорош мой любимый Builder, только вот справочная система подкачала. Жму F1 на PostError, вижу описание, а где же samples?! Короче написала так:
Но что-то не очень нравиться. Как бы добавить действие "Отменить редактирование", чтобы запись вернулась в исходное состояние? А то пользователь будет щелкать, не понимая в чем проблема, и будет получать ShowMessage. Хочется вернуть проблемную запись в первоначальный вид в этом обработчике. Это возможно? P.S. Наверное есть смысл снабдить все мои ClientDataSet-ы обработчиком ClientDataSet1PostError? И еще наверное хорошо бы добавить ClientDataSet1DeleteError? |
| Автор: Vyacheslav 17.4.2007, 13:38 | ||||
| А разве запись не возвращается в исходное состояние после daAbort А так?
Добавлено @ 13:49 Вообще, насколько я понимаю, у Вас постановка задачи не совсем верна. Откуда пользователю знать, есть или нет в БД такое число. Это же у Вас, как я понимаю, уникальный ключ. Ну так подставляйте его сами по результатам запроса от БД и запретите пользователю редактировать это поле. Добавте обработчик OnNewRecord?в котором будете присваивать значение
где getNewValue() - метод, который будет возвращать значение запроса SELECT MAX(Поле) + 1 AS Result FROM Table |
| Автор: Лена 17.4.2007, 13:58 | ||
М-да, слона не заметила! Это то что нужно, работает. Спасибо! Меня сбило столку слово daAbort, думала оно все вернет в исходный вид. Если у меня в других гридах нет проблемы с дублированием, то достаточно ли будет для всех ClientDataSet-ов написать просто:
Или везде добавить DataSet->Cancel();? Или может еще что добавить в код? P.S. >Это же у Вас, как я понимаю, уникальный ключ. Это поле в конечном итоге будут вводиться данные из другой программы, сделанной другим человеком. Пользователь не сможет ввести туда данные и эти данные будут уникальными. НО! Прежде чем это будет сделано, моя программа попадет к промежуточному звену людей, которые не знают, как все это будет выглядеть. Эти люди просто будут знакомиться с интерфейсом, и я не хочу их пугать не понятными исключениями, поэтому просто добавляю эту возможность перехвата. |
| Автор: Vyacheslav 17.4.2007, 14:05 | ||
Лучше добавить DataSet->Cancel();. Только зачем дублировать обработчики? Вы напишите один, и присвойте его всем ClientDataSet в инспекторах. Если что-то впоследствии надо будет добвать, то только в одном месте |
| Автор: Лена 17.4.2007, 15:30 |
| Большое спасибо! |