Topic: Looping through tablegrid using inputquery

Hi All,
Some help please if anyone has any suggestions.
I have a tablegrid that I am looping through and using 'inputquery' to update each row. 
In the attached example, click on 'Update Status' to start processing through the table.  Valid inputs are 'A' (Approved') and 'D' (Denied).  This works fine.
The problem is when something other than 'A' or 'D' is input.  I trap the error using 'messagebox' and when the User selects 'Retry', I need to remain on the row in the tablegrid where the error occurred. 
Everything I have tried so far detects the error but advances to the next row in the tablegrid by which stage it's too late.
Using MVD 6.1 and Windows 10.
Any ideas would be most welcome.
Derek.

Post's attachments

Attachment icon admissions board.zip 450.08 kb, 32 downloads since 2024-04-16 

2 (edited by sparrow 2024-04-16 12:01:18)

Re: Looping through tablegrid using inputquery

Hi Derek,


Try this solution:
+ added exit via Cancel.

procedure Form1_Button1_OnClick (Sender: TObject; var Cancel: boolean);
var  vi: integer; vs: string;
begin
  vi := 0;
  While vi <= form1.tablegrid1.RowCount-1 do
  begin
    form1.tablegrid1.SelectedRow := vi;
    if inputquery('Candidate:  ' + form1.tablegrid1.cells[1,vi] + ' ' + form1.tablegrid1.cells[0,vi], 'Review:', vs) then
    begin
      if not (vs in ['a','d','A','D']) then
      begin
        showmessage('Invalid Input');
      end else
      begin
        if (vs in ['a','A']) then vs := 'APPROVED' else if (vs in ['d','D']) then vs := 'DENIED';
        sqlexecute('update candidates set outcome = "'+uppercase(vs)+'" where id = "'+inttostr(form1.tablegrid1.row[vi].id)+'"');
        vi := vi + 1;
      end;
      form1.tablegrid1.dbupdate;
      vs := '';
    end else Exit;
  end;
end;

Re: Looping through tablegrid using inputquery

You can add an eternal repeat..until loop, which is exited with the break command if the input is correct or if the input is not repeated. The exit command terminates the execution of the main loop when the Cancel button on the text entry form is clicked.

procedure Form1_Button1_OnClick (Sender: TObject; var Cancel: boolean);
var  vi: integer; vs: string;
begin
  for vi := 0 to form1.tablegrid1.RowCount-1 do
  begin
    form1.tablegrid1.SelectedRow := vi;
    repeat
      if inputquery('Candidate:  ' + form1.tablegrid1.cells[1,vi] + ' ' + form1.tablegrid1.cells[0,vi], 'Review:', vs) then
      begin
        if not (vs in ['a','d','A','D']) then
        begin
          if (messagebox('Invalid Input','Warning',MB_RETRYCANCEL+MB_ICONWARNING) = IDCANCEL) then
            break;
        end
        else
        begin
          if (vs in ['a','A']) then vs := 'APPROVED' else if (vs in ['d','D']) then vs := 'DENIED';
          sqlexecute('update candidates set outcome = "'+uppercase(vs)+'" where id = "'+inttostr(form1.tablegrid1.row[vi].id)+'"');
          form1.tablegrid1.dbupdate;
          vs := '';
          break;
        end;
      end
      else
        exit;
    until 1=0;
  end;
end;
Визуальное программирование: блог и телеграм-канал.

Re: Looping through tablegrid using inputquery

Hi Sparrow, Konstantin,
Excellent - both solutions do exactly what I need.  Specifically:
1.  I hadn't really appreciated how using
'while vi <= form1.tablegrid1.rowcount -1'
behaves differently from
'for vi := 0 to form1.tablegrid1.rowcount -1'
2.  I also wouldn't have thought to use 'break' to interrupt the 'for vi: = 0 to form1.tablegrid1.rowcount -1' loop.
As always, everything becomes so clear and obvious once someone shows you how! big_smile 
Thanks to both of you for your help.
Regards,
Derek.

Re: Looping through tablegrid using inputquery

There's nothing unusual there.
For ... loop that automatically changes the value to 1 until it reaches the condition value.
While ... loop while the condition is true. How much to change the value and when to do it depends on the user.
Used for increments other than 1 and other conditions.
In your example, there is no increment until the correct cell value is entered.
Repeat ... until - a cycle similar to the previous one but backwards.
The difference between the last two is that “Repeat ... until” will be executed at least once.
Therefore, in your case, the choice fell on WHILE.
In Konstantin's example there are essentially two "Repeat ... until" loops inside a "For".