Помощь - Поиск - Пользователи - Календарь
Полная версия: Сравнение в AdvStringGrid
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Atreides
Добрый день!
Нужно сравнить два ячейки в AdvStringGrid.Казалось, что может быть проще, но что-то у меня возникли трудности. Задача, есть две колонки в гриде "от" и "до". Пользователь может редактировать обе, но значения "до" не должно быть меньше "от" и соответственно "от" не должно превышать "до", строка значений "от" и "до" одинаковая, разница только в колонках. В итоге нельзя отпускать пользователя пока не введет корректно. Не удается привязать ни к одному событию, ибо если число многозначное условие срабатывает на первом символе и не дает ввести дальше. Есть еще варианты кроме просто сравнения?
IUnknown
Цитата
Казалось, что может быть проще
Оказалось, что не казалось. Ничего проще в TAdvStringGrid-е быть действительно не может. У него есть событие OnEditCellDone, в котором можно проверять, какой именно столбец редактировался, сравнить данные с данными соседнего столбца, и, при необходимости, вернуть пользователя к редактированию через EditorMode = True
Atreides
Цитата(IUnknown @ 19.07.2012 13:39) *

Оказалось, что не казалось. Ничего проще в TAdvStringGrid-е быть действительно не может. У него есть событие OnEditCellDone, в котором можно проверять, какой именно столбец редактировался, сравнить данные с данными соседнего столбца, и, при необходимости, вернуть пользователя к редактированию через EditorMode = True

Так, а можно немного подробней про EditorMode? Событие срабатывает только когда перескакиваю на другую ячейку (что логично), а вот как тогда остаться на той же в которой только что вводил? Значения второй колонки не могут быть больше значений значений третьей.

Код

procedure GridEditCellDone(Sender: TObject; ACol,
  ARow: Integer);
begin
Grid.EditorMode := False;
if Grid.Cells[3,ARow] < Grid.Cells[2,ARow] then
ShowMessage('Повторите ввод');
Grid.EditorMode := True;

end;

Типа как то так?
IUnknown
У меня в Дельфи нет этого компонента, есть в Билдере. Но смысл должен быть понятен:

void __fastcall TForm1::AdvStringGrid1EditCellDone(TObject *Sender, int ACol, int ARow)

{
TAdvStringGrid *grid = dynamic_cast<TAdvStringGrid*>(Sender);
int Col = ACol, Row = ARow;
switch(Col)
{
case 3:
if(!(grid->Cells[Col - 1][Row]).IsEmpty())
if(StrToInt(grid->Cells[Col][Row]) < StrToInt(grid->Cells[Col - 1][Row]))
{
// В Дельфи можешь выделить это во вложенную процедуру, чтоб не дублировать код
ShowMessage("Oops, error!!!");
grid->SetFocus();
grid->Col = Col; grid->Row = Row;
grid->EditorMode = true;
}
break;
case 2:
if(!(grid->Cells[Col + 1][Row]).IsEmpty())
if(StrToInt(grid->Cells[Col][Row]) > StrToInt(grid->Cells[Col + 1][Row]))
{
ShowMessage("Oops, error!!!");
grid->SetFocus();
grid->Col = Col; grid->Row = Row;
grid->EditorMode = true;
}
break;
}
}

Atreides
Не владею С, вот попробовал. Вроде верно отрабатывает, но чет с фокусом не совсем разобрался. Мне как не отпускать пользователя с клетки?
Код
procedure TfrmNormRemont.sgNormRemontEditCellDone(Sender: TObject; ACol,
  ARow: Integer);
begin
if StrToInt(sgNormRemont.Cells[3, ARow])<StrToInt(sgNormRemont.Cells[2, ARow]) then
  begin
   ShowMessage('Oops, error!!!');
   sgNormRemont.SetFocus();
    sgNormRemont.EditMode :=True;
  end;
end;
IUnknown
Установи активной ячейкой ту, которая была изначально отредактирована, и только потом переходи в EditMode:

procedure TfrmNormRemont.sgNormRemontEditCellDone(Sender: TObject; ACol,
ARow: Integer);
var TheCol, TheRow : Integer;
begin
TheCol := ACol; TheRow := ARow;
if StrToInt(sgNormRemont.Cells[3, ARow])<StrToInt(sgNormRemont.Cells[2, ARow]) then
begin
ShowMessage('Oops, error!!!');
sgNormRemont.Row := TheRow; sgNormRemont.Col := TheCol;
sgNormRemont.SetFocus;
sgNormRemont.EditMode :=True;
end;
end;

Только зачем тебе это делать при редактировании любой ячейки? Поставь доп. условие, если ACol = 2 или 3, только тогда проверяй...
Atreides
Я так догадываюсь, что он должен войти в режим ввода числа, а он просто выделяет ячейку.
TarasBer
> // В Дельфи можешь выделить это во вложенную процедуру, чтоб не дублировать код


auto ShowError = [grid, Col, Row](){
ShowMessage("Oops, error!!!");
grid->SetFocus();
grid->Col = Col; grid->Row = Row;
grid->EditorMode = true;
}

IUnknown
TarasBer, ты на самом деле думаешь, что Билдер (любой, у меня 2009, если что) поддерживает все фишки нового стандарта? smile.gif

Цитата
Я так догадываюсь, что он должен войти в режим ввода числа, а он просто выделяет ячейку.
Я написал тебе код во втором сообщении, он работает корректно. Проверить на Дельфи не могу, сказал уже. Тебе что, записать видео, как ведет себя программа при запуске? Пока не введешь в столбцах 2 или 3 корректное число - не выйдешь из режима редактирования. Твой огрызок, который приведен ниже этого не делает.

Добавлено через 4 мин.
Блин... EditorMode а не EditMode !!!
Гость
Работает! Огромное спасибо!

Вопрос не в темку. Как сделать, чтоб запретить ввод значений в двух столбцах. Сделал так, но лочит только последнюю колонку. Надо залочить 0 и 19 колонку.
Код
procedure TfrmNormRemont.sgNormRemontSelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
begin
   CanSelect := ACol <> 19; //19 and 0;
end;
IUnknown
   // CanSelect := not (ACol in [0, 19]);
CanSelect := (ACol <> 0) and (ACol <> 19);
Выбирай, что больше нравится
Гость
Все нравится! Огромное спасибо!
Atreides
Есть ли возможность запретить ввод с клавиатуры в ячейки Грида? При чем оставить возможность выбора из вписанного в эти ячейки комбобокса.
IUnknown
В событии AdvStringGrid1GetEditorType для тех столбцов (или строк, как тебе нужно) в которых надо запретить ввод с клавиатуры - выставляй AEditor := edNone, тогда Inplace-редактор создаваться не будет, с клавиатуры ничего не введешь. А там, где AEditor := edComboList (Лист, а не Эдит) - и так только выбирать из списка, клавиатура там не помогает.
TarasBer
Цитата(IUnknown @ 19.07.2012 16:09) *

TarasBer, ты на самом деле думаешь, что Билдер (любой, у меня 2009, если что) поддерживает все фишки нового стандарта? smile.gif



class ShowError
{
TGrid grid, int Col, int Row;
public :
ShowError (TGrid grid, int Col, int Row) : grid(grid), Col(Col), Row(Row) {}
void Do ()
{
ShowMessage("Oops, error!!!");
grid->SetFocus();
grid->Col = Col; grid->Row = Row;
grid->EditorMode = true;
}
};


Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.