Имя: Пароль:
1C
 
Код 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) Круть! Спасибо! Работает!
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой