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