1

Тема: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

1С:7.7 бедна на типы данных. Напрямую из нее не удается передавать/получать координаты и некоторые строковые переменные.
В описании объектной модели, ориентированном на VBA (на примере ф-ции GetPoint (ПолучитьТочку)):

RetVal = GetPoint([Point][, Prompt]) 
...
Point  - Variant (three-element array of doubles); input-only; optional The 3D WCS coordinates specifying the relative base point. 

Prompt - Variant (string); input-only; optional The text used to prompt the user for input. 

RetVal - Variant (three-element array of doubles)  The 3D WCS coordinates of the point the AutoCAD user has selected.

Инициализирую ACAD, как положено:

            ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
            ScrptCtrl.Language="vbscript";
            ScrptCtrl.AddCode("
            |Public objACAD, objThisDrawing,obj_MSpase
            |Function ACAD_Create()
            |    SET objACAD=CreateObject(""AutoCAD.Application"")
            |    SET objThisDrawing = objACAD.ActiveDocument
            |    SET obj_MSpase     = objThisDrawing.ModelSpace
    //        |    MsgBox "" Acad открыт!""
            |End Function
            |");

далее пишу и вызываю такую функцию:

 ....
            |    Point = objThisDrawing.Utility.GetPoint(, ""Укажите точку 1"")
            |    MsgBox ""Point LBound="" & LBound (Point) & ""  Point UBound="" & UBound (Point)
            |    MsgBox ""         Point TypeName="" & TypeName(Point) & vbCr &  ""         Point VarType="" & VarType(Point)
.....

Отрабатывает хорошо, точку получает с экрана Acad`а
В MsgBox говорит:

Lbond=0, Ubound=2
..TypeName=Double()  .. VarType=8197

т.е. POINT - это массив из 3-х Double чисел.
Все попытки потрогать Point через индексы ( Point(0) и т.д.. Например

Point(1)    =    Point(1) + 100.0

) заканчиваются в 1С:   так:
Ошибка выполнения Microsoft VBScript: Несоответствие типа: 'Point'
Чего то я не знаю про типы данных..Подскажите, пожалуйста, Знатоки..

2

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

MsgBox Point(1)  работает?

3

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Нет!! Та же песня:
Ошибка выполнения Microsoft VBScript: Несоответствие типа: 'Point'
Спасибо за отклик..

4

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Более того Cstr(Point(1)) этим же заканчивается.
А передаю эту Point далее в кач-ве параметра в другую Acad`овскую функцию - глотает и использует ее адекватно.
Только я потрогать не могу..

5

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

а такая конструкция?

|For Each z IN Point
| MsgBox z
|Next

6

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

И вот такая

|Set  z = Point(1)
|
|MsgBox TypeName(z)

7

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

После первого варианта:
Ошибка выполнения Microsoft VBScript: Несоответствие типа
После второго..:
Ошибка выполнения Microsoft VBScript: Несоответствие типа: 'Point'

8

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Создай макрос в Ворде, скорми переменную watches , может так что-нить прояснится.

9

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Попробую, а как советуешь, напрямую из VBA рулить AutoCADом или из VBA запустить VBS?
Терзают смутные сомнения, что из VBA все гладко пройдет.
Ну, попробую. Спасибо за участие..

10

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Сейчас проверю еще одно предположение, по результатам отпишусь.

11 (изменено: chessman, 2011-12-21 15:25:04)

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Выскажу свое подозрение, почему VBS не нравится тип параметра. В VBS все параметры представляются в VARIANT, в том числе и элементы массива. В этом легко убедиться, создав массив и вызвав  ф-ю VarType, она вернет значение 8204 (200Сh = VT_ARRAY | VT_VARIANT).
В твоем случае VarType  возвращает 8197 (2005h = VT_ARRAY | VT_R8), т.е. массив с элементами типа Double. VBS "видит", что тип Double, а не VARIANT и собственно возвращает DISP_E_TYPEMISMATCH.

Что я могу предложить, для решения данной задачи,  являясь давним поклонником DynamicWrapperX - конечно именно этот компонент.
Может быть есть какие-то готовые решения, как в VBS обратится к данным подобного массива, я их не знаю, но готов спуститься на уровень структур в памяти и решить данную задачу. По крайней мере, вытянуть данные из стандартного VBS-го массива получилось.
В общем, если есть желание можно продолжить.

12

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

КОнечно, желание есть. Я очень благодарен за отзывчивость.
Какой режим общения предпочитаешь - e-mail или здесь, же "по-серому"?
Для меня "DynamicWrapperX" - облако в штанах. Даже не слыхал.
Если подскажешь/покажешь, буду счастлив..

13

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Думаю, что всем будет интересно, так что продолжим здесь.

Начнем по-тихоньку...
1. Скачай отсюда http://forum.script-coding.com/viewtopic.php?id=5341 и зарегистрируй DynamicWrapperX (DWX).
2. Почитай документацию http://www.script-coding.com/dynwrapx.html.

Немного теории.
DWX умеет напрямую работать с памятью, а это серьезно расширяет наши возможности.
Фактически, на связке VBS+DWX можно реализовать практически все, вплоть до программирования в кодах
Вернемся к твоей задаче - наша цель, получить прямой доступ к т.н. массиву SafeArray. Это можно было бы сделать, если бы мы могли передать в DWX массив "Point", а в ответ получить адрес этого SafeArray в памяти. К сожалению текущая версия DWX не поддерживает переменные типа массив и если мы попытаемся его передать, то получим тот же DISP_E_TYPEMISMATCH.
Но, учитываю возможности работы с памятью напрямую, мы на определенный момент "поправим" сам DWX, после чего он "скушает" наш массив, вернет нам адрес структуры SafeArray и после этого мы вернем все статус-кво.
Далее, имея указатель на SafeArray, мы попытаемся получить значения массива.
Из-за таких нюансов, код на скрипте получится несколько больше.
В след. посте выложу скрипт.

14

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Спасибо огромное заранее..С наступающим Новым Годом!! Нет войне в Иране!!!

15

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

    |Public Const     PAGE_EXECUTE_READWRITE    = &h40
    |Public Const     HEAP_ZERO_MEMORY        = &h08
    |'============================================
    |Public Wrap
    |Set Wrap = CreateObject(""DynamicWrapperX"")
    |
    |Public oServ
    |Public Point
    |'============================================
    |
    |Class    Service
    |    Private hHeap
    |    Private    ppv
    |    Private    pVal
    |    Private    pFlag    
    |    Private    addrParamTypesAvailable
    |
    |    Private Sub Class_Initialize
    |        'Необходимые функции
    |        Wrap.Register ""Kernel32"",    ""LoadLibrary"" , ""i=s"", ""r=h""
    |        Wrap.Register ""Kernel32"",    ""GetProcAddress"" , ""i=hs"", ""r=u""
    |        Wrap.Register ""Kernel32"",    ""VirtualProtect"" , ""i=lllp"", ""r=l""
    |        Wrap.Register ""Kernel32"",    ""HeapAlloc"",    ""i=lll"",    ""r=l""
    |        Wrap.Register ""Kernel32"",    ""GetProcessHeap"", ""r=l""
    |        Wrap.Register ""Kernel32"",    ""HeapFree"", ""i=lll"",""r=l""
    |
    |        Wrap.Register ""Oleaut32"",    ""SafeArrayGetDim"", ""i=p"",""r=l""
    |        Wrap.Register ""Oleaut32"",    ""SafeArrayGetElement"", ""i=plp"",""r=l""
    |        Wrap.Register ""Oleaut32"",    ""SafeArrayGetLBound"", ""i=plp"",""r=l""
    |        Wrap.Register ""Oleaut32"",    ""SafeArrayGetUBound"", ""i=plp"",""r=l""
    |
    |        'Выделяем память под результат
    |        hHeap    = Wrap.GetProcessHeap() 
    |        ppv        = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
    |        pFlag    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
    |        pVal    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 16)
    |
    |        'Для патча DWX налету
    |        '=============================================================
    |        handle = Wrap.LoadLibrary(""dynwrapx"")
    |        Addr   = Wrap.GetProcAddress(handle, ""DllGetClassObject"")
    |        DllSeg = Addr And &hFFFF0000
    |
    |        Offset                         = &h41C8 + 10        'VT_Dispatch
    |        addrParamTypesAvailable     = DllSeg + Offset
    |        '=============================================================
    |        Wrap.VirtualProtect addrParamTypesAvailable, 2, PAGE_EXECUTE_READWRITE, pFlag
    |    End Sub
    |    
    |    Private Sub Class_Terminate
    |        Wrap.VirtualProtect addrParamTypesAvailable, 2, Wrap.NumGet(pFlag), pFlag
    |        Wrap.HeapFree hHeap, 0, ppv
    |        Wrap.HeapFree hHeap, 0, pFlag
    |        Wrap.HeapFree hHeap, 0, pVal
    |    End Sub
    |
    |    Public Function GetSafeArray(Arr)
    |        'Учим DWX принимать массив
    |        vtType = Wrap.NumGet(addrParamTypesAvailable, 0, ""t"")    
    |        Wrap.NumPut VarType(Arr), addrParamTypesAvailable, 0, ""t""    
    |
    |        'Получим указатель на SafeArray
    |        GetSafeArray = Wrap.GetIDispatch(Arr)
    |        
    |        'Возвращаем статус-кво
    |        Wrap.NumPut vtType, addrParamTypesAvailable, 0, ""t""    
    |    End Function
    |
    |    Public Function GetElement(pSafeArray, ind)
    |        Wrap.NumPut ind, ppv
    |        Wrap.SafeArrayGetElement pSafeArray, ppv, pVal
    |
    |        GetElement = Wrap.NumGet(pVal, 8, ""d"")
    |    End Function
    |End Class
    |
    |Set oServ = New Service
    |
    |'===========================================================
    |Public Function GetSafeArray(Arr)
    |    GetSafeArray = oServ.GetSafeArray(Arr)
    |End Function
    |
    |Public Function GetElement(pSafeArray, ind)
    |    GetElement = oServ.GetElement(pSafeArray, ind)
    |End Function
    |
    |Public Function Test()
    |    pArr = GetSafeArray(Point)
    |
    |    item0 = GetElement(pArr, 0)
    |    item1 = GetElement(pArr, 1)
    |
    |    MsgBox ""item0 = "" & CSTR(item0)
    |    MsgBox ""item1 = "" & CSTR(item1)
    |End Function
    |'===========================================================
    |
    |Point     = Array(10.454, 11.56944656, 12, 15, 25)

16 (изменено: chessman, 2011-12-22 12:00:30)

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Готовая обработка для 1С 7.7

http://narod.ru/disk/35168901001/SafeArray.ert.html

В этом примере используется массив из Variant.
В случае массива из Double нужно изменить вот этот код

GetElement = Wrap.NumGet(pVal, 0, ""d"")

В общем, жду результатов тестирования.

17

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

chessman, спасибо огромное. Буду разбираться, сегодня не успею проверить.

18

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Проверяю. Монтирую предложенный код в свою обработку, вызывающую Автокад:
1. слегка дополняю ф-ю "Test":

        |Public Function Test(Point_)
        |
        |    MsgBox ""Point LBound="" & LBound (Point_) & ""  UBound="" & UBound (Point_)  & vbCr & _
        |           ""     TypeName="" & TypeName(Point_) & vbCr & _
        |          ""      VarType="" & VarType(Point_)
        |
        |    pArr = GetSafeArray(Point_)
        |
        |    item0 = GetElement(pArr, 0)
        |    item1 = GetElement(pArr, 1)
        |
        |    MsgBox ""item0 = "" & CSTR(item0)
        |    MsgBox ""item1 = "" & CSTR(item1)
        |End Function

2. Вввожу в Автокаде Точку (Point):

            |    Point = objThisDrawing.Utility.GetPoint(, ""Укажите точку 1"")
            |    MsgBox ""Point LBound="" & LBound (Point) & ""  Point UBound="" & UBound (Point) & vbCr & _
            |        ""     Point TypeName="" & TypeName(Point) & vbCr &  ""    Point VarType="" & VarType(Point)
            |   Test(Point)

3. Оно отрабатывает. Что до вызова Test(Point), что из него MsgBox показывает одно и то же:
    LBound=0, UBound=2, TypeName=Double(), VarType = 8197
4. Затем после GetSafeArray(Point_) показывает
item0 = 0 и item1 = 0

Что-то не так...

19

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

а ты это поменял?

GetElement = Wrap.NumGet(pVal, 0, ""d"")

20

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Это вот здесь?:

      | Public Function GetElement(pSafeArray, ind)
| Wrap.NumPut ind, ppv
| Wrap.SafeArrayGetElement pSafeArray, ppv, pVal
|
| GetElement = Wrap.NumGet(pVal, 8, ""d"")
| End Function
|End Class

21

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

да

22

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Это связано с длиной данных?

23

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Dbeer пишет:

Это связано с длиной данных?

Ты лучше попробуй, потому как я не уверен, что это верно.

24

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

ЙЕССС!! проканало!!! Огромное тебе!!!!:lol::lol:
Теперь вторая засада: принимать то из Акада точки ты меня научил, а теперь мне надо из простых 1С:-овских чисел формировать потребного вида массив и запихивать егов Акад.
Иными словами, полностью обратный ход- из трех 1С:овских чисел создать POINT для передачи в Акад..

25

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Догадываюсь, что тут надо применять NumPut, но наглости не хватит в этих кодах извиваться. Я на низком уровне программирования неуютно чувствую себя - всю жизнь прикладным занимался. Поможешь?

26

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Это уже не проблема. Будем использовать этот же массив Point.
Нам потребуется вот эта функция http://msdn.microsoft.com/en-us/library/ms891261.aspx.
Можно конечно работать совсем напрямую, но это не имеет смысла.
Сейчас попробую в своем примере ее заюзать, если успею выложу дополнения к скрипту.

27

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Можно конечно работать совсем напрямую, но это не имеет смысла.

..Нормальные герои всегда идут в обход..:):D

28

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Итоговый скрипт, сначала получаем "нештатным для vbs" образом значения элементов массива, потом нештатным присваиваем значение.
(Скрипт для массива из VARIANT'ов. Для Double напишу ниже.)

|Public Const     PAGE_EXECUTE_READWRITE    = &h40
|Public Const     HEAP_ZERO_MEMORY        = &h08
|Public Const     VT_R8                   = &h5
|'============================================
|Public Wrap
|Set Wrap = CreateObject(""DynamicWrapperX"")
|
|Public oServ
|Public Point
|'============================================
|
|Class    Service
|    Private hHeap
|    Private    ppv
|    Private    pVal
|    Private    pFlag    
|    Private    addrParamTypesAvailable
|
|    Private Sub Class_Initialize
|        'Необходимые функции
|        Wrap.Register ""Kernel32"",    ""LoadLibrary"" , ""i=s"", ""r=h""
|        Wrap.Register ""Kernel32"",    ""GetProcAddress"" , ""i=hs"", ""r=u""
|        Wrap.Register ""Kernel32"",    ""VirtualProtect"" , ""i=lllp"", ""r=l""
|        Wrap.Register ""Kernel32"",    ""HeapAlloc"",    ""i=lll"",    ""r=l""
|        Wrap.Register ""Kernel32"",    ""GetProcessHeap"", ""r=l""
|        Wrap.Register ""Kernel32"",    ""HeapFree"", ""i=lll"",""r=l""
|
|        Wrap.Register ""Oleaut32"",    ""SafeArrayGetDim"", ""i=p"",""r=l""
|        Wrap.Register ""Oleaut32"",    ""SafeArrayGetElement"", ""i=plp"",""r=l""
|        Wrap.Register ""Oleaut32"",    ""SafeArrayPutElement"", ""i=plp"",""r=l""
|
|        'Выделяем память под результат
|        hHeap    = Wrap.GetProcessHeap() 
|        ppv        = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
|        pFlag    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
|        pVal    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 16)
|
|        'Для патча DWX налету
|        '=============================================================
|        handle = Wrap.LoadLibrary(""dynwrapx"")
|        Addr   = Wrap.GetProcAddress(handle, ""DllGetClassObject"")
|        DllSeg = Addr And &hFFFF0000
|
|        Offset                         = &h41C8 + 10        'VT_Dispatch
|        addrParamTypesAvailable     = DllSeg + Offset
|        '=============================================================
|        Wrap.VirtualProtect addrParamTypesAvailable, 2, PAGE_EXECUTE_READWRITE, pFlag
|    End Sub
|    
|    Private Sub Class_Terminate
|        Wrap.VirtualProtect addrParamTypesAvailable, 2, Wrap.NumGet(pFlag), pFlag
|        Wrap.HeapFree hHeap, 0, ppv
|        Wrap.HeapFree hHeap, 0, pFlag
|        Wrap.HeapFree hHeap, 0, pVal
|    End Sub
|
|    Public Function GetSafeArray(Arr)
|        'Учим DWX принимать массив
|        vtType = Wrap.NumGet(addrParamTypesAvailable, 0, ""t"")    
|        Wrap.NumPut VarType(Arr), addrParamTypesAvailable, 0, ""t""    
|
|        'Получим указатель на SafeArray
|        GetSafeArray = Wrap.GetIDispatch(Arr)
|        
|        'Возвращаем статус-кво
|        Wrap.NumPut vtType, addrParamTypesAvailable, 0, ""t""    
|    End Function
|
|    Public Function GetElement(pSafeArray, ind)
|        Wrap.NumPut ind, ppv
|        Wrap.SafeArrayGetElement pSafeArray, ppv, pVal
|
|        GetElement = Wrap.NumGet(pVal, 8, ""d"")
|    End Function
|
|    Public Function PutElement(pSafeArray, ind, vl)
|        'Тип Variant - VT_R8
|        Wrap.NumPut    VT_R8, pVal, 0, ""t""    
|        'Значение Variant
|        Wrap.NumPut    vl, pVal, 8, ""d""    
|
|        Wrap.NumPut ind, ppv
|        Wrap.SafeArrayPutElement pSafeArray, ppv, pVal
|    End Function
|
|End Class
|
|Set oServ = New Service
|
|'===========================================================
|Public Function GetSafeArray(Arr)
|    GetSafeArray = oServ.GetSafeArray(Arr)
|End Function
|
|Public Function GetElement(pSafeArray, ind)
|    GetElement = oServ.GetElement(pSafeArray, ind)
|End Function
|
|Public Function PutElement(pSafeArray, ind, vl)
|    oServ.PutElement pSafeArray, ind, vl
|End Function
|
|Public Function Test()
|    pArr = GetSafeArray(Point)
|
|    item0 = GetElement(pArr, 0)
|    item1 = GetElement(pArr, 1)
|
|    MsgBox ""item0 = "" & CSTR(item0)
|    MsgBox ""item1 = "" & CSTR(item1)
|
|    PutElement pArr, 0, 3.14
|    MsgBox ""item0 = "" & CSTR(Point(0))
|End Function
|'===========================================================
|
|Point     = Array(10.454, 11.56944656, 12, 15, 25)
|";

29 (изменено: chessman, 2011-12-23 17:28:14)

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Теперь исправления для Double, к тем, что уже были

|    Public Function PutElement(pSafeArray, ind, vl)
|        Wrap.NumPut    vl, pVal, 0, ""d""    
|
|        Wrap.NumPut ind, ppv
|        Wrap.SafeArrayPutElement pSafeArray, ppv, pVal
|    End Function

ну и соответственно убрать MsgBox из Test

MsgBox ""item0 = "" & CSTR(Point(0))

т.к. ругнется на Тип значения

В общем жду результатов.

30

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

СПасибо огромное за участие. Опробую завтра с утра - работаем за Новый Год. Доложу.
Сообщи мне на мыло какой-нить почтовый адрес - вышлю посылочку..Жажду отомстить
Ну не могу же я тебе по интернету пива послать или еще чего..:P

31

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

на самом деле самому было интересно, так что просто enjoy! 

32

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Пока не пробовал, изучал "всухую".
Почти понятно. Только вот что смущает:

|Public Function Test()
|    pArr = GetSafeArray(Point) ' здесь я конвертирую в съедобную форму то, что мне вернулось из автокада
|
|    PutElement pArr, 0, 3.14     ' а здесь наверное д.б. :
                                               PutElement Point, 0, 3.14 ????
|    MsgBox ""item0 = "" & CSTR(Point(0))
|End Function

получается, что сначала я должен получить из Автокада Point, тем самым получив ссылку на созданный Автокадом массив,
и потом его использовать, как контейнер для УЖЕ моих данных (запихивать туда свои цифры и снова передавать АвтоКаду).
А как самому с нуля создать такой контейнер?

33

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Погорячился я, видимо, если pArr - это указатель, а не значение, то тогда так и д.б.
Т.е. "PutElement pArr, 0, 3.14" запихивает правильно число Pi в адрес, вычисляемый от pArr по индексу.
А в POINT уже лежит готовый измененный массив.
Но проблема с созданием контейнера с нуля остается..

34

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

OFF:

Dbeer пишет:

Ну не могу же я тебе по интернету пива послать или еще чего..tongue

Есть службы доставки, если что .

35

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Sorry, за OFF, конечно. Но ведь, я, как раз, об этом - адрес нужен реальный. Разберемся..С новым Годом!! Alexii (I или II-ой?)

36

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Dbeer пишет:

…(I или II-ой?)

Последнее.

37 (изменено: chessman, 2011-12-24 18:23:57)

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Dbeer пишет:

Но проблема с созданием контейнера с нуля остается..

Нам потребуется функция SafeArrayCreate
http://msdn.microsoft.com/en-us/library … s.85).aspx

она возвращает указатель на SafeArray .
Все остальное мы делать уже умеем(получить/поместить элемент).

Остается только  научить DWX возвращать массив.

38 (изменено: chessman, 2011-12-25 14:15:49)

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

Добавлен код создания массива "нештатными" для vbs средствами

|Public Const     PAGE_EXECUTE_READWRITE    = &h40
|Public Const     HEAP_ZERO_MEMORY        = &h08
|Public Const     VT_R8                   = 5
|Public Const     VT_VARIANT              = 12    
|Public Const     VT_ARRAY                  = &h2000 
|'============================================
|Public Wrap
|Set Wrap = CreateObject(""DynamicWrapperX"")
|
|Public oServ
|Public Point
|'============================================
|
|Class    Service
|    Private hHeap
|    Private    ppv
|    Private    pVal
|    Private    pFlag    
|    Private    addrParamTypesAvailable
|    Private    rgsabound
|    Private        DllSeg    
|
|    Private Sub Class_Initialize
|        'Необходимые функции
|        Wrap.Register ""Kernel32"",    ""LoadLibrary"" , ""i=s"", ""r=h""
|        Wrap.Register ""Kernel32"",    ""GetProcAddress"" , ""i=hs"", ""r=u""
|        Wrap.Register ""Kernel32"",    ""VirtualProtect"" , ""i=lllp"", ""r=l""
|        Wrap.Register ""Kernel32"",    ""HeapAlloc"",    ""i=lll"",    ""r=l""
|        Wrap.Register ""Kernel32"",    ""GetProcessHeap"", ""r=l""
|        Wrap.Register ""Kernel32"",    ""HeapFree"", ""i=lll"",""r=l""
|        
|        Wrap.Register ""Oleaut32"",    ""SafeArrayCreate"", ""i=llp"",""r=l""    
|        Wrap.Register ""Oleaut32"",    ""SafeArrayGetDim"", ""i=p"",""r=l""
|        Wrap.Register ""Oleaut32"",    ""SafeArrayGetElement"", ""i=plp"",""r=l""
|        Wrap.Register ""Oleaut32"",    ""SafeArrayPutElement"", ""i=plp"",""r=l""
|        
|        'Выделяем память под результат
|        hHeap    = Wrap.GetProcessHeap() 
|        ppv        = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
|        pFlag    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
|        pVal    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 16)
|        rgsabound = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 8)
|        
|        
|        'Для патча DWX налету
|        '=============================================================
|        handle = Wrap.LoadLibrary(""dynwrapx"")
|        Addr   = Wrap.GetProcAddress(handle, ""DllGetClassObject"")
|        DllSeg = Addr And &hFFFF0000
|        
|        Offset                         = &h41C8 + 10        'VT_Dispatch
|        addrParamTypesAvailable     = DllSeg + Offset
|        '=============================================================
|        Wrap.VirtualProtect addrParamTypesAvailable, 2, PAGE_EXECUTE_READWRITE, pFlag
|    End Sub
|    
|    Private Sub Class_Terminate
|        Wrap.VirtualProtect addrParamTypesAvailable, 2, Wrap.NumGet(pFlag), pFlag
|        Wrap.HeapFree hHeap, 0, ppv
|        Wrap.HeapFree hHeap, 0, pFlag
|        Wrap.HeapFree hHeap, 0, pVal
|        Wrap.HeapFree hHeap, 0, rgsabound
|    End Sub
|    
|    Public Function GetSafeArray(Arr)
|        'Учим DWX принимать массив
|        vtType = Wrap.NumGet(addrParamTypesAvailable, 0, ""t"")    
|        Wrap.NumPut VarType(Arr), addrParamTypesAvailable, 0, ""t""    
|        
|        'Получим указатель на SafeArray
|        GetSafeArray = Wrap.GetIDispatch(Arr)
|        
|        'Возвращаем статус-кво
|        Wrap.NumPut vtType, addrParamTypesAvailable, 0, ""t""    
|    End Function
|    
|    Public Function GetElement(pSafeArray, ind)
|        Wrap.NumPut ind, ppv
|        Wrap.SafeArrayGetElement pSafeArray, ppv, pVal
|        
|        GetElement = Wrap.NumGet(pVal, 8, ""d"")
|    End Function
|    
|    Public Function PutElement(pSafeArray, ind, vl)
|        'Тип Variant - VT_R8
|        Wrap.NumPut    VT_R8, pVal, 0, ""t""    
|        'Значение Variant
|        Wrap.NumPut    vl, pVal, 8, ""d""    
|        
|        Wrap.NumPut ind, ppv
|        Wrap.SafeArrayPutElement pSafeArray, ppv, pVal
|    End Function
|    
|    Public Function ArrayCreate(vt, cElements)
|        'Структура SAFEARRAYBOUND
|        Wrap.NumPut cElements, rgsabound, 0
|        Wrap.NumPut 0         , rgsabound, 4
|        
|        pSA = Wrap.SafeArrayCreate(vt, 1, rgsabound)
|        
|        'Научим DWX возвращать массивы
|        '=============================================================
|        addr = DllSeg + &h278D
|        Wrap.VirtualProtect addr, 8, PAGE_EXECUTE_READWRITE, pFlag
|        
|        'Запоминаем участок памяти
|        mem1 = Wrap.NumGet(addr, 0)
|        mem2 = Wrap.NumGet(addr, 4)
|        
|        'Меняем участок памяти
|        Wrap.NumPut    &h90909090, addr, 0 
|        Wrap.NumPut    &h90909090, addr, 4
|        
|        Wrap.NumPut    VT_ARRAY + vt, addr, 0, ""t""
|        
|        ArrayCreate = Wrap.GetObject(pSA)
|
|        'Возвращаем статус-кво
|        Wrap.NumPut    mem1, addr, 0 
|        Wrap.NumPut    mem2, addr, 4
|        '=============================================================
|    End Function
|End Class
|
|Set oServ = New Service
|
|'===========================================================
|Public Function GetSafeArray(Arr)
|    GetSafeArray = oServ.GetSafeArray(Arr)
|End Function
|
|Public Function GetElement(pSafeArray, ind)
|    GetElement = oServ.GetElement(pSafeArray, ind)
|End Function
|
|Public Function PutElement(pSafeArray, ind, vl)
|    oServ.PutElement pSafeArray, ind, vl
|End Function
|
|Public Function ArrayCreate(vt, cElements)
|    ArrayCreate = oServ.ArrayCreate(vt, cElements)
|End Function
|
|Public Function Test()
|    pArr = GetSafeArray(Point)
|    
|    item0 = GetElement(pArr, 0)
|    item1 = GetElement(pArr, 1)
|    
|    MsgBox ""item0 = "" & CSTR(item0)
|    MsgBox ""item1 = "" & CSTR(item1)
|    
|    PutElement pArr, 0, 3.14
|    MsgBox ""item0 = "" & CSTR(Point(0))
|    
|    newArray    =    ArrayCreate(VT_VARIANT, 3)    
|    MsgBox TypeName(newArray)
|
|    newArray(0)    = 15.56
|    MsgBox newArray(0)
|End Function
|'===========================================================
|
|Point     = Array(10.454, 11.56944656, 12, 15, 25)
|";

39 (изменено: chessman, 2011-12-25 16:08:04)

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

|    newArray    =    ArrayCreate(VT_VARIANT, 3)
|    MsgBox TypeName(newArray)
|
|    newArray(0)    = 15.56
|    MsgBox newArray(0)

Чтобы создать массив типа Double, нужно VT_VARIANT заменить на VT_R8. "3" - размерность массива.
Соответственно, после этого ни присвоить, ни получить значения массива штатным способом не получится.
Но мы уже знаем, как это сделать "нештатным" образом.

ЗЫ: (для массива типа Double) нам с одной стороны нужен  указатель на массив, чтобы манипулировать значениями элементов,  а с другой  переменная типа "Array" в vbs'e, чтобы ее передать дальше в AutoCAD. Сейчас ф-я ArrayCreate возвращает переменную типа Array. Чтобы не делать лишних телодвижений, по получению указателя на массив, можно сам указатель хранить в какой-то глобальной переменной(нужно поправить ф-ю ArrayCreate в классе Service).

40

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

OFF.
Прочитал название темы, видать туго соображаю, но не понял почему автокад и 1с через VBS?? В первом посте нет поставленной задачи.. поэтому я не понял принципиального принятого решения, жаль, а мое любопытство вначале пересилило меня. Не подскажите почему данные из 1 с надо в графическом редакторе Автокад обрабатывать? (1с очень хорошо дружит с екселем, например, где можно строить графики и не только..)

Любители построили Ковчег, а профессионалы - Титаник.

41

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

1С:7.7 - понятно - легко и элегантно содавать, манипулировать, сопровождать БД (ту, которая требуется в данной прикладной задаче).
AutoCAD - в нем автоматом по исходным из 1С: создаются фрагменты, да и целые листы инженерной графики. Вся организация работает в Акаде, да и предыдущий опыт программирования в Ём же есть.
Ессно, у Автокада есть масса интерфейсов для обена данными, свои скрипты, VLISP, DIESEL, DXF и пр. но они с разной степенью успешности (далеко не идеальной) обеспечивают реальный интерактив. Хочется более коротким путем сразу из прикладной среды рулить АКАДом. Предлагаемые Chessman`ом меры решают многие проблемы, но иные остаются. Объектная модель АКАДа (правда, об этом говорится в разных источниках) выглядит и ведет себя по-разному в разных клиентских средах.
Например  в связке 1С:-АКАД мало того, что есть проблемы с обменом данными, так и методы и свойства некоторые не отзываются. некоторые, вообще отсутствуют.
С событиями, вообще швах..Т.ч. побьюсь еще и не исключаю, откачусь к традиционным средствам без интерактива.

42

Re: VBS: хочу рулить AutoCAD'ом из 1С:7.7 через VBS. ??? с типами данных

сафемассив получается просче и симпатишнее

Я конечно далек от мысли... (с)