FAQ для начинающего программиста 1С

Пример создания типизированых колонок в таблице значений

Форма списка  с деревом групп

  1. Отладка 1С не в файловом варианте (SQL)

  2. Отладка 1С web сервисов

  3. Сверхбыстрое удаление элементов справочника

  4. Пример создания типизированых колонок в таблице значений

  5. Псевдо-листы (ссыла на регистры)

  6. Регистрация 1С Com connector

  7. Примеры запросов. Отбор из регистра по документу регистратору

  8. Вызываем процедуру другой формы

  9. Прогресс-бар для длительных операций в цикле

  10. Форма списка с реквизитом отбора

  11. Форма cписка новый Элемент с заполнением

  12. Форма спикка  с деревом групп


Отладка 1С не в файловом варианте

   Очень часто в клиент-серверном варианте, у начинающих программистов 1С, возникат вопросы относительно отсутсвия останова в тексте модуля под тегом &НаСервере.

По умолчанию, при использовании клиент-серверного режима работы 1С-предприятия никакие серверные функции и процедуры не будут поддаваться пошаговой отладке. Система будет выполнять их «на сервере 1С 8.3″, такие процедуры не видны для клиентской машины. То есть, точки останова на сервере 1С не работают.

Исправляется это редактированием записи в реестре

  1. [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\1C:Enterprise 8.1 Server Agent].
  2. Скорректировать ключ для ragent.exe , добавив «-debug».
  3. Пример редактирования: C:\Program Files (x86)\1cv82\8.2.18.109\bin\ragent.exe» -srvc -agent -regport 1541 -port 1540 -range 1560:1591  -debug -d «C:\Program Files (x86)\1cv82\srvinfo»

После правки перезапускаем сервер с новыми параметрами. Теперь программист 1с может отслеживать процедуры на сервере.


Отладка 1С Web-сервиса

Для разрешения отладки на веб-сервере нужно перейти на вкладку "Прочие" диалога публикации на веб-сервере, установить флаг "разрешить отладку" или выбрать (Разрешена (протокол TCP/IP)) и указать адрес отладчика. Для локальной отладки можно указать tcp://localhost

После правки перезапускаем ОБЯЗАТЕЛЬНО! перезапускаем web сервер с новыми параметрами.

Меню - Отладка - Подключение - Автоматическое подключение - выбрать тип сервиса для отладки

Теперь программист 1с может отслеживать процедуры на сервере.


Сверхбыстрое удаление элементов справочника и других объектов конфигурации

//=====================================
&НаСервере
Процедура УдалитьНоменклатуруТестНаСервере()
    
Запрос = Новый Запрос( "ВЫБРАТЬ
                           |    НоменклатураТест.Ссылка
                           |ИЗ
                           |    Справочник.НоменклатураТест КАК НоменклатураТест"

    );    
Результат = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
УдалитьОбъекты(Результат,,);  

КонецПроцедуры
//=====================================

.Процедура удаляет все элементы справочника НоменклатураТест без всяких проверок

// удаление помеченных объектов с контролем ссылочной целостности
Помеченные = НайтиПомеченныеНаУдаление();
Найденные = 0;
УдалитьОбъекты(Помеченные, Истина, Найденные);
Для каждого Ссылка из Найденные Цикл
    СтрСообщения = "Объект не удален: " + СокрЛП(Ссылка[0]);
    СтрСсылка = ", используется в " + СокрЛП(Ссылка[1]);
    Сообщить (СтрСообщения + СтрСсылка);
КонецЦикла;

Пример создания типизированых колонок в таблице значений

    ТЗ.Колонки.Добавить("ИндексСортировки"		, Новый ОписаниеТипов("Число"));
	ТЗ.Колонки.Добавить("ИмяРаздела"		, Новый ОписаниеТипов("Строка"));
	ТЗ.Колонки.Добавить("ДатаКорр"			, Новый ОписаниеТипов("Дата"));
	ТЗ.Колонки.Добавить("БезусловноеУдаление"	, Новый ОписаниеТипов("Булево"));
	ТЗ.Колонки.Добавить("Номенклатура"		, Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
	ТЗ.Колонки.Добавить("ДанныеРаздела"		, Новый ОписаниеТипов("Структура"));
	// пример создания колонок "число" и "строка" с уточнением параметров:
	ТЗ.Колонки.Добавить("ПроцентВыполнения"		, Новый ОписаниеТипов("Число"	, Новый КвалификаторыЧисла(18, 2)));
	ТЗ.Колонки.Добавить("ИмяРаздела"		, Новый ОписаниеТипов("Строка"	, , Новый КвалификаторыСтроки(200, ДопустимаяДлина.Переменная)));
	ТЗ.Колонки.Добавить("ДатаСписаания"		, Новый ОписаниеТипов("Дата"	, , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));

 


Расширение командного интерфейса ( Псевдо листы)

Пример настроек для регистра сведений или подчиненного справочника.

 

Если нам необходимо создать справочник подчиненный документу.
То делаем у этого справочник реквизит ОбъектВладелец с галочкой Заполнять из Данных заполнения. И создаем команду справочника с параметрами (свойства):

Группа  - Панель навигации формы.Перейти
Тип ПараметрКоманды - ДокументВладелец.ссылка

И в модуле команды

&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
  
ПараметрыОтбора = Новый Структура; ПараметрыОтбора.Вставить("ОбъектВладелец",ПараметрКоманды);
 
ПараметрыФормы = Новый Структура;  ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);

ОткрытьФорму("Справочник.ПодчиненныйДокументуСправочник.ФормаСписка", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Уникальность, ПараметрыВыполненияКоманды.Окно, ПараметрыВыполненияКоманды.НавигационнаяСсылка);

КонецПроцедуры

В документе форме проверяем командный интерфейс, а в форме элемента справочника процедуру

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
     //Костыль для подстановки документа владельца
КонецПроцедуры

 

 


Регистрация 1С COM connector

  1. regsvr32 (1C.../bin/)commcntr.dll ( Регистрируем библиотеку)
  2. "Службы компонентов" (например: Пуск -> Администрирование -> Службы компонентов. *Приложения COM+* добавляем новое приложение: Создать -> Приложение. На вопрос "Установка или создание нового приложения" — выбираем "Создать новое приложение". Имя нового приложения лучше написать чтобы было понятно о чем речь: *1CV8_ComConnector*, способ активации — "серверное приложение".Учетная запись для запуска приложения *Локальная Служба* после нужно будт выбирать учетку users под которой стартует сервер 1С.
  3. В ветке созданного приложения *1CV8_ComConnector* переходим на ветку "Компоненты" и создаем компонент: Создать -> Компонент
     Выбираем "Установка новых компонент", и в диалоге выбираем нужную библиотеку (comcntr.dll)
  4. Идем в роли, в createrOwner  выбираем учетку users под которой стартует сервер 1С. "1CV8_ComConnector" свойства - безопасность - убираем галку с Принудительная проверка доступа для приложения. Убеждаемся, что галка напротив  createrOwner - Есть.


Примеры запросов. Отбор из регистра по документу регистратору

|ВЫБРАТЬ

|    ЦеныНоменклатурыПоставщиковСрезПоследних.Номенклатура КАК Номенклатура,
|    ЦеныНоменклатурыПоставщиковСрезПоследних.Цена КАК Цена,
|    ЦеныНоменклатурыПоставщиковСрезПоследних.Регистратор КАК Регистратор
|ИЗ
|    РегистрСведений.ЦеныНоменклатурыПоставщиков.СрезПоследних(, Регистратор ССЫЛКА Документ.ПриобретениеТоваровУслуг) КАК ЦеныНоменклатурыПоставщиковСрезПоследних
 

ВЫБРАТЬ
    ЦеныНоменклатурыПоставщиковСрезПоследних.Номенклатура КАК Номенклатура,
    ЦеныНоменклатурыПоставщиковСрезПоследних.Цена КАК Цена
ИЗ
    РегистрСведений.ЦеныНоменклатурыПоставщиков.СрезПоследних КАК ЦеныНоменклатурыПоставщиковСрезПоследних
ГДЕ
    ЦеныНоменклатурыПоставщиковСрезПоследних.Регистратор ССЫЛКА Документ.ПриобретениеТоваровУслуг

ВЫБРАТЬ
    ЦеныНоменклатурыПоставщиковСрезПоследних.Номенклатура КАК Номенклатура,
    ЦеныНоменклатурыПоставщиковСрезПоследних.Цена КАК Цена
ИЗ
    РегистрСведений.ЦеныНоменклатурыПоставщиков.СрезПоследних КАК ЦеныНоменклатурыПоставщиковСрезПоследних
ГДЕ
    ТИПЗНАЧЕНИЯ(ЦеныНоменклатурыПоставщиковСрезПоследних.Регистратор) = ТИП(Документ.ПриобретениеТоваровУслуг)

 


Вызываем процедуру другой формы

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

    
Форма = Ссылка.ПолучитьФорму("ФормаКакогоТоДокумента");
Форма.Открыть();
Форма.ПроцедураДругойФормы() // в форме должна быть объявлена как экспортная
Форма.Закрыть();


Тяжелый цикл сервера с прогресс-баром.
Порция - количество в пакете. ОбработатьДокументыНаСервере отрабатывает пакет и возвращается на клиент за новым. В этот момент обновляем прогресс-бар

&НаСервере
Функция ОбработатьДокументыНаСервере(Начало,Конец);
    Для I = Начало+1 По Конец Цикл    
    Сообщить(
""+I);    
    КонецЦикла;
КонецФункции

 

&НаКлиенте
Процедура ОбработатьДокументы(Команда)
Всего
= 33;    
Порция
= 10;
Частей = Цел(Всего/Порция);
Остаток = Всего%Порция;
Состояние("
Выполняется обработка ",0,"Старт ");    

Для I = 1 По Частей Цикл    
ОбработатьДокументыНаСервере((I-1)*Порция,I*Порция);
Состояние(
"Выполняется обработка ",Цел((I*Порция*100)/Всего),"Обработано "+Строка(I*Порция)+" из "+Всего );    
КонецЦикла  ;

ОбработатьДокументыНаСервере(Порция*Частей,Порция*Частей + Остаток);
Состояние(
"Завершено ",100,"Обработано "+Всего+" из "+Всего );
КонецПроцедуры


Форма  списка с реквизитом отбора

Форма : Два реквизита - ФильтрРеквизитA,ФильтрРеквизитB
Список: Две  колонки списка - РеквизитA,РеквизитB

&НаКлиенте
Процедура ВключитьФильтр()
 Фильтр = Новый FixedStructure("A,B",Этаформа.ФильтрРеквизитA,Этаформа.ФильтрРеквизитB);
 ФильтрНаСервере(Фильтр);
 КонецПроцедуры

&НаСервере
Процедура ФильтрНаСервере(Фильтр)
Список.Отбор.Элементы.Очистить();
// Item = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));  
// Если один
// Если много...
GroupAND                 = Список.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
GroupAND.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИ;

Item0GroupAND = GroupAND.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Item0GroupAND.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитA");
Item0GroupAND.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Item0GroupAND.ПравоеЗначение = Фильтр.A;

Item1GroupAND = GroupAND.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Item1GroupAND.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитB");
Item1GroupAND.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Item1GroupAND.ПравоеЗначение = Фильтр.B;

GroupAND.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
GroupAN .Использование = Истина; 

КонецПроцедуры

 

===========
&НаСервере
Процедура ФильтрПриИзмененииНаСервере(Фильтр)
Список.Отбор.Элементы.Очистить();    
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));    
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Реквизит1");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Фильтр;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
ЭлементОтбора.Использование = Истина;    
КонецПроцедуры


&НаКлиенте
Процедура ФильтрПриИзменении(Элемент)
    ФильтрПриИзмененииНаСервере(Этаформа.Фильтр);
КонецПроцедуры


Форма cписка новый Элемент с заполнением

У динамического списка на форме делаем вызов перехватывающий создание нового ( в том числе и с кнопки "Создать")
Заполняем программно "ПараметрыЗаполнения". Если у  измерений стоит флаг "заполнять из данных заполнения" Процедура "Обработка заполнения" будет вызвана автоматически и не явно

&НаКлиенте
Процедура СписокПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)
    // Если у  измерений стоит флаг "заполнять из данных заполнения" = Истина, Процедура "Обработка заполнения" - не нужна!
    Отказ= Истина;
    ПараметрыЗаполнения = Новый Структура;
    ПараметрыЗаполнения.Вставить("Измерение1",Этаформа.Реквизит1);
    ПараметрыЗаполнения.Вставить("Измерение2",Этаформа.Реквизит2);
    ПараметрыФормы  = Новый Структура("ЗначенияЗаполнения",ПараметрыЗаполнения );
    Форма = ПолучитьФорму("РегистрСведений.Тест1.Форма.ФормаЗаписи",ПараметрыФормы,Этаформа,,);
    Форма.Открыть();
КонецПроцедуры


Выбор из формы списка

Установить списку атрибут - Режим выбора в Истина.
СписокВыбор - Отработает при двойном клике

СписокВыборЗначения - По кнопке Выбрать формы

&НаКлиенте
Процедура СписокВыборЗначения(Элемент, Значение, СтандартнаяОбработка)
ОповеститьОВыборе(Элемент.ТекущиеДанные);
СтандартнаяОбработка = Ложь;
КонецПроцедуры
 


 

 

Форма списка  с деревом групп

 

Динамический список  - Дерево Отображение  = Дерево
Динамический список  - Список  Отображение = Иерархия

Форма свойства: (Использование:) Список групп = Дерево(Динамический список)

 

 


Работа с XML

//======================================   вспомогательные функции  XML    =========================

Функция    Create_Node (Root_Node,Node_Name)
Возврат Root_Node.AppendChild(Root_Node.OwnerDocument.CreateElement(Node_Name));    
конецФункции

Функция    Add_Node_Vol(UpNode,Элемент,Значение)
 NodeTxt  = Create_Node(UpNode,Элемент);
 NodeTxt.AppendChild(UpNode.ДокументВладелец.СоздатьТекстовыйУзел(XMLСтрока(Значение)));
Возврат UpNode;    
конецФункции

Функция    Set_Node_Arg(UpNode,Элемент,Значение)
UpNode.LastChild.SetAttribute(Элемент,Значение);
Возврат UpNode;    
конецФункции

//======================================   вспомогательные функции  XML    =========================

//Создает тело сообщения и записывает его в файл
Функция    New_MESSAGE(PathFileSave="С:\test.xml")                  Export
MESSAGE        = Новый ДокументDOM(НЕОПРЕДЕЛЕНО, "MESSAGE");
RootDOM          = MESSAGE.DocumentElement;
MESSAGE_BodyCreate(RootDOM);
MESSAGE_2_File(MESSAGE,PathFileSave);
Возврат ""
КонецФункции

//Запись тела сообщения в файл
Функция    MESSAGE_2_File(Doc_DOM,FullFileName);

ХМЛ=Новый ЗаписьXML;
ХМЛ.ОткрытьФайл(FullFileName,Новый ПараметрыЗаписиXML("UTF-8",,Ложь,Ложь));
SaveDOM=Новый ЗаписьDOM;
SaveDOM.Write(Doc_DOM ,ХМЛ);
ХМЛ.Закрыть();
Возврат FullFileName;
КонецФункции

Функция    MESSAGE_BodyCreate(RootDOM)  
SubNode   =             Create_Node   (RootDOM ,"Node");
Add_Node_Vol          (SubNode,"A"  , "A");             
Add_Node_Vol          (SubNode,"B"  , "B");  
SUB2 = Add_Node_Vol          (SubNode,"C"  , "C"); 
Set_Node_Arg(SUB2,"SUB2","2")

КонецФункции

 

 


Многоколоночный динамический массив:
Array     = Новый Массив(2);
Array[0]  = Новый Массив();
Array[1]  = Новый Массив();

Для каждого I из K цикл
Array[0].Добавить(I.Код);
Array[1].Добавить(I.Наименование);
КонецЦикла;

F = Array[0].Количество()