Реализация потока данных Назад В начало Вперед

Файл 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.