Имя: Пароль:
1C
1С v8
Как обратиться к справочнику по номеру из VB.NET
0 gumoldova
 
11.10.14
21:25
Уважаемые форумчане помогите в следующей проблеме

Как реализовать в VB.Net (VisualStudio2008) выборку справочника по его имени или номеру из метаданных

Строка с четким указанием имени работает

VidiEdIzm = v83.Справочники.КлассификаторЕдиницИзмерения.Выбрать()

v83 - это работающее соединение c 1C - ComConnector

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

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

Хочу обратиться к справочнику по номеру (точно знаю, что его номер к примеру 35)

По логике должно быть :

VidiEdIzm = v83.Справочники[35].Выбрать()

или по имени

VidiEdIzm = v83.Справочники["КлассификаторЕдиницИзмерения"].Выбрать()

Но проблема в том, что VB выдает ошибку из-за квадратных скобок.
Может кто подскажет как правильно составить такое обращение ?
1 zulu_mix
 
11.10.14
21:46
а чего не запросом?
2 gumoldova
 
11.10.14
21:50
Хорошая мысль, как-то не подумал, попробую. Спасибо за наводку.
3 gumoldova
 
11.10.14
22:26
К сожалению я больше по VB чем по 1С.
Не могли бы примерчик кинуть как текст запроса составить для выборки одного справочника из справочников.
4 gumoldova
 
11.10.14
22:47
Выбрать элементы из справочника по имени я еще смогу запросом, а как создать документ запросом ?

По имени из метаданных просто (но зараза квадратные скобки не пускает)

Nakl1C = v83.Документы["РасхНалоговаяНакладная"].СоздатьДокумент()
5 zippygrill
 
11.10.14
23:09
Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Номенклатура.Наименование
        |ИЗ
        |    Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |    Номенклатура.Ссылка В ИЕРАРХИИ(&Папка)";

    Запрос.УстановитьПараметр("Папка", Папка);

    РезультатЗапроса = Запрос.Выполнить();

    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        // Вставить обработку выборки ВыборкаДетальныеЗаписи
    КонецЦикла;
6 zippygrill
 
11.10.14
23:10
В результате какой условии создать документы хочешь?
7 gumoldova
 
11.10.14
23:17
Создать новый документ (например РасхНалоговаяНакладная), заполнить его шапку и табличную часть и записать.
8 Jaap Vduul
 
12.10.14
00:27
Nakl1C = v83.NewObject("ДокументыМенеджер.РасхНалоговаяНакладная").СоздатьДокумент()
9 Jaap Vduul
 
12.10.14
00:29
+(8)
Или так (не помню уже точно):
Nakl1C = v83.NewObject("ДокументМенеджер.РасхНалоговаяНакладная").СоздатьДокумент()
10 gumoldova
 
12.10.14
00:51
(9) Супер !!!

Заработало.

Всем участникам Большое человеческое СПАСИБО !
Особенно Jaap Vduul

Вопрос закрыт.
11 gumoldova
 
12.10.14
18:46
(9) Немного поторопился с радостью.

Документ то создается, но надо его реквизиты заполнить.

Может подскажете как.

Сейчас делаю через прямую ссылку на имя реквизита

Nakl1C.Контрагент = v83.Справочники.Контрагенты.НайтиПоКоду("0526")

А как записать по ссылке на имя
В 1с было-бы :

Nakl1C["Контрагент"] = v83.Справочники.Контрагенты.НайтиПоКоду("0526")

Но тут опять гадские прямоугольные скобки которые VB не пропускает

Уже и через запрос пытался, но ничего не выходит.
Помогите ктонить!
12 Jaap Vduul
 
12.10.14
22:47
(11)Создать через NewObject структуру, заполнить необходимые свойства через Вставить(), скопировать из структуры в документ через ЗаполнитьЗначенияСвойств().
13 gumoldova
 
13.10.14
00:07
(12) А можно какой-то, хоть маленький примерчик, идею понял, но вот с реализацией беда. (В любом случае спасибо)
14 gumoldova
 
13.10.14
15:52
(12) На 90% Решил проблему Напишу как для тех такое тоже ищет

Напомню, задача стоит в заполнении заполнить документ 1С(Шапку и Таб. Часть) по COM (ComConnector) соединению из софта на VB.NET.
Софтом пользуются разные клиенты и соединение производиться по хранящимся в SQL базе параметрам (путь к базе, User, Login) и у разных клиентов могут быть разные конфигурации.
Считать сами метаданные с названиями не проблема,

        For i = 0 To v77.Метаданные.Перечисления().count - 1
            MsgBox("Перечисления : " & v77.Метаданные.Перечисления.Получить(i).name)
            For l = 0 To v77.Метаданные.Перечисления.Получить(i).ЗначенияПеречисления().count - 1
                MsgBox("Перечисления Значения : " & v77.Метаданные.Перечисления.Получить(i).ЗначенияПеречисления.Получить(l).name)
            Next
        Next

        For i = 0 To v77.Метаданные.Документы().count - 1
            MsgBox("Документы : " & v77.Метаданные.Документы.Получить(i).name)
            For l = 0 To v77.Метаданные.Документы.Получить(i).Реквизиты().count - 1
                MsgBox("Документы Реквизит : " & v77.Метаданные.Документы.Получить(i).Реквизиты.Получить(l).name)
            Next
            For l = 0 To v77.Метаданные.Документы.Получить(i).ТабличныеЧасти().count - 1
                MsgBox("Документы ТЧ : " & v77.Метаданные.Документы.Получить(i).ТабличныеЧасти.Получить(l).name)
                For k = 0 To v77.Метаданные.Документы.Получить(i).ТабличныеЧасти.Получить(l).Реквизиты().count - 1
                    MsgBox("Документы ТЧ Реквизит : " & v77.Метаданные.Документы.Получить(i).ТабличныеЧасти.Получить(l).Реквизиты.Получить(k).name)
                Next
            Next
        Next


вот заполнять по этим названиям сложнее, так как надо использовать переменные, для их подстановки в 1С используются квдратные скодки [ ] которые компилятор VB.Net не пропускает и выдает ошибку.

Метод решения:

1. Создаем новую накладную в 1С

Nakl1C = v83.NewObject("ДокументМенеджер.РасхНалоговаяНакладная").СоздатьДокумент()

2. Создаем пустую структуру 1С
  
Struktura = v83.NewObject("Структура")

3. Добавляем в структуру (или изменяем если уже добавлен) свойства и их значения

Struktura.Вставить("Дата", Format(Date.Now, "yyyy") & Format(Date.Now, "MM") & Format(Date.Now, "dd"))
Struktura.Вставить("Валюта", v83.Справочники.Валюты.НайтиПоКоду("498"))
Struktura.Вставить("Фирма", v83.Справочники.Фирмы.НайтиПоКоду("00000001"))
Struktura.Вставить("ВидОперации", v83.Перечисления.ВидыРасходных.РасходнаяНН)
и т.д.

4. Копируем эти свойства из структуры в документ
  v83.ЗаполнитьЗначенияСвойств(Nakl1C, Struktura)
   Nakl1C.Записать()

Также можно заполнить и табличную часть.
15 gumoldova
 
13.10.14
16:04
(14) Но Остались 10 % нерешенных а именно :

1. Конструкция

Struktura.Вставить("ВидОперации", v83.Перечисления.ВидыРасходных.РасходнаяНН)

Выдает ошибку, хотя напрямую в документ проблем не создает

Nakl1C.ВидОперации = v83.Перечисления.ВидыРасходных.РасходнаяНН

2. Как добавить строку Табличной части документа с использованием имени этой ТЧ в переменной

так Работает
StrNakl1C = Nakl1C.ТМЦ.Добавить()

Так НЕ Работает
StrNakl1C = Nakl1C["ТМЦ"].Добавить()

И так не работает
StrNakl1C = v83.NewObject("ДокументМенеджер.РасхНалоговаяНакладная.ТМЦ").Добавить()


Может подскажет кто нибудь ?
16 silent person
 
13.10.14
16:38
с помощью метода Eval не получится ? вот только я не знаю как он точно в VB вызывается

StrNakl1C = EVAL("Nakl1C.ТМЦ").Добавить()
17 gumoldova
 
13.10.14
17:33
(16)
Такое было раньше в 7.7

v77.EvalExpr("СоздатьОбъект(""Документ.РасхНалоговаяНакладная"")")

Не уверен, что пойдет в 8

Попробую. Спасибо.
18 silent person
 
13.10.14
17:53
то что было в 7.7 подойдет для создания нового документа в 1С 8.х.
Но тебе дальше надо получать табличную часть по имени, а Nakl1C это переменная VB, а не сеанса 1С и вычислять ее надо на стороне VB, а не 1С.
19 Serginio1
 
13.10.14
18:12
D 1c  Nakl1C["ТМЦ"]  это вызов свойства равнозначно Nakl1C.ТМЦ То есть это вызов Idisatch Invoke с параметром
DISPATCH_PROPERTYGET

Как VB это обрабатывает я не знаю.
Но многое можно решить через внешние отчеты.
Например

В модуле внешней обработки создать
Функция ВычислитьВыражение(Выражение) Экспорт
  возврат вычислить(Выражение);    
КонецФункции

Функция ВычислитьСвойствоОбъекта(Объект,Свойство) Экспорт
  возврат Объект[Свойство];    
КонецФункции

Процедура УстановитьСвойство(Объект,Свойство,Значение) Экспорт
Объект[Свойство]=Значение
КонецПроцедуры

и


    ДляВнешнегоСоединения= Сервер.ВнешниеОбработки.Создать(ПутьКОбработке);
    
    Объект=ДляВнешнегоСоединения.ВычислитьВыражение("Документы.РасхНалоговаяНакладная.СоздатьДокумент()");


ДляВнешнегоСоединения.УстановитьСвойство(Объект,ТМЦ,Значение)

А вообще лучше большую часть обработки вынести во внешний отчет, а из ВБ дергать только методы с параметрами
20 gumoldova
 
13.10.14
19:40
(19) Да, для одной конфигурации проблем нет, но когда много клиентов, с разными конфигурациями, вариант с редактированием конфигурации не подходит.
21 Serginio1
 
13.10.14
20:18
(19) Я говорил про внешние отчеты, без редактирования конфигурации
22 Serginio1
 
13.10.14
20:21
23 gumoldova
 
13.10.14
20:44
(22) Если правильно понял предлагается внешний файл с фрагментом кода 1С (внешний отчет или обработка) подключать к клиентской конфе.
Если так, то файлов должно быть много и разных для многих клиентов. Имеет право на жизнь но очень муторно на первый взгляд.
Идея в том, чтобы создать одно VB приложение умеющее общаться с многими конфами 1С зная их метаданные. И в принципе, за малым исключением оно работает.
24 Serginio1
 
13.10.14
20:51
Либо используй рефлексию

http://msdn.microsoft.com/ru-ru/library/system.reflection.ireflect.invokemember(v=vs.110).aspx

tDate=Nakl1C.GetType();
Object result = tDate.InvokeMember("ТМЦ",
            BindingFlags.GetProperty, null, null, new Object[0]);
25 Serginio1
 
13.10.14
20:52
Зачем? Можно в одном файле все сделать?
26 Serginio1
 
13.10.14
20:58
тьфу
tDate=Nakl1C.GetType();
Object result = tDate.InvokeMember("ТМЦ",
            BindingFlags.GetProperty, null, Nakl1C, new Object[0]);
27 gumoldova
 
13.10.14
21:11
Получилось следующее


Dim tdate As Type
Dim StrNakl1C As Object

tdate = Nakl1C.GetType()

StrNakl1C = tdate.InvokeMember("ТМЦ", BindingFlags.GetProperty, Nothing, Nakl1C, New Object)

(На последние квадратные скобки с нулем ругалось)
Имеется ввиду StrNakl1C это и есть новая строка ТЧ?
28 Serginio1
 
13.10.14
21:21
Нет.

ТабличнаяЧастьТмц=StrNakl1C = tdate.InvokeMember("ТМЦ", BindingFlags.GetProperty, Nothing, Nakl1C, New Object);
СтрокаНакл=ТабличнаяЧастьТмц.Добавить()
29 Serginio1
 
13.10.14
21:21
Тьфу
ТабличнаяЧастьТмц = tdate.InvokeMember("ТМЦ", BindingFlags.GetProperty, Nothing, Nakl1C, New Object);
СтрокаНакл=ТабличнаяЧастьТмц.Добавить()
30 Serginio1
 
13.10.14
21:37
Кстати в примере по вб
http://msdn.microsoft.com/ru-ru/library/system.reflection.ireflect.invokemember(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2


Dim result As [Object] = tDate.InvokeMember("Now", _
            BindingFlags.GetProperty, Nothing, Nothing, New [Object](-1) {})
31 gumoldova
 
13.10.14
21:59
(30) Работает (что удивительно)

Окончательный вариант таков


Dim tdate As Type
Dim Resalt As Object
tdate = Nakl1C.GetType()
Resalt = tdate.InvokeMember("ТМЦ", BindingFlags.GetProperty, Nothing, Nakl1C, New [Object](-1) {})
StrNakl1C = Resalt.Добавить()
   заполнение строки ТЧ
Nakl1C.Записать()

Спасибо!
32 gumoldova
 
13.10.14
22:03
Осталась одна не решенная проблема

Struktura.Вставить("ВидОперации", v83.Перечисления.ВидыРасходных.РасходнаяНН)

Не хочет заполнять реквизит из перечисления
хотя напрямую в документ проблем не создает

Nakl1C.ВидОперации = v83.Перечисления.ВидыРасходных.РасходнаяНН

В чем же отличия этих двух вариантов и как это обойти?
33 Serginio1
 
13.10.14
22:10
То есть не работает
v83.ЗаполнитьЗначенияСвойств(Nakl1C, Struktura)
?
34 gumoldova
 
13.10.14
22:22
Именно при вызове

Struktura.Вставить("ВидОперации", v83.Перечисления.ВидыРасходных.РасходнаяНН)

Вылетает с ошибкой

Подозреваю, что дело в перечислении, так как с справочник.НайтиПоКоду или ПланСчетов.НайтиПокоду или строка идет без збоев

Struktura.Вставить("СубкНДС", v83.Справочники.Налоги.НайтиПоКоду("20"))
Struktura.Вставить("СерияСФ", Mid(RowNakl("Name1CNakl"), 1, 2))
35 gumoldova
 
13.10.14
22:26
Типа надо как-то дать ссылку на ЗначениеПеречисления
36 Serginio1
 
13.10.14
22:49
Перечисление это не справочник и не план счетов.
А что за ошибка?
Если, что можно посмотреть ошибку в журнале регистрации
37 Serginio1
 
13.10.14
22:49
Для проверки заполни без
Struktura.Вставить("ВидОперации", v83.Перечисления.ВидыРасходных.РасходнаяНН)
38 Serginio1
 
13.10.14
22:57
Не забывай проверить модуль расходной на ошибки включая внешнее соединение
v8: .NET и 1С V82.COMConnector ошибка при вызове .ПолучитьОбъект
39 Serginio1
 
13.10.14
23:05
40 gumoldova
 
13.10.14
23:11
Если заполняю без использования структуры, в объект накладной
с четким указанием реквизита то все работает


Nakl1C.ВидОперации = v83.Перечисления.ВидыРасходных.РасходнаяНН


где

Nakl1C = v83.NewObject("ДокументМенеджер.РасхНалоговаяНакладная").СоздатьДокумент()
или
Nakl1C = v83.Документы.РасхНалоговаяНакладная.СоздатьДокумент()
41 gumoldova
 
13.10.14
23:11
За ссылки спасибо!
42 gumoldova
 
14.10.14
00:12
Надо попробовать сделать все через рефлекшен, и отказаться от структуры. Попробую отпишусь.
43 Serginio1
 
14.10.14
00:25
Посмотри v8: v8: 1c и c#
44 Jaap Vduul
 
14.10.14
01:36
>> Именно при вызове
>> Struktura.Вставить("ВидОперации",v83.Перечисления.ВидыРасходных.РасходнаяНН)
>> Вылетает с ошибкой
Там, насколько помню, какой-то косяк с передачей по ссылке.
Помогает трюк с промежуточной переменной:
Dim enumv83 as object = v83.Перечисления.ВидыРасходных.РасходнаяНН
Struktura.Вставить("ВидОперации", enumv83)

>>Надо попробовать сделать все через рефлекшен, и отказаться от структуры.
В VB.Net есть функция CallByName, упрощающая этот процесс:
http://msdn.microsoft.com/en-us/library/chsc1tx6(v=vs.80).aspx
45 Serginio1
 
14.10.14
11:24
Можно еще попробовать через импорт классов из xsd.

То есть экспорт схемы конфигурации из XDTO-пакеты.
Правда нужно её подправить а именно

<xs:import namespace="http://v8.1c.ru/8.1/data/core"; schemaLocation="ПутьКПапке\data_core.xsd"/>
  <xs:import namespace="http://v8.1c.ru/8.1/data/enterprise"; schemaLocation="ПутьКПапке\data_enterprise.xsd"/>


Выгрузить пакеты через

Процедура ЗпаисатьПакет(Фабрика,URIПространстваИмен,ИмяФайла) Экспорт

         НаборСхем = Фабрика.ЭкспортСхемыXML(URIПространстваИмен);
        Для Счетчик = 0 по НаборСхем.Количество() - 1 Цикл
            Схема = НаборСхем.Получить(Счетчик);
            Схема.ОбновитьЭлементDOM();
            ЗаписьDOM = Новый ЗаписьDOM;
            ЗаписьXMLСтрока = Новый ЗаписьXML;
            ЗаписьXMLСтрока.УстановитьСтроку();
            ЗаписьXMLФайл = Новый ЗаписьXML;
            ЗаписьDOM.Записать(Схема.ДокументDOM, ЗаписьXMLСтрока);
            ЗаписьXMLФайл.ОткрытьФайл(ИмяФайла +"[" + Формат(Счетчик,"ЧЦ=10;ЧГ=0;ЧН=") + "].xsd");
            ЗаписьXMLФайл.ЗаписатьБезОбработки(ЗаписьXMLСтрока.Закрыть());
            ЗаписьXMLФайл.Закрыть()
        КонецЦикла;    
  
КонецПроцедуры


    ЗпаисатьПакет(ФабрикаXDTO,"http://v8.1c.ru/8.1/data/core",Каталог+"data_core";);
    ЗпаисатьПакет(ФабрикаXDTO,"http://v8.1c.ru/8.1/data/enterprise",Каталог+"data_enterprise";);

Ну и через десериализацию можно выгрузить в файл а на стороне 1С загрузить через СериализаторXDTO
46 Serginio1
 
14.10.14
11:53
Кстати мне очень нравится вот этот генератор
https://wscfblue.codeplex.com/
https://wscfblue.codeplex.com/discussions/544680
47 gumoldova
 
15.10.14
23:08
Дотачивал интерфейс приложения, без него не мог вводить связи для проверки, поэтому долго не отписывался.

Во первых, СПАСИБО всем, очень толковые ребята, много инфы и все по делу.

По результатам экспериментов, перебор и заполнение реквизитов Документа и ТабличнойЧасти (в VB через ComConnector) проще всего замутить через СТРУКТУРУ , только когда реквизит заполняется из Перечисления использовал рефлекшн, так как там нет значений (как в справочниках или планах счетов) только свойства.
Ну и для добавления строки Таб. Части тоже рефлекшн.
48 gumoldova
 
15.10.14
23:21
Добавление в структуру Перечисления через рефлекшн:

Строка с перечислением к примеру

Resalt = v83.Перечисления.ВидыОперацийПоступлениеТоваровУслуг.ПокупкаКомисия


Само добавление пошагово


tdate = v83.Перечисления.GetType()
Resalt = tdate.InvokeMember("ВидыОперацийПоступлениеТоваровУслуг", BindingFlags.GetProperty, Nothing, v83.Перечисления, New [Object](-1) {})
tdate1 = Resalt.GetType()
Resalt1 = tdate1.InvokeMember("ПокупкаКомисия", BindingFlags.GetProperty, Nothing, Resalt, New [Object](-1) {})
Struktura.Вставить("ВидОперации", Resalt1)
49 Serginio1
 
16.10.14
12:39
(48) Если ВБ используешь то действительно лучше использовать
44 CallByName

CallByName(TextBox1, "Text", CallType.Set, "New Text")

    'Retrieve the value of a property.
    MsgBox(CallByName(TextBox1, "Text", CallType.Get))

    'Call a method.
    CallByName(TextBox1, "Hide", CallType.Method)

В твоем случае
Result =CallByName(v83.Перечисления, "ВидыОперацийПоступлениеТоваровУслуг", CallType.Get)

Значительно проще
50 Serginio1
 
16.10.14
12:42
По поводу ЗаполнитьЗначенияСвойств в свое время например при заполнение объекта XDTO не сравбатывало на полях у которых поле может иметь значения нескольких типов
51 gumoldova
 
21.10.14
21:03
Да действительно CallByName гораздо удобнее.

Еще раз всем откликнувшимся БОЛЬШОЕ СПАСИБО !!!!