Delphi 11, problem with output from mysql

  Kiến thức lập trình

The problem is that I’m making an electronic journal, ratings with full name are taken from the MYSQL database, and inside the code I have filtering in ascending alphabetical order. And if, let’s say, one person has a rating and after filtering he changes the position, then the rating remains where the name should have been before filtering.
Code:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Forms, Vcl.Grids, Vcl.StdCtrls,
  System.IOUtils, Vcl.Controls, Data.DB, Data.Win.ADODB, Vcl.Dialogs, ActiveX, ComObj, Unit5;

type
  TForm2 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
    ADOQuery2: TADOQuery;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure LoadNamesFromDatabase;
    procedure LoadDatesFromDatabase;
    procedure LoadGradesFromDatabase;
  private
    a: Integer;
    procedure AddRowsIfNeeded(const RowCount: Integer);
    procedure SaveGradeToDatabase(const ADate: TDateTime; const Grade: Integer);
    procedure SaveDateToDatabase(const ADate: TDateTime);
    procedure CreateTablesIfNeeded;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.LoadNamesFromDatabase;
var
  I: Integer;
begin
  ADOQuery2.SQL.Text := 'SELECT fio FROM students ORDER BY fio';
  ADOQuery2.Open;
  if not ADOQuery2.IsEmpty then
  begin
    try
      StringGrid1.RowCount := ADOQuery2.RecordCount + 1;
      StringGrid1.FixedRows := 1;

      I := 1;
      while not ADOQuery2.Eof do
      begin
        StringGrid1.Cells[0, I] := ADOQuery2.FieldByName('fio').AsString;
        Inc(I);
        ADOQuery2.Next;
      end;
    finally
      ADOQuery2.Close;
    end;
  end;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  Form5.Show;
end;

procedure TForm2.Button3Click(Sender: TObject);
begin
  SaveGradeToDatabase(Now, StrToInt(StringGrid1.Cells[a - 1, 1]));
  ADOConnection1.Connected := True;
end;

procedure TForm2.CreateTablesIfNeeded;
var
  Query: TADOQuery;
begin
  Query := TADOQuery.Create(nil);
  try
    Query.Connection := ADOConnection1;
    Query.SQL.Text :=
      'CREATE TABLE IF NOT EXISTS predmets (' +
      '  id INTEGER,' +
      '  name VARCHAR(255)' +
      ');';
    Query.ExecSQL;

    Query.SQL.Text :=
      'CREATE TABLE IF NOT EXISTS lections (' +
      '  id INTEGER,' +
      '  id_predmets INTEGER,' +
      '  date_l DATE' +
      ');';
    Query.ExecSQL;

    Query.SQL.Text :=
      'CREATE TABLE IF NOT EXISTS students (' +
      '  id INTEGER,' +
      '  fio VARCHAR(255)' +
      ');';
    Query.ExecSQL;

    Query.SQL.Text :=
      'CREATE TABLE IF NOT EXISTS works (' +
      '  id INTEGER,' +
      '  ball INTEGER,' +
      '  id_lection INTEGER,' +
      '  id_student INTEGER' +
      ');';
    Query.ExecSQL;
  finally
    Query.Free;
  end;
end;

procedure TForm2.SaveGradeToDatabase(const ADate: TDateTime; const Grade: Integer);
var
  DateId: Integer;
begin
  ADOQuery1.SQL.Text := 'SELECT id FROM dates WHERE ddate = :DateValue';
  ADOQuery1.Parameters.ParamByName('DateValue').Value := DateToStr(ADate);
  ADOQuery1.Open;
  try
    if not ADOQuery1.IsEmpty then
    begin
      DateId := ADOQuery1.FieldByName('id').AsInteger;
      ADOQuery1.SQL.Text := 'INSERT INTO math (date_id, grade) VALUES (:DateId, :Grade)';
      ADOQuery1.Parameters.ParamByName('DateId').Value := DateId;
      ADOQuery1.Parameters.ParamByName('Grade').Value := Grade;
      ADOQuery1.ExecSQL;
    end;
  finally
    ADOQuery1.Close;
  end;
end;

procedure TForm2.SaveDateToDatabase(const ADate: TDateTime);
begin
  ADOQuery1.SQL.Text := 'INSERT INTO dates (ddate) VALUES (:DateValue)';
  ADOQuery1.Parameters.ParamByName('DateValue').Value := DateToStr(ADate);
  ADOQuery1.ExecSQL;
end;

procedure TForm2.AddRowsIfNeeded(const RowCount: Integer);
begin
  if StringGrid1.RowCount <= RowCount then
    StringGrid1.RowCount := RowCount + 5;
end;

procedure TForm2.LoadGradesFromDatabase;
var
  I, J: Integer;
  dateIndex: Integer;
begin
  ADOQuery1.SQL.Text :=
    'SELECT works.id_student, works.ball, lections.date_l ' +
    'FROM works ' +
    'INNER JOIN lections ON lections.id = works.id_lection ' +
    'INNER JOIN students ON students.id = works.id_student ' +
    'WHERE lections.id_predmets = (SELECT id FROM predmets WHERE name = ''math'') ' +
    'ORDER BY lections.date_l, students.fio';
  ADOQuery1.Open;

  if not ADOQuery1.IsEmpty then
  begin
    try
      dateIndex := 0;

      while not ADOQuery1.Eof do
      begin
        I := StringGrid1.Rows[0].IndexOf(ADOQuery1.FieldByName('students.fio').AsString);
        J := StringGrid1.Cols[0].IndexOf(ADOQuery1.FieldByName('date_l').AsString);

        if J = -1 then
        begin
          J := StringGrid1.ColCount;
          StringGrid1.Cells[J, 0] := ADOQuery1.FieldByName('date_l').AsString;
          StringGrid1.ColCount := J + 1;
        end;

        StringGrid1.Cells[J, I] := ADOQuery1.FieldByName('ball').AsString;

        ADOQuery1.Next;
      end;
    finally
      ADOQuery1.Close;
    end;
  end;
end;

procedure TForm2.LoadDatesFromDatabase;
var
  I: Integer;
begin
  ADOQuery1.SQL.Text :=
    'SELECT lections.date_l ' +
    'FROM lections ' +
    'INNER JOIN predmets ON predmets.id = lections.id_predmets ' +
    'WHERE predmets.name = "math" ' +
    'ORDER BY lections.date_l';
  ADOQuery1.Open;
  if not ADOQuery1.IsEmpty then
  begin
    try
      I := 1;
      while not ADOQuery1.Eof do
      begin
        StringGrid1.Cells[I, 0] := FormatDateTime('dd.mm.yyyy', ADOQuery1.FieldByName('date_l').AsDateTime);
        Inc(I);
        ADOQuery1.Next;
      end;
    finally
      ADOQuery1.Close;
    end;
  end;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  Grade: Integer;
  CurrentDate: TDateTime;
  DateStr: string;
begin
  DateStr := InputBox('Enter Date', 'Enter the date (dd.mm.yyyy):', '');
  if TryStrToDate(DateStr, CurrentDate) then
  begin
    Grade := StrToInt(InputBox('Enter Grade', 'Enter the grade for the current date:', ''));
    if Grade >= 0 then
    begin
      SaveDateToDatabase(CurrentDate);
      StringGrid1.Cells[a, 0] := DateStr;
      StringGrid1.Cells[a, 1] := IntToStr(Grade);
      Inc(a);
      StringGrid1.ColCount := a + 1;
      AddRowsIfNeeded(a);
      SaveGradeToDatabase(CurrentDate, Grade);
    end;
  end
  else
    ShowMessage('Invalid date format. Please enter the date in dd.mm.yyyy format.');

  LoadGradesFromDatabase;
  LoadDatesFromDatabase;
  LoadNamesFromDatabase;
end;

procedure TForm2.FormCreate(Sender: TObject);
var
  Today: TDateTime;
begin
  a := 1;
  CreateTablesIfNeeded;
  LoadGradesFromDatabase;
  LoadDatesFromDatabase;

  Today := Now;
  LoadNamesFromDatabase;
  AddRowsIfNeeded(a);
end;

end.

I tried different options, such as changing the structure of the database, or moving the ratings at the same time with filtering, but it turned out terrible

New contributor

ImCluzzy Xz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

LEAVE A COMMENT