Re: Обход спецификаций в заказе

Здравствуйте. Стоит такая задача - программно обойти все дерево спецификаций на VBA. С задачей, вроде бы, справился, пользуясь App.NmkSpecification и ключами "NMK_ID"; тривиальный обход...
Но, почему-то, странная ошибка - никак не "вываливается" в отчет больше 70 (+-приблизительно) записей. Это около 10 спецификаций
Непонятно - до обхода данные из середины читаются, после - нет
Заранее благодарен

Re: Обход спецификаций в заказе

Ну там есть частично наша ошибка. Суть заключается в следующем - объекты от Application они идут глобальные, и создаются только один раз. Если запросить активную версию (это передавать идентификатор номенклатуры и -1 в качестве идентификатора версии ), и попадется объект у которого версий вообще нет, то после этого будут возвращаться объект все время этот объект. Видимо вы как раз разузловывали активные версии (кстати не забудьте проверить зацикливание, так как в данном случае при зацикливании ошибки будут еще интереснее).

Но в любом случае новой версии использование активной версии не есть правильно, так как есть механизм фиксации версии, и будет более правильно использовать его. Даю пример ниже, он должен работать. Ну а ошибка как будет исправлена, обязательно сообщим. Если нужны именно активные, то придется пока работать через объект версии спецификации NMkSpecificationVersions, а у него уже брать по идентификатору версии конкретную версию (спозиционироваться на активную и взять ее идентификатор).

Пример работы через зафиксированные версии дан ниже.


Option Explicit

Dim TCS As CSDN.TCS
Dim App As CSDN.Tcs_Application

Public Sub Login()

'Создадим объект ТКС АПИ

If TCS Is Nothing Then Set TCS = CreateObject("CSDN.TCS")

'Создадим экземляр приложения (сеанс). Внимание ! создание повторного сеанса не допустимо!


If App Is Nothing Then Set App = TCS.Login 'вызывает стандартное окно аутентификации пользователя

'Set App = TCS.LoginEx("Администратор", "0")  ' Если вы сами пишите диалог ввода пользователя и пароля или просто его знаете

'Set App = TCS.LoginCurrent ' если вы хотите использовать сеанс уже запущенного ТКС

End Sub


Public Function LoadNmkSpec(CellPos As Long, StartPos As Long, NMkId As Long, VerId As Long)
Dim NmkSpec As CSDN.NmkSpecification
Dim UsedVer As CSDN.UsedNMkVersions


On Error GoTo L1
 Set NmkSpec = App.NmkSpecification(NMkId, VerId)
 If Not NmkSpec Is Nothing Then
  
  NmkSpec.First
  While Not NmkSpec.EOF
    CellPos = CellPos + 1
    ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 1) = NmkSpec.Properties("NMK_NOTE").DisplayText
    ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 2) = NmkSpec.Properties("NMK_NAME").DisplayText
    ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 3) = NmkSpec.Properties("QUANTITY").DisplayText
    Set UsedVer = NmkSpec.Properties("UsedVersions").AsIDispatch
    UsedVer.First
    While Not UsedVer.EOF
      If UsedVer.UsedVersionIsSpecification And UsedVer.Properties("USED_VERSION").DisplayText <> "" Then
         CellPos = LoadNmkSpec(CellPos, StartPos + 1, NmkSpec.Properties("NMK_ID").AsInteger, UsedVer.Properties("USED_VERSION").AsInteger)
      End If
      UsedVer.Next
    Wend
    Set UsedVer = Nothing
    
    NmkSpec.Next
  Wend
  
 End If
 
 GoTo L2
L1:
 CellPos = CellPos + 1
 ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 1) = "Ошибка при чтении спецификации!"
L2:
  Set UsedVer = Nothing
  Set NmkSpec = Nothing

  LoadNmkSpec = CellPos
End Function

Public Sub LoadSpec()

  Call Login
  
  Dim NMks As CSDN.Nomenclatures
  Dim CellPos As Long
    
  If App.NmkClasses.RunModuleForSelect("Выберите класс", False) Then
    Set NMks = App.Nomenclatures(App.NmkClasses.Properties("ID").AsInteger)
    
    If NMks.RunModuleForSelect("Выбериет номенклатуру для разузлования", False) Then
      ActiveWorkbook.Sheets(1).Select
      ActiveWorkbook.Sheets(1).Cells.Select
      Selection.ClearContents
      CellPos = 2
      CellPos = LoadNmkSpec(CellPos, 1, NMks.Properties("ID").AsInteger, -1)
      CellPos = CellPos + 1
      ActiveWorkbook.Sheets(1).Cells(CellPos, 1) = "Успешно завершено!"
    End If
    
    Set NMks = Nothing
    
  End If
End Sub

Re: Обход спецификаций в заказе

Гордон, вы правы, мне необходимо разузловывать именно активные версии. Теперь сваял следующее сомнительное произведение:
'-------------------------------------------------
Sub show_spec(specID As Long)
     
     iPos = iPos + 1
     On Error Resume Next
     Dim spec, version As Object
     Set version = App.NmkSpecificationVersions(specID)
     Call version.first
     cs1 = version.Properties("ID").displaytext
     If (cs1 = "")  Then GoTo 100
     
     Set spec = App.NmkSpecification(specID, cs1)

     On Error GoTo 90
     If (spec Is Nothing) Then GoTo 100
     Call spec.first
     While Not spec.EOF
            Dim number, designation, name, sID As String
            '  читаем (для теста удобно)
            sID = spec.Properties("NMK_ID").displaytext
            number = spec.Properties("POSITION").displaytext
            designation = spec.Properties("NMK_NOTE").displaytext
            name = spec.Properties("NMK_NAME").displaytext
            '  ну, тут добавляем в коллекшн, просто обходим все дерево итерационно
            Call childs.Add(sID, sID)
            Call spec.Next
           ' отображаем
            mySheet.Cells(iPos, 3) = sID
            mySheet.Cells(iPos, 4) = number
            mySheet.Cells(iPos, 5) = designation
            mySheet.Cells(iPos, 6) = name
            iPos = iPos + 1
     Wend
90
     Set spec = Nothing
100
End Sub
'-----------
вызывается эта красота примерно так:

            While childs.Count
                Dim sID As String
                sID = childs.Item(1)
                Call childs.Remove(1)
                Call show_spec(CLng(sID))
              Wend

Сомнительность произведения в том, что всю информацию оно все равно не выдает! Правда, записей триста вываливается, но не более. Может, из-за того, что NmkSpecificationVersions тоже объект TCS_App?
Вы не подскажете какое-нибудь решение?

Re: Обход спецификаций в заказе

Ну тут код не весь, так что точно не скажу (цикла не вижу напрямую). Но если модифицировать тот что я дал, получится вот так (разузлование по активным) - зацикливание не проверятся, так что его предварительно хотя бы в ТКС проверить, иначе пример никогда не отработает.


Public Function LoadNmkSpec1(CellPos As Long, StartPos As Long, NMkId As Long, VerId As Long)
Dim NmkSpec As CSDN.NmkSpecification
Dim NmkVer As CSDN.NMkVersions

On Error GoTo L1
 Set NmkSpec = App.NmkSpecification(NMkId, VerId)
 If Not NmkSpec Is Nothing Then
  
  NmkSpec.First
  While Not NmkSpec.EOF
    CellPos = CellPos + 1
    ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 1) = NmkSpec.Properties("NMK_NOTE").DisplayText
    ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 2) = NmkSpec.Properties("NMK_NAME").DisplayText
    ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 3) = NmkSpec.Properties("QUANTITY").DisplayText
    Set NmkVer = App.NMkSpecificationVersions(NmkSpec.Properties("NMK_ID").AsInteger)
    If Not NmkVer Is Nothing Then
      NmkVer.First
      While Not NmkVer.EOF
        'Ищем активную
        If NmkVer.Properties("VER_STATE").DisplayText = "Активная(Утверждена)" Or NmkVer.Properties("VER_STATE").DisplayText = "Активная(Редактирование)" Then
        'Можно также было использовать If NmkVer.Properties("VER_STATE").Asinteger=0 or 1, хотя еще правильней оформить отдельное свойство для этого (удобней работать).  Наш недочет, исправим.
         CellPos = LoadNmkSpec1(CellPos, StartPos + 1, NmkSpec.Properties("NMK_ID").AsInteger, NmkVer.Properties("ID").AsInteger)
        End If
        NmkVer.Next
      Wend
    End If
    Set NmkVer = Nothing
    
    NmkSpec.Next
  Wend
  
 End If
 
 GoTo L2
L1:
 CellPos = CellPos + 1
 ActiveWorkbook.Sheets(1).Cells(CellPos, StartPos + 1) = "Ошибка при чтении спецификации!"
L2:
  Set NmkVer = Nothing
  Set NmkSpec = Nothing

  LoadNmkSpec1 = CellPos
End Function

Public Sub LoadSpec()

  Call Login
  
  Dim NMks As CSDN.Nomenclatures
  Dim CellPos As Long
    
  If App.NmkClasses.RunModuleForSelect("Выберите класс", False) Then
    Set NMks = App.Nomenclatures(App.NmkClasses.Properties("ID").AsInteger)
    
    If NMks.RunModuleForSelect("Выбериет номенклатуру для разузлования", False) Then
      ActiveWorkbook.Sheets(1).Select
      ActiveWorkbook.Sheets(1).Cells.Select
      Selection.ClearContents
      CellPos = 2
      CellPos = LoadNmkSpec1(CellPos, 1, NMks.Properties("ID").AsInteger, -1)
      CellPos = CellPos + 1
      ActiveWorkbook.Sheets(1).Cells(CellPos, 1) = "Успешно завершено!"
    End If
    
    Set NMks = Nothing
    
  End If
End Sub

Re: Обход спецификаций в заказе

Однако, этот скрипт на нашей базе тоже выдает от силы записей 20, потом идут сообщения "Ошибка в спецификации... "
При пошаговом просмотре - генерируется ошибка при считывании версии. Из-за чего это может быть?

Re: Обход спецификаций в заказе

А вы обработчик снимите или допишите чтобы он текст ошибки выдал. Там будет все сказано надеюсь.А наиболее вероятно - прав может нету каких нибудь? Дай тебе себе права просмотра всех версий спецификаций.

В первую очередь текст ошибки скажите. Там видно будет.

Re: Обход спецификаций в заказе

Текст следующий:

  Run-time error '-2147418113 (8000ffff)':
  Too many open files. You may need to increase MAXFILEHANDLE limit in IDAPI configuration.
  File: D\Temp\Del48.MB
  Table: D:\Temp\Del48.MB
  File: D\Temp\Del48.DB

вылетает в строке
  Set NmkVer = App.NMkSpecificationVersions(NmkSpec.Properties("NMK_ID").AsInteger)

Re: Обход спецификаций в заказе

В BDE администраторе на закладке Configuration - System - Init установите MAXFILEHANDLE = (у меня стоит 200). При этом надо все БДЕ приложения закрыть или перегрузить комп!

Re: Обход спецификаций в заказе

Кино ) Если в БДЕ Администраторе поставить MAXFILEHANDLES 128 к примеру, вывыливается в 3 раза больше данных и мессадж:

  Run-time error '-2147418113 (8000ffff)':
  Too many open files. You may need to increase MAXFILEHANDLE limit in IDAPI configuration.
  File: D\Temp\Del128.MB
  Table: D:\Temp\De128.MB
  File: D\Temp\Del128.DB

Re: Обход спецификаций в заказе

А если поставить 200, вылетает с криком:

> Run-time error '-2147418133 (8000ffff)':
> Insufficient memory for this operation

при вызове 
Set NmkSpec = App.NmkSpecification(NMkId, VerId)

параметры вполне валидные
nmkid=69697
verid=996

Re: Обход спецификаций в заказе

вы перегружались?

Re: Обход спецификаций в заказе

Перезагружался
машина: Celeron 2.2 мгц 512 мб

Re: Обход спецификаций в заказе

а каков размер спецификаций ваших?

Re: Обход спецификаций в заказе

хотя по количеству записей что выгрузились - их не много вроде. Закройте все БДЕ приложения кроме АПИ. Может и БДЕ переставить лучше. У меня 3.5 тысячи выдала без проблем.

Re: Обход спецификаций в заказе

Да и еще вопрос. Вы ее в ТКС разузловали перед этим? МОжет у вас зацикливание имеет место быть? тогд аона просто в бесконечно цикле сидит пока ресурсы не кончатся (сказать точно что произойдет не могу)