Реализация потока данных |
Файл PrjMngFR.vip
Данные таблицы Projects организованы иерархически. Поэтому для их выгрузки используется элемент dataset, позволяющий управлять обходом дерева. Подцепленные таблицы имеют обычную реляционную организацию, поэтому для них используется элемент table.
Перед вызовом ContinueDataset необходимо убедиться, что в базе остались записи для вывода в отчет. В связи с этим поля текущей записи запоминаются в переменных и производится попытка перейти к следующей записи таблицы Projects.
#include PrjMngFR.vih interface PrjMngFR; create view var cSuperStack : longInt; cSuperStage : comp; // вышестоящий этап, 0 для проектов wMasterCode : word; // код текущего владельца ресурса sRep : string; ProjectLevel : integer; // для хранения полей ProjectCode : string; // таблицы Projects ProjectName : string; // т.к. записи выводятся ProjectSummP : double; // в отчет с задержкой ProjectNRec : comp; // на шаг i : longInt; as select if(Projects.Status = 'З','Завершенный', if(Projects.Status = 'Т','Текущий', if(Projects.Status = 'П','Планируемый', 'Неопределенное состояние' ))) (FieldName = ProjectStatus), PrjExecutors.*, KatPersons.*, PrjMaterials.*, KatMaterials.*, Projects.* from PrjExecutors, objref KatPersons, Projects, PrjMaterials, objref KatMaterials where (( cSuperStage == Projects.cParent and //Cвязь: Проекты -> Сотрудники wMasterCode == PrjExecutors.MasterCode and ProjectNRec == PrjExecutors.cMaster and resResourceOriginal == PrjExecutors.Status and PrjExecutors.cEmployee == KatPersons.NREC and //Связь: Проекты -> Материалы wMasterCode == PrjMaterials.MasterCode and ProjectNRec == PrjMaterials.cMaster and resResourceOriginal == PrjMaterials.Status and PrjMaterials.cMaterial == KatMaterials.NREC )); dataStream PrjMngFR01Stream ( [ HdrStr ] sRep; dataset ProjectsDS ( [ PrjLevel ] ProjectLevel; [ PrjCode ] ProjectCode; [ PrjName ] ProjectName; [ PrjStatus ] ProjectStatus; [ PrjSummP ] ProjectSummP; table PrjMaterials ( [ MatName ] KatMaterials.Name; [ MatEI ] KatMaterials.EI; [ MatQuantP ] PrjMaterials.QuantP; [ MatSummP ] PrjMaterials.SummP; ); table PrjExecutors ( [ PsnFIO ] KatPersons.FIO; [ PsnDepartment ] KatPersons.Department; [ PsnPost ] KatPersons.Post; [ PsnSalary ] KatPersons.Salary; [ PsnQuant ] PrjExecutors.QuantP; [ PsnSummP ] PrjExecutors.SummP; ); ); ) handleEvent dataset ProjectsDS cmPreProcess: { cSuperStage := 0; ProjectCode := ''; ProjectName := ''; ProjectSummP := 0; ProjectNRec := 0; } cmOnProcess: { // текущую запись Projects - в отчет ProjectLevel := Container_GetCount(cSuperStack); ProjectCode := Projects.Code; ProjectName := Projects.Name; ProjectSummP := Projects.SummP; ProjectNRec := Projects.NRec; // следующую готовим (если она есть) // запоминаем точку отката ... PushPos(tnProjects); Container_Insert(cSuperStack, cSuperStage); // ... и идем вниз по дереву cSuperStage := Projects.Nrec; if (getFirst Projects = tsOK) // есть поддерево - обработаем его на след. шаге { ContinueDataset; exit; } else // нет поддерева - возвращаемся .... { i := Container_GetCount(cSuperStack) - 1; cSuperStage := Container_AtC(cSuperStack, i); Container_AtDelete(cSuperStack, i); PopPos(tnProjects); } // ... и продолжаем перебор уровня // если на текущем уровне листья закончились, // то поднимаемся, пока не найдем данные while (getNext Projects <> tsOK) do { i := Container_GetCount(cSuperStack); if (i = 0) // обошли все дерево { exit; } i := i - 1; cSuperStage := Container_AtC(cSuperStack, i); Container_AtDelete(cSuperStack, i); PopPos(tnProjects); }; ContinueDataset; } end; end; screen scrRpt; buttons cmTestShow,,,'Показать отчет'; << <.Показать.> >> end; handleEvent cmInit: { wMasterCode := resProject; cSuperStack := Container_Init('',8,100,10); sRep := 'переменная часть заголовка'; } cmTestShow: { RunFReport(PrjMngFR01Stream, 'PrjMngRep', true); } end; // handleEvent end.