|
|
|||||||||||||||||||||||||||||
|
Уроки Delphi. Обобщающий графический отчет.Источник: pro-delphi Александр Веселов
Пройдет время. Скажем, год. База данных наполнится цифрами... Кроме того, графические отчеты, которые я представлял ранее были псевдо статичны, т.е. не менялись после их составления. Новый отчет будет практически динамическим, т.е. он, конечно, не в реальном масштабе времени будет строиться (не та задачка у нас), но будет изменять свой вид по желанию оператора, как сейчас говорят - будет интерактивен.
назвав ее AnalizTrendsForm, а модуль формы соответственно AnalizTendenc.
Большинство компонентов (кнопки, панели, TPageControl и TDBGridEh) нам знакомы, вряд ли стоит подробно останавливаться на них. К тому же, если компонент не обрабатывается в коде, то я даже не имею привычки его переименовывать.
К таким же привычным компонентам можно отнести TADOQuery, которому советую не забыть назначить свойство Connection. Любознательно-наблюдательные читатели спросят, а, может быть, даже упрекнут меня в том, что вместо этого компонента можно использовать имеющийся на главной форме TempQuery. Да, можно. Внесите изменения (оптимизируйте) самостоятельно :-)
аким же привычным компонентом уже стал, наверное, компонент TChart.
Одним из новых для нас компонентов будет компонент TStringGrid. Чуть позже будет понятно, почему я выбрал именно его.
И уж совсем "неожиданным" будет использование компонента TClientDataSet, на котором я хотел бы остановиться немного подробнее.
По сути этого компонента можно сказать, что это невизуальный компонент, аналогичный обычному массиву. Все, что в него попадает, остается в ОЗУ, поэтому работает он очень быстро. Но, есть одна особенность. Являясь стандартным компонентом, устанавливаемым совместно со средой обработки, этот компонент не будет работать без наличия в системе специальной библиотеки midas.dll, что удивительно. Этот файл необходимо расположить в каталоге C:\Windows\System32, а затем зарегистрировать его с помощью "Выполнить: regsvr32 c:\windows\system32\midas.dll". Если Вы не знаете, как это сделать, скачайте исполняемый файл, разместите его в том же каталоге, куда скачали Dll, и дважды щелкните по этому файлу. Все произойдет само собой :-)
Не убирайте далеко в корзину и навсегда файл библиотеки. Ближе к финалу данной темы я планирую рассказать о создании (мы же с Вами - взрослые люди) настоящего инсталлятора для программы "Расходы", так что файл библиотеки нам еще пригодится.
Самое "страшное" на сей раз позади, "продолжаем разговор", как говорит любимый мультяшный герой Карлсон.
Слиентский датасет можно создать (наполнить полями) в конструкторе, но ниже я покажу, как это сделать программно.
Чтобы данные, размещенные в CDS были видны в таблице, расположенной на одноименной вкладке на форме, необходимо оформить связь:
В качестве вступительного слова при переходе к коду программы, приведу почти знакомый фрагмент, включающий традиционные процедуры создания формы, закрытия ее и некоторые другие: var implementation {$R *.dfm} Uses Main;
// Традиционный набор процедур
procedure TAnalizTrendsForm.FormCreate(Sender: TObject);
begin
StringGrid1.ColWidths[0]:=50;
StringGrid1.ColWidths[1]:=150;
PageControl1.ActivePage:=TabSheet1;
Prepare();
end;
procedure TAnalizTrendsForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;
procedure TAnalizTrendsForm.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of // Start Case
VK_ESCAPE:
begin
MyClose;
end;
else
End; // End case
end;
procedure TAnalizTrendsForm.MyClose();
begin
close;
end;
procedure TAnalizTrendsForm.PrDOkButton1Click(Sender: TObject);
begin
if (ModalResult=1) OR (ModalResult=2)
then
Begin
MyClose;
end;
end;
А ниже - то, ради чего все это затевалось: Процедура очистки графика: procedure TAnalizTrendsForm.BitBtn1Click(Sender: TObject); // Очистка графика Здесь я должен пояснить основную идею, которую должна реализовать данная форма:
в список слева (StringGrid) нужно вывести все счета, по которым были обороты в текущем году. При щелчке по строке этого списка программа должна добавлять в график новую серию, раскрасив ее в один из 16 оговоренных в массиве MyColor цветов и изменив масштаб отображения.
Использованная в процедуре создания формы подпрограмма Prepare() по сути - наполняет список счетов в StringGrid (обратите внимание, что здесь, как и в следующей процедуре прописан механизм обработки ошибок):
procedure TAnalizTrendsForm.Prepare();
Var
MyStr: String;
j,i: Integer;
ErrKod: Integer; // Код ошибки
ErrMes: String; // Описание ошибки
Label
ErrorsLab; // Метка, после которой начинается текст обработчика ошибок
begin
// Стартовые значения
ErrKod:=0;
ErrMes:='Операция завершена успешно';
// Определить количество задействованных счетов в течение года
ADOQuery1.Active:=False;
ADOQuery1.SQL.Clear;
MyStr:='SELECT Accounts.ID, Accounts.Name ';
MyStr:=MyStr + 'FROM Accounts INNER JOIN Main ON Accounts.ID = Main.D ';
MyStr:=MyStr + 'WHERE (((Accounts.Analiz)=True) AND ((Year([Main]![MyDate]))='+FormatDateTime('yyyy',(now()))+')) ';
MyStr:=MyStr + 'GROUP BY Accounts.ID, Accounts.Name';
ADOQuery1.SQL.Add(MyStr);
ADOQuery1.Active:=True;
// Есть ли данные за текущий год?
If Not (ADOQuery1.RecordCount>0)
then
begin
ErrKod:=1;
ErrMes:='Список пуст:'+CR+'Нет счетов, задействованных в текущем году';
GoTo ErrorsLab;
end;
// Создать CDS
CDS.Active:=False;
CDS.FieldDefs.Clear;
CDS.FieldDefs.add('Месяц',ftInteger,0,False); // Будут вписаны номера месяцев от 1 до 12
// В цикле по созданному массиву создаем поля - коды счетов в заголовках
// а также - наполняем сетку, отображающую набор счетов
j:=0;
while (Not ADOQuery1.Eof) do
Begin
CDS.FieldDefs.add(ADOQuery1.FieldByName('ID').AsString,ftInteger,0,False);
StringGrid1.Cells[0,j]:=ADOQuery1.FieldByName('ID').AsString;
StringGrid1.Cells[1,j]:=ADOQuery1.FieldByName('Name').AsString;
StringGrid1.RowCount:=StringGrid1.RowCount+1;
inc(j);
ADOQuery1.Next;
end;
StringGrid1.RowCount:=StringGrid1.RowCount-1; // Одна строка лишняя
CDS.CreateDataSet; // Создание датасета
CDS.IndexFieldNames:='Месяц';
// Наполнение CDS
// Номера месяцев
For j:=1 to 12 do
begin
CDS.Insert;
// Обнуление CDS
for i := 0 to CDS.FieldCount - 1 do
CDS.Fields[i].Value:=0;
CDS.FieldByName('Месяц').Value:=j;
CDS.Post;
end;
// Данные
CDS.First;
While Not CDS.Eof do
begin
ADOQuery1.Active:=False;
ADOQuery1.SQL.Clear;
MyStr:='SELECT Month([MyDate]) AS Mes, Sum(Main.Summa) AS [MySum], Accounts.Name, Accounts.ID ';
MyStr:=MyStr + 'FROM Accounts INNER JOIN Main ON Accounts.ID = Main.D ';
MyStr:=MyStr + 'WHERE (((Accounts.Analiz)=True) AND ((Year([Main]![MyDate]))='+FormatDateTime('yyyy',(now()))+')) ';
MyStr:=MyStr + 'GROUP BY Month([MyDate]), Accounts.Name, Accounts.ID, Year([Main]![MyDate]) ';
MyStr:=MyStr + 'HAVING (((Month([MyDate]))='+CDS.FieldByName('Месяц').AsString+'))';
ADOQuery1.SQL.Add(MyStr);
ADOQuery1.Active:=True;
While Not ADOQuery1.Eof do
begin
CDS.Edit;
CDS.FieldByName(ADOQuery1.FieldByName('ID').AsString).Value:=ADOQuery1.FieldByName('MySum').Value;
CDS.Post;
ADOQuery1.Next;
end;
CDS.Next;
end;
// Настройка сетки
DBGridEh1.Columns.AddAllColumns(True);
exit; // Нужен, если нет необходимости выводить сообщение об успешном завершении операции
ErrorsLab:
case ErrKod of // Start Case
0:
begin
// Сообщение об успешном завершении
MainFrm.MyMessenger.TitleString:='...';
MainFrm.MyMessenger.MessageType:=mtInformation;
end;
else
begin
// Сообщения об ошибках
MainFrm.MyMessenger.TitleString:='Ошибка ('+IntToStr(ErrKod)+')';
MainFrm.MyMessenger.MessageType:=mtError;
end;
End; // End case
MainFrm.MyMessenger.MessageString:=ErrMes;
MainFrm.MyMessenger.Buttons:=[mbOk];
MainFrm.MyMessenger.ShowMessage;
end;
А теперь - обработчик клика по сетке (списку счетов): procedure TAnalizTrendsForm.StringGrid1Click(Sender: TObject); Label // Стартовые значения для // Если в сетке ничего нет, то - выход // Первая из возможных проверок (количество графиков не может быть более 16)
// Добавление новой серии i:=SeriesCount; AddSeries(TLineSeries.Create(Self)); end; With Chart1.Series[i] do exit; // Нужен, если нет необходимости выводить сообщение об успешном завершении операции ErrorsLab: case ErrKod of // Start Case 0: // Сообщение об успешном завершении end; // Сообщения об ошибках MainFrm.MyMessenger.MessageString:=ErrMes; end; В результате Вы получите вот такие графики, если станете щелчком выбирать строки в списке (в моей БД сохранилась информация только за первые два месяца :-) ): Ссылки по теме
|
|