Лоцман API + Плагин + Delphi

Автор Dim, 30.04.08, 10:05:17

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

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

Администратор

Друзья!

Убедительно прошу не раздувать одну большую тему с «кашей» из разнообразных вопросов по программированию на API ЛОЦМАНа. А, как это и положено по Правилам Форума, создавать отдельную тему с информативным названием для каждого отдельного вопроса.

Если в настоящей теме продолжится сваливание разнородных вопросов в одну кучу, она будет закрыта.

Спасибо за понимание!


Maxxx

Может тогда будет целесообразно создать подраздел по программированию под ЛОЦМАН чтобы не получалось "каши" из КОМПАСА и ЛОЦМАНА? И темы создавать в этом подразделе...

Администратор

Создам в ближайшее время. Но темы все равно пока отдельные начинайте. Я их потом перенесу в нужный раздел.

И если из настоящей темы можно выделить какие-то сообщения в отдельную — скажите мне (дайте ссылки, что можно объединить в одну тему и как её назвать), я разделю топик.

Спасибо!

Dim

Здравствуй Уважаемый Администратор!!!  ::)
Прав Маххх!!! Мне нужен форум только-только для Лоцмана.
Хорошо, что буду создавать отдельную тему с информативным названием для каждого отдельного вопроса. Но не удобно.
Уверен что Вы создаете в ближайшее время... А главнее "создать подраздел по программированию под ЛОЦМАН чтобы не получалось "каши" из КОМПАСА и ЛОЦМАНА и т.д."...  :um:
С уважением Dim.  :)

ardent

Всем привет, нашел на этом форуме вот такую вот интересную процедурку...скажите, у кого нибудь получилось её использовать? Если да то как если нет то какие ещё варианты есть?

2. Открыть в новом окне
//Открыть один объект в новом окне

procedure OpenObjectInNewWindow(AppHandle: THandle; inID: integer; stDatabaseName: string; stCheckOutName: string = '');
begin
  with TPBShareMap.Create(nil) do
  try
    MapName := 'Loodsman';
    MaxSize := 4096;
    AutoSynchronize := False;
    OpenMap;

    repeat
      sleep(100);
      ReadMap;
    until (Values['_READY'] = 'TRUE');

    Values['_DATABASENAME'] := stDatabaseName;
    Values['_CHECKOUTNAME'] := stCheckOutName;
    Values['_ID_VERSION']   := inttostr(inID);
   
    WriteMap;
    sleep(100);
    PostMessage(AppHandle, WM_OPENOBJECTINNEWWINDOW, 0, 0);
  finally Free; end;
end;

Muk

Ууу, какую я тему интересную пропустил. В отпуске был...

Может Администратор любезно переместит во вновь созданный раздел и этот топик?

Мне конечно далеко до уважаемого YorikER в плане изучения возможностей Лоцман API, но зато на моем сайте уже лежат некоторые исходники, причем уже два года как лежат. ;)

По поводу модальности/немодальности. Идея выполнять Application.Run вместо Form1.ShowModal интересна. Только хотелось бы услышать экспертное мнение специалистов Аскон насчет возможных побочных эффектов запуска вложенного цикла обработки сообщений. Вроде на первый взгляд в этот ничего страшного нет. Но может Аскон переделал стандартный цикл и новый Application.Run в плагине погубит какой-то функционал Лоцмана?

Muk

Цитата: YorikER от 15.07.08, 09:16:07Я храню id  в свойстве Node.Data тип Pointer, преобразуя в integer... Это на мой взгляд более правильно, т.к. Data для этого и предназначена...
А я создаю один или несколько классов-наследников класса TTreeNode. Например:

type
  TLoodsmanTreeNode = class(TTreeNode)
  public
    ObjectType: string;
    KeyValue: string;
    Version: string;
    VersionID: Integer;
    LinkType: string;
    LinkID: Integer;
  end;

А потом определяю обработчик

procedure TNCArchMainForm.TreeViewCreateNodeClass(Sender: TCustomTreeView;
  var NodeClass: TTreeNodeClass);
begin
  NodeClass := TLoodsmanTreeNode;
end;

в случае одного наследника. Или создаю объекты нужного класса вручную:

  Node := TSecondLoodsmanTreeNode.Create(TreeView.Items);
  TreeView.Items.AddNode(Node, ParentNode, 'Заголовок узла', nil, naAddChild);

В этом случае удобно писать

begin
  if TreeView.Selected is TLoodsmanTreeNode then
    ...
  else if TreeView.Selected is TSecondLoodsmanTreeNode then
    ...
end;

YorikER

Подход более чем верный, ну тогда я бы пошел дальше... Вложил бы в данный объект еще и методы сервера приложений по аналогии с TVersion Лоцман API.

У себя в приложениях я создал объект TVLVer...

type
  //Версия
  TVLVer = class(TObject)
  private
    { Private declarations }
   
    iRC,sEM:      Variant;
  public
    { Public declarations }
    DCOM:         TVLDComConnection;
    //Параметры объекта  - Нельзя менять порядок и набор этих полей
    inID: longInt;         // ID
    stProduct: string;     // Наименование
    stType:    string;     // Тип
    stVersion: string;     // Версия
    stState:   string;     // Состояние
    inAccessLevel: byte;   // Уровень доступа
    inLockLevel:   byte;   // Уровень блокировки
    boDocument: byte;      // Признак объекта-документа
    stCheckOut: string;    // Текущий чекаут
    boParentCheckOut: Boolean;// Признак головного объекта в чекауте
    _inLock:   integer;    // буфер уровня блокировки
    inBuffer:   integer;   // буфер

    stBaseName: string;
    cdsAtt:    TClientDataSet; // список атрибутов

    constructor FromIDVersion(_ID_Version : Integer; curDCOM: TVLDCOMConnection); virtual;
    destructor Destroy; virtual;

    function GetLinkedFast(stLinkName: string; boDirection: boolean): Variant;
    function GetLinkedObjectsEx(stLinkName: string;
                                boDirection, boFullLink, boGroupByProduct  :boolean): Variant; virtual;
    function GetTree(stLinkName: string; boWithAttr: boolean): Variant;
    function GetAttributes: Variant; virtual;
    function GetLinkAttributes(inLink: integer): Variant;
    function GetAttrImageValueById(stNameAttr: string): Variant; virtual;
    function IsAdmin: Variant; virtual;
    function GetInfoAboutVersion(inMode: integer): Variant;

    function CheckOut: boolean;
    procedure CheckIn;
    function ConnectToMyCheckOut: boolean;
    function InWork: boolean;
    procedure OutWork;
    procedure UpAttrValue(stName: string; vaValue: Variant; boDel: boolean = false);
    function UpLinkAttrValue(inIdLink:    integer;
                             stAttrName:  string;
                             vaAttrValue: Variant;
                             stIdUnit:    string;
                             boDel:       boolean): integer;
    function UpObject(Name: string): Variant; virtual;
    function CreateCopy(stProductName, stStateName: string; vaFileList: Variant; inParams: integer): Variant;                         
    function InsertObject(stChildType,stChildProduct,stChildVersion,
                          stLinkType,stState: string; boKeyInsert: boolean): Variant;
    function GetChildIdForIdLink(inLink: integer): integer;
    function GetMinQuantity(inLink: integer): double;
    procedure KillVersion(inObj: integer);
    function UpLink(stChildType,stChildProduct,stChildVersion: string;
                    inIdLink: integer;
                    reMinQuantity,reMaxQuantity: double;
                    stIdUnit: string;
                    boDel: boolean;
                    stLinkType: string): Variant;
    function NewLink(idChild: integer; stLink:  string): integer;
    procedure UpGrantOnVersion(stName: string; inAcc: integer;
                               dtFinishTime: TDateTime; boDel: boolean);
  end;

Muk

Цитата: YorikER от 10.09.08, 13:58:00
Подход более чем верный, ну тогда я бы пошел дальше... Вложил бы в данный объект еще и методы сервера приложений по аналогии с TVersion Лоцман API.
Конечно. Но я еще не замахивался на коммерческие версии. ;) Просто в моем варианте не надо вручную освобождать объекты, прицепленные на Data.

YorikER

Да, это действительно серьезное преимущество, я об этом как-то не подумал...

Muk

#110
Я выложил новую версию Loodsman Suite, включая "дерево", на http://www.mea.dol.ru/loodsman. В исходниках. Сделал похоже на Асконовское (за исключением хинтов, которые у меня смещены). :) Жду комментариев.

Dim

Здравствуйте Многоуважаемые  88))!!!
Я вернул... У меня проблема...
Помогите пожалуйста, вот см рис.
Мне нужен это дерево в Memo, вот, например,
Выводить в Memo:
Шайба -> Т55 -> Т1
Шайба -> Т45 -> Т55->  Т1
Шайба -> Т45 -> Т100 -> Т1
Шайба -> Т45 -> Т100 -> Т200 -> Т1

Это все от начала "Шайба" и до конца " Т1" - это все связь...

Ну как бы сказать это все связь "Входит в ..." от функции API "GetLinkedObjects2(data.FieldByName('_ID_VERSION').AsInteger,'Состоит из ...', true (истина - это "Входит в ..."), false, false, inErrCode, stErrMess)"

Вот у мя есть исходник с процедурами, проверь пожалуйста, может есть ошибка, это вроде как рекурсия.

procedure WhileAll(data: TClientDataSet);
Var
  data1: TClientDataSet;
  i:  Integer;
Begin
  data1:=TClientDataSet.Create(nil);
  while not data.Eof do Begin
    Data1.Data:=Form1.DCOMConnection1.AppServer.GetLinkedObjects2(data.FieldByName('_ID_VERSION').AsInteger,'Состоит из ...', true, false, false, inErrCode, stErrMess);
    Form1.Memo1.Lines.Add(data.FieldByName('_PRODUCT').AsStringt);
    WhileAll(data1);
    data.Next;
  End;

End;


Заранее спасибо!!!
С наибольшим уважением, Dim

teplinskiy

#112
Цитата: Dim от 20.08.09, 22:37:53
Мне нужен это дерево в Memo, вот, например,
Выводить в Memo:
Шайба -> Т55 -> Т1
Шайба -> Т45 -> Т55->  Т1
Шайба -> Т45 -> Т100 -> Т1
Шайба -> Т45 -> Т100 -> Т200 -> Т1

Это все от начала "Шайба" и до конца " Т1" - это все связь...

Ну как бы сказать это все связь "Входит в ..." от функции API "GetLinkedObjects2(data.FieldByName('_ID_VERSION').AsInteger,'Состоит из ...', true (истина - это "Входит в ..."), false, false, inErrCode, stErrMess)"

Вот у мя есть исходник с процедурами, проверь пожалуйста, может есть ошибка, это вроде как рекурсия.

Обращаю всеобщее внимание на то, что...РЕКУРСИЯ...это НЕ ЕСТЬ ХОРОШО...
когда мы говорим  о вызовах методов сервера приложений...

да...на рисунке представлены всего лишь 6 объектов,
но представьте, что их 10 тысяч...и что даст...РЕКУРСИЯ...
можно будет после запуска тихо стоять и курить в сторонке минут 5...
пока сервер захлебывается от нашей рекурсии...

Предлагаю следующий ход действий:
1. Написать SQL скрипт хранимой процедуры.
Скрипт возвращает таблицу c полями, например:
ID_PARENT, PARENT_PRODUCT, ID_CHILD, CHILD_PRODUCT, LEVEL
То есть получится:
-------------
NULL, NULL, ID шайбы, "Шайба", 0
ID шайбы, "Шайба", ID T55, "T55", 1
ID шайбы, "Шайба", ID T45, "T45", 1
ID T55, "T55", ID T1, "T1", 2
и т.д.
-------------
Приготовить его для использования, отработав в нашей БД
(Подсказки искать в разделах по созданию отчетов)

2. Теперь 1 раз забираем данные вызвав метод СП "GetReport" во временный датасет

   cdsTemp.Data := DCOMConnection1.AppServer.GetReport('rep_Наш SQL скрипт', vaObj, stParam); 

правда есть одно но...ID шайбы нужно передавать как вариантный массив:
   vaObj := VarArrayCreate([0,0], varInteger);
   vaObj[0] := ID шайбы;

3. И делаем с датасетом, что душа просит...))). Уже к нему применяем рекурсию...сравнивая ID родителя и потомка...выстраивая цепочку...

А вообще такой вопрос:
"Какую смысловую нагрузку несет данная задача???"
мне кажется бессмысленным построение таких цепочек...с точки зрения применяемости этой задачи

teplinskiy

#113
Цитата: Dim от 20.08.09, 22:37:53

procedure WhileAll(data: TClientDataSet);
Var
  data1: TClientDataSet;
  i:  Integer;
Begin
  data1:=TClientDataSet.Create(nil);
  while not data.Eof do Begin
    Data1.Data:=Form1.DCOMConnection1.AppServer.GetLinkedObjects2(data.FieldByName('_ID_VERSION').AsInteger,'Состоит из ...', true, false, false, inErrCode, stErrMess);
    Form1.Memo1.Lines.Add(data.FieldByName('_PRODUCT').AsStringt);
    WhileAll(data1);
    data.Next;
  End;

End;



Попробуйте так...внимание это только набросок
(как пример...отсутствует блок обработки искл. ситуаций):

procedure TForm1.Button3Click(Sender: TObject);
var
  inIDOdj : integer;
  stProdObj : string;
begin
  Memo1.Clear;
  Memo1.Lines.EndUpdate;
  Memo1.Lines.BeginUpdate;

  inIDOdj := 12150;          \\ здесь Ваш ID и PRUDUCT
  stProdObj := 'Шайба';

  GetLinkedObjects(inIDOdj, stProdObj);

  Memo1.Lines.EndUpdate;
end;

procedure TForm1.GetLinkedObjects(inIDObj : integer; stProdObj : string);
var
vaErrCode, vaErrStr : Variant;
cdTemp : TClientDataSet;
stPath, stFullPath : string;
begin
  stPath := stPath + stProdObj;
  cdTemp := TClientDataSet.Create(nil);
  cdTemp.Data := DCOMConnection1.AppServer.GetLinkedObjects2(inIDObj,
                                                             'Состоит из ...',
                                                             False,
                                                             False,
                                                             False,
                                                             vaErrCode, vaErrStr);
  if vaErrCode = 0 then
    begin
      if cdTemp.IsEmpty then Memo1.Lines.Add(stPath)
      else
        begin
          cdTemp.First;
          while not cdTemp.Eof do
            begin
              stFullPath := stPath + '->' + cdTemp.FieldByName('_PRODUCT').AsString;
              GetLinkedObjects(cdTemp.FieldByName('_ID_VERSION').AsInteger, stFullPath);
              cdTemp.Next;
            end;
        end;
    end;
  cdTemp.Free;
end;

---------------
отрабатывает по нажатию кнопки...
не забудте процедуру "GetLinkedObjects" объявить для вашей формы...

--------------

НО...не оставляйте без внимания предыдущий ответ...

Dim

Здравствуй, многоуважаемый teplinskiy  :)!!!
Спасибо огромное!!! У мя получается твою процедуру GetLinkedObjects(inIDOdj, stProdObj), но я исправил не False, как ты написал, а на True, то есть связь "Входит в ..."...
Я с тобой согласен: если 10 тысяч объектов, то плохо будет. Скорее всего лучше написать SQL скрипт хранимой процедуры. Я пробовал, все-таки не получается. Напишите, пожалуйста,  SQL скрипт хранимой процедуры, и я обязательно разберусь, освоюсь. А ещё я не понял: "передавать как вариантный массив:
   vaObj := VarArrayCreate([0,0], varInteger);
   vaObj[0] := ID шайбы;"
.

С наибольшим уважением, Dim  :shu:.

P.S. Я ни разу не пробовал метод СП "GetReport"  88))

teplinskiy

Цитата: Dim от 24.08.09, 11:29:47
но я исправил не False, как ты написал, а на True, то есть связь "Входит в ..."...

День добрый...
Dim...на приложенном рисунке мой тестовый состав объектов по вашим требованиям...
Особо обращать внимание на тип объектов "Папка" не стоит...
так как используется метод...пользующий ID объекта и Связь "Систоит из ..."
и только это важно...
На рисунке видно что "Шайба" - это родитель, она "Систоит из ..." объектов "Т45" и "Т55" - это ее потомки...
Таким образом построено все дерево...Т.е. "родитель" состоит из "потомков"...
Поэтому в методе СП "GetLinkedObjects2" флаг "boInverse" (направление) выставлен в "False"...
так как в справке по методу сказано:

boInverse
[in] Направление (True - обратное/False - прямое).

А значит...у Вас Dim...ошибка в организации связей между родителями и их потомками, видимо они поменяны местами...т.е. "Шайба" - это потомок (хотя она родитель), она "Входит в" объекты "Т45" и "Т55" - это ее родители (хотя они потомки)...
Поскольку мой код рабочий...и замена значения флага привела бы к пустому результату...

teplinskiy

Цитата: Dim от 24.08.09, 11:29:47
Напишите, пожалуйста,  SQL скрипт хранимой процедуры, и я обязательно разберусь, освоюсь. А ещё я не понял: "передавать как вариантный массив:
   vaObj := VarArrayCreate([0,0], varInteger);
   vaObj[0] := ID шайбы;"
.

К выше сказанному как Вы и просили прилагаю SQL скрипт выбирающий необходимые данные по вашим требованиям, а также скрин результата его работы...

По поводу вариантного массива повторю...что метод  СП "GetReport" запрашивает в качестве одного из параметров ID объекта...в нашем случае шайбы...но передать мы этот ID должны как вариантный массив из одного числа (иначе не сработает...фича такая)...т.е.
создаем такой массив, присваиваем ему ID шайбы...и передаем массив в метод как параметр...

Dim

Добрый вечер, teplinskiy!!!
Вы правы по родителями и потомками. Но Вы наверно не поняли меня, а может вы  и так поняли, те это можно и так и есть. Получается вы говорите так, а я имею в виду наоборот, те Вы имеете ввиду, что от Шайб до Т1, а у мя наоборот, От Т1 до Шайб, но все таки верная процедура GetLinkedObjects ... А насчет SQL скрипт - завтра разберу. Если что, то сообщу. Спасибо Вам очень-очень огромное  :) :) :) 88)) :) :) :)...
С уважением, Dim!!!

teplinskiy

#118
Цитата: Dim от 24.08.09, 22:56:31
те Вы имеете ввиду, что от Шайб до Т1, а у мя наоборот, От Т1 до Шайб

ясно...простите...видимо сбило с толку направление связи "->" вместо "<-"...
тогда правильно...флаг должен быть "True"

также поменяйте в SQL скрипте (если будете использовать):
- название связи с "Состоит из ..." на "Входит в"
- наименование столбцов у таблицы с "PARENT" на "CHILD" и наоборот (не обязательно)

Dim

Цитироватьтакже поменяйте в SQL скрипте (если будете использовать):
- название связи с "Состоит из ..." на "Входит в"
- наименование столбцов у таблицы с "PARENT" на "CHILD" и наоборот (не обязательно)

Здравствуйте teplinskiy!!!  :)
Я попровал - название связи с "Состоит из ..." на "Входит в". Получается, что неверно (выводит только одна строка), и также поменял наименование столбцов у таблицы с "PARENT" на "CHILD" и все таки нет... Может Вы не проверили... А может я что то упустил... Скиньте пожалуйста исправленный скрипт SQL
С уважением, Dim!!!  88))