|   |   | 
| 
 | Код VB выполняется в 1С с ошибками, куда копать? | ☑ | ||
|---|---|---|---|---|
| 0
    
        ОператорПК 29.12.14✎ 10:39 | 
        Здравствуйте.
 Заказчик поставил следующую задачу: Организовать в электронном документе 1С (акт об оказании услуг) возможность расписываться исполнителю и ответственному со стороны клиента, само собой подписи должны сохраняться в документе в виде картинок и должна быть возможность вывода подписей на печать. Иными словами приехал сотрудник на объект, выполнил работы – вместо бумаги для подписи акта, расписывается сам в электронной форме документа потом протягивает планшет/телефон и там расписывается представитель заказчика. Саму задачу обсуждать не хотелось бы – особенно ее юридическую сторону и легитимность таких подписей, единственное что скажу – все действия происходят не в России, ни про какие ЭЦП там слыхом не слыхивали и знать не знают что это и зачем. Короче по техническому решению пытаюсь сделать это на обычных формах 1С 8.х. (работать на планшете/телефоне будут через rdp). Для этого на поле документа поместил объект ActiveX с типом значения «Microsoft lnk Picture Control» пытаюсь сохранить данные этого поля в файл (потом загружу его в 1С в реквизит с типом «Хранилище значения» и полученный файл удалю) не выходит каменный цветок…. 1 Украл код С# по моей задаче от сюда http://www.dotnetthoughts.net/using-microsoft-ink-picture-control/ 2 Через вот этот замечательный конвертер http://foxtools.ru/converter перевел код в VB. Адаптировал мега код под себя окончательно пишу в 1С: ScrptCtrl=Новый COMObject("MSScriptControl.ScriptControl"); ScrptCtrl.Language="vbscript"; ScrptCtrl.AddCode("Function GetLord(Pig) |Dim targetFilename As String = ""C:\new1.jpg"" |Dim bytes As var = Pig.Ink.Save(PersistenceFormat.Gif, CompressionMode.Maximum) |Using ms As New MemoryStream(bytes) |Using bmp As New Bitmap(ms) |bmp.Save(targetFilename) |End Using |End Using |End Function"); ScrptCtrl.Run("GetLord",Controls.Element1); Здесь Controls.Element1 – это как раз тот самый элемент формы ActiveX. Код при выполнении выдает ошибку: {Документ.Документ2.Форма.ФормаДокумента1.Форма(140)}: Ошибка при вызове метода контекста (AddCode) ScrptCtrl.AddCode("Function GetLord(Pig) по причине: Произошла исключительная ситуация (Ошибка компиляции Microsoft VBScript): Предполагается наличие окончания инструкции 3 В vb не силен переписал немного «по колхозному» : ScrptCtrl.AddCode("Function GetLord(Pig) |bytes = Pig.Ink.Save() |ms = MemoryStream(bytes) |End Function"); Получаю ошибку: {Документ.Документ2.Форма.ФормаДокумента1.Форма(144)}: Ошибка при вызове метода контекста (Run) ScrptCtrl.Run("GetLord",Controls.Element1); по причине: Произошла исключительная ситуация (Ошибка выполнения Microsoft VBScript): Несоответствие типа: 'MemoryStream' Т.е. VB Не узнает что такое MemoryStream…. Хотя на компе установлен framework 4.5 и в msdn про существование метода MemoryStream черным по белому написано: http://msdn.microsoft.com/ru-ru/library/system.io.memorystream(v=vs.110).aspx . какие будут версии? Чего не хватает для выполнения кода vb? p.s. сори за много букв – сокращал как мог. | |||
| 1
    
        IUnknown 29.12.14✎ 10:41 | 
        у тебя bytes - должно быть целым     | |||
| 2
    
        ОператорПК 29.12.14✎ 10:47 | 
        (1) почему целым? bytes - вполне (судя по msdn) http://msdn.microsoft.com/ru-ru/library/e55f3s5k(v=vs.110).aspx может принимать тип "Массив байтов без знака, из которого создается текущий поток. 
 " | |||
| 3
    
        tridog 29.12.14✎ 10:56 | 
        (0) Твой MemoryStream - это класс из .Net, напрямую его могут использовать программы, исполняемые поверх инфраструктуры  CLR (программы, скомпилирвоанные в  MSIL).
 Вполне естветственно, что бедный vbscript ничего об этом классе не знает - когда его делали не то что класса MemoryStream, но и всего этого вашего дотнета еще даже в проекте не было. И да, кажется, что записать массив байт в файл вполне можно и без дотнета. | |||
| 4
    
        ОператорПК 29.12.14✎ 10:58 | 
        (3) ок а есть предложение как решить такую задачу?     | |||
| 5
    
        IUnknown 29.12.14✎ 11:04 | 
        а почему тупо не хранить подписи в хранилищезначений?     | |||
| 6
    
        ОператорПК 29.12.14✎ 11:07 | 
        (5) дак именно так и планируется делать, только сперва они должны быть где-то внестись.     | |||
| 7
    
        IUnknown 29.12.14✎ 11:12 | 
        сканеры сейчас сами умеют сканировать в картинку ... ты эту картинку и грузишь в 1С     | |||
| 8
    
        ОператорПК 29.12.14✎ 11:15 | 
        (7) т.е. ты предлагаешь расписываться на листе бумаги потом сканировать это и помечать в документ? тут как раз задача полностью отказать от бумажных носителей.     | |||
| 9
    
        tridog 29.12.14✎ 11:43 | 
        (4) Предложения как сохранить массив байт на диск в vbs? Ставить себе всю эту галиматью конечно не буду, но память подсказывает, что будет как-то так:
 Dim theSavedInk() As Byte theSavedInk = ...Ink.Save() // Здесь вызываете Save() от своего контрола-вундервафли // Теперь запишем на диск Open "c:\myfile.jpg" For Output As #1 Write #1, theSavedInk Close #1 P.S. Когда приходить вместо тебя зарплату получать? | |||
| 10
    
        Jaap Vduul 29.12.14✎ 11:46 | 
        А без скриптовой обёртки не работает?
 bytes = Pig.Ink.Save(2, 1); А потом в файл через ADODB.Stream... | |||
| 11
    
        tridog 29.12.14✎ 11:53 | 
        (10) Как-ни крути - runtime от ADO сильно тяжелее обвеса от vbs. Т.е. через ADO просто потратим больше ресурсов.
 Но на задачах автора пофиг - взглядом разницу заметить будет нельзя. | |||
| 12
    
        ОператорПК 29.12.14✎ 12:03 | 
        (9) я тут зп уже пообещал одному челу который предложил ИМХО гениальное решение - открывать из 1С паинт модально (он утверждает что это возможно, а я этого не знал!!!!!) 
 Парам=1; WshShell = Новый COMОбъект("WScript.Shell"); WshShell.Run("C:\Windows\notepad.exe", 1, Парам); здесь парам - как раз и отвечает за модальность. так что вставай в очередь за ним. | |||
| 13
    
        Jaap Vduul 29.12.14✎ 12:12 | 
        (11)Что за ерунда?
 В vbs вам всё равно тот же самый Stream придётся использовать, т.к. в инструкции Open/Write/Close не поддерживаются. Так что ресурсов потратите ещё больше. | |||
| 14
    
        tridog 29.12.14✎ 12:39 | 
        (12) Не вижу тут модальности - http://msdn.microsoft.com/en-us/library/d5fk67ky(v=vs.84).aspx. Так что давай ка меня первым в очередь?)
 (13) Кто не поддерживаются в инструкции Open/Write/Close? | |||
| 15
    
        ОператорПК 29.12.14✎ 12:45 | 
        (14) ну может модальность не работает через "WScript.Shell" но через обычное одноэсовское ЗапуститьПриложение() точно работает - проверено, так что ветвь первенства не твоя, хотя конечно большое спасибо за помощь и проявленный интерес к вопросу.     | |||
| 16
    
        tridog 29.12.14✎ 13:23 | 
        (15) Оно правда откроется модально? Т.е. что выполнение кода на 1Сике прерывается до момента закрытия paint'а - это конечно да, в ЗапуститьПриложение() параметр специальный есть для этого. А вот например свернуть paint можно? А то юзеры свернут, а потом с разворачиванием тупить будут)
 P.S. А вообще сделал бы по человечески, без всяких paint'ов) | |||
| 17
    
        Garykom гуру 29.12.14✎ 13:34 | 
        (16) угу по человечески это прога для планшета/телефона в которой можно расписаться и она картинку в 1С отправит ))     | |||
| 18
    
        sapphire 29.12.14✎ 13:45 | 
        (0) Организовать в электронном документе 1С (акт об оказании услуг) возможность расписываться исполнителю и ответственному со стороны клиента, само собой подписи должны сохраняться в документе в виде картинок и должна быть возможность вывода подписей на печать. 
 Откуда они картинку подписи брать будут? | |||
| 19
    
        ОператорПК 29.12.14✎ 14:11 | 
        (16) Да свернуть паинт можно, но все равно работать с 1С не получится, по этому будут тупить пока не развернуть обратно,
 я тут большой проблемы не вижу. решение с модальным с паинтом - просто как три копейки и как следствие элегантно. кода пишется 10 строк. //Считаем что сразу несколько пользователей //могут делать такую операцию, по этому //чтобы не блокировать один файл делаем каждый //раз новый, а потом его удаляем. ИмяФайла=Новый УникальныйИдентификатор(); НовыйПуть="C:\"+ИмяФайла+".png"; //считаем что на диске уже есть пустой файл который нам нужно скопировать КопироватьФайл("C:\new.png",НовыйПуть); ЗапуститьПриложение(НовыйПуть,,Истина); //Загрузим файл в 1С ВыбранноеИзображение = Новый Картинка(НовыйПуть, Ложь); РеквизитКартинка=Новый ХранилищеЗначения(ВыбранноеИзображение); ЭлементыФормы.ПолеКартинки1.Картинка = РеквизитКартинка.Получить(); //удалим не нужный файл УдалитьФайлы(НовыйПуть); (18) в 1С картинка будет храниться в реквизите с типом "Хранилище значений". | |||
| 20
    
        sapphire 29.12.14✎ 14:24 | 
        (19) С 1С я уже понял.     | |||
| 21
    
        ОператорПК 29.12.14✎ 14:25 | 
        (20) а в чем тогда вопрос?     | |||
| 22
    
        karabas11 29.12.14✎ 15:05 | 
        Нормально работает через аццкую кучу преобразований
 InkPictureControl>ADOStream>Файл>ДвоичныеДанные>Картинка http://savepic.ru/6448989.png | |||
| 23
    
        ОператорПК 29.12.14✎ 15:30 | 
        (22) а код не пришлёшь?     | |||
| 24
    
        karabas11 29.12.14✎ 15:45 | 
        (23) типа код пожалуйста
 По мотивам (10) и копипасты кода ADOStream из интернета потому что лень набирать ручками Процедура КнопкаВыполнитьНажатие(Кнопка) //Перечисления InkPersistenceFormat = Новый Структура; InkPersistenceFormat.Вставить("IPF_InkSerializedFormat",0); InkPersistenceFormat.Вставить("IPF_Base64InkSerializedFormat",1); InkPersistenceFormat.Вставить("IPF_Gif",2); InkPersistenceFormat.Вставить("IPF_Base64Gif",3); StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2); ConnectModeEnum = Новый Структура( "adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone, |adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive, |adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2); SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2); // Код Данные = ЭтаФорма.ЭлементыФормы.InkPicture.Ink.Save(InkPersistenceFormat.IPF_Gif); СодержимоеМассив = Данные.Выгрузить(); StreamOut = Новый COMОбъект("ADODB.Stream"); StreamOut.Type = StreamTypeEnum.adTypeBinary; StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись. ИмяФайла = КаталогВременныхФайлов()+"\temp.gif"; StreamOut.Open(); //Открыли на чтение и запись StreamOut.Write(Данные); StreamOut.SaveToFile(ИмяФайла, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла StreamOut.Close(); ДД = Новый ДвоичныеДанные(ИмяФайла); ЭтаФорма.ЭлементыФормы.ПолеКартинки1.Картинка = Новый Картинка(ДД); КонецПроцедуры | |||
| 25
    
        ОператорПК 29.12.14✎ 15:55 | 
        (24) Круть! Спасибо! Работает!     | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |