TClientDataSet.Locate - ошибка runtime в автооперации WF

Автор Chipollino, 05.02.14, 10:33:49

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Chipollino

В WorkFlow появилась необходимость назначать исполнителя по данным из атрибута объекта БП.

Данные из атрибута берутся, список пользователей для следующей стадии получается, но никак не могу перейти на нужную мне запись.
При запуске процесса появляется такая ошибка:

ЦитироватьТест автоназначения
При выполнении метода бизнес-логики WorkFlow произошла ошибка
Метод: "WFSetStateOfProcess"
Сообщение: "Ошибка в скрипте автооперации [Назначить исполнителя из атрибута]
RUNTIME ERROR
Could not convert variant of type (Array Variant) into type (Integer) when evaluating instruction CallProc ($0,$3,$B9FFDB4,$7B1B350,'Locate').
Stack content is: [String:Фамилия Имя Отчество].
Source position: 17,71"

Текст самой автооперации:

Program Main;
var
   stAttrVar: String;

begin
     result := Route.vrParamValue('Результат если не нашли');
     cdsUsers := TClientDataSet.Create(nil);
     stAttr := Route.vrParamValue('Имя атрибута');
     stAttrVar := VarToStr(PDMObject.Attribute(stAttr));

     for i := 0 to Route.inNextStageCount - 1 do
     begin
          Stage := Route.NextStage(i);
          if (Stage.stType = 'Stage') then
          begin
               cdsUsers.Data := GetUserList(Stage.inIdRole);
               result := cdsUsers.Locate( '_FullName', stAttrVar , []);
               if result then
               begin
                    inIdUser := StrToInt(cdsUsers.FieldByName('_ID').asString);
                    result := Stage.SetExecutor(inIdUser);
               end;
               cdsUsers.Free;
               SetResultOperation(result);
          end;
     end;
end;


Собственно сама команда cdsUsers.Locate( '_FullName', stAttrVar , []) не выполняется вообще (пробовал заменить параметр _FullName на заведомо неправильный - ошибка оставалась прежней )

Если верить справке, то всё должно работать...
Лоцман 2013 sp1

Chaa

Попробуйте для начала:
result := cdsUsers.Locate( '_FullName', stAttrVar , 0);
В языке скрипта есть отличия от Delphi. Насколько я понял из текста ошибка, в скрипте [] это Array Variant, а в Delphi это будет множество (суть битовая маска), или Integer.
+ Благодарностей: 1

Chipollino

Да, теперь всё сошлось - почему он ругался на массив и на перевод в int. Странно, что в примерах скриптов указаны именно квадратные скобки (TRoute.stTypicalName)
Правда теперь ругается на адрес:
ЦитироватьТест автоназначения
При выполнении метода бизнес-логики WorkFlow произошла ошибка
Метод: "WFSetStateOfProcess"
Сообщение: "Ошибка в скрипте автооперации [Назначить исполнителя из атрибута]
RUNTIME ERROR
Access violation at address 0B9FB022 in module 'WORKFL~1.DLL'. Read of address 0700BBE8 when evaluating instruction CallProc ($0,$3,$B9FFDB4,$7B1B350,'Locate').
Stack content is: [String:Фамилия Имя Отчество].
Source position: 17,70"

Но я на просторах интернета наткнулся на другой вариант поиска - обход всех записей в цикле и он работает как надо.

Program Main;
var
   stAttrVar: String;

begin
     result := Route.vrParamValue('Результат если не нашли');
     cdsUsers := TClientDataSet.Create(nil);
     stAttr := Route.vrParamValue('Имя атрибута');
     stAttrVar := VarToStr(PDMObject.Attribute(stAttr));

     for i := 0 to Route.inNextStageCount - 1 do
     begin
          Stage := Route.NextStage(i);
          if (Stage.stType = 'Stage') then
          begin
               cdsUsers.Data := GetUserList(Stage.inIdRole);
               while not cdsUsers.EOF do
               begin
                    if cdsUsers.FieldByName('_FullName').asString = stAttrVar then
                    begin
                         inIdUser := cdsUsers.FieldByName('_ID').asInteger;
                         result := Stage.SetExecutor(inIdUser);
                    end;
                    cdsUsers.Next;
               end;
               cdsUsers.Free;
               SetResultOperation(result);
          end;
     end;
end;

z-arthur

Скорей всего ошибка "Access violation" появляется из-за того, что cdsUsers у вас уничтожается внутри цикла:

Цитироватьif (Stage.stType = 'Stage') then
          begin
               cdsUsers.Data := GetUserList(Stage.inIdRole);
               result := cdsUsers.Locate( '_FullName', stAttrVar , []);
               if result then
               begin
                    inIdUser := StrToInt(cdsUsers.FieldByName('_ID').asString);
                    result := Stage.SetExecutor(inIdUser);
               end;
               cdsUsers.Free;
               SetResultOperation(result);
          end;

Перенесите cdsUsers.Free за пределы цикла и ошибка  должна исчезнуть.
Или добавьте выход из цикла:

Цитироватьif (Stage.stType = 'Stage') then
          begin
               cdsUsers.Data := GetUserList(Stage.inIdRole);
               result := cdsUsers.Locate( '_FullName', stAttrVar , []);
               if result then
               begin
                    inIdUser := StrToInt(cdsUsers.FieldByName('_ID').asString);
                    result := Stage.SetExecutor(inIdUser);
                    Break;
               end;
               cdsUsers.Free;
               SetResultOperation(result);
          end;

Chipollino

Проблема оказалась не в расположении (если условие по переходу к искомой записи выполнилось, то следующая итерация не происходит)

Ошибка исчезла после перезапуска клиента лоцмана.