Код для массового перименования позиций

Автор Sprinter500, 22.03.13, 20:25:41

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

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

Sprinter500

Добрый день! Пытаюсь написать код для массового переименования обозначений позиций (скажем сдвиг нумерации или приписка/удаление буквы), но ничего не выход. Нашел в SDK два кода на Visual Basic: один для перебора объектов, а другой - для создания и редактирования позиции. Думаю они должны подойти. Но как их объединить? Все мои попытки не увенчались успехом.
Вот примеры кодов:
1.
Sub WalkFromView(doc As Object) ' хождение по виду
  ' в текущем документе и виде создадим итератор для хождения по всем элементам
  Dim obj As Long
  Dim count As Integer
  count = 0
  Dim iIter As Object ' ksIterator
  Set iIter = iKompasObject.GetIterator
  iIter.ksCreateIterator ALL_OBJ, 0
  If iIter.reference Then
    obj = iIter.ksMoveIterator("F")
    If doc.ksExistObj(obj) Then
      Do
        doc.ksLightObj obj, 1
        count = count + 1
        iKompasObject.ksMessage "номер = " & count
        doc.ksLightObj obj, 0
        obj = iIter.ksMoveIterator("N")
      Loop Until doc.ksExistObj(obj) = 0
    End If
  End If
End Sub


2.
Sub DrawPosLeader(doc As Object)
  Dim ilead As Object ' ksPosLeaderParam
  Set ilead = iKompasObject.GetParamStruct(ko_PosLeaderParam)
  Dim itLinePar As Object ' ksTextLineParam
  Set itLinePar = iKompasObject.GetParamStruct(ko_TextLineParam)
  Dim iItemPar As Object ' ksTextItemParam
  Set iItemPar = iKompasObject.GetParamStruct(ko_TextItemParam)
  Dim itFont As Object ' ksTextItemFont
  Set itFont = iItemPar.GetItemFont()
  Dim itMathPoint As Object ' ksMathPointParam
  Set itMathPoint = iKompasObject.GetParamStruct(ko_MathPointParam)
  If Not ilead Is Nothing And Not itLinePar Is Nothing And Not iItemPar Is Nothing And Not itFont Is Nothing And Not itMathPoint Is Nothing Then
    ilead.Init
    itLinePar.Init
    iItemPar.Init
    itFont.Init
    itMathPoint.Init

    'ilead.Style = INDICATIN_TEXT_LINE_ARR
    itFont.SetBitVectorValue NEW_LINE, True
    itLinePar.Style = 0
    Dim iptext As Object ' ksDynamicArray
    Set iptext = ilead.GetpTextline()
    Dim iTextItemArr As Object ' ksDynamicArray
    Set iTextItemArr = itLinePar.GetTextItemArr()
   
    iItemPar.s = "1"
    iTextItemArr.ksAddArrayItem -1, iItemPar
    iptext.ksAddArrayItem -1, itLinePar

    Dim ipPolyLin As Object ' ksDynamicArray
    Set ipPolyLin = ilead.GetpPolyline
    Dim ipMathPoint As Object ' ksDynamicArray
    Set ipMathPoint = iKompasObject.GetDynamicArray(POINT_ARR)

    If Not ipPolyLin Is Nothing And Not ipMathPoint Is Nothing Then
      itMathPoint.x = 10
      itMathPoint.y = 10
 
      ipMathPoint.ksAddArrayItem -1, itMathPoint
      ipPolyLin.ksAddArrayItem -1, ipMathPoint
 
      itMathPoint.x = 30
      itMathPoint.y = 10
      ipMathPoint.ksClearArray
      ipMathPoint.ksAddArrayItem -1, itMathPoint
      ipPolyLin.ksAddArrayItem -1, ipMathPoint
 
      ilead.SetpPolyline ipPolyLin
    End If
   
    ' заполним параметры
    ilead.x = 50 ' координаты базовой точки ( начало полки )
    ilead.y = 50
    ilead.arrowType = 1
    ilead.dirX = -1

    Dim obj As Long
    obj = doc.ksPositionLeader(ilead)
    If obj Then
      doc.ksGetObjParam obj, ilead, ALLPARAM
      ilead.x = 100
      iKompasObject.ksMessage "Поменяем параметры"
      doc.ksSetObjParam obj, ilead, ALLPARAM
    End If
  End If
End Sub

Sprinter500

Неужели никто подсказать не может?

KrissKross

ИМХО
за чем такие сложности
через API7 - все достаточно просто
Виды - Вид - Контейнер условных обозначений - Линии-Выноски - Линия-выноска -
Линия-выноска для обозначения позиции -
смотрим 2 свойства:
Positions
UnderPositionText
+ Благодарностей: 1

Получаете от вида ISymbols2DContainer контейнер условных обозначений, далее коллекцию линий-выносок Leaders, получаете IBaseLeader от свойства ILeaders.Leader, приводите интерфейс IBaseLeader к IDrawingObject и проверяете свойство DrawingObjectType , если равно ksDrPosLeader, то приводите интерфейс IBaseLeader к IPositionLeader - интерфейс параметров линии-выноски для обозначения позиции и редактируете его.
Второй вариант, получаете от вида(IView) контейнер объектов вида графического документа IDrawingContainer, далее получаете массив SAFEARRAY объектов Air:=IDrawingContainer.Objects[ksDrPosLeader] линий-выносок для обозначения позиций, входящих в состав данного объекта вида.
+ Благодарностей: 1

Sprinter500

Спасибо. Теперь знаю направление дальнейшего поиска. Было бы конечно лучше увидеть образец кода, хотя бы выполнящего не в точности то что мне нужно, а например смежную или схожую функцию.

Sprinter500

Добрый день! На VB я так и не решил задачу. Теперь перешел на программирование в Delphi. На нем даже решилась проблема из соседней, основанной мною ветки о работе с переменными в 3D.
Но по данной теме как решить? Я смотрю куда больше знатоков Delphi, чем VB. Может кто чем помочь?
Надо сделать следующее:
1. Пройтись по всем видам, или только по текущему, или только по выделенным элементам (всего 3варианта) по тексту в линиях-выносках, позиционных линиях выносках и текстовым надписям (тоже три варианта).
2. И соответственно изменить один текст на другой в линиях-выносках, позиционных линиях выносках и текстовым надписям.

И еще доп. вопрос: Как произвести замену в вертикальном тексте таблиц?

Slaviation

#6
В прицепе, но на Python (для его популяризации среди уважаемых форумчан :))
Должны быть установлены:
КОМПАС-3D V13 или новее, Python, расширение PyWin32 для Python.
Запускаем компас, открываем чертеж с выносками и текстами, запускаем тест.

Slaviation

ЦитироватьИ соответственно изменить один текст на другой
Добавил в тест заменяемый текст
+ Благодарностей: 1

Sprinter500

Вот набросал такой код:

procedure RENM();
var
   newKompasAPI : IApplication;
   disp : IDispatch;
   pDocuments : iDocuments;
   pDocument : IKompasDocument;
   pKompasDocument2D : IKompasDocument2D;
   pViewsAndLayersManager : IViewsAndLayersManager;
   pViews : IViews;
   pView : IView;
   pSymbols2DContainer : ISymbols2DContainer;
   // pDrawingContainer : IDrawingContainer;
   pLeaders : ILeaders;
   pBaseLeader : IBaseLeader;
begin
     disp := IDispatch( CreateKompasApplication );
     newKompasAPI := disp As IApplication;
     pDocuments := newKompasAPI.Documents;
     pDocument := pDocuments.Add(1,true);//(doc tupe,visible-regim)
     pKompasDocument2D :=  pDocument as iKompasDocument2D;
     pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager;
     pViews := pViewsAndLayersManager.Views;
     pView := pViews.ViewByNumber[1];
     pView.Current := true;
     //pDrawingContainer := pView as iDrawingContainer;
     pSymbols2DContainer := pView as iSymbols2DContainer;
     pLeaders:= pSymbols2DContainer.Leaders;
     pBaseLeader := pLeaders.Leader;
     //Дальше что делать?
end;

Дальше что нужно делать? В Питоне есть код, но как в Delphi  перевести?:

        if self.__context != 2:
            viewsAndLayersManager =activeDoc2D.ViewsAndLayersManager
            views = viewsAndLayersManager.Views
            context = []
            if self.__context == 0:
                for i in range(views.Count):
                    context.append(views.View(i))
            else:
                context.append(views.ActiveView)
               
            if self.__target != 2:
                for i, view in enumerate(context):
                    symbols2DContainer = module.ISymbols2DContainer(view._oleobj_.QueryInterface(module.ISymbols2DContainer.CLSID, pythoncom.IID_IDispatch))
                    leaders = symbols2DContainer.Leaders
                    for j in range(leaders.Count):
                        baseLeader = leaders.Leader(j)
                        if self.__target == 0 and baseLeader.DrawingObjectType == 20: #Простая линия-выноска
                            leader = module.ILeader(baseLeader._oleobj_.QueryInterface(module.ILeader.CLSID, pythoncom.IID_IDispatch))
                            if leader != None and  leader.TextOnShelf.Str == self.__oldValue:
                                leader.TextOnShelf.Str = self.__newValue
                        if self.__target == 1 and baseLeader.DrawingObjectType == 21: #Линия-выноски для обозначения позиции
                            positionLeader = module.IPositionLeader(baseLeader._oleobj_.QueryInterface(module.IPositionLeader.CLSID, pythoncom.IID_IDispatch))
                            if positionLeader != None and  positionLeader.Positions.Str == self.__oldValue:
                                positionLeader.Positions.Str = self.__newValue
                        baseLeader.Update()
            else:
                for i, view in enumerate(context):
                    drawingContainer = module.IDrawingContainer(view._oleobj_.QueryInterface(module.IDrawingContainer.CLSID, pythoncom.IID_IDispatch))
                    drawingTexts = drawingContainer.DrawingTexts
                    for j in range(drawingTexts.Count):
                        drawingText = drawingTexts(j)
                        text = module.IText(drawingText._oleobj_.QueryInterface(module.IText.CLSID, pythoncom.IID_IDispatch))
                        if text.Str == self.__oldValue:
                            text.Str = self.__newValue
                            drawingText.Update()
           
        else:
            activeDoc2D1 = module.IKompasDocument2D1(activeDoc2D._oleobj_.QueryInterface(module.IKompasDocument2D1.CLSID, pythoncom.IID_IDispatch))
            selectionManager = activeDoc2D1.SelectionManager
            selectedObjects =  selectionManager.SelectedObjects
           
            if isinstance(selectedObjects, tuple):
                for item in selectedObjects:
                    drawingObject = module.IDrawingObject(item._oleobj_.QueryInterface(module.IDrawingObject.CLSID, pythoncom.IID_IDispatch))
                    if self.__target  == 0 and drawingObject.DrawingObjectType == 20: #Простая линия-выноска
                        leader = module.ILeader(drawingObject._oleobj_.QueryInterface(module.ILeader.CLSID, pythoncom.IID_IDispatch))
                        if leader != None and leader.TextOnShelf.Str == self.__oldalue:
                            leader.TextOnShelf.Str = self.__newValue
                    elif self.__target  == 1 and drawingObject.DrawingObjectType == 21: #Линия-выноски для обозначения позиции
                            positionLeader = module.IPositionLeader(drawingObject._oleobj_.QueryInterface(module.IPositionLeader.CLSID, pythoncom.IID_IDispatch))
                            if positionLeader != None and positionLeader.Positions.Str == self.__oldValue:
                                positionLeader.Positions.Str = self.__newValue
                    elif self.__target  == 2 and drawingObject.DrawingObjectType == 4: #Текст на чертеже
                            drawingText = module.IDrawingText(drawingObject._oleobj_.QueryInterface(module.IDrawingText.CLSID, pythoncom.IID_IDispatch))
                            if drawingText != None:
                                text = module.IText(drawingText._oleobj_.QueryInterface(module.IText.CLSID, pythoncom.IID_IDispatch))
                                if text.Str == self.__oldValue:
                                    text.Str = self.__newValue
                    drawingObject.Update()
            else:
                drawingObject = module.IDrawingObject(selectedObjects._oleobj_.QueryInterface(module.IDrawingObject.CLSID, pythoncom.IID_IDispatch))
                if self.__target  == 0 and drawingObject.DrawingObjectType == 20: #Простая линия-выноска
                    leader = module.ILeader(drawingObject._oleobj_.QueryInterface(module.ILeader.CLSID, pythoncom.IID_IDispatch))
                    if leader != None and  leader.TextOnShelf.Str == self.__oldValue:
                        leader.TextOnShelf.Str = self.__newValue
                elif self.__target  == 1 and drawingObject.DrawingObjectType == 21: #Линия-выноски для обозначения позиции
                        positionLeader = module.IPositionLeader(drawingObject._oleobj_.QueryInterface(module.IPositionLeader.CLSID, pythoncom.IID_IDispatch))
                        if positionLeader != None and positionLeader.Positions.Str == self.__oldValue:
                            positionLeader.Positions.Str = self.__newValue
                elif self.__target  == 2 and drawingObject.DrawingObjectType == 4: #Текст на чертеже
                        drawingText = module.IDrawingText(drawingObject._oleobj_.QueryInterface(module.IDrawingText.CLSID, pythoncom.IID_IDispatch))
                        if drawingText != None:
                            text = module.IText(drawingText._oleobj_.QueryInterface(module.IText.CLSID, pythoncom.IID_IDispatch))
                            if text.Str == self.__oldValue:
                                text.Str = self.__newValue
                drawingObject.Update()


Sprinter500

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

Maxxx

Вы наверное пошутили? В коде ни одного коментария... Ни смысла кода... Т.е. посмотри и догадайся сам что я хочу сделать.... Называется нагрузить кого то работой по расшифровке)

Sprinter500

Коды не мои. Взял подходящие участки из других примеров. В них не было изначально коментариев. А разбираюсь я в SDK компаса плохо. Была бы хорошая литература, где описывался бы весь SDK (и API5 и API7), наверно бы и вопросов не было. А Справка по SDK не помощник, все по спартански для "джедаев" программирования, но не для чайников.

ЦитироватьpBaseLeader := pLeaders.Leader;
     //Дальше что делать?
Меняем на:
for I:=0 to pLeaders.Count-1 do
   begin
     pDrawingObject:=pLeaders.Item;
     if pDrawingObject<>nil then
      begin
        if pDrawingObject.DrawingObjectType=ksDrLeader then
         begin // Простая линия-выноска
           pLeader:=pDrawingObject as ILeader;
           if pLeader<>nil then
            begin
              if pLeader.TextOnShelf.Str=oldValue then
               begin
                 pLeader.TextOnShelf.Str=newValue;
                 pDrawingObject.Update;
               end;
              pLeader:=nil;
            end;
         end
        else if pDrawingObject.DrawingObjectType=ksDrPosLeader then
         begin // Линия-выноска для обо­значе­ния по­зиции
             ...
         end
        else if pDrawingObject.DrawingObjectType=ksDrBrandLeader then
         begin // Линия-выноска для для обозна­чения клейме­ния
             ...
         end
        else if pDrawingObject.DrawingObjectType=ksDrMarkerLeader then
         begin // Линия-выноска для обо­значе­ния мар­кирования
             ...
         end
        else if pDrawingObject.DrawingObjectType=ksDrChangeLeader then
         begin // Знак из­менения
             ...
         end;
        pDrawingObject:=nil;
      end;
   end;
для ... делаем аналогично в зависимости от типа.
+ Благодарностей: 1

Sprinter500

Спасибо большое!!!!

Но нарисовалась новая проблема. Delphi при компиляции выдает: "запуск программы не возможен, так как на компьютере отсутствует kAPI7.DLL". Но она точно есть и лежит на своем месте. Куда эту библиотеку скопировать или где мне размещать проект, чтобы было видно библиотеку? Может что в подключаемых модулях стоит поменять?


Sprinter500

Да, да. И у меня там же. Просто что то делаю не так и Delphi ругается, не может найти библиотеку. Даже ругается на примеры SDK по API7. С API5 все хорошо.

Как Вы подключаете API7 в Delphi ? Через ksAPI7.pas или через TLB.  Может адрес где лежит библиотека надо где то прописывать? Или что то не так объявляю. Если не трудно можете какой-нибудь простейший пример проекта на API7 (пускай в нем даже ничего не будет) ?

Запустите  KOMPAS.Exe /register
Подключаю через ksAPI7.pas, но все ссылки на kAPI7.DLL находятся в ksAuto.pas.

Sprinter500

Прописал полный путь. Помогло (почему относительные пути у меня не работают?). Но теперь kSys1.DLL не может найти. В каком файле его путь задать? Напасть какая то. 

Вы регистрацию компонентов делали? - KOMPAS.Exe /register
Что у Вас неправильно, я сказать не могу, я не телепат, скорее всего криво Компас стоит.
По поводу dll, они все взаимно завязаны, стоит зацепить одну и они друг друга начнут тянуть.   

Sprinter500

Нет. Не делал. Как она делается? Куда эту команду вбивать? Возможно и в правду Компас криво стоит. Вечерком попробую переустановить. И почему то запрещены изменения в папке где Компас установлен, убираешь галочку "только для чтения", а потом она опять появляется. Может антивирус это делает.

И как вариант то что Delphi позже Компаса ставилось, может из-за этого?