БЛАНКСШАБЛОНОМ "Общие функции для отчетов НФА";
-- Разработка бланка: ТБ.БЮДЖЕТ

2-- Константы
var sМаскаНФА :String="((*.101.*|*.102.*|*.105.*)&(ЗАБ.??.???.??|???.????.???????.???.?.???.??.???))";
var crdГРП    :String="РПО_ОКЕИ_ГРУППЫ";
var pfxУЧН    :String="УЧН";

2-- Переменные
var valКБК :String;  -- Фильтр по КБК (полное значение - для возвратов в меню)
var keyГРП :String;  -- Фильтр по группам НФА (ссылка на значение)
var LastGRP_num   :Integer;
var LastGRP_key   :String=["{0}"];
var раздел_Счетов :String; -- Для фильтра по счетам, раздел 101 (значение "101") или 105 (значение "105") или все (значения нет)

2--0 2Массивы
var GRPBUF[] :String; -- Группы НФА (для вывода)
var GRPDAT[] :String; -- Группы НФА (данные)
var GRPKEY[] :String; -- Группы НФА (системная инфа)

var bindVOC[] :String;  -- Привязанный справочник
var bindINT[] :Integer; -- Количество привязок

var LibAna[] :String;
var LibBuf[] :String;
var LibMsk[] :String;
var LibStr[] :String;
var KeyMsk[] :String;
var KeyStr[] :String;
var LibTxt[] :String;
var LibFlg[] :Logical;
var LibInt[] :Integer;

2-- Вспомогательное

Proc Очистить;
 ClearVariable(РАБ.НФА.LIBREP.bindVOC);
 ClearVariable(РАБ.НФА.LIBREP.bindINT);
 --
 ClearVariable(РАБ.НФА.LIBREP.LibAna);
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 ClearVariable(РАБ.НФА.LIBREP.LibMsk);
 ClearVariable(РАБ.НФА.LIBREP.LibStr);
 ClearVariable(РАБ.НФА.LIBREP.KeyMsk);
 ClearVariable(РАБ.НФА.LIBREP.KeyStr);
 ClearVariable(РАБ.НФА.LIBREP.LibTxt);
 ClearVariable(РАБ.НФА.LIBREP.LibFlg);
 ClearVariable(РАБ.НФА.LIBREP.LibInt);
 --
 ClearVariable(РАБ.НФА.LIBREP.раздел_Счетов);
end;

2-- Процедуры и функции

-- Общие
Func TimeToHMSstring_adv(valTime:Integer; valSep:String) :String;
var ihh, imm, icc :Integer;
var shh, smm, scc :String;
 shh=''; smm=''; scc='';
 ihh=Int(Trunc(valTime/3600));
 imm=Int(Trunc((valTime-ihh*3600)/60));
 icc=valTime-ihh*3600-imm*60;
 shh=Format("%.2d", ihh);
 smm=Format("%.2d", imm);
 scc=Format("%.2d", icc);
 ^(shh+valSep+smm+valSep+scc);
end;

Proc CopyCfgPrn(Cfg:String; iniНФА:Logical);
var PathCfg :String;
var OK :Logical;
 OK=ExistFile(РАБ.БЮДЖЕТ2005.Контроль2Слэш(PlanVar("INI")+"\"+Cfg));
 PathCfg=if(iniНФА, "НФА", "Общие");
 if OK: 
   Try 
     DeleteFile(РАБ.БЮДЖЕТ2005.Контроль2Слэш(PlanVar("INI")+"\"+Cfg));
     РАБ.НАСТР_ПЕЧАТЬ.CreateCfg(PlanVar(PathCfg)+"\Настройки\", Cfg);
   Except
   end;
 else
   РАБ.НАСТР_ПЕЧАТЬ.CreateCfg(PlanVar(PathCfg)+"\Настройки\", Cfg);
 fi;
end;

Func Объединить(Value1:String; Value2:String; Separator:String) :String;
var Ret :String;
 if Value1<>"" and Value2<>"": Ret=Value1+Separator+Value2;
 |  Value1= "" and Value2<>"": Ret=Value2;
 |  Value1<>"" and Value2="" : Ret=Value1;
 |  True: Ret="";
 fi;
 ^Ret;
end;

Func ЗаменитьСимволСтроки_ПоПозиции(valStr:String; repChar:String; repPos:Integer) :String;
var tmpFirst, tmpLast, out :String;
var len :Integer;
 tmpFirst=""; tmpLast=""; out="";
 len=Length(valStr);
 if repPos<1: repPos=1; fi;
 if repPos>len or repChar="" or valStr="": ^valStr; fi;
 repChar=SubStr(repChar, 1, 1);
 if repPos>1: tmpFirst=SubStr(valStr, 1, repPos-1); else tmpFirst=""; fi;
 if repPos<len: tmpLast=SubStr(valStr, repPos+1, len-repPos); else tmpLast=""; fi;
 out=tmpFirst+repChar+tmpLast;
 ^out;
end;

Func ЗаменитьРазделитель_Символ(Value:String; SepChar:String) :String;
var nn :Integer;
 if Length(SepChar)=1:
   nn=Pos(SepChar, Value);
   while nn>0 do Value=ЗаменитьСимволСтроки_ПоПозиции(Value, "_", nn); nn=Pos(SepChar, Value); od;
 fi;
 ^Value;
end;

Func ЗаменитьРазделители(Value:String) :String;
 Value=ЗаменитьРазделитель_Символ(Value, "|");
 Value=ЗаменитьРазделитель_Символ(Value, "#");
 Value=ЗаменитьРазделитель_Символ(Value, Chr(169));
 ^Value;
end;

Func Цвет(r:Integer; g:Integer; b:Integer) :Integer; -- цвет по стандарту ТБ 6.9
 ^(256*256*b+256*g+r);
end;

Func Mod(X:Integer; Y:Integer) :Integer; -- возвращает остаток от деления (X - делимое; Y - делитель)
 ^Int(X-Y*Int(Trunc(X/Y)));
end;

Func ЧетныйИндекс(Iter:Integer) :Logical;
 Iter=Abs(Iter);
 if Iter=1: ^False;
 |  Iter=2: ^True;
 |  Iter>2: if Mod(Iter, 2)=0: ^True; else ^False; fi;
 else ^False;
 fi;
end;

Func DeleteWordInStr(sStr:String; dStr:String; Sep:String) :String;
var out :String;
var pp, len :Integer;
 out="";
 len=Length(dStr);
 if len=0: ^sStr; fi;
 pp=Pos(Up(dStr), Up(sStr));
 if pp=0: ^sStr; fi;
 if pp>1: pp=pp-1; fi;
 len=len+1;
 out=Delete(sStr, pp, len);
 ^out;
end;

Func КорректныеСимволыПризнака(Value:String) :String;
var num, ii, intChars :Integer;
var Res, Chars :String;
 Res="";
 num=Length(Value);
 if num>0:
   for ii=1 to num do
     Chars=SubStr(Value, ii, 1);
     intChars=Ascii(Chars);
     if intChars=46 or                        -- точка
        (intChars>= 48 and intChars<= 57) or  -- цифры
        (intChars>= 65 and intChars<= 90) or  -- латиница заглавные
        intChars=95 or                        -- нижнее подчеркивание
        (intChars>= 97 and intChars<=122) or  -- латиница строчные
        (intChars>=192 and intChars<=255):    -- национальный алфавит
           Res=Res+Chars; else Res=Res+"_";
     fi;
   od;
 fi;
 ^Res;
end;

Func ПравильныйСимволАналитики(Value:String) :Logical;
var intChars :Integer;
 intChars=Ascii(Value);
 if intChars=42 or                        -- звездочка (*)
    intChars=46 or                        -- точка
    (intChars>= 48 and intChars<= 57) or  -- цифры
    intChars=63 or                        -- знак вопроса (?)
    (intChars>= 65 and intChars<= 90) or  -- латиница заглавные
    intChars=95 or                        -- нижнее подчеркивание
    (intChars>= 97 and intChars<=122) or  -- латиница строчные
    (intChars>=192 and intChars<=255):    -- национальный алфавит
       ^True;
 fi;
 ^False;
end;

Func ВхожденийНет(ANA:String; MSK:String) :Logical;
 ^(Pos(ANA, MSK)=0);
end;

Func MatchMask(Src:String; Mask:String; SepMask:String) :Logical;
var ii, num :Integer;
var tmp :String;
 num=WordsCount(Mask, SepMask);
 for ii=1 to num do
   tmp=ExtractWord(ii, Mask, SepMask);
   if Match(Src, tmp): ^True; fi;
 od;
 ^if(num=0, Match(Src, Mask), False);
end;

Func УдалитьСловоНомер(strNumber:Integer; strValue:String; strSep:String) :String;
var ii, num :Integer;
var newValue :String;
 newValue=strValue;
 num=WordsCount(strValue, strSep);
 if num>0:
   newValue="";
   if num>=strNumber:
     for ii=1 to num do
       if not strNumber=ii:
         newValue=Объединить(newValue,  ExtractWord(ii, strValue, strSep), strSep);
       fi;
     od;
   fi;
 fi;
 ^newValue;
end;

Func УдалитьСловоИзНабора_Диалог(Set:String; SepSet:String) :String;
var num, ii, nn :Integer;
var Value, tmp :String;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 ClearVariable(РАБ.НФА.LIBREP.LibTxt);
 num=WordsCount(Set, SepSet);
 if num<2: ^""; fi;
 for ii=1 to num do
   Value=ExtractWord(ii, Set, SepSet);
   tmp=Trim(Name_A(Value));
   РАБ.НФА.LIBREP.LibBuf[ii+1]=Value;
   РАБ.НФА.LIBREP.LibTxt[ii+1]=Value+if(tmp<>"", " - "+tmp, "");
 od;
 РАБ.НФА.LIBREP.LibTxt[1]="Удалить все";
 РАБ.НФА.LIBREP.LibBuf[1]="";
 nn=Alternate("Удаление...", РАБ.НФА.LIBREP.LibTxt, -1, 1, 12);
 if nn<1: ^Set;
 |  nn=1: ^"";
 else
   Set="";
   num=num+1;
   for ii=2 to num do if not ii=nn: Set=Объединить(Set, РАБ.НФА.LIBREP.LibBuf[ii], SepSet); fi; od;
 fi;
 ^Trim(Set);
end;

Func СортироватьНаборСлов(Set:String; SepSet:String; Flag:Logical) :String; --Сортирует набор по словам
-- Set набор слов; SepSet разделитель; Flag направление сортировки
var ii, kk :Integer;
var Value :String;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 kk=0;
 for ii=1 to WordsCount(Set, SepSet) do
   Value=ExtractWord(ii, Set, SepSet);
   if Value<>"": kk=kk+1; РАБ.НФА.LIBREP.LibBuf[kk]=Value; fi;
 od;
 Value="";
 if kk>0:
   SortArray(РАБ.НФА.LIBREP.LibBuf, Flag);
   for ii=1 to kk do Value=Объединить(Value, РАБ.НФА.LIBREP.LibBuf[ii], SepSet); od; --Value обязательно 1 параметром
 fi;
 ^Value;
end;

Func УдалитьСловаИзНабораПоМаске(Set:String; SetSep:String; Mask:String; MaskSep:String) :String;
var nn1, nn2, ii, jj :Integer;
var Res, tmp1, tmp2 :String;
 if Set="" or Mask="": ^Set; fi;
 Res="";
 nn1=WordsCount(Set,   SetSep);
 nn2=WordsCount(Mask, MaskSep);
 for ii=1 to nn1 do
   tmp1=ExtractWord(ii, Set, SetSep);
   for jj=1 to nn2 do
     tmp2=ExtractWord(jj, Mask, MaskSep);
     if Match(tmp1, tmp2): tmp1=""; Break; fi;
   od;
   if not tmp1="": Res=Объединить(Res, tmp1, SetSep); fi;
 od;
 ^Res;
end;

Func ДобавитьСловоВНаборСЗаменой(Set:String; SetSep:String; Value:String; Mask:String; MaskSep:String) :String;
var Res :String;
 if Set="": ^Value; fi;
 Res=УдалитьСловаИзНабораПоМаске(Set, SetSep, Mask, MaskSep);
 Res=Объединить(Res, Value, SetSep);
 ^Res;
end;

Func ДобавитьПризнак(Set:String; NewSign:String) :String;
var Voc :String;
 Voc=GetAnaGlossary(NewSign);
 if Voc<>"": Voc=Voc+".*"; else Voc="*"; fi;
 ^ДобавитьСловоВНаборСЗаменой(Set, " ", NewSign, Voc, "");
end;

Func ОбъединитьНаборПризнаков(SetIn1:String; SepIn1:String; SetIn2:String; SepIn2:String; SepOut:String) :String;
var len, ii, pp :Integer;
var RES, VOC, ANA :String;
 ClearVariable(РАБ.НФА.LIBREP.LibMsk);
 ClearVariable(РАБ.НФА.LIBREP.LibStr);
 RES="";
 len=WordsCount(SetIn2, SepIn2);
 if len>0:
   for ii=1 to len do
     ANA=Trim(ExtractWord(ii, SetIn2, SepIn2));
     VOC=ExtractWord(1, ANA, ".");
     pp=SearchInArray(РАБ.НФА.LIBREP.LibMsk, VOC, True, 1);
     if not pp>0: -- такого справочника еще нет, можно добавить
       pp=InsertInArraySort(РАБ.НФА.LIBREP.LibMsk, VOC);
       InsertInArray(РАБ.НФА.LIBREP.LibStr, pp, ANA);
     fi;
   od;
 fi;
 len=WordsCount(SetIn1, SepIn1);
 if len>0:
   for ii=1 to len do
     ANA=Trim(ExtractWord(ii, SetIn1, SepIn1));
     VOC=ExtractWord(1, ANA, ".");
     pp=SearchInArray(РАБ.НФА.LIBREP.LibMsk, VOC, True, 1);
     if not pp>0: -- такого справочника еще нет, можно добавить
       pp=InsertInArraySort(РАБ.НФА.LIBREP.LibMsk, VOC);
       InsertInArray(РАБ.НФА.LIBREP.LibStr, pp, ANA);
     fi;
   od;
 fi;
 len=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
 if len>0:
   for ii=1 to len do 
     RES=Объединить(RES, РАБ.НФА.LIBREP.LibStr[ii], SepOut);
   od;
 fi;
 ^RES;
end;

Func ПроверитьНаборСлов(Set:String; SepSet:String; Mask:String; SepMask:String; Msg:String) :Logical;
--Проверяет набор слов "Set" на соотвествие маске "Mask"; SepSet, SepMask - разделители; если Msg не пустое то выдаеться сообщение
var nn1,nn2, i, j :Integer;
var tmp1, tmp2 :String;
var Flag :Logical;
 nn1=WordsCount(Mask, SepMask);
 nn2=WordsCount(Set,   SepSet);
 if not nn1=0 and nn2=0: if not Msg="": Message(Msg+ExtractWord(1, Mask, SepMask), mtError); fi; ^False; fi;
 for i=1 to nn1 do
   tmp1=ExtractWord(i, Mask, SepMask);
   Flag=False;
   for j=1 to nn2 do
     tmp2=ExtractWord(j, Set, SepSet);
     if Match(tmp2, tmp1): Flag=True; Break; fi;
   od;
   if not Flag: if not Msg="": Message(Msg+tmp1, mtError); fi; ^False; fi;
 od;
 ^True;
end;

Func НаборСлов_Маску(Set:String; SetSep:String; MaskSep:String; Множество:Logical) :String;
--Возвращает маску набора слов "Set"
var num, ii :Integer;
var Res, voc :String;
 Res="";
 num=WordsCount(Set, SetSep);
 if num>0:
    for ii=1 to num do
      voc=Trim(GetAnaGlossary(ExtractWord(ii, Set, SetSep)));
      if voc<>"": Res=Res+MaskSep+voc+if(Множество, ".*", ""); fi;
    od;
    if Res<>"": Res=Trim(SubStr(Res, Length(MaskSep)+1, 255)); fi;
 fi;
 ^Res;
end;

Func ОтменитьИзмененияУсловийОтчета(CountRow:Integer; NameProcExecute:String) :Logical;
-- NameProcExecute - процедура очистки, должна быть описана в бланке вызова данной функции
var FF :Logical;
var qq :Integer;
 FF=False;
 if CountRow>0:
   qq=EnqOkCancel("Условия отбора данных для отчета изменились!^MОчистить отчет?", mtConfirmation);
   if qq=cmOk: if ProcExists(NameProcExecute): ExecuteProc(NameProcExecute); else Message("Ошибка вызова процедуры очистки отчета.", mtError); fi;
   |  qq=cmCancel: FF=True;
   fi;
 fi;
 ^FF;
end;

-- ***** ВЫБОР СУБСЧЕТОВ НФА - префикс Счета *****

Proc Счета_ПеременныеVМассивФлагов(ftrACC:Integer; StrFlags:String);
var Value :String;
var ii :Integer;
 ClearVariable(РАБ.НФА.LIBREP.LibFlg);
 if ftrACC=2: -- 11111111100000000
   Value = SubStr(StrFlags, 01, 09);  for ii=1 to 09 do РАБ.НФА.LIBREP.LibFlg[ii]=if(SubStr(Value, ii, 1)="1", True, False); od;
 |  ftrACC=3: -- 00000000011111111
   Value = SubStr(StrFlags, 10, 08);  for ii=1 to 08 do РАБ.НФА.LIBREP.LibFlg[ii]=if(SubStr(Value, ii, 1)="1", True, False); od;
 else         -- 11111111111111111
   Value = StrFlags;                  for ii=1 to 17 do РАБ.НФА.LIBREP.LibFlg[ii]=if(SubStr(Value, ii, 1)="1", True, False); od;
 fi;
end;

Func Счета_МассивФлаговVПеременные(ftrACC:Integer) :String;
var Value, StrFlags :String;
var ii :Integer;
 StrFlags=""; Value="";
 if ftrACC=2: -- 11111111100000000
   for ii=1 to 09 do Value=Value+if(РАБ.НФА.LIBREP.LibFlg[ii], "1", "0"); od; StrFlags = Value+RepStr("0", 8);
 |  ftrACC=3: -- 00000000011111111
   for ii=1 to 08 do Value=Value+if(РАБ.НФА.LIBREP.LibFlg[ii], "1", "0"); od; StrFlags = RepStr("0", 9)+Value;
 else         -- 11111111111111111
   for ii=1 to 17 do Value=Value+if(РАБ.НФА.LIBREP.LibFlg[ii], "1", "0"); od; StrFlags = Value;
 fi;
 ^StrFlags;
end;

Proc Счета_СоздатьМассивСубсчетовНФА(ftrACC:Integer);
 ClearVariable(РАБ.НФА.LIBREP.LibMsk); ClearVariable(РАБ.НФА.LIBREP.LibStr);
 if ftrACC=2: -- 11111111100000000
   РАБ.НФА.LIBREP.LibMsk[01] = "101.?1"; РАБ.НФА.LIBREP.LibStr[01] = "жилые помещения";
   РАБ.НФА.LIBREP.LibMsk[02] = "101.?2"; РАБ.НФА.LIBREP.LibStr[02] = "нежилые помещения";
   РАБ.НФА.LIBREP.LibMsk[03] = "101.?3"; РАБ.НФА.LIBREP.LibStr[03] = "сооружения";
   РАБ.НФА.LIBREP.LibMsk[04] = "101.?4"; РАБ.НФА.LIBREP.LibStr[04] = "машины и оборудование";
   РАБ.НФА.LIBREP.LibMsk[05] = "101.?5"; РАБ.НФА.LIBREP.LibStr[05] = "транспортные средства";
   РАБ.НФА.LIBREP.LibMsk[06] = "101.?6"; РАБ.НФА.LIBREP.LibStr[06] = "производственный и хозяйственный инвентарь";
   РАБ.НФА.LIBREP.LibMsk[07] = "101.?7"; РАБ.НФА.LIBREP.LibStr[07] = "библиотечный фонд";
   РАБ.НФА.LIBREP.LibMsk[08] = "101.?8"; РАБ.НФА.LIBREP.LibStr[08] = "прочие основные средства";
   РАБ.НФА.LIBREP.LibMsk[09] = "102.?0"; РАБ.НФА.LIBREP.LibStr[09] = "нематериальные активы";
 |  ftrACC=3: -- 00000000011111111
   РАБ.НФА.LIBREP.LibMsk[01] = "105.?1"; РАБ.НФА.LIBREP.LibStr[01] = "медикаменты и перевязочные средства";
   РАБ.НФА.LIBREP.LibMsk[02] = "105.?2"; РАБ.НФА.LIBREP.LibStr[02] = "продукты питания";
   РАБ.НФА.LIBREP.LibMsk[03] = "105.?3"; РАБ.НФА.LIBREP.LibStr[03] = "горюче-смазочные материалы";
   РАБ.НФА.LIBREP.LibMsk[04] = "105.?4"; РАБ.НФА.LIBREP.LibStr[04] = "строительные материалы";
   РАБ.НФА.LIBREP.LibMsk[05] = "105.?5"; РАБ.НФА.LIBREP.LibStr[05] = "мягкий инвентарь";
   РАБ.НФА.LIBREP.LibMsk[06] = "105.?6"; РАБ.НФА.LIBREP.LibStr[06] = "прочие материальные запасы";
   РАБ.НФА.LIBREP.LibMsk[07] = "105.?7"; РАБ.НФА.LIBREP.LibStr[07] = "готовая продукция";
   РАБ.НФА.LIBREP.LibMsk[08] = "105.?8"; РАБ.НФА.LIBREP.LibStr[08] = "товары";
 else         -- 11111111111111111
   РАБ.НФА.LIBREP.LibMsk[01] = "101.?1"; РАБ.НФА.LIBREP.LibStr[01] = "жилые помещения";
   РАБ.НФА.LIBREP.LibMsk[02] = "101.?2"; РАБ.НФА.LIBREP.LibStr[02] = "нежилые помещения";
   РАБ.НФА.LIBREP.LibMsk[03] = "101.?3"; РАБ.НФА.LIBREP.LibStr[03] = "сооружения";
   РАБ.НФА.LIBREP.LibMsk[04] = "101.?4"; РАБ.НФА.LIBREP.LibStr[04] = "машины и оборудование";
   РАБ.НФА.LIBREP.LibMsk[05] = "101.?5"; РАБ.НФА.LIBREP.LibStr[05] = "транспортные средства";
   РАБ.НФА.LIBREP.LibMsk[06] = "101.?6"; РАБ.НФА.LIBREP.LibStr[06] = "производственный и хозяйственный инвентарь";
   РАБ.НФА.LIBREP.LibMsk[07] = "101.?7"; РАБ.НФА.LIBREP.LibStr[07] = "библиотечный фонд";
   РАБ.НФА.LIBREP.LibMsk[08] = "101.?8"; РАБ.НФА.LIBREP.LibStr[08] = "прочие основные средства";
   РАБ.НФА.LIBREP.LibMsk[09] = "102.?0"; РАБ.НФА.LIBREP.LibStr[09] = "нематериальные активы";
   РАБ.НФА.LIBREP.LibMsk[10] = "105.?1"; РАБ.НФА.LIBREP.LibStr[10] = "медикаменты и перевязочные средства";
   РАБ.НФА.LIBREP.LibMsk[11] = "105.?2"; РАБ.НФА.LIBREP.LibStr[11] = "продукты питания";
   РАБ.НФА.LIBREP.LibMsk[12] = "105.?3"; РАБ.НФА.LIBREP.LibStr[12] = "горюче-смазочные материалы";
   РАБ.НФА.LIBREP.LibMsk[13] = "105.?4"; РАБ.НФА.LIBREP.LibStr[13] = "строительные материалы";
   РАБ.НФА.LIBREP.LibMsk[14] = "105.?5"; РАБ.НФА.LIBREP.LibStr[14] = "мягкий инвентарь";
   РАБ.НФА.LIBREP.LibMsk[15] = "105.?6"; РАБ.НФА.LIBREP.LibStr[15] = "прочие материальные запасы";
   РАБ.НФА.LIBREP.LibMsk[16] = "105.?7"; РАБ.НФА.LIBREP.LibStr[16] = "готовая продукция";
   РАБ.НФА.LIBREP.LibMsk[17] = "105.?8"; РАБ.НФА.LIBREP.LibStr[17] = "товары";
 fi;
end;

Proc Счета_ОбновитьМеню(Iter:Integer; MaxK:Integer);
 if Iter>MaxK: РАБ.НФА.LIBREP.LibBuf[Iter]="КОД$"+РАБ.НФА.LIBREP.LibMsk[Iter-MaxK]+"-->> "+if(РАБ.НФА.LIBREP.LibFlg[Iter-MaxK], "[ВКЛ.]: ", "[ВЫКЛ.]: ")+РАБ.НФА.LIBREP.LibStr[Iter-MaxK]; fi;
end;

Func Счета_ФлагиСубсчетовВТекст(ftrACC:Integer) :String;
var num, ii, kk, j1, j2, j5 :Integer;
var res, res101, res102, res105 :String;
 num=LengthOfArray(РАБ.НФА.LIBREP.LibFlg);
 kk=0; j1=0; j2=0; j5=0;
 res101=""; res102=""; res105="";
 for ii=1 to num do
   if РАБ.НФА.LIBREP.LibFlg[ii]:
     kk=kk+1;
     if ftrACC=2:
       if Match(РАБ.НФА.LIBREP.LibMsk[ii], "101.??"): j1=j1+1; res101=res101+" "+РАБ.НФА.LIBREP.LibMsk[ii];
       |  Match(РАБ.НФА.LIBREP.LibMsk[ii], "102.??"): j2=j2+1; res102=res102+" "+РАБ.НФА.LIBREP.LibMsk[ii];
       fi;
     |  ftrACC=3:
       if Match(РАБ.НФА.LIBREP.LibMsk[ii], "105.??"): j5=j5+1; res105=res105+" "+РАБ.НФА.LIBREP.LibMsk[ii]; fi;
     else
       if Match(РАБ.НФА.LIBREP.LibMsk[ii], "101.??"): j1=j1+1; res101=res101+" "+РАБ.НФА.LIBREP.LibMsk[ii];
       |  Match(РАБ.НФА.LIBREP.LibMsk[ii], "102.??"): j2=j2+1; res102=res102+" "+РАБ.НФА.LIBREP.LibMsk[ii];
       |  Match(РАБ.НФА.LIBREP.LibMsk[ii], "105.??"): j5=j5+1; res105=res105+" "+РАБ.НФА.LIBREP.LibMsk[ii];
       fi;
     fi;
   fi;
 od;
 res101=Trim(res101);
 res102=Trim(res102);
 res105=Trim(res105);
 if j1=8: res101="101.??"; fi; -- субсчетов 101 - 8 штук
 if j2=1: res102="102.?0"; fi; -- субсчетов 102 - 1 штук
 if j5=8: res105="105.??"; fi; -- субсчетов 105 - 8 штук
 res="";
 if ftrACC=2: if kk=num: res="101.?? 102.?0";        else res=res101+" "+res102;            fi;
 |  ftrACC=3: if kk=num: res="105.??";               else res=res105;                       fi;
 else         if kk=num: res="101.?? 102.?0 105.??"; else res=res101+" "+res102+" "+res105; fi;
 fi;
 ^Trim(res);
end;

Func ПравильныеФлаги(StrFlags:String; TrueLen:Integer) :Logical;
var sChar :String;
var Work :Logical;
var ii :Integer;
 Work=False;
 if Length(StrFlags)=TrueLen and TrueLen>0:
   Work=True;
   for ii=1 to TrueLen do
     sChar=SubStr(StrFlags, ii, 1);
     if not (sChar="0" or sChar="1"): Work=False; Break; fi;
   od;
 fi;
 ^Work;
end;

Func Счета_ВыборСубсчетовНФА(ftrACC:Integer; prevFlags:String) :String;
var kk, MaxK, num, ii :Integer;
var currFlags :String;
 -- XXXXXXXXYZZZZZZZZ
 -- 12345678901234567
 if ПравильныеФлаги(prevFlags, 17): currFlags=prevFlags; else currFlags=RepStr("0", 17); fi;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 MaxK=0;
 РАБ.НФА.LIBREP.LibBuf[1]=Chr(149)+"-->> Отмена изменений";
 РАБ.НФА.LIBREP.LibBuf[2]=Chr(169)+"-->> Утвердить изменения";
 РАБ.НФА.LIBREP.LibBuf[3]=Chr(187)+Chr(043)+Chr(171)+"-->> Выделить все счета НФА";
 РАБ.НФА.LIBREP.LibBuf[4]=Chr(171)+Chr(151)+Chr(187)+"-->> Сбросить все счета НФА";
 РАБ.НФА.LIBREP.LibBuf[5]="КОД$-->> Счета учета НФА.";
 MaxK=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 Счета_СоздатьМассивСубсчетовНФА(ftrACC);
 Счета_ПеременныеVМассивФлагов(ftrACC, currFlags);
 num=LengthOfArray(РАБ.НФА.LIBREP.LibMsk);
 for ii=1 to num do
   РАБ.НФА.LIBREP.LibBuf[ii+MaxK]="КОД$"+РАБ.НФА.LIBREP.LibMsk[ii]+"-->> "+if(РАБ.НФА.LIBREP.LibFlg[ii], "[ВКЛ.]: ", "[ВЫКЛ.]: ")+РАБ.НФА.LIBREP.LibStr[ii];
 od;
 kk=0;
 while kk=0 or kk>MaxK do
   Счета_ОбновитьМеню(kk, MaxK);
   kk=AlternateTree("", РАБ.НФА.LIBREP.LibBuf, -1, if(kk>MaxK, kk, MaxK), 12, "$", "Параметр", "Комментарий", -1, False);
   if kk=1:
     ^currFlags;
   |  kk=2:
     if SearchInArray(РАБ.НФА.LIBREP.LibFlg, True, False, 1)<1:
        Message("[Утвердить изменения]^MНет выбранных счетов!", mtWarning);
        kk=0;
     fi;
   |  kk=3:
     for ii=1 to num do РАБ.НФА.LIBREP.LibFlg[ii]=True;  Счета_ОбновитьМеню(ii+MaxK, MaxK); od;
     kk=0;
   |  kk=4:
     for ii=1 to num do РАБ.НФА.LIBREP.LibFlg[ii]=False; Счета_ОбновитьМеню(ii+MaxK, MaxK); od;
     kk=0;
   |  kk>MaxK:
     РАБ.НФА.LIBREP.LibFlg[kk-MaxK] = not РАБ.НФА.LIBREP.LibFlg[kk-MaxK];
   fi;
 od;
 ^(Счета_МассивФлаговVПеременные(ftrACC));
end;

-- ***** ВЫБОР СУБСЧЕТОВ АМОРТИЗАЦИИ - префикс Амортизация *****

Proc Амортизация_ПеременныеVМассивФлагов(StrFlags:String);
var ii :Integer;
 ClearVariable(РАБ.НФА.LIBREP.LibFlg);
 for ii=1 to 9 do РАБ.НФА.LIBREP.LibFlg[ii]=if(SubStr(StrFlags, ii, 1)="1", True, False); od;
end;

Func Амортизация_МассивФлаговVПеременные :String;
var StrFlags :String;
var ii :Integer;
 StrFlags="";
 for ii=1 to 9 do StrFlags=StrFlags+if(РАБ.НФА.LIBREP.LibFlg[ii], "1", "0"); od;
 ^StrFlags;
end;

Proc Амортизация_СоздатьМассивСубсчетовАмортизации;
 ClearVariable(РАБ.НФА.LIBREP.LibMsk); ClearVariable(РАБ.НФА.LIBREP.LibStr);
 РАБ.НФА.LIBREP.LibMsk[01] = "104.?1"; РАБ.НФА.LIBREP.LibStr[01] = "амортизация жилых помещений";
 РАБ.НФА.LIBREP.LibMsk[02] = "104.?2"; РАБ.НФА.LIBREP.LibStr[02] = "амортизация нежилых помещений";
 РАБ.НФА.LIBREP.LibMsk[03] = "104.?3"; РАБ.НФА.LIBREP.LibStr[03] = "амортизация сооружений";
 РАБ.НФА.LIBREP.LibMsk[04] = "104.?4"; РАБ.НФА.LIBREP.LibStr[04] = "амортизация машин и оборудования";
 РАБ.НФА.LIBREP.LibMsk[05] = "104.?5"; РАБ.НФА.LIBREP.LibStr[05] = "амортизация транспортных средств";
 РАБ.НФА.LIBREP.LibMsk[06] = "104.?6"; РАБ.НФА.LIBREP.LibStr[06] = "амортизация производственного и хозяйственного инвентаря";
 РАБ.НФА.LIBREP.LibMsk[07] = "104.?7"; РАБ.НФА.LIBREP.LibStr[07] = "амортизация библиотечного фонда";
 РАБ.НФА.LIBREP.LibMsk[08] = "104.?8"; РАБ.НФА.LIBREP.LibStr[08] = "амортизация прочих основных средств";
 РАБ.НФА.LIBREP.LibMsk[09] = "104.?9"; РАБ.НФА.LIBREP.LibStr[09] = "амортизация нематериальных активов";
end;

Proc Амортизация_ОбновитьМеню(Iter:Integer; MaxK:Integer);
 if Iter>MaxK: РАБ.НФА.LIBREP.LibBuf[Iter]="КОД$"+РАБ.НФА.LIBREP.LibMsk[Iter-MaxK]+"-->> "+if(РАБ.НФА.LIBREP.LibFlg[Iter-MaxK], "[ВКЛ.]: ", "[ВЫКЛ.]: ")+РАБ.НФА.LIBREP.LibStr[Iter-MaxK]; fi;
end;

Func Амортизация_ФлагиСубсчетовВТекст :String;
var num, ii, kk :Integer;
var RES :String;
 num=LengthOfArray(РАБ.НФА.LIBREP.LibFlg);
 RES="";
 kk=0;
 for ii=1 to num do
   if РАБ.НФА.LIBREP.LibFlg[ii]:
     if Match(РАБ.НФА.LIBREP.LibMsk[ii], "104.??"): kk=kk+1; RES=RES+" "+РАБ.НФА.LIBREP.LibMsk[ii]; fi;
   fi;
 od;
 if (kk=9 or RES=""): RES="104.??"; else RES=Trim(RES); fi; -- субсчетов 104 - 9 штук
 ^RES;
end;

Func Амортизация_ВыборСубсчетовАмортизации(prevFlags:String) :String;
var kk, MaxK, num, ii :Integer;
var currFlags :String;
 if ПравильныеФлаги(prevFlags, 9): currFlags=prevFlags; else currFlags=RepStr("0", 9); fi;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 MaxK=0;
 РАБ.НФА.LIBREP.LibBuf[1]=Chr(149)+"-->> Отмена изменений";
 РАБ.НФА.LIBREP.LibBuf[2]=Chr(169)+"-->> Утвердить изменения";
 РАБ.НФА.LIBREP.LibBuf[3]=Chr(187)+Chr(043)+Chr(171)+"-->> Выделить все счета амортизации";
 РАБ.НФА.LIBREP.LibBuf[4]=Chr(171)+Chr(151)+Chr(187)+"-->> Сбросить все счета амортизации";
 РАБ.НФА.LIBREP.LibBuf[5]="КОД$-->> Счета учета амортизации.";
 MaxK=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 Амортизация_СоздатьМассивСубсчетовАмортизации;
 Амортизация_ПеременныеVМассивФлагов(currFlags);
 num=LengthOfArray(РАБ.НФА.LIBREP.LibMsk);
 for ii=1 to num do
   РАБ.НФА.LIBREP.LibBuf[ii+MaxK]="КОД$"+РАБ.НФА.LIBREP.LibMsk[ii]+"-->> "+if(РАБ.НФА.LIBREP.LibFlg[ii], "[ВКЛ.]: ", "[ВЫКЛ.]: ")+РАБ.НФА.LIBREP.LibStr[ii];
 od;
 kk=0;
 while kk=0 or kk>MaxK do
   Амортизация_ОбновитьМеню(kk, MaxK);
   kk=AlternateTree("", РАБ.НФА.LIBREP.LibBuf, -1, if(kk>MaxK, kk, MaxK), 12, "$", "Параметр", "Комментарий", -1, False);
   if kk=1:
     ^currFlags;
   |  kk=2:
     if SearchInArray(РАБ.НФА.LIBREP.LibFlg, True, False, 1)<1:
        Message("[Утвердить изменения]^MНет выбранных счетов!", mtWarning);
        kk=0;
     fi;
   |  kk=3:
     for ii=1 to num do РАБ.НФА.LIBREP.LibFlg[ii]=True;  Амортизация_ОбновитьМеню(ii+MaxK, MaxK); od;
     kk=0;
   |  kk=4:
     for ii=1 to num do РАБ.НФА.LIBREP.LibFlg[ii]=False; Амортизация_ОбновитьМеню(ii+MaxK, MaxK); od;
     kk=0;
   |  kk>MaxK:
     РАБ.НФА.LIBREP.LibFlg[kk-MaxK] = not РАБ.НФА.LIBREP.LibFlg[kk-MaxK];
   fi;
 od;
 ^(Амортизация_МассивФлаговVПеременные);
end;

-- ***** ДЛЯ ВЫБОРА ПАРАМЕТРОВ ИЕРАРХИЧЕСКОЙ ГРУППИРОВКИ - префикс ПорядокГрупп *****

Func ПорядокГрупп_ГруппаТекст(nameField:String) :String;
 nameField=Up(nameField);
 if Pos("ВФО", nameField)>0: ^"Вид финансового обеспечения (источники)";
 |  Pos("ГРП", nameField)>0: ^"Пользовательские группы нфа";
 |  Pos("ДОП", nameField)>0: ^"Дополнительный справочник";
 |  Pos("ДС1", nameField)>0: ^"Дополнительный справочник 1";
 |  Pos("ДС2", nameField)>0: ^"Дополнительный справочник 2";
 |  Pos("КБК", nameField)>0: ^"Код бюджетной классификации (КБК)";
 |  Pos("МОЛ", nameField)>0: ^"Материально ответственное лицо";
 |  Pos("МХЭ", nameField)>0: ^"Местонахождение";
 |  Pos("НФА", nameField)>0: ^"НФА по типам";
 |  Pos("СЧТ", nameField)>0: ^"Счет (синтетический)";
 else ^"";
 fi;
end;

Proc ПорядокГрупп_СформироватьМеню(wrdИерархия:String);
var ii, kk, num :Integer;
var Value :String;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf); ClearVariable(РАБ.НФА.LIBREP.LibStr);
 РАБ.НФА.LIBREP.LibBuf[1]=Chr(149)+" ВЫПОЛНЕНО "+Chr(149);
 kk=2;
 num=WordsCount(wrdИерархия, " ");
 for ii=1 to num do
   Value=ExtractWord(ii, wrdИерархия, " ");
   РАБ.НФА.LIBREP.LibStr[ii]   = Value;
   РАБ.НФА.LIBREP.LibBuf[kk]   = "на уровень ВЫШЕ - "+ПорядокГрупп_ГруппаТекст(Value);
   РАБ.НФА.LIBREP.LibBuf[kk+1] = "на уровень НИЖЕ - "+ПорядокГрупп_ГруппаТекст(Value);
   kk=kk+2;
 od;
end;

Func ПорядокГрупп_ПоменятьМестами(Iter:Integer; Вверх:Logical) :String;
var ii, num :Integer;
var RES, Value :String;

 RES="";

 if Вверх:
   if Iter=1:
     Message("Это первая строчка.^MПередвинуть выше строчку нельзя!", mtInformation);
   else
     Value=РАБ.НФА.LIBREP.LibStr[Iter-1]; РАБ.НФА.LIBREP.LibStr[Iter-1]=РАБ.НФА.LIBREP.LibStr[Iter]; РАБ.НФА.LIBREP.LibStr[Iter]=Value;
   fi;
 else
   if Iter=LengthOfArray(РАБ.НФА.LIBREP.LibStr):
     Message("Это последняя строчка.^MПередвинуть ниже строчку нельзя!", mtInformation);
   else
     Value=РАБ.НФА.LIBREP.LibStr[Iter+1]; РАБ.НФА.LIBREP.LibStr[Iter+1]=РАБ.НФА.LIBREP.LibStr[Iter]; РАБ.НФА.LIBREP.LibStr[Iter]=Value;
   fi;
 fi;

 -- Формируем новый порядок полей групп
 RES="";
 num=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
 for ii=1 to num do RES=Объединить(RES, РАБ.НФА.LIBREP.LibStr[ii], " "); od;
 ^RES;

end;

Func ПорядокГрупп_ПоменятьМестами_Менюшка(prevValue:String; fldGoTo:String) :String;
var num, kk, jj :Integer;
var Flag :Logical;
var newValue :String;

 if Trim(prevValue)="":
   Message("Нет ни одной группы,^Mприменяемой при построении таблицы!", mtError);
   Template.Field=fldGoTo;
   ^prevValue;
 fi;

 num=WordsCount(prevValue, " ");
 if num=1: Message("Обнаружена одна группа.^MПередвигать нечего!", mtInformation); ^prevValue; fi;

 ПорядокГрупп_СформироватьМеню(prevValue);

 num=0; jj=1; newValue="";
 while num<>1 do
   num=Alternate("Выберите действие...", РАБ.НФА.LIBREP.LibBuf, -1, jj, 12);
   if num>1:
     Flag=ЧетныйИндекс(num);
     kk=Int(Trunc(num/2));
     newValue=ПорядокГрупп_ПоменятьМестами(kk, Flag);
     ПорядокГрупп_СформироватьМеню(newValue);
     if Flag: jj=num-2; if jj<2: jj=2; fi; else jj=num+2; fi;
   fi;
 od;

 ^newValue;
end;

Func ПорядокГрупп_СобратьГруппы(curValue:String;
                                uВФО:Integer;
                                uГРП:Integer;
                                uДОП:Integer;
                                uДС1:Integer;
                                uДС2:Integer;
                                uКБК:Integer;
                                uМОЛ:Integer;
                                uМХЭ:Integer;
                                uНФА:Integer;
                                uСЧТ:Integer
                               ) :String;
var xx, num, ii, pp :Integer;
var newValue :String;
 ClearVariable(РАБ.НФА.LIBREP.LibStr); ClearVariable(РАБ.НФА.LIBREP.LibInt);
 xx=0; newValue="";
 -- узнаем текущие настройки
 if not uВФО<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<ВФО>"; РАБ.НФА.LIBREP.LibInt[xx] = uВФО; fi;  -- группировка (Вид финансового обеспечения (источники))
 if not uГРП<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<ГРП>"; РАБ.НФА.LIBREP.LibInt[xx] = uГРП; fi;  -- группировка (Пользовательские группы НФА)
 if not uДОП<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<ДОП>"; РАБ.НФА.LIBREP.LibInt[xx] = uДОП; fi;  -- группировка "Дополнительный справочник (единственный)"
 if not uДС1<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<ДС1>"; РАБ.НФА.LIBREP.LibInt[xx] = uДС1; fi;  -- группировка "Дополнительный справочник 1"
 if not uДС2<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<ДС2>"; РАБ.НФА.LIBREP.LibInt[xx] = uДС2; fi;  -- группировка "Дополнительный справочник 2"
 if not uКБК<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<КБК>"; РАБ.НФА.LIBREP.LibInt[xx] = uКБК; fi;  -- группировка "Код бюджетной классификации (КБК)"
 if not uМОЛ<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<МОЛ>"; РАБ.НФА.LIBREP.LibInt[xx] = uМОЛ; fi;  -- группировка "Материально ответственное лицо"
 if not uМХЭ<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<МХЭ>"; РАБ.НФА.LIBREP.LibInt[xx] = uМХЭ; fi;  -- группировка "Местонахождение"
 if not uНФА<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<НФА>"; РАБ.НФА.LIBREP.LibInt[xx] = uНФА; fi;  -- группировка "По типам НФА (больше 40'000 меньше 3'000)"
 if not uСЧТ<0: xx=xx+1; РАБ.НФА.LIBREP.LibStr[xx]="<СЧТ>"; РАБ.НФА.LIBREP.LibInt[xx] = uСЧТ; fi;  -- группировка "Счет синтетический"
 -- синхронизируем порядок группировки полей с настройками
 num=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
 if num>0:
   for ii=1 to num do
     pp=Pos(РАБ.НФА.LIBREP.LibStr[ii], curValue);
     if РАБ.НФА.LIBREP.LibInt[ii] =2 and pp<1: curValue =      Объединить(curValue, РАБ.НФА.LIBREP.LibStr[ii], " ");
     |  РАБ.НФА.LIBREP.LibInt[ii]<>2 and pp>0: curValue = DeleteWordInStr(curValue, РАБ.НФА.LIBREP.LibStr[ii], " ");
     fi;
   od;
   newValue=curValue;
 else
   newValue="";
 fi;
 ^newValue;

end;

Proc ПорядокГрупп_ОтобразитьГруппыТаблицы(ObjRef:String; wrdИерархия:String; maxFlags:Integer; WrkCol:Integer; HdrRow:Integer);
var num, kk, ii, cc, rc :Integer;
var СекцИмя : Object;
var Flag :Logical;
 --ObjRef        - секция для отображения настройки иерархии
 --wrdИерархия   - сама строчка иерархии
 --maxFlags      - максимальное число узлов иерархии
 --col           - начальная колонка в секции для отображения текущей настройки порядка следования узлов иерархии
 if FindObject(ObjRef, СекцИмя):
   cc=asInteger(СекцИмя.ColsCount);
   rc=asInteger(СекцИмя.RowsCount);
   if WrkCol<cc and maxFlags<rc:
     num=WordsCount(wrdИерархия, " ");
     if num>0:
       for ii=1 to num do
         СекцИмя.Cell(ii+HdrRow, WrkCol  , CellContents, Str(ii)+" уровень");
         СекцИмя.Cell(ii+HdrRow, WrkCol+1, CellContents, ПорядокГрупп_ГруппаТекст(ExtractWord(ii, wrdИерархия, " ")));
       od;
       Flag=True;
     else
       num=1;
       СекцИмя.Cell(num+HdrRow, WrkCol  , CellContents, "", True);
       СекцИмя.Cell(num+HdrRow, WrkCol+1, CellContents, "нет групп для разбиения на таблицы");
       Flag=False;
     fi;
     kk=maxFlags-num;
     if kk>0:
       for ii=1 to kk do
         СекцИмя.Cell(ii+HdrRow+num, WrkCol  , CellContents, "", True);
         СекцИмя.Cell(ii+HdrRow+num, WrkCol+1, CellContents, "", True);
       od;
     fi;
   fi; -- col<cc and maxFlags<rc
 fi; --FindObject

end;

-- ***** ВЫБОР ВИДА ФИНАНСОВОГО ОБЕСПЕЧЕНИЯ (ИСТОЧНИКА)  - префикс ВФО *****

Proc ВФО_ПеременныеVМассивФлагов(StrFlags:String);
var ii :Integer;
 ClearVariable(РАБ.НФА.LIBREP.LibFlg);
 for ii=1 to 8 do РАБ.НФА.LIBREP.LibFlg[ii]=if(SubStr(StrFlags, ii, 1)="1", True, False); od;
end;

Func ВФО_МассивФлаговVПеременные :String;
var StrFlags :String;
var ii :Integer;
 StrFlags="";
 for ii=1 to 8 do StrFlags=StrFlags+if(РАБ.НФА.LIBREP.LibFlg[ii], "1", "0"); od;
 ^StrFlags;
end;

Proc ВФО_СоздатьМассивИсточников;
 ClearVariable(РАБ.НФА.LIBREP.LibMsk); ClearVariable(РАБ.НФА.LIBREP.LibStr);
 РАБ.НФА.LIBREP.LibMsk[1] = "1"; РАБ.НФА.LIBREP.LibStr[1] = "Бюджетная деятельность";
 РАБ.НФА.LIBREP.LibMsk[2] = "2"; РАБ.НФА.LIBREP.LibStr[2] = "Приносящая доход деятельность (собственные доходы учреждения)";
 РАБ.НФА.LIBREP.LibMsk[3] = "3"; РАБ.НФА.LIBREP.LibStr[3] = "Средства во временном распоряжении";
 РАБ.НФА.LIBREP.LibMsk[4] = "4"; РАБ.НФА.LIBREP.LibStr[4] = "Субсидии на выполнение государственного (муниципального) задания";
 РАБ.НФА.LIBREP.LibMsk[5] = "5"; РАБ.НФА.LIBREP.LibStr[5] = "Субсидии на иные цели";
 РАБ.НФА.LIBREP.LibMsk[6] = "6"; РАБ.НФА.LIBREP.LibStr[6] = "Субсидии на цели осуществления капитальных вложений";
 РАБ.НФА.LIBREP.LibMsk[7] = "7"; РАБ.НФА.LIBREP.LibStr[7] = "Средства по обязательному медицинскому страхованию";
 РАБ.НФА.LIBREP.LibMsk[8] = "8"; РАБ.НФА.LIBREP.LibStr[8] = "Средства некоммерческих организаций на лицевых счетах";
end;

Proc ВФО_ОбновитьМеню(Iter:Integer; MaxK:Integer);
 if Iter>MaxK: РАБ.НФА.LIBREP.LibBuf[Iter]="КОД$"+РАБ.НФА.LIBREP.LibMsk[Iter-MaxK]+"-->> "+if(РАБ.НФА.LIBREP.LibFlg[Iter-MaxK], "[ВКЛ.]: ", "[ВЫКЛ.]: ")+РАБ.НФА.LIBREP.LibStr[Iter-MaxK]; fi;
end;

Func ВФО_ФлагиВТекст :String;
var num, ii, kk :Integer;
var RES, Value :String;
 num=LengthOfArray(РАБ.НФА.LIBREP.LibFlg); kk=0; RES="";
 for ii=1 to num do
   if РАБ.НФА.LIBREP.LibFlg[ii]: kk=kk+1; Value="["+РАБ.НФА.LIBREP.LibMsk[ii]+"] "+РАБ.НФА.LIBREP.LibStr[ii]; RES=Объединить(RES, Value, " | "); fi;
 od;
 if kk=num: RES="[?] Все виды финансового обеспечения"; fi;
 ^RES;
end;

Func ВФО_ВыбратьВидФинансовогоОбеспечения(prevFlags:String) :String;
var kk, MaxK, num, ii, zz :Integer;
var currFlags :String;
 if ПравильныеФлаги(prevFlags, 8): currFlags=prevFlags; else currFlags=RepStr("1", 8); fi;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 MaxK=0;
 РАБ.НФА.LIBREP.LibBuf[1]=Chr(149)+"-->> Отмена изменений";
 РАБ.НФА.LIBREP.LibBuf[2]=Chr(169)+"-->> Утвердить изменения";
 РАБ.НФА.LIBREP.LibBuf[3]=Chr(187)+Chr(043)+Chr(171)+"-->> Выделить все виды финансового обеспечения";
 РАБ.НФА.LIBREP.LibBuf[4]=Chr(171)+Chr(151)+Chr(187)+"-->> Сбросить все виды финансового обеспечения";
 РАБ.НФА.LIBREP.LibBuf[5]="КОД$-->> Виды финансового обеспечения";
 MaxK=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 ВФО_СоздатьМассивИсточников;
 ВФО_ПеременныеVМассивФлагов(currFlags);
 num=LengthOfArray(РАБ.НФА.LIBREP.LibMsk);
 for ii=1 to num do
   РАБ.НФА.LIBREP.LibBuf[ii+MaxK]="КОД$"+РАБ.НФА.LIBREP.LibMsk[ii]+"-->> "+if(РАБ.НФА.LIBREP.LibFlg[ii], "[ВКЛ.]: ", "[ВЫКЛ.]: ")+РАБ.НФА.LIBREP.LibStr[ii];
 od;
 kk=0;
 while kk=0 or kk>MaxK do
   ВФО_ОбновитьМеню(kk, MaxK);
   kk=AlternateTree("", РАБ.НФА.LIBREP.LibBuf, -1, if(kk>MaxK, kk, MaxK), 12, "$", "Параметр", "Комментарий", -1, False);
   if kk=1:
     ^currFlags;
   |  kk=2:
     zz=0;
     for ii=1 to num do if РАБ.НФА.LIBREP.LibFlg[ii]: zz=zz+1; fi; od;
     if zz<1:
        Message("[Утвердить изменения]^MНет выбранных видов финансового обеспечения!", mtWarning);
        kk=0;
     |  zz>3 and zz<>num:
        Message("[Утвердить изменения]^MПо техническим причинам возможен выбор не более 3 видов финансового обеспечения^MУменьшите количество видов или выберите пункт 'Выделить все виды финансового обеспечения'", mtWarning);
        kk=0;
     fi;
   |  kk=3:
     for ii=1 to num do РАБ.НФА.LIBREP.LibFlg[ii]=True;  ВФО_ОбновитьМеню(ii+MaxK, MaxK); od;
     kk=0;
   |  kk=4:
     for ii=1 to num do РАБ.НФА.LIBREP.LibFlg[ii]=False; ВФО_ОбновитьМеню(ii+MaxK, MaxK); od;
     kk=0;
   |  kk>MaxK:
     РАБ.НФА.LIBREP.LibFlg[kk-MaxK] = not РАБ.НФА.LIBREP.LibFlg[kk-MaxK];
   fi;
 od;
 --
 ^(ВФО_МассивФлаговVПеременные);
end;

-- ***** ВЫБОР ДОПОЛНИТЕЛЬНОГО СПРАВОЧНИКА - префикс ДопСпр *****

Func AddVoc_OSTOPER_MOD2(RepDat:Date; ИсключитьОбязательные:Logical; ВсеСправочники:Logical; SepRes:String; Auto:Logical; ПринудительноИсключить:String) :String;
-- ИсключитьОбязательные - исключать набор обязательных для учета НФА справочников (М МОЛ НФА УЧН)
-- ВсеСправочники - всегда выводить все найденные справочники
var RO, OA, num, ii, len, jj, kk, cnt :Integer;
var Путь, ANA, Value, VOC :String;
var Отч1 :Report;
var REC :Record;
var OK :Logical;

 Refresh(False);
 ClearVariable(РАБ.НФА.LIBREP.LibTxt);
 Путь=PlanVar("НФА")+"\ОТЧЕТЫ\НФАОТЧ2007.lst";
 if ExistFile(Путь):
   Try
     Отч1=RepOpen(Путь+"|По_признакам_БАЛиЗАБ", sМаскаНФА, "(ДНФА.РАСХ.*|ДНФА.ВНПР.*)&МОЛ.*&М.*&НФА.*", 1.1.100, RepDat+1, "", "ДНФА");
     Try while RepNext(Отч1) do AddInArray(РАБ.НФА.LIBREP.LibTxt, True, False, RepIdent(Отч1)); end; Finally Отч1=RepClose(Отч1); end;
   Except
   end;
 fi;
 if LengthOfArray(РАБ.НФА.LIBREP.LibTxt)=0: for Sign ANA="ДНФА.РАСХ.*|ДНФА.ВНПР.*" do AddInArray(РАБ.НФА.LIBREP.LibTxt, True, False, ANA); od; fi;
 ClearVariable(РАБ.НФА.LIBREP.LibStr);
 ClearVariable(РАБ.НФА.LIBREP.LibInt);
 num=LengthOfArray(РАБ.НФА.LIBREP.LibTxt); -- количество нужных типов операций движения НФА
 if num>0:
   ShowProgress(num, "Анализируем...");
   RO=OpenWorkArea("РПО_ДНФА", "", "1=0");
   Try
     for ii=1 to num do
       ProgressPos(ii);
       ClearVariable(РАБ.НФА.LIBREP.LibMsk);
       ANA=РАБ.НФА.LIBREP.LibTxt[ii];
       if SignCardFile(ANA)="РПО_ДНФА": -- чтоб не попасть на текстовый признак
         REC=SignToRecord(ANA, False);
         if REC<>NIL:
           SetFilter(RO, "Ukey="+RecordToString(REC));
           if Records(RO)=1:
             ClearVariable(РАБ.НФА.LIBREP.LibBuf); -- для исключенных справочников
             if ИсключитьОбязательные:
               РАБ.НФА.LIBREP.LibBuf[1]="М";
               РАБ.НФА.LIBREP.LibBuf[2]="МОЛ";
               РАБ.НФА.LIBREP.LibBuf[3]="НФА";
               РАБ.НФА.LIBREP.LibBuf[4]="УЧН";
             fi;
             Value=Up(Trim(ПринудительноИсключить));
             len=WordsCount(Value, "|"); if len>0: for jj=1 to len do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(jj, Value, "|")); od; ВсеСправочники=True; fi;
             Value=Up(Trim(GetFieldS(RO, 1, "НЕДЕЙСТВСПР")));
             len=WordsCount(Value, "|"); if len>0: for jj=1 to len do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(jj, Value, "|")); od; fi;
             Value=Up(Trim(GetFieldS(RO, 1, "НЕДЕЙСТВОСТ")));
             len=WordsCount(Value, "|"); if len>0: for jj=1 to len do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(jj, Value, "|")); od; fi;
             OA=OpenArray(RO, 1, "ЗАПРОС", "", "ОСТАТОК and (ТИППАРАМЕТРА=1 or ТИППАРАМЕТРА=9 or ТИППАРАМЕТРА=14)"); -- (1 НФА) (9 аналитика) (14 аналитика ручного ввода)
             len=Records(OA);
             if len>0:
               for jj=1 to len do
                 OK=False;
                 Value=Trim(GetFieldS(OA, jj, "СПР"));
                 if Value<>"":
                   cnt=WordsCount(Value, "|");
                   if cnt>0:
                     for kk=1 to cnt do
                       VOC=GetAnaGlossary(Up(ExtractWord(1, ExtractWord(kk, Value, "|"), ".")));
                       if VOC<>"": 
                         if SearchInArray(РАБ.НФА.LIBREP.LibBuf, VOC, True, 1)=-1:
                           AddInArray(РАБ.НФА.LIBREP.LibMsk, True, False, VOC);
                           if not OK: OK=True; fi;
                         fi;
                       fi;
                     od;
                   fi;
                 fi;
                 if not OK:
                   Value=Trim(GetFieldS(OA, jj, "ОТВЕТ"));
                   if Value<>"":
                     cnt=WordsCount(Value, "|");
                     if cnt>0:
                       for kk=1 to cnt do
                         VOC=GetAnaGlossary(Up(ExtractWord(1, ExtractWord(kk, Value, "|"), ".")));
                         if VOC<>"":
                           if SearchInArray(РАБ.НФА.LIBREP.LibBuf, VOC, True, 1)=-1:
                             AddInArray(РАБ.НФА.LIBREP.LibMsk, True, False, VOC);
                             if not OK: OK=True; fi;
                           fi;
                         fi;
                       od;
                     fi;
                   fi;
                 fi;
               od;
             fi;
             CloseWorkArea(OA);
           fi;
         fi;
       fi;
       len=lengthOfArray(РАБ.НФА.LIBREP.LibMsk);
       if len>0:
         for jj=1 to len do
           cnt=SearchInArray(РАБ.НФА.LIBREP.LibStr, РАБ.НФА.LIBREP.LibMsk[jj], True, 1);
           if cnt=-1:
             kk=InsertInArraySort(РАБ.НФА.LIBREP.LibStr, РАБ.НФА.LIBREP.LibMsk[jj]);
             InsertInArray(РАБ.НФА.LIBREP.LibInt, kk, 1);
           else
             РАБ.НФА.LIBREP.LibInt[cnt]=РАБ.НФА.LIBREP.LibInt[cnt]+1;
           fi;
         od;
       fi;
     od;
   Finally
     CloseWorkArea(RO);
     CloseProgress;
   end;
   Value="";
   len=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
   if len>0:
     cnt=0;
     if not ВсеСправочники and not Auto:
       OK=False;
       for jj=1 to len do if РАБ.НФА.LIBREP.LibInt[jj]<>num: OK=True; Break; fi; od;
       if OK:
         kk=0;
         while kk=0 do
           kk=Enquiry("Выберите действие...", "В операциях движения НФА обнаружены неодинаковые наборы справочников для остатков.^MНеобходимо выбрать...", "...только общие справочники;...все справочники", mtConfirmation);
         od;
         if kk=1: cnt=+1; | kk=2: cnt=-1; fi;
       else
         cnt=-1;
       fi;
     else
       cnt=-1;
     fi;
     if cnt>0:
       for jj=1 to len do if РАБ.НФА.LIBREP.LibInt[jj]=num: Value=Объединить(Value, РАБ.НФА.LIBREP.LibStr[jj], SepRes); fi; od;
     else
       for jj=1 to len do Value=Объединить(Value, РАБ.НФА.LIBREP.LibStr[jj], SepRes); od;
     fi;
   fi;
   ClearVariable(РАБ.НФА.LIBREP.LibBuf);
   ClearVariable(РАБ.НФА.LIBREP.LibTxt);
   ClearVariable(РАБ.НФА.LIBREP.LibStr);
   ClearVariable(РАБ.НФА.LIBREP.LibMsk);
   ClearVariable(РАБ.НФА.LIBREP.LibInt);
   ^Value;
 fi; --num>0
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 ClearVariable(РАБ.НФА.LIBREP.LibTxt);
 ClearVariable(РАБ.НФА.LIBREP.LibStr);
 ClearVariable(РАБ.НФА.LIBREP.LibMsk);
 ClearVariable(РАБ.НФА.LIBREP.LibInt);
 ^"";
end;

Func AddVoc_OSTOPER(aRepDat:Date; aИсключитьОбязательные:Logical; aВсеСправочники:Logical; aSepRes:String; aAuto:Logical) :String;
 ^AddVoc_OSTOPER_MOD2(aRepDat, aИсключитьОбязательные, aВсеСправочники, aSepRes, aAuto, "");
end;

Func AddVoc_OSTOPER_ПоГруппеСчетов(RepDat:Date; RepMskACC:String; RepMskNFA:String; ВсеСправочники:Logical; ИсключитьОбязательные:Logical; ПринудительноИсключить:String; SepRes:String; Auto:Logical) :String;
-- ВсеСправочники - всегда выводить все найденные справочники
-- ИсключитьОбязательные - исключать набор обязательных для учета НФА справочников (М МОЛ НФА УЧН)
-- ПринудительноИсключить - исключить указанные в строке справочники (разделитель |)
var RO, OA, num, ii, len, jj, kk, cnt :Integer;
var Путь, ANA, Value, VOC :String;
var Отч1 :Report;
var REC :Record;
var OK :Logical;

 Refresh(False);
 ClearVariable(РАБ.НФА.LIBREP.LibTxt);
 Путь=PlanVar("НФА")+"\ОТЧЕТЫ\НФАОТЧ2007.lst";
 if ExistFile(Путь):
   Try
     Отч1=RepOpen(Путь+"|По_признакам_БАЛиЗАБ", RepMskACC, "(ДНФА.РАСХ.*|ДНФА.ВНПР.*)&(МОЛ.*)&(М.*)&("+RepMskNFA+")", 1.1.100, RepDat+1, "", "ДНФА");
     Try while RepNext(Отч1) do AddInArray(РАБ.НФА.LIBREP.LibTxt, True, False, RepIdent(Отч1)); end; Finally Отч1=RepClose(Отч1); end;
   Except
   end;
 fi;
 num=LengthOfArray(РАБ.НФА.LIBREP.LibTxt); -- количество нужных типов операций движения НФА
 if num>0:
   ClearVariable(РАБ.НФА.LIBREP.LibStr);
   ClearVariable(РАБ.НФА.LIBREP.LibInt);
   ShowProgress(num, "Анализируем...");
   RO=OpenWorkArea("РПО_ДНФА", "", "1=0");
   Try
     for ii=1 to num do
       ProgressPos(ii);
       ClearVariable(РАБ.НФА.LIBREP.LibMsk);
       ANA=РАБ.НФА.LIBREP.LibTxt[ii];
       if SignCardFile(ANA)="РПО_ДНФА": -- чтоб не попасть на текстовый признак
         REC=SignToRecord(ANA, False);
         if REC<>NIL:
           SetFilter(RO, "Ukey="+RecordToString(REC));
           if Records(RO)=1:
             ClearVariable(РАБ.НФА.LIBREP.LibBuf); -- для исключенных справочников
             if ИсключитьОбязательные:
               РАБ.НФА.LIBREP.LibBuf[1]="М";
               РАБ.НФА.LIBREP.LibBuf[2]="МОЛ";
               РАБ.НФА.LIBREP.LibBuf[3]="НФА";
               РАБ.НФА.LIBREP.LibBuf[4]="УЧН";
             fi;
             Value=Up(Trim(ПринудительноИсключить));
             len=WordsCount(Value, "|"); if len>0: for jj=1 to len do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(jj, Value, "|")); od; ВсеСправочники=True; fi;
             Value=Up(Trim(GetFieldS(RO, 1, "НЕДЕЙСТВСПР")));
             len=WordsCount(Value, "|"); if len>0: for jj=1 to len do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(jj, Value, "|")); od; fi;
             Value=Up(Trim(GetFieldS(RO, 1, "НЕДЕЙСТВОСТ")));
             len=WordsCount(Value, "|"); if len>0: for jj=1 to len do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(jj, Value, "|")); od; fi;
             OA=OpenArray(RO, 1, "ЗАПРОС", "", "ОСТАТОК and (ТИППАРАМЕТРА=1 or ТИППАРАМЕТРА=9 or ТИППАРАМЕТРА=14)"); -- (1 НФА) (9 аналитика) (14 аналитика ручного ввода)
             len=Records(OA);
             if len>0:
               for jj=1 to len do
                 OK=False;
                 Value=Trim(GetFieldS(OA, jj, "СПР"));
                 if Value<>"":
                   cnt=WordsCount(Value, "|");
                   if cnt>0:
                     for kk=1 to cnt do
                       VOC=GetAnaGlossary(Up(ExtractWord(1, ExtractWord(kk, Value, "|"), ".")));
                       if VOC<>"": 
                         if SearchInArray(РАБ.НФА.LIBREP.LibBuf, VOC, True, 1)=-1:
                           AddInArray(РАБ.НФА.LIBREP.LibMsk, True, False, VOC);
                           if not OK: OK=True; fi;
                         fi;
                       fi;
                     od;
                   fi;
                 fi;
                 if not OK:
                   Value=Trim(GetFieldS(OA, jj, "ОТВЕТ"));
                   if Value<>"":
                     cnt=WordsCount(Value, "|");
                     if cnt>0:
                       for kk=1 to cnt do
                         VOC=GetAnaGlossary(Up(ExtractWord(1, ExtractWord(kk, Value, "|"), ".")));
                         if VOC<>"":
                           if SearchInArray(РАБ.НФА.LIBREP.LibBuf, VOC, True, 1)=-1:
                             AddInArray(РАБ.НФА.LIBREP.LibMsk, True, False, VOC);
                             if not OK: OK=True; fi;
                           fi;
                         fi;
                       od;
                     fi;
                   fi;
                 fi;
               od;
             fi;
             CloseWorkArea(OA);
           fi;
         fi;
       fi;
       len=lengthOfArray(РАБ.НФА.LIBREP.LibMsk);
       if len>0:
         for jj=1 to len do
           cnt=SearchInArray(РАБ.НФА.LIBREP.LibStr, РАБ.НФА.LIBREP.LibMsk[jj], True, 1);
           if cnt=-1:
             kk=InsertInArraySort(РАБ.НФА.LIBREP.LibStr, РАБ.НФА.LIBREP.LibMsk[jj]);
             InsertInArray(РАБ.НФА.LIBREP.LibInt, kk, 1);
           else
             РАБ.НФА.LIBREP.LibInt[cnt]=РАБ.НФА.LIBREP.LibInt[cnt]+1;
           fi;
         od;
       fi;
     od;
   Finally
     CloseWorkArea(RO);
     CloseProgress;
   end;
   Value="";
   len=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
   if len>0:
     cnt=0;
     if not ВсеСправочники and not Auto:
       OK=False;
       for jj=1 to len do if РАБ.НФА.LIBREP.LibInt[jj]<>num: OK=True; Break; fi; od;
       if OK:
         kk=0;
         while kk=0 do
           kk=Enquiry("Выберите действие...", "В операциях движения НФА обнаружены неодинаковые наборы справочников для остатков.^MНеобходимо выбрать...", "...только общие справочники;...все справочники", mtConfirmation);
         od;
         if kk=1: cnt=+1; | kk=2: cnt=-1; fi;
       else
         cnt=-1;
       fi;
     else
       cnt=-1;
     fi;
     if cnt>0:
       for jj=1 to len do if РАБ.НФА.LIBREP.LibInt[jj]=num: Value=Объединить(Value, РАБ.НФА.LIBREP.LibStr[jj], SepRes); fi; od;
     else
       for jj=1 to len do Value=Объединить(Value, РАБ.НФА.LIBREP.LibStr[jj], SepRes); od;
     fi;
   fi;
   ClearVariable(РАБ.НФА.LIBREP.LibBuf);
   ClearVariable(РАБ.НФА.LIBREP.LibTxt);
   ClearVariable(РАБ.НФА.LIBREP.LibStr);
   ClearVariable(РАБ.НФА.LIBREP.LibMsk);
   ClearVariable(РАБ.НФА.LIBREP.LibInt);
   ^Value;
 fi; --num>0
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 ClearVariable(РАБ.НФА.LIBREP.LibTxt);
 ClearVariable(РАБ.НФА.LIBREP.LibStr);
 ClearVariable(РАБ.НФА.LIBREP.LibMsk);
 ClearVariable(РАБ.НФА.LIBREP.LibInt);
 ^"";
end;

Func ДопСпр_СобираемДопСправочники(MskUsrVoc:String; DatRep:Date; currVOC:String; Исключаем:String) :String;
var ii, num :Integer;
var ANA, RES, tmp :String;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 ANA=AddVoc_OSTOPER(DatRep, True, False, "|", False);
 if ANA<>"":
   num=WordsCount(ANA, "|");
   if num>0: for ii=1 to num do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(ii, ANA, "|")+".*"); od; fi;
 fi;
 ANA=MskUsrVoc;
 if ANA<>"":
   num=WordsCount(ANA, "|");
   if num>0: for ii=1 to num do AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, ExtractWord(ii, ANA, "|"));      od; fi;
 fi;
 ANA="";
 num=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 if num>0: for ii=1 to num do ANA=Объединить(ANA, РАБ.НФА.LIBREP.LibBuf[ii], "|"); od; fi;
 tmp=if(Name_A(Исключаем+".")<>" ", Исключаем, "");
 ANA="("+ANA+")&~(М.*|МОЛ.*|НФА.*|УЧН.*"+if(tmp<>"", "|"+tmp+".*", "")+")";
 RES=AnaElection(ANA, True, False, currVOC+".");
 if RES="": ^currVOC; else ^RES; fi;
 ^"";
end;

-- ***** Создание масок счетов для фильтра отбора по счетам *****

Func Отчеты_ПравильнаяМаскаСчетовНФА(maskСчета:String) :String;
var num, ii :Integer;
var res :String;
 res="";
 num=WordsCount(maskСчета, " ");
 if num>0: for ii=1 to num do res=res+"|"+"*."+ExtractWord(ii, maskСчета, " ")+"*"; od; fi;
 if SubStr(res, 1, 1)="|": res=Trim(SubStr(res, 2, 255)); fi;
 ^res;
end;

Func ВзятьАналитическуюГруппуСчета(aАСЧТ:Integer) :String;
 if aАСЧТ=1: ^"1";
 |  aАСЧТ=2: ^"2";
 |  aАСЧТ=3: ^"3";
 |  aАСЧТ=4: ^"4";
 else ^"?";
 fi;
end;

Func ТранспонироватьСчетаАмортизацииVСчетаНФА(aAmtAcc:String) :String;
var num, ii :Integer;
var RES, Value :String;
 RES="";
 num=WordsCount(aAmtAcc, " ");
 if num>0:
   for ii=1 to num do
     Value=ExtractWord(ii, aAmtAcc, " ");
     if Value="104.?1": RES=Объединить(RES, "101.?1", " ");
     |  Value="104.?2": RES=Объединить(RES, "101.?2", " ");
     |  Value="104.?3": RES=Объединить(RES, "101.?3", " ");
     |  Value="104.?4": RES=Объединить(RES, "101.?4", " ");
     |  Value="104.?5": RES=Объединить(RES, "101.?5", " ");
     |  Value="104.?6": RES=Объединить(RES, "101.?6", " ");
     |  Value="104.?7": RES=Объединить(RES, "101.?7", " ");
     |  Value="104.?8": RES=Объединить(RES, "101.?8", " ");
     |  Value="104.?9": RES=Объединить(RES, "102.?0", " ");
     fi;
   od;
 else
   RES="101.?? 102.?0";
 fi;
 if RES="": RES="101.?? 102.?0"; fi;
 ^RES;
end;

Func Отчеты_ИтоговаяМаскаСчета(FlagВФО:String; maskСЧТ:String; mskАСЧТ:Integer; maskКБК:String; useБАЛ:Logical; useЗАБ:Logical) :String;
var maskUSEсчт, maskUSEкбк, maskUSEвфо, resMask, groupСЧТ :String;
var num, ii :Integer;
var AllUse :Logical;
 groupСЧТ=РАБ.НФА.LIBREP.раздел_Счетов;
 ClearVariable(РАБ.НФА.LIBREP.раздел_Счетов);
 maskUSEвфо="";
 AllUse=if(FlagВФО=RepStr("1", 8), True, False); -- 8 источников !!!
 if not AllUse:
   num=Length(FlagВФО);
   if num>0:
     for ii=1 to num do
       if SubStr(FlagВФО, ii, 1)="1":
         maskUSEвфо=Объединить(maskUSEвфо, "*."+Str(ii)+".*", "|");
       fi;
     od;
   fi;
 fi;
 if maskUSEвфо="": AllUse=True; fi; -- на всякий случай
 if Match(maskКБК, "???.????.???????.???"):
   maskUSEкбк=maskКБК+".?.???."+ВзятьАналитическуюГруппуСчета(mskАСЧТ)+"?.???";
 else
   maskUSEкбк="???.????.???????.???.?.???."+ВзятьАналитическуюГруппуСчета(mskАСЧТ)+"?.???";
 fi;
 if maskСЧТ<>"": 
   maskUSEсчт=Отчеты_ПравильнаяМаскаСчетовНФА(maskСЧТ);
 else 
   if groupСЧТ="101": maskUSEсчт="*.101.??*|*.102.?0*|*.103.??*";
   |  groupСЧТ="105": maskUSEсчт="*.105.??*";
   else               maskUSEсчт="*.101.??*|*.102.?0*|*.103.??*|*.105.??*";
   fi;
 fi;
 --
 resMask="("+maskUSEсчт+")&("+if(useБАЛ, if(AllUse, "", "(")+maskUSEкбк+if(AllUse, "", "&("+maskUSEвфо+"))"), "")+if(useБАЛ and useЗАБ, "|", "")+if(useЗАБ, "ЗАБ.??.10?.??", "")+")";
 ^resMask;
end;

Func Отчеты_ИтоговаяМаскаАмортизации(FlagВФО:String; maskСЧТ:String; mskАСЧТ:Integer; maskКБК:String) :String;
var maskUSEсчт, maskUSEкбк, maskUSEвфо, resMask :String;
var num, ii :Integer;
var AllUse :Logical;
 maskUSEвфо="";
 AllUse=if(FlagВФО=RepStr("1", 8), True, False); -- 8 источников !!!
 if not AllUse:
   num=Length(FlagВФО);
   if num=8:
     for ii=1 to num do
       if SubStr(FlagВФО, ii, 1)="1":
         maskUSEвфо=Объединить(maskUSEвфо, "*."+Str(ii)+".*", "|");
       fi;
     od;
   fi;
 fi;
 if maskUSEвфо="": AllUse=True; fi; -- на всякий случай
 if Match(maskКБК, "???.????.???????.???"):
   maskUSEкбк=maskКБК+".?.???."+ВзятьАналитическуюГруппуСчета(mskАСЧТ)+"?.???";
 else
   maskUSEкбк="???.????.???????.???.?.???."+ВзятьАналитическуюГруппуСчета(mskАСЧТ)+"?.???";
 fi;
 if maskСЧТ<>"": maskUSEсчт=Отчеты_ПравильнаяМаскаСчетовНФА(maskСЧТ); else maskUSEсчт="*.104.??.???"; fi;
 --
 resMask="("+maskUSEсчт+")&("+if(AllUse, "", "(")+maskUSEкбк+if(AllUse, "", "&("+maskUSEвфо+"))")+")";
 ^resMask;
end;

-- ***** ВЫБОР КБК - префикс КБК *****

Func КБК_ИмяЭлементаСтруктурыКБК(НомерЭлемента:Integer; ТипСтруктуры:String) :String;
--???.????.???????.??? - Глава # Подраздел # Целевая статья # Вид расходов
--???.?.??.?????.??.???? - Администратор # Группа # Подгруппа # Статья # Элемент # Программа, Подпрограмма
--???.??.??.??.??.??.???? - Администратор # Группа # Подгруппа # Статья # Подстатья # Элемент # Программа, Подпрограмма
 if ТипСтруктуры="ФКР":  ТипСтруктуры="КР"; fi;
 if ТипСтруктуры="КИФД": ТипСтруктуры="ФД"; fi;
 if ТипСтруктуры="КР":
   if НомерЭлемента=1: ^"Глава";
   |  НомерЭлемента=2: ^"Подраздел";
   |  НомерЭлемента=3: ^"Целевая статья";
   |  НомерЭлемента=4: ^"Вид расходов";
   fi;
 |  ТипСтруктуры="КД":
   if НомерЭлемента=1: ^"Администратор";
   |  НомерЭлемента=2: ^"Группа";
   |  НомерЭлемента=3: ^"Подгруппа";
   |  НомерЭлемента=4: ^"Статья";
   |  НомерЭлемента=5: ^"Элемент";
   |  НомерЭлемента=6: ^"Программа, подпрограмма";
   fi;
 |  ТипСтруктуры="ФД":
   if НомерЭлемента=1: ^"Администратор";
   |  НомерЭлемента=2: ^"Группа";
   |  НомерЭлемента=3: ^"Подгруппа";
   |  НомерЭлемента=4: ^"Статья";
   |  НомерЭлемента=5: ^"Подстатья";
   |  НомерЭлемента=6: ^"Элемент";
   |  НомерЭлемента=7: ^"Программа, подпрограмма";
   fi;
 fi;
 ^"";
end;

Proc КБК_ОбновитьМенюВсе(isMaxA:Integer; isMaxS:Integer; isResVal:String; isResMsk:String; isтипКБК:String);
var ii :Integer;
 for ii=1 to isMaxS do
   РАБ.НФА.LIBREP.LibStr[ii]=ExtractWord(ii, isResVal, ".");
   РАБ.НФА.LIBREP.LibMsk[ii]=ExtractWord(ii, isResMsk, ".");
   РАБ.НФА.LIBREP.LibBuf[ii+isMaxA]=РАБ.НФА.LIBREP.LibMsk[ii]+"--"+Chr(187)+" "+КБК_ИмяЭлементаСтруктурыКБК(ii, isтипКБК);
 od;
end;

Proc КБК_ОбновитьМенюЭлемент(Iter:Integer; isMaxA:Integer; isтипКБК:String);
 if Iter>isMaxA: РАБ.НФА.LIBREP.LibBuf[Iter]=РАБ.НФА.LIBREP.LibMsk[Iter-isMaxA]+"--"+Chr(187)+" "+КБК_ИмяЭлементаСтруктурыКБК(Iter-isMaxA, isтипКБК); fi;
end;

Func КБК_СформироватьМенюМасокКБК(StoreКБКMsk:String; StoreКБКVal:String; maskСЧТ:String; ModeКБК:Integer; editКБК:Logical) :String;
var MaxA, MaxS, num, ii :Integer;
var типКБК, ResVal, ResMsk, маскКБК, tmp :String;
 if ModeКБК=1: типКБК="КР";   MaxS=4; маскКБК="???.????.???????.???";
 |  ModeКБК=2: типКБК="КД";   MaxS=6; маскКБК="???.?.??.?????.??.????";
 |  ModeКБК=3: типКБК="КИФД"; MaxS=7; маскКБК="???.??.??.??.??.??.????";
 else типКБК="";
 fi;
 if типКБК="": ^StoreКБКMsk; fi;
 --
 ClearVariable(РАБ.НФА.LIBREP.LibBuf); ClearVariable(РАБ.НФА.LIBREP.LibStr); ClearVariable(РАБ.НФА.LIBREP.LibMsk);
 --
 if Match(StoreКБКVal, маскКБК) and not Pos("?", StoreКБКVal)>0: РАБ.УПП.КБК2005.StoreКБК=StoreКБКVal; fi;
 if editКБК: if not Match(StoreКБКVal, маскКБК) or Pos("?", StoreКБКVal)>0: editКБК=False; fi; fi;
 if editКБК:
   ResMsk=StoreКБКMsk;
   ResVal=StoreКБКVal;
 else

   ResMsk=Trim(РАБ.УПП.КБК2005.ВыборКБКиерарх2005(maskСЧТ, типКБК, False));
   if ResMsk="": ^StoreКБКMsk; fi;
   ResVal=ResMsk;
 fi;
 --
 РАБ.НФА.LIBREP.LibBuf[1]="...--К выбору КБК";
 РАБ.НФА.LIBREP.LibBuf[2]=Chr(169)+"--Утвердить маску";
 MaxA=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 КБК_ОбновитьМенюВсе(MaxA, MaxS, ResVal, ResMsk, типКБК);
 num=0;
 while num<>2 do
   КБК_ОбновитьМенюЭлемент(num, MaxA, типКБК);
   num=AlternateTree("", РАБ.НФА.LIBREP.LibBuf, 35, num, 12, "$", "Параметр", "Комментарий", -1, False);
   if num=1:
     ResMsk=Trim(РАБ.УПП.КБК2005.ВыборКБКиерарх2005(maskСЧТ, типКБК, False));
     if ResMsk="": ^StoreКБКMsk; fi;
     ResVal=ResMsk;
     КБК_ОбновитьМенюВсе(MaxA, MaxS, ResVal, ResMsk, типКБК);
   | num=2: Break;
   | num>2:
     tmp=РАБ.НФА.LIBREP.LibMsk[num-MaxA];
     if Pos("?", tmp)>0:
       РАБ.НФА.LIBREP.LibMsk[num-MaxA]=РАБ.НФА.LIBREP.LibStr[num-MaxA];
     else
       РАБ.НФА.LIBREP.LibMsk[num-MaxA]=RepStr("?", Length(tmp));
     fi;
   else
     ^StoreКБКMsk;
   fi;
 od;
 ResMsk="";
 for ii=1 to MaxS do ResMsk=ResMsk+"."+РАБ.НФА.LIBREP.LibMsk[ii]; od;
 if SubStr(ResMsk, 1, 1)=".": ResMsk=SubStr(ResMsk, 2, Length(ResMsk)-1); fi;
 РАБ.НФА.LIBREP.valКБК=ResVal;
 ^ResMsk;
end;

Func КБК_ВыборКБК(maskСЧТ:String; SaveКБК:String) :String;
var Value :String;
var Edit :Logical;
 Value="";
 if Match(SaveКБК, "???.????.???????.???"):  Edit=True; else Edit=False; fi;
 РАБ.БЮДЖЕТ2005.РежимМаски="?";
 Value=КБК_СформироватьМенюМасокКБК(SaveКБК, РАБ.НФА.LIBREP.valКБК, maskСЧТ, 1, Edit);
 if Trim(Value)="": ^SaveКБК; else ^Value; fi;
end;

-- ***** ВЫБОР ПОЛЬЗОВАТЕЛЬСКИХ ГРУПП НФА - префикс ГруппаНФА *****

Func СоответствуетФильтруПоСчетам(mskAcc:String; grpAcc:String) :Logical;
var num1, num2, ii, jj :Integer;
var OK :Logical;
 ClearVariable(РАБ.НФА.LIBREP.KeyMsk);
 num1=WordsCount(mskAcc, " ");
 if num1>0: for ii=1 to num1 do РАБ.НФА.LIBREP.KeyMsk[ii]=ExtractWord(ii, mskAcc, " "); od; fi; -- фильтр счетов отчета
 ClearVariable(РАБ.НФА.LIBREP.KeyStr);
 num2=WordsCount(grpAcc, " ");
 if num2>0: for jj=1 to num2 do РАБ.НФА.LIBREP.KeyStr[jj]=ExtractWord(jj, grpAcc, " "); od; fi; -- фильтр счетов группы НФА
 if num1>0 and num2>0:
   for ii=1 to num1 do
     for jj=1 to num2 do
       OK=MatchMask(РАБ.НФА.LIBREP.KeyStr[jj], РАБ.НФА.LIBREP.KeyMsk[ii], " ");
       if OK: ^True; fi;
     od;
   od;
 fi;
 ^False;
end;

Func ГруппаНФА_СчитатьСправочник(maskAcc:String; FlagUpdate:Logical) :Logical;
var RO, jj, num, kk :Integer;
var OK, Work :Logical;
var GRPUNQ, GRPВИД, GRPКОД, GRPИМЯ, GRPСЧТ, Value :String;
 OK=False;
 if not FlagUpdate:
    if РАБ.НФА.LIBREP.GRPBUF[1]="" or not LengthOfArray(РАБ.НФА.LIBREP.GRPBUF)>0:
      FlagUpdate=True;
    else
      if LengthOfArray(РАБ.НФА.LIBREP.GRPBUF)<>LengthOfArray(РАБ.НФА.LIBREP.GRPDAT) or LengthOfArray(РАБ.НФА.LIBREP.GRPBUF)<>LengthOfArray(РАБ.НФА.LIBREP.GRPKEY):
        FlagUpdate=True;
      fi;
    fi;
 fi;
 if not FlagUpdate: ^True; fi;
 RO=OpenWorkArea(crdГРП, "ВИД", "КОД<>'' or НАИМЕНОВАНИЕ<>''");
 ShowProgress(0, "Считывание групп НФА...");
 Try
   num=Records(RO);
   if num>0:
     ClearVariable(РАБ.НФА.LIBREP.GRPBUF);
     ClearVariable(РАБ.НФА.LIBREP.GRPDAT);
     ClearVariable(РАБ.НФА.LIBREP.GRPKEY);
     ShowProgress(num, "Считывание групп НФА...");
     for jj=1 to num do
       ProgressPos(jj);
       GRPСЧТ=Lo(Trim(GetFieldS(RO, jj, "ГРНФА")));
       Work=СоответствуетФильтруПоСчетам(maskAcc, GRPСЧТ);
       if Work:
         GRPUNQ=RecordToString(GetRecordKey(RO, jj));
         GRPВИД=КорректныеСимволыПризнака(Lo(Trim(GetFieldS(RO, jj, "ВИД"))));
         if GRPВИД="": GRPВИД="_без группировки"; fi;
         GRPКОД=КорректныеСимволыПризнака(Lo(Trim(GetFieldS(RO, jj, "КОД"))));
         GRPИМЯ=ЗаменитьРазделитель_Символ(Lo(Trim(GetFieldS(RO, jj, "НАИМЕНОВАНИЕ"))), "|");
         if GRPКОД=""  and GRPИМЯ<>"": GRPКОД=GRPИМЯ;
         |  GRPКОД<>"" and GRPИМЯ="" : GRPИМЯ=GRPКОД;
         fi;
         Value=Up(GRPВИД)+"|"+Up(GRPКОД)+"--Подгруппа '"+GRPИМЯ+"'";
         if SearchInArray(РАБ.НФА.LIBREP.GRPBUF, Value, True, 1)<0:
           kk=InsertInArraySort(РАБ.НФА.LIBREP.GRPBUF, Value);
           InsertInArray(РАБ.НФА.LIBREP.GRPDAT, kk, GRPВИД+"|"+GRPКОД+"|"+GRPИМЯ);
           InsertInArray(РАБ.НФА.LIBREP.GRPKEY, kk, GRPUNQ);
         fi;
         Value=Up(GRPВИД)+"|--Группа '"+GRPВИД+"'";
         if SearchInArray(РАБ.НФА.LIBREP.GRPBUF, Value, True, 1)<0:
           kk=InsertInArraySort(РАБ.НФА.LIBREP.GRPBUF, Value);
           InsertInArray(РАБ.НФА.LIBREP.GRPDAT, kk, GRPВИД);
           InsertInArray(РАБ.НФА.LIBREP.GRPKEY, kk, "{0}");
         fi;
       fi;
     od;
     if LengthOfArray(РАБ.НФА.LIBREP.GRPBUF)>0: OK=True; else OK=False; fi;
     InsertInArray(РАБ.НФА.LIBREP.GRPBUF, 1, "*--Перечитать группы НФА");
     InsertInArray(РАБ.НФА.LIBREP.GRPDAT, 1, "");
     InsertInArray(РАБ.НФА.LIBREP.GRPKEY, 1, "");
   fi;
 Finally
   CloseProgress;
   CloseWorkArea(RO);
 end;
 ^OK;
end;

Func ГруппыНФА_ВзятьИменаГрупп(грпValue:String; кейValue:String; Sep:String) :String;
var Final_NAME, currVal, currKey, ИМЯGRP, GRPвер, GRPниж, tmp1, tmp2, tmp3 :String;
var num, ii, pp :Integer;
var OK: Logical;
 Final_NAME="";
 num=WordsCount(грпValue, Sep);
 if num>0:
   for ii=1 to num do
     ИМЯGRP="";
     currVal=ExtractWord(ii, грпValue, Sep);
     currKey=ExtractWord(ii, кейValue, Sep);
     GRPвер=ExtractWord(1, currVal, "$");
     GRPниж=ExtractWord(2, currVal, "$");
     if GRPниж="*":
       ИМЯGRP="Вся группа "+Up(GRPвер);
     else
       if currKey<>"{0}":
         pp=SearchInArray(РАБ.НФА.LIBREP.GRPKEY, currKey, False, 1);
         if pp>0:
           OK=False;
           tmp1=Lo(ExtractWord(1, РАБ.НФА.LIBREP.GRPDAT[pp], "|"));
           tmp2=Lo(ExtractWord(2, РАБ.НФА.LIBREP.GRPDAT[pp], "|"));
           tmp3=Lo(ExtractWord(3, РАБ.НФА.LIBREP.GRPDAT[pp], "|"));
           if Lo(GRPвер)=tmp1 and Lo(GRPниж)=tmp2: OK=True; fi;
           if OK: ИМЯGRP=Up(GRPвер)+" "+Chr(151)+" "+Lo(tmp3); fi;
         fi;
       fi;
       if ИМЯGRP="": ИМЯGRP=Up(GRPвер)+" "+Chr(151)+" "+Lo(GRPниж); fi;
     fi;
     Final_NAME=Объединить(Final_NAME, ИМЯGRP, " | ");
   od;
 fi;
 ^Final_NAME;
end;

Func ГруппыНФА_ВыборФильтраОтбораГруппНФА(StoreVal:String; StoreKey:String; Sep:String; MaskAcc:String) :String;
var len, ii, num1, num2, kk, nn, pp :Integer;
var NewValue, tmp, ANA, UKG, currVal, currKey, ВИДGRP, КОДGRP, КЛЧGRP :String;
var ВыбранаМаска, f1, f2 :Logical;
 if not ГруппаНФА_СчитатьСправочник(MaskAcc, False):
   Message("Не заполнен справочник групп НФА ["+crdГРП+"]!", mtError);
   РАБ.НФА.LIBREP.keyГРП=StoreKey;
   ^StoreVal;
 fi;
 currVal=Up(StoreVal);
 currKey=Up(StoreKey);
 kk=-1;
 if Pos("|", currVal)<1:
   ii=Length(currVal);
   if Pos("*", currVal)=ii and ii>2:
     tmp=Up(SubStr(currVal, 1, ii-2))+"|--Группа '"+Lo(SubStr(currVal, 1, ii-2))+"'";
     kk=SearchInArray(РАБ.НФА.LIBREP.GRPBUF, tmp, True, 1);
   else
     if РАБ.НФА.LIBREP.LastGRP_key<>"{0}": kk=SearchInArray(РАБ.НФА.LIBREP.GRPKEY, РАБ.НФА.LIBREP.LastGRP_key, False, 1); fi;
   fi;
 fi;
 if kk=-1: if РАБ.НФА.LIBREP.LastGRP_num>0: kk=РАБ.НФА.LIBREP.LastGRP_num; else kk=1; fi; fi;
 len=1;
 while len=1 do
   len=AlternateTree("Выберите группу...", РАБ.НФА.LIBREP.GRPBUF, -1, kk, 12, "|", "ГРУППЫ", "ПОЯСНЕНИЕ", -1, True);
   if len=0:
     --Message("Отказ от выбора группы!", mtInformation);
     keyГРП=StoreKey;
     ^StoreVal;
   |  len=1:
     if not ГруппаНФА_СчитатьСправочник(MaskAcc, True):
       Message("Не заполнен справочник групп НФА ["+crdГРП+"]!", mtError);
       keyГРП=StoreKey;
       ^StoreVal;
     fi;
   fi;
 od;
 ВыбранаМаска=False;
 ВИДGRP=ExtractWord(1, РАБ.НФА.LIBREP.GRPDAT[len], "|");
 КОДGRP=ExtractWord(2, РАБ.НФА.LIBREP.GRPDAT[len], "|");
 КЛЧGRP=РАБ.НФА.LIBREP.GRPKEY[len];
 if Pos("|--", РАБ.НФА.LIBREP.GRPBUF[len])>0: NewValue=Up(ВИДGRP+"$*"); tmp=SubStr(NewValue, 1, Length(NewValue)-2); ВыбранаМаска=True; else NewValue=Up(ВИДGRP+"$"+КОДGRP); tmp=NewValue; fi;
 if currVal="": РАБ.НФА.LIBREP.LastGRP_key=КЛЧGRP; РАБ.НФА.LIBREP.LastGRP_num=len; keyГРП=КЛЧGRP; ^NewValue; fi;
 --
 ClearVariable(РАБ.НФА.LIBREP.LibBuf); ClearVariable(РАБ.НФА.LIBREP.LibMsk); ClearVariable(РАБ.НФА.LIBREP.LibStr); 
 ClearVariable(РАБ.НФА.LIBREP.LibTxt); ClearVariable(РАБ.НФА.LIBREP.KeyMsk); ClearVariable(РАБ.НФА.LIBREP.KeyStr);
 num1=WordsCount(currVal, Sep);
 for ii=1 to num1 do
   ANA=ExtractWord(ii, currVal, Sep);
   UKG=ExtractWord(ii, currKey, Sep);
   if Pos("*", ANA)>0:
     pp=InsertInArraySort(РАБ.НФА.LIBREP.LibMsk, ANA);
     InsertInArray(РАБ.НФА.LIBREP.KeyMsk, pp, UKG);
   else
     pp=InsertInArraySort(РАБ.НФА.LIBREP.LibStr, ANA);
     InsertInArray(РАБ.НФА.LIBREP.KeyStr, pp, UKG);
   fi;
 od;
 num1=LengthOfArray(РАБ.НФА.LIBREP.LibMsk);
 num2=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
 if ВыбранаМаска:
   pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, NewValue); InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, КЛЧGRP);
   if num1>0:
     for ii=1 to num1 do
       f1=Match(NewValue, РАБ.НФА.LIBREP.LibMsk[ii]);
       f2=ВхожденийНет(tmp, РАБ.НФА.LIBREP.LibMsk[ii]);
       if (not f1) and f2: pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]); InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, РАБ.НФА.LIBREP.KeyMsk[ii]); fi;
     od;
   fi;
   if num2>0:
     for ii=1 to num2 do
       f1=Match(РАБ.НФА.LIBREP.LibStr[ii], NewValue);
       f2=ВхожденийНет(РАБ.НФА.LIBREP.LibStr[ii], NewValue);
       if (not f1) and f2: pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibStr[ii]); InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, РАБ.НФА.LIBREP.KeyStr[ii]); fi;
     od;
   fi;
 else
   if num1>0:
     for ii=1 to num1 do
       f1=Match(NewValue+"$", РАБ.НФА.LIBREP.LibMsk[ii]);
       if not f1:
         pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]); InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, РАБ.НФА.LIBREP.KeyMsk[ii]);
       else
         nn=Enquiry("Выберите действие...", "Значение '"+NewValue+"' соответствует маске '"+РАБ.НФА.LIBREP.LibMsk[ii]+"'!", "Заменить маску на значение;Сохранить маску, значение опустить", mtConfirmation);
         if nn=2: pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]); InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, РАБ.НФА.LIBREP.KeyMsk[ii]); NewValue=""; fi;
       fi;
     od;
   fi;
   if num2>0:
     for ii=1 to num2 do
       pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibStr[ii]);
       InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, РАБ.НФА.LIBREP.KeyStr[ii]);
     od;
   fi;
   --
   if NewValue<>"":
     num1=SearchInArray(РАБ.НФА.LIBREP.LibBuf, NewValue, True, 1);
     if num1=-1: pp=InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, NewValue); InsertInArray(РАБ.НФА.LIBREP.LibTxt, pp, КЛЧGRP); fi;
   fi;
 fi;
 num1=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 ANA=""; UKG="";
 for ii=1 to num1 do
   ANA=Объединить(ANA, РАБ.НФА.LIBREP.LibBuf[ii], Sep);
   UKG=Объединить(UKG, РАБ.НФА.LIBREP.LibTxt[ii], Sep);
   if Length(ANA)>250:
     Message("Строка аналитики не может быть больше 255 символов.^MВыбор отменен!", mtWarning);
     РАБ.НФА.LIBREP.keyГРП=StoreKey;
     ^StoreVal;
   fi;
 od;
 -- Заполняем служебную инфу
 if Pos("|", ANA)<1: РАБ.НФА.LIBREP.LastGRP_key=КЛЧGRP; else РАБ.НФА.LIBREP.LastGRP_key="{0}"; fi;
 РАБ.НФА.LIBREP.LastGRP_num=len;
 РАБ.НФА.LIBREP.keyГРП=UKG;
 ^ANA;
end;

Func ГруппыНФА_УдалитьИзНабора_Диалог(грпVal:String; грпKey:String; грпSep:String) :String;
var num, ii, nn :Integer;
var currVal, currKey, ИМЯGRP, GRPвер, GRPниж, tmp1, tmp2, tmp3 :String;
var OK :Logical;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 num=WordsCount(грпVal, грпSep);
 if num<2: РАБ.НФА.LIBREP.keyГРП=""; ^""; fi;
   for ii=1 to num do
     ИМЯGRP="";
     currVal=ExtractWord(ii, грпVal, грпSep);
     currKey=ExtractWord(ii, грпKey, грпSep);
     GRPвер=ExtractWord(1, currVal, "$");
     GRPниж=ExtractWord(2, currVal, "$");
     if GRPниж="*":
       ИМЯGRP="Вся группа "+Up(GRPвер);
     else
       if currKey<>"{0}":
         nn=SearchInArray(РАБ.НФА.LIBREP.GRPKEY, currKey, False, 1);
         if nn>0:
           OK=False;
           tmp1=Lo(ExtractWord(1, РАБ.НФА.LIBREP.GRPDAT[nn], "|"));
           tmp2=Lo(ExtractWord(2, РАБ.НФА.LIBREP.GRPDAT[nn], "|"));
           tmp3=Lo(ExtractWord(3, РАБ.НФА.LIBREP.GRPDAT[nn], "|"));
           if Lo(GRPвер)=tmp1 and Lo(GRPниж)=tmp2: OK=True; fi;
           if OK: ИМЯGRP=Up(GRPвер)+" "+Chr(151)+" "+Lo(tmp3); fi;
         fi;
       fi;
       if ИМЯGRP="": ИМЯGRP=Up(GRPвер)+" "+Chr(151)+" "+Lo(GRPниж); fi;
     fi;
     РАБ.НФА.LIBREP.LibBuf[ii+1]=ИМЯGRP;
   od;
 РАБ.НФА.LIBREP.LibBuf[1]="* Удалить все значения *";
 nn=Alternate("Удаление...", РАБ.НФА.LIBREP.LibBuf, -1, 1, 12);
 if nn<1:
   РАБ.НФА.LIBREP.keyГРП=грпKey;
   ^грпVal;
 |  nn=1:
   РАБ.НФА.LIBREP.keyГРП="";
   ^"";
 |  nn>1:
   грпVal=УдалитьСловоНомер(nn-1, грпVal, грпSep);
   грпKey=УдалитьСловоНомер(nn-1, грпKey, грпSep);
   РАБ.НФА.LIBREP.keyГРП=грпKey;
   ^грпVal;
 fi;
end;

-- ***** ВЫБОР ФИЛЬТРА ПО АНАЛИТИКЕ - префикс Аналитика *****

Func Аналитика_СформироватьУсловиеОтбораНФА(MaskAcc:String) :String;
var ii, num :Integer;
var Res, Value :String;
 Res="";
 num=WordsCount(MaskAcc, " ");
 if num>0:
   for ii=1 to num do
     Value=ExtractWord(ii, MaskAcc, " ");
     Res=Объединить(Res, "НФА."+Value+".*", "|");
   od;
 fi;
 if Res="": Res="НФА.*"; fi;
 ^Res;
end;

Func Аналитика_ВыборПризнака(VOC:String; StoreANA:String; MaskAcc:String) :String;
var Value, MaskAnaElec :String;
 Value="";
 RefreshAna;
 if Up(VOC)="НФА": MaskAnaElec=Аналитика_СформироватьУсловиеОтбораНФА(MaskAcc); else MaskAnaElec=VOC+".*"; fi;
 Value=AnaElection(MaskAnaElec, False, True, StoreANA);
 if Trim(Value)="": ^""; fi;
 ^Value;
end;

Func Аналитика_ВыборПризнакаИзПроводок(VOC:String; StoreANA:String; FlagИСТ:String; MaskСЧТ:String; MskАСЧТ:Integer; MaskКБК:String; FlagСЧТ:Integer; RepDate:Date) :String;
var Путь, Value, MaskAnaElec, MaskAcc, tmp :String;
var num, kk, jj :Integer;
var ИзСписка, OK :Logical;
var Отч1 :Report;
 Value="";
 ИзСписка=False;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 ClearVariable(РАБ.НФА.LIBREP.LibMsk);
 ClearVariable(РАБ.НФА.LIBREP.LibStr);
 Путь=PlanVar("НФА")+"\ОТЧЕТЫ\НФАОТЧ2007.lst";
 if not ExistFile(Путь): Message("Файл с отчетами отсутствует!", mtError); ИзСписка=True; fi;
 if not ИзСписка:
   Try
     MaskAcc=Отчеты_ИтоговаяМаскаСчета(FlagИСТ, MaskСЧТ, MskАСЧТ, MaskКБК, if(FlagСЧТ=0 or FlagСЧТ=1, True, False), if(FlagСЧТ=0 or FlagСЧТ=2, True, False));
     if Up(VOC)="НФА":
       MaskAnaElec=Аналитика_СформироватьУсловиеОтбораНФА(MaskСЧТ);
       if (Length(MaskAcc)+Length(MaskAnaElec)+7)>255: MaskAnaElec=VOC+".*"; fi; -- 7=5+2 -5[знак()'*]  -2[{}]
     else
       MaskAnaElec=VOC+".*";
     fi;
     Refresh(False);
     Отч1=RepOpen(Путь+"|По_признакам_БАЛиЗАБ", MaskAcc, MaskAnaElec, 1.1.100, if(RepDate>1.1.2000, RepDate, ToDay), "", VOC);
     RepReset(Отч1);
     Try
       while RepNext(Отч1) do
         if RepIdent(Отч1)<>"":
           tmp=Trim(Name_A(RepIdent(Отч1)));
           if tmp="": tmp=" "; fi;
           kk=InsertInArraySort(РАБ.НФА.LIBREP.LibStr, tmp);
           InsertInArray(РАБ.НФА.LIBREP.LibMsk, kk, RepIdent(Отч1));
           InsertInArray(РАБ.НФА.LIBREP.LibBuf,    kk, RepIdent(Отч1)+"--"+tmp);
         fi;
       end;
     Finally
       Отч1=RepClose(Отч1);
     end;
   Except
     ИзСписка=True;
     --Message("Ошибка создания отчета^Mпри выборке аналитики из проводок!", mtError);
     --Raise;
     --^"";
   end;
   num=LengthOfArray(РАБ.НФА.LIBREP.LibMsk);
   if not ИзСписка and num>0:
     InsertInArray(РАБ.НФА.LIBREP.LibBuf,    1, Chr(149)+"--");
     InsertInArray(РАБ.НФА.LIBREP.LibBuf,    1, Chr(169)+"--Выбор признака или группы признаков из списка");
     kk=SearchInArray(РАБ.НФА.LIBREP.LibMsk, StoreANA, False, 1);
     OK=True;
     while OK do
       jj=AlternateTree("Выберите признак...", РАБ.НФА.LIBREP.LibBuf, -1, kk+2, 12, "#", "Код признака", "Расшифровка признака", -1, False);
       if jj=0: OK=False; ^"";
       |  jj=1: OK=False; Value=Аналитика_ВыборПризнака(VOC, StoreANA, MaskСЧТ);
       |  jj>2: OK=False; Value=РАБ.НФА.LIBREP.LibMsk[jj-2];
       fi;
     od;
   else
     ИзСписка=True;
   fi;
 fi;
 if ИзСписка: Value=Аналитика_ВыборПризнака(VOC, StoreANA, MaskСЧТ); fi;
 if Trim(Value)="": ^""; fi;
 ^Value;
end;

Func Аналитика_ВыборГрупповойАналитики(VOC:String; StoreANA:String; Sep:String; МаскаЗначение:Logical; FlagИСТ:String; MaskСЧТ:String; MskАСЧТ:Integer; MaskКБК:String; FlagСЧТ:Integer; RepDate:Date) :String;
var ANA, wrd, curValue, newValue :String;
var ВыбранаМаска, flg1, flg2 :Logical;
var ii, num1, num2, nn :Integer;
 ВыбранаМаска=False;
 curValue=Up(StoreANA);
 if Pos(Sep, curValue)>0:
   wrd="";
 else
   ii=Length(curValue);
   if Pos("*", curValue)=ii and ii>2:
     wrd=SubStr(curValue, 1, ii-1);
   else
     wrd=if(ValidSign(curValue), curValue, "");
   fi;
 fi;
 --
 -- newValue=Up(Аналитика_ВыборПризнака(VOC, wrd, MaskСЧТ));
 newValue=Up(Аналитика_ВыборПризнакаИзПроводок(VOC, wrd, FlagИСТ, MaskСЧТ, MskАСЧТ, MaskКБК, FlagСЧТ, RepDate));
 --
 if newValue="": ^StoreANA; fi;
 if SubStr(newValue, Length(newValue), 1)=".": newValue=newValue+"*"; wrd=SubStr(newValue, 1, Length(newValue)-2); ВыбранаМаска=True; else wrd=newValue; fi;
 if curValue="" or (ВыбранаМаска and (WordsCount(newValue, ".")<3)): ^newValue; fi;
 --
 ClearVariable(РАБ.НФА.LIBREP.LibBuf); ClearVariable(РАБ.НФА.LIBREP.LibMsk); ClearVariable(РАБ.НФА.LIBREP.LibStr);
 -- отделяем маски значений от конкретных значений
 num1=WordsCount(curValue, Sep);
 for ii=1 to num1 do
   ANA=ExtractWord(ii, curValue, Sep);
   if Pos("*", ANA)>0: InsertInArraySort(РАБ.НФА.LIBREP.LibMsk, ANA); else InsertInArraySort(РАБ.НФА.LIBREP.LibStr, ANA); fi;
 od;
 num1=LengthOfArray(РАБ.НФА.LIBREP.LibMsk);
 num2=LengthOfArray(РАБ.НФА.LIBREP.LibStr);
 -- синхронизируем выбранное значение или маску с результирующим набором
 if ВыбранаМаска:
   InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, newValue);
   if num1>0:
     for ii=1 to num1 do
       flg1=Match(newValue, РАБ.НФА.LIBREP.LibMsk[ii]);
       flg2=ВхожденийНет(wrd, РАБ.НФА.LIBREP.LibMsk[ii]);
       if not flg1 and flg2: InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]); fi;
     od;
   fi;
   if num2>0:
     for ii=1 to num2 do
       flg1=Match(РАБ.НФА.LIBREP.LibStr[ii], newValue);
       flg2=ВхожденийНет(РАБ.НФА.LIBREP.LibStr[ii], newValue);
       if not flg1 and flg2: InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibStr[ii]); fi;
     od;
   fi;
 else
   if num1>0:
     for ii=1 to num1 do
       flg1=Match(newValue+".", РАБ.НФА.LIBREP.LibMsk[ii]);
       if not flg1:
         InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]);
       else
         if МаскаЗначение:
           nn=Enquiry("Выберите действие...", "Значение '"+newValue+"' соответствует маске '"+РАБ.НФА.LIBREP.LibMsk[ii]+"'!", "Заменить маску на значение;Сохранить маску, значение опустить;Вставить значение и сохранить маску", mtConfirmation);
           if nn=2: InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]); newValue="";
           |  nn=3: InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]);
           fi;
         else
           nn=Enquiry("Выберите действие...", "Значение '"+newValue+"' соответствует маске '"+РАБ.НФА.LIBREP.LibMsk[ii]+"'!", "Заменить маску на значение;Сохранить маску, значение опустить", mtConfirmation);
           if nn=2: InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, РАБ.НФА.LIBREP.LibMsk[ii]); newValue=""; fi;
         fi;
       fi;
     od;
   fi;
   if num2>0:
     CopyArray(РАБ.НФА.LIBREP.LibStr, РАБ.НФА.LIBREP.LibBuf, 1, LengthOfArray(РАБ.НФА.LIBREP.LibBuf)+1);
   fi;
   SortArray(РАБ.НФА.LIBREP.LibBuf, True);
   if newValue<>"":
     num1=SearchInArray(РАБ.НФА.LIBREP.LibBuf, newValue, True, 1);
     if num1=-1: InsertInArraySort(РАБ.НФА.LIBREP.LibBuf, newValue); fi;
   fi;
 fi;
 num1=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
 ANA="";
 for ii=1 to num1 do
   ANA=Объединить(ANA, РАБ.НФА.LIBREP.LibBuf[ii], Sep);
   if Length(ANA)>248:
     Message("Строка аналитики не может быть больше 248 символов.^MВыбор отменен!", mtWarning);
     ^StoreANA;
   fi;
 od;
 ^ANA;
end;

Func Аналитика_ВыбранВесьСправочник(voc:String) :String;
 if voc="ВД"  : ^"Все виды деятельности ["+voc+".*]";
 |  voc="ВКЛ" : ^"Вся ведомственная классификация ["+voc+".*]";
 |  voc="КТ"  : ^"Все категории ["+voc+".*]";
 |  voc="М"   : ^"Все местонахождения ["+voc+".*]";
 |  voc="МОЛ" : ^"Все материально ответственные лица ["+voc+".*]";
 |  voc="П"   : ^"Все подразделения ["+voc+".*]";
 |  voc="ПБС" : ^"Все получатели средств бюджета ["+voc+".*]";
 |  voc="ПГР" : ^"Все пункты генерального разрешния ["+voc+".*]";
 |  voc="РБС" : ^"Все распорядители бюджетных средств ["+voc+".*]";
 |  voc=""    : ^"";
 else ^"Все элементы справочника ["+voc+".*]";
 fi;
end;

Func Аналитика_ИмяГруппы(ANA:String) :String;
var nn :Integer;
var tmp :String;
 tmp="";
 nn=Length(ANA);
 if Pos("*", ANA)=nn and nn>2: tmp=(Name_A(SubStr(ANA, 1, nn-1))); else tmp=""; fi;
 if tmp="": tmp="нет наименования"; fi;
 ^tmp;
end;

Func Аналитика_FormatSetANA(Set:String; SepSet:String; SepOut:String) :String;-- набор описаний признаков в одной строке (разделители разные)
var num, i :Integer;
var OUT, ANA, tmp, tmp2, voc :String;
 OUT="";
 if SepSet<>"":
   num=WordsCount(Set, SepSet);
   for i=1 to num do
     ANA=ExtractWord(i, Set, SepSet);
     voc=ExtractWord(1, ANA, ".");
     tmp=Name_A(ANA);
     tmp2=if(tmp<>"" and tmp<>" ", tmp, if(ANA=voc+".*", Аналитика_ВыбранВесьСправочник(voc), Аналитика_ИмяГруппы(ANA)));
     OUT=Объединить(OUT, tmp2, SepOut);
   od;
 fi;
 ^OUT;
end;

-- ***** проверка условий отбора *****

Func Оператор :String;
var nn :Integer;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 РАБ.НФА.LIBREP.LibBuf[1]="И";
 РАБ.НФА.LIBREP.LibBuf[2]="ИЛИ";
 РАБ.НФА.LIBREP.LibBuf[3]="И ИСКЛЮЧИТЬ";
 nn=Alternate("Выбор оператора",РАБ.НФА.LIBREP.LibBuf, 20, 1, 12);
 if nn=1: ^"&";
 |  nn=2: ^"|";
 |  nn=3: ^"&~";
 fi;
 ^"";
end;

Func СчетаНФА_вУчете(maskСЧТ:String; ddBP:Date; ddEP:Date) :Integer;
var Путь, Acc :String;
var num, kk :Integer;
var Отч1 :Report;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 Путь=PlanVar("НФА")+"\ОТЧЕТЫ\НФАОТЧ2007.lst";
 if not ExistFile(Путь): ^-1; fi;
 Try
   Отч1=RepOpen(Путь+"|По_счетам_НФА_Бал_Заб", maskСЧТ, "", if(ddBP>1.1.1990, ddBP, 1.1.100), if(ddEP>1.1.1990, ddEP, ToDay));
   RepReset(Отч1);
   Try
     num=RepRowsCount(Отч1);
     kk=0;
     while RepNext(Отч1) do
       Acc=RepIdent(Отч1);
       if Match(Acc, "???.????.???????.???.?.???.??.???")    or
          Match(Acc, "???.??.??.??.??.??.????.?.???.??.???") or
          Match(Acc, "ЗАБ.??.???.??"):
         kk=kk+1;
         РАБ.НФА.LIBREP.LibBuf[kk]=Объединить(SignsMask(Acc, True), SignsMask(Acc, False), "|");
       fi;
     end; -- while
   Finally
     Отч1=RepClose(Отч1);
   end;
 Except
   ^-1;
 end;
 ^LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
end;

Func СчетаНФА_поСтруктуре(maskСЧТ:String) :Integer;
var Acc :String;
var kk :Integer;
 ClearVariable(РАБ.НФА.LIBREP.LibBuf);
 kk=0;
 for Account Acc=maskСЧТ, Sort do
   kk=kk+1;
   РАБ.НФА.LIBREP.LibBuf[kk]=Объединить(SignsMask(Acc, True), SignsMask(Acc, False), "|");
 od;
 ^LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
end;

Func СправочникиСтруктурыПоМаскеСчетовПрогресс(maskСЧТ:String; ddBP:Date; ddEP:Date; OnlyUseAcc:Logical; EnableProgress:Logical) :String;
var Voc, MaskVoc :String;
var xx, ii, num, jj, kk :Integer;
var qq :Numeric;
 Try qq=Saldo(maskСЧТ, 1.1.100); Except ^" "; end;
 ClearVariable(РАБ.НФА.LIBREP.bindVOC); ClearVariable(РАБ.НФА.LIBREP.bindINT);
 if EnableProgress: ShowProgress(0, "Подготовка..."); fi;
 MaskVoc="";
 Try
   xx=0;
   if OnlyUseAcc: xx=СчетаНФА_вУчете(maskСЧТ, ddBP, ddEP); fi;
   if not xx>0:   xx=СчетаНФА_поСтруктуре(maskСЧТ); fi;
   if xx>0:
     if EnableProgress: ShowProgress(xx, "Анализ привязки справочников к счетам..."); fi;
     for ii=1 to xx do
       if EnableProgress: ProgressPos(ii); fi;
       num=WordsCount(РАБ.НФА.LIBREP.LibBuf[ii], "|");
       for jj=1 to num do
         Voc=ExtractWord(jj, РАБ.НФА.LIBREP.LibBuf[ii], "|");
         kk=SearchInArray(РАБ.НФА.LIBREP.bindVOC, Voc, True, 1);
         if kk>0:
           РАБ.НФА.LIBREP.bindINT[kk]=РАБ.НФА.LIBREP.bindINT[kk]+1;
         else
           kk=InsertInArraySort(РАБ.НФА.LIBREP.bindVOC, Voc);
           InsertInArray(РАБ.НФА.LIBREP.bindINT, kk, 1);
         fi;
       od;
     od;
     num=LengthOfArray(РАБ.НФА.LIBREP.bindVOC);
     if num>0:
       if EnableProgress: ShowProgress(num, "Обработка полученных данных..."); fi;
       jj=num; -- удаляем с конца
       for ii=1 to num do
         if EnableProgress: ProgressPos(ii); fi;
         -- xx - количество рабочих счетов
         if РАБ.НФА.LIBREP.bindINT[jj]<>xx: DeleteFromArray(РАБ.НФА.LIBREP.bindVOC, jj); else MaskVoc=Объединить(MaskVoc, РАБ.НФА.LIBREP.bindVOC[jj], "|"); fi;
         jj=jj-1;
       od;
     fi;
   fi; -- xx>0
 Finally
   if EnableProgress: CloseProgress; fi;
 end;
 ^MaskVoc;
end;

Func ВсеСправочникиДопАналитикиПривязаны(vДопАна:String) :Integer;
var ii, num :Integer;
var Value, tmp :String;
 vДопАна=Trim(vДопАна);
 if vДопАна<>"" and LengthOfArray(РАБ.НФА.LIBREP.bindVOC)>0:
   num=Length(vДопАна);
   if num>0:
     ClearVariable(РАБ.НФА.LIBREP.LibBuf);
     Value="";
     for ii=1 to num do
       tmp=SubStr(vДопАна, ii, 1);
       if ПравильныйСимволАналитики(tmp):
         Value=Value+tmp;
       else
         if Value<>"":
           if Pos(".", Value)>0: Value=ExtractWord(1, Value, ".")+".*"; fi;
           AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, Value);
           Value="";
         fi;
       fi;
     od;
     if Value<>"": AddInArray(РАБ.НФА.LIBREP.LibBuf, True, False, Value); Value=""; fi;
     num=LengthOfArray(РАБ.НФА.LIBREP.LibBuf);
     if num>0:
       for ii=1 to num do
         if SearchInArray(РАБ.НФА.LIBREP.bindVOC, РАБ.НФА.LIBREP.LibBuf[ii], True, 1)<1:
           Message("Длинное условие отбора аналитики.^MИспользуется свертка...^M^MСправочник '"+РАБ.НФА.LIBREP.LibBuf[ii]+"' не привязан к выбранному фильтру по счетам!", mtError);
           ^-1;
         fi;
       od;
       ^+1;
     fi;
   fi;
 fi;
 ^0;
end;

Func ПризнакСоотвМаске(Призн:String; услANA:String) :Logical;
-- Призн должно являтся полным значением, а не маской!
var Ana :String;
 if услANA="": ^False; fi;
 if Name_A(Призн)=" ": ^False; fi;
 if услANA="*": ^True; fi;
 for Sign Ana=услANA, Sort do if Призн=Ana: ^True; fi; od;
 ^False;
end;

Func ПризнакСоотвНабору(ANA:String; Набор:String) :Logical;
-- ANA должно являтся полным значением, а не маской!
var ii, num :Integer;
var Value :String;
 num=WordsCount(Набор, "|");
 if num>0:
   for ii=1 to num do
     Value=Up(ExtractWord(ii, Набор, "|"));
     if Match(Up(ANA), Value): ^True; fi;
   od;
 fi;
 ^False;
end;

Func ПроводкаПроходитОтборПоАналитике(len:Integer; УслАналитики:String; СложноеУсловие:Logical) :Logical;
-- массив LibAna должен быть предварительно подготовлен (необходимые данные скопированы в массив LibAna)
var OK, MatchOK :Logical;
var ii, pp :Integer;
var Value, tmp :String;
 if Trim(УслАналитики)<>"":
   OK=False;
   if len>0: -- у проводки есть аналитика
     MatchOK=False;
     for ii=1 to len do  -- цикл по аналитике проводки
       pp=Pos(":", РАБ.НФА.LIBREP.LibAna[ii]);
       if pp>0: Value=SubStr(РАБ.НФА.LIBREP.LibAna[ii], 1, pp-1); else Value=РАБ.НФА.LIBREP.LibAna[ii]; fi;
       tmp=SubStr(Value, 1, 1);
       if tmp="+" or tmp="-": Value=Trim(SubStr(Value, 2, 255)); fi;
       if СложноеУсловие: -- простое условие - один признак или набор признаков через логическое "или" ( "|" )
         MatchOK=ПризнакСоотвМаске(Value, Trim(УслАналитики));
       else
         MatchOK=ПризнакСоотвНабору(Value, Trim(УслАналитики));
       fi;
       if MatchOK: Break; fi;
     od;
     if MatchOK: OK=True; fi;
   fi;
 else
   OK=True;
 fi;
 ^OK;
end;

Func СоответствуетФильтруПоГруппеНФА(аФтрГРП:String; аКОДГРП:String; аКОДПГР:String) :Logical;
var aValГРП, aValПГР, wdValue :String;
var ii, num :Integer;
var OK :Logical;
 if аФтрГРП<>"":
   num=WordsCount(аФтрГРП, "|");
   if num>0:
     OK=False;
     for ii=1 to num do
       wdValue=Lo(ExtractWord(ii, аФтрГРП, "|"));
       aValГРП=ExtractWord(1, wdValue, "$");
       aValПГР=ExtractWord(2, wdValue, "$");
       if (aValГРП=Lo(аКОДГРП) and aValПГР=Lo(аКОДПГР)) or (aValГРП=Lo(аКОДГРП) and aValПГР="*"): OK=True; fi;
       if OK: Break; fi;
     od;
     if OK: ^True; else ^False; fi;
   fi;
 else
   ^True;
 fi;
 ^False;
end;

-- *** *** *** *** ***

Func USE_ИНВЕНТАРНЫЙ_НОМЕР(ACC:String; SUM:Numeric; KOL:Numeric; FindУЧН:String; ctНФА100П:Numeric; ctНФА_ИНВ:Numeric) :Logical;
var Цена :Numeric;
 if Match(ACC, "*.?.101.??.???"):
    if Match(ACC, "*.?.101.?7.???"):
      if Match(FindУЧН, РАБ.НФА.LIBREP.pfxУЧН+".*"): ^True; else if ctНФА100П>0.00 and SUM<>0.00 and KOL<>0.00: Цена=Abs(SUM)/Abs(KOL); if Цена>ctНФА100П: ^True; fi; fi; fi;
    else 
      if Match(FindУЧН, РАБ.НФА.LIBREP.pfxУЧН+".*"): ^True; else if ctНФА_ИНВ>0.00 and SUM<>0.00 and KOL<>0.00: Цена=Abs(SUM)/Abs(KOL); if Цена>ctНФА_ИНВ: ^True; fi; fi; fi;
    fi;
 |  Match(ACC, "*.?.102.??.???"): ^True;
 |  Match(ACC, "*.?.103.??.???"): ^True;
 fi;
 ^False;
end;

Func СчетАмортизацииПоСчетуНФА(СЧТНФА:String) :String;
var sLeft, s1ACC, s2ACC, RES :String;
 RES="";
 if Match(СЧТНФА, "???.????.???????.???.?.101.??.???"):
    sLeft=SubStr(СЧТНФА, 1, 23);
    s1ACC=SubStr(СЧТНФА, 28, 1);
    s2ACC=SubStr(СЧТНФА, 29, 1);
    if s2ACC="1": RES=sLeft+"104."+s1ACC+"1.410";
    |  s2ACC="2": RES=sLeft+"104."+s1ACC+"2.410";
    |  s2ACC="3": RES=sLeft+"104."+s1ACC+"3.410";
    |  s2ACC="4": RES=sLeft+"104."+s1ACC+"4.410";
    |  s2ACC="5": RES=sLeft+"104."+s1ACC+"5.410";
    |  s2ACC="6": RES=sLeft+"104."+s1ACC+"6.410";
    |  s2ACC="7": RES=sLeft+"104."+s1ACC+"7.410";
    |  s2ACC="8": RES=sLeft+"104."+s1ACC+"8.410";
    else ^"";
    fi;
 |  Match(СЧТНФА, "???.????.???????.???.?.102.??.???"):
    sLeft=SubStr(СЧТНФА, 1, 23);
    s1ACC=SubStr(СЧТНФА, 28, 1);
    s2ACC=SubStr(СЧТНФА, 29, 1);
    if s2ACC="0": RES=sLeft+"104."+s1ACC+"9.420"; else ^""; fi;
 else ^"";
 fi;
 ^RES;
end;

Func СчетНФАпоСчетуАмортизации(СЧТАМТ:String) :String;
var sLeft, s1ACC, s2ACC, RES :String;
 RES="";
 if Match(СЧТАМТ, "???.????.???????.???.?.104.??.410"):
    sLeft=SubStr(СЧТАМТ, 1, 23);
    s1ACC=SubStr(СЧТАМТ, 28, 1);
    s2ACC=SubStr(СЧТАМТ, 29, 1);
    if s2ACC="1": RES=sLeft+"101."+s1ACC+"1.???";
    |  s2ACC="2": RES=sLeft+"101."+s1ACC+"2.???";
    |  s2ACC="3": RES=sLeft+"101."+s1ACC+"3.???";
    |  s2ACC="4": RES=sLeft+"101."+s1ACC+"4.???";
    |  s2ACC="5": RES=sLeft+"101."+s1ACC+"5.???";
    |  s2ACC="6": RES=sLeft+"101."+s1ACC+"6.???";
    |  s2ACC="7": RES=sLeft+"101."+s1ACC+"7.???";
    |  s2ACC="8": RES=sLeft+"101."+s1ACC+"8.???";
    else ^"";
    fi;
 |  Match(СЧТАМТ, "???.????.???????.???.?.104.?9.420"):
    sLeft=SubStr(СЧТАМТ, 1, 23);
    s1ACC=SubStr(СЧТАМТ, 28, 1);
    if s1ACC="2": RES=sLeft+"102.20.???";
    |  s1ACC="3": RES=sLeft+"102.30.???";
    |  s1ACC="4": RES=sLeft+"102.40.???";
    else ^"";
    fi;
 else ^"";
 fi;
 ^RES;
end;

Func ПоследнийПризнакВПроводкахИзСправочника(uACC:String; uANA:String; wdBt:Date; wdEt:Date; VOC:String) :String;
var AnaTrn, Value :String;
var Iter, pp :Integer;
var tSum :Numeric;
var Work :Logical;
 Value="";
 AnaTrn=uACC+"{"+uANA+"&"+VOC+".*}";
 Try tSum=Saldo(AnaTrn, 1.1.100); Except ^""; end;
 Work=True;
 for Transaction Iter=AnaTrn, wdBt, wdEt, Reverse do
   if TransSum(Iter, "РУБ")>0 and TransSum(Iter, "КОЛ")>0:
     if Work: pp=TransNumSign(Iter,     VOC+"."); if pp>0: Value=Trim(       TransSignName(Iter, pp)         ); Work=False; fi; fi;
     if Work: pp=TransNumSign(Iter, "+"+VOC+"."); if pp>0: Value=Trim(SubStr(TransSignName(Iter, pp), 2, 255)); Work=False; fi; fi;
     if Work: pp=TransNumSign(Iter, "-"+VOC+"."); if pp>0: Value=Trim(SubStr(TransSignName(Iter, pp), 2, 255)); Work=False; fi; fi;
     if not Work: Break; fi;
   fi;
 od;
 ^Value;
end;

Func ПоследнийПризнакВПроводкахИзСправочника_для104(uACC:String; uANA:String; wdBt:Date; wdEt:Date; VOC:String) :String;
var AnaTrn, Value :String;
var Iter, pp :Integer;
var tSum :Numeric;
var Work :Logical;
 Value="";
 AnaTrn=uACC+"{"+uANA+"&"+VOC+".*}";
 Try tSum=Saldo(AnaTrn, 1.1.100); Except ^""; end;
 Work=True;
 for Transaction Iter=AnaTrn, wdBt, wdEt, Reverse do
   if TransSum(Iter, "РУБ")<>0 or TransSum(Iter, "КОЛ")<>0:
     if Work: pp=TransNumSign(Iter,     VOC+"."); if pp>0: Value=Trim(       TransSignName(Iter, pp)         ); Work=False; fi; fi;
     if Work: pp=TransNumSign(Iter, "+"+VOC+"."); if pp>0: Value=Trim(SubStr(TransSignName(Iter, pp), 2, 255)); Work=False; fi; fi;
     if Work: pp=TransNumSign(Iter, "-"+VOC+"."); if pp>0: Value=Trim(SubStr(TransSignName(Iter, pp), 2, 255)); Work=False; fi; fi;
     if not Work: Break; fi;
   fi;
 od;
 ^Value;
end;

2-- События шаблона
Proc Template_OnOpen(Create:Logical); -- при открытии шаблона
 Очистить;
end;

Proc Template_AfterOpen(Create:Logical); -- после открытия шаблона
end;

Proc Template_OnClose(Destroy:Logical); -- при закрытии шаблона
 Очистить;
end;

КОНЕЦ -- бланка
