function Bk_Kvr_Ex( BudgetId: String;
                      StatusBar: TStatusBar;
                      ProgressBar: TProgressBar;
                      Ref: Boolean = False;
                      aCfgSelector: integer = 0): Variant;
var
  i, cnt: Integer;
  xsql, kvr: String;
  xCode: string;
  xNode: Variant;
begin

    try
      if not Ref then
      begin
        xsql :=
     ' select'
//    +' kl.master_id KBK_ID,'
    +' kl.ID LINE_ID,'
    +' 0 TYPE_KBK,'
    +' kl.CAPTION CAPTION,'
    +' kl.DESCRIPTION DESCRIPTION,'
    +' kl.begin_date BEGIN_DATE,'
    +' kl.end_date END_DATE,'
    +' kl.change_date CHANGE_DATE,'
    +' kl.unload_date UNLOAD_DATE,'
    +' C.CODE KVR_CODE,'
    +' 0 TYPE_KBK,'
    +' 0 LIMITED_FLAG'
    +' from EXPBUDGET B'
    +' join Kvr C on (C.CODE = B.KVR_CODE and C.BUDGET_ID = B.budget_id)'
    +' join Kvr_LINES KL on (KL.MASTER_ID = C.ID)'
    +' where B.BUDGET_ID = ?'
          +'  ~2 '
    +' group by'
//    +' kl.master_id,'
    +' kl.ID,'
    +' kl.CAPTION,'
    +' kl.DESCRIPTION,'
    +' kl.begin_date,'
    +' kl.end_date,'
    +' kl.change_date,'
    +' kl.unload_date,'
    +' C.CODE';
        Query.AddStr( BudgetId);
      end
      else begin
        xsql :=
     ' select distinct '
//    +' kl.master_id KBK_ID,'
    +' kl.ID LINE_ID,'
    +' 0 TYPE_KBK,'
    +' kl.CAPTION CAPTION,'
    +' kl.DESCRIPTION DESCRIPTION,'
    +' kl.begin_date BEGIN_DATE,'
    +' kl.end_date END_DATE,'
    +' kl.change_date CHANGE_DATE,'
    +' kl.unload_date UNLOAD_DATE,'
    +' C.CODE KVR_CODE,'
    +' 0 TYPE_KBK,'
    +' 0 LIMITED_FLAG,'
    +' 0 LINE_VERSION'
    +' from Kvr C'
    +' join Kvr_LINES KL on (KL.MASTER_ID = C.ID)'
    +' where C.BUDGET_ID = ?'
          +' ~2 ';
        Query.AddStr( BudgetId);
      end;
{
      xSQL := StringReplace( xSQL,
                             '~1',
                             SqlFilterQueryEx( aCfgSelector, 'KL'));
                             }

    // exchange #2596
    // если параметр Выгружать только «Утвержден на уровне субъекта
    // (муниципального образования)»» = да, то фильтруем по полю
    // «Утвержден на уровне субъекта (муниципального образования)».
    // допускаются записи у которых значение в этом поле =1.
    if vCfg_2596
      then Result := ExecuteQueryLoadEx( xSql, 'KL', '~2', ' and C.APPROVED_ENTITY_LEVEL=1 ')
      else Result := ExecuteQueryLoadEx( xSql, 'KL', '~2');
//        Result := ExecuteQueryLoadEx( xSql, 'KL', '~2');
    (*
      if not Ref then
      begin
        sql := 'Select C.Kvr_Code, KL.Description, KL.Caption, KL.Begin_Date,' +
          ' KL.Change_Date, KL.End_Date' +
          ' From ExpBudget C' +
          ' Join Kvr On (Kvr.Code = C.Kvr_Code And Kvr.Budget_Id = ?)' +
          ' Join Kvr_Lines KL on (KL.Master_Id = Kvr.Id and KL.Unapproved = 0)' +
          ' Where C.Budget_Id = ?' +
          ' Group By C.Kvr_Code, KL.Description, KL.Caption, KL.Begin_Date,' +
          ' KL.Change_Date, KL.End_Date';
        Result := QueryXml(Sql, [BudgetId, BudgetId]);
      end
      else begin
        sql := 'Select distinct C.Code Kvr_Code, KL.Description, KL.Caption,' +
          ' KL.Begin_Date, KL.Change_Date, KL.End_Date' +
            ' From Kvr C' +
            ' Join Kvr_Lines KL on (KL.Master_Id = C.Id and KL.Unapproved = 0)' +
            ' Where C.Budget_Id = ?';
        Result := QueryXml(Sql, [BudgetId]);
      end;
      *)
      cnt := Result.documentElement.ChildNodes.Length;
      ProgressBar.Max := cnt;
      for i := 0 to Result.documentElement.ChildNodes.Length - 1 do begin
        xNode := Result.documentElement.ChildNodes.item[i];

        ProgressBar.Position := i + 1;
        StatusBar.SimpleText := 'Приведение КБК в соответсвие с маской. Обработано: ' +
          IntToStr(i + 1) + ' из ' + IntToStr(cnt);

        { доработка заключается в удалении кеша - это не нужно.
          поскольку теперь при форматировании используется кэш более эффективно.
          это связано с тем, что в разных бюджетов маски могут быть разными.
          и потом: иметь один кеш на все коды - не эффективно: много памяти
          потребляется.
          так же добавлено новое поле: CODE_COPY.
          в него заносится исходный код БК, а в поле CODE сохраняем форматированный
          по максе (в отличие от старого кода, где форматирование только по длине).
          это больше похоже на АЦК-Ф, только для линейного списка.}
        xCode := xNode.getAttribute('KVR_CODE');
        {
        Kvr := CacheFormatKbk.Values['Kvr' +
          Result.documentElement.ChildNodes.item[i].getAttribute('KVR_CODE')];
        if Kvr = '' then
        begin
          Kvr := KvrCodeFormat(
            Result.documentElement.ChildNodes.item[i].getAttribute('KVR_CODE'),
              BudgetId);
          CacheFormatKbk.Add('Kvr' +
            Result.documentElement.ChildNodes.item[i].getAttribute('KVR_CODE') +
              '=' + Kvr);
        end;
        Result.documentElement.ChildNodes.item[i].setAttribute('CODE', Kvr);
        }

        xNode.setAttribute('CODE', KvrCodeFormat( xCode, BudgetId, kbkMaskOfChar));
        xNode.setAttribute('CODE_COPY', xCode);
      end;
      ProgressBar.Position := 0;

      except
        ExceptionLog( 'Сбой Un_Kbk5.Bk_Kvr_Ex');
    end;

end;

begin
end.
