Как ты думаешь, дорогой читатель, для чего я так много времени посвятил каким-то абстрактным группам затрат?
Ответ прост: чтобы получить еще пару удобных отчетов.
Добавьте в проект новую форму, назвав ее AnalizGroupFrm, как уже описывалось ранее, не забыв прописать имя модуля в Uses главной формы и исключив ее из автоматически загружаемых в установках проекта.
На второй вкладке расположена сетка с итогами в футере:
В разделе implementation модуля формы (я назвал его AnalizGroup) имеются уже привычные процедуры, которые я здесь приведу (для порядку), но особого интереса они уже для нас не представляют, как привычные:
implementation
{$R *.dfm}
Uses Main
, AnalizGroupDetails
;
procedure TAnalizGroupFrm.FormCreate(Sender: TObject);
begin
// Создание формы
// Задание начальных значений для контролов - дат
Date_N.Value:=Now()-365;
Date_K.Value:=Now()+1;
// Назначение подключения запросу
ADOQuery1.Connection:=MainFrm.ADOConnection1;
end;
procedure TAnalizGroupFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// Освобождение памяти
Action:= caFree;
end;
procedure TAnalizGroupFrm.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 TAnalizGroupFrm.MyClose();
Begin
Close;
end;
procedure TAnalizGroupFrm.ButtonClickExecuteExecute(Sender: TObject);
begin
// Акшн, обрабатывающий события нажатия кнопок (ОК и Cancel) при наличии
if (ModalResult=1) OR (ModalResult=2)
then
Begin
MyClose;
end;
end;
Еще одна знакомая вещь - использование ранее разработанной функции экспорта в Excel:
procedure TAnalizGroupFrm.N_ExportClick(Sender: TObject);
begin
Try
MainFrm.ExportTo(PCHAR('Лист 1'), DBGridEh1, MainFrm.XLApp, PCHAR('Затраты по группам'), PCHAR('Период: '+FormatDateTime('dd/mm/yy',Date_N.Value)+' - '+FormatDateTime('dd/mm/yy',Date_K.Value)));
Finally
end;
end;
А теперь - собственно алгоритм получения результатов:
procedure TAnalizGroupFrm.Button1Click(Sender: TObject);
Var MyStr: String;
j: Integer;
begin
// Наполнение грида
// Подготовка запроса
ADOQuery1.Active:=False;
ADOQuery1.SQL.Clear;
// Формирование строки запроса
MyStr:='SELECT ExpenseGroup.ID, ExpenseGroup.Name, Sum(Main.Summa) AS [MySum] ';
MyStr:=MyStr + 'FROM (Accounts INNER JOIN (ExpenseGroup INNER JOIN ExpenseAcc ON ExpenseGroup.ID = ExpenseAcc.IDGroup) ON Accounts.ID = ExpenseAcc.IDAcc) INNER JOIN Main ON Accounts.ID = Main.D ';
MyStr:=MyStr + 'WHERE (((Accounts.Val)='+IntToStr(MySelect.MySel_IDVal)+') ';
MyStr:=MyStr + 'AND ((Main.MyDate)>=#'+FormatDateTime('mm/dd/yyyy',Date_N.Value)+'# And (Main.MyDate)<#'+FormatDateTime('mm/dd/yyyy',Date_K.Value)+'#)) ';
MyStr:=MyStr + 'GROUP BY ExpenseGroup.ID, ExpenseGroup.Name ';
MyStr:=MyStr + 'ORDER BY Sum(Main.Summa) DESC';
ADOQuery1.SQL.Add(MyStr);
ADOQuery1.Active:=True;
// Сопоставление полученных в запросе данных сериям на графике
j:=1;
With Series1 do
begin
Clear;
while (Not ADOQuery1.Eof) do
Begin
if j>16
then
j:=1
else
j:=j+1;
Add(ADOQuery1.FieldByName('MySum').Value, ADOQuery1.FieldByName('Name').Text, MyColor[j]);
ADOQuery1.Next;
end;
Active:=True;
end;
end;
Пару слов о строке, формирующей запрос.
Составить необходимый запрос проще в среде MS ACCESS:
В результат запроса должны быть отобраны записи, счета Дебета в таблице Main, которых присутствуют в корреляционной таблице ExpenseAcc.
Запрос содержит два условия:
- Выбираются записи по одной из валют (поле Val)
- Выбираются записи в интервале дат
Условия отбора я указал не через переменные и параметры, на напрямую.
Еще раз обращаю Ваше внимание, что даты в Access положено заключать в символы "#".
Этот запрос - запрос с группировкой (интересует общая сумма по той или иной группе с учетом условий).
Теперь не сложно взять текст SQL из конструктора запросов Access и перенести его в среду разработки:
SELECT ExpenseGroup.ID, ExpenseGroup.Name, Sum(Main.Summa) AS MySum
FROM ExpenseGroup INNER JOIN ((Accounts INNER JOIN ExpenseAcc ON Accounts.ID = ExpenseAcc.IDAcc) INNER JOIN Main ON Accounts.ID = Main.D) ON ExpenseGroup.ID = ExpenseAcc.IDGroup
WHERE (((Accounts.Val)=1) AND ((Main.MyDate)>=#1/1/2011# And (Main.MyDate)<#1/1/2012#))
GROUP BY ExpenseGroup.ID, ExpenseGroup.Name
ORDER BY Sum(Main.Summa) DESC;
Обратите внимание, что постфикс "DESC" указывает на обратный порядок сортировки по полю сумм.
В итоге должен получиться ответ на интересующий вопрос: список затрат по группам:
Точно такую же табличку нужно получить в Grid на форме.
Остается только подставить текст запроса в переменную MyStr, указав вместо кода валюты и даты начала и конца периода обработанные (преобразованные) значения соответствующих переменных и контролов:
IntToStr(MySelect.MySel_IDVal) - код валюты преобразуется в строковое значение,
FormatDateTime('mm/dd/yyyy',Date_N.Value) - значение даты из контрола Date_N преобразуется в строковое значение приемлемого формата.
В итоге, должна получиться вот такая картинка:
Но, любого бухгалтера (или вторую половинку:-)) такая диаграмма устроит мало. Вот, чтобы она не огорошила Вас вопросом: "А чего это такой большой зеленый столбик? Откуда эта огромная сумма? Куда делись деньги? А?" Чтобы Вам не пришлось краснеть у руководства и мямлить: "Так, ведь, это ж за целый год...", предлагаю подумать, как использовать кнопку "Детализация", которую я предусмотрел на форме.
Вы можете использовать текущую форму, а можете создать другую, очень похожую.
Пусть это будет небольшим домашним заданием.
Картинка, к которой можно стремиться, примерно вот такая:
Имея детализированный отчет, Вы быстро можете ответить, из чего и в какой пропорции складываются затраты по той или иной группе.
Комментариев нет:
Отправить комментарий
Примечание. Отправлять комментарии могут только участники этого блога.