При разработке механизмов автоматического заполнения документов в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда стандартный конструктор ввода на основании генерирует код, который при выполнении выдает ошибку: «Переменная не определена (ДанныеЗаполнения)». Особенно часто это происходит в конфигурациях на обычных формах, таких как БГУ 1.0 или УПП 1.3.
В данной статье мы подробно разберем причины возникновения этой ошибки, выясним, почему данные могут не переноситься даже при отсутствии ошибок в коде, и научимся правильно настраивать метаданные для корректной работы механизма «Ввод на основании».
Проанализируем структуру процедуры ОбработкаЗаполнения. В разных версиях платформы и в зависимости от того, как был запущен конструктор, первый параметр этой процедуры может называться по-разному. В старых редакциях платформы (8.0, 8.1 и ранних 8.2) стандартным именем было Основание. В современных версиях (8.3) конструктор по умолчанию использует имя ДанныеЗаполнения.
Ошибка возникает тогда, когда в заголовке процедуры указано одно имя, а внутри тела кода — другое. Рассмотрим пример ошибочного кода:
Процедура ОбработкаЗаполнения(Основание, ТекстЗаполнения, СтандартнаяОбработка)
// ОШИБКА: Используется ДанныеЗаполнения, хотя в параметрах выше указано Основание
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.РасчетСтоимостиУслуг") Тогда
Контрагент = ДанныеЗаполнения.Контрагент;
КонецЕсли;
КонецПроцедуры
Выясним, как это исправить. Нам необходимо обеспечить строгое соответствие. Если мы решили использовать ДанныеЗаполнения, то и в скобках после названия процедуры должно стоять именно это слово. Исправленный вариант будет выглядеть так:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.РасчетСтоимостиУслуг") Тогда
// Теперь переменная определена и содержит ссылку на документ-основание
Контрагент = ДанныеЗаполнения.Контрагент;
Учреждение = ДанныеЗаполнения.Учреждение;
КонецЕсли;
КонецПроцедуры
Иногда после исправления имени переменной программист замечает, что ошибка исчезла, но данные в новом документе все равно не заполняются. При проверке отладчиком оказывается, что переменная ДанныеЗаполнения имеет значение Неопределено. Разберем по шагам, почему это происходит:
ОбработкаЗаполнения вызывается всегда при создании нового объекта. Если вы просто нажали кнопку «Создать» (или «Добавить») в списке документов, платформа вызывает эту процедуру, но не передает в нее никакой объект-основание. В этом случае переменная будет пустой, и условие Если ТипЗнч(...) просто не сработает.СоздатьДокумент(), автоматического заполнения не произойдет. Чтобы механизм сработал, необходимо явно вызвать метод Заполнить(), передав в него ссылку на документ-источник.Рассмотрим пример правильного программного вызова:
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// Явный вызов процедуры ОбработкаЗаполнения
НовыйДокумент.Заполнить(СсылкаНаСчетНаОплату);
НовыйДокумент.Записать();
Для того чтобы кнопка «Ввести на основании» появилась в интерфейсе и корректно передавала данные, необходимо проверить настройки в дереве метаданных. Выясним, на что обратить внимание:
Во-первых, откроем документ-приемник (тот, который мы создаем). На вкладке «Ввод на основании» в поле «Является основанием для» (или в списке вводимых на основании объектов в зависимости от версии) должен быть отмечен документ-источник.
Во-вторых, проверим документ-источник. У него в списке «Вводится на основании» должен быть указан наш документ-приемник. Если эта связь настроена только в одну сторону, стандартные команды платформы могут вести себя некорректно, передавая пустые ссылки в процедуру заполнения.
При переносе данных из табличных частей важно помнить, что обращение к ним происходит через точку от объекта-основания. Рассмотрим типичный цикл заполнения, который генерирует конструктор:
Для Каждого ТекСтрокаИзИсточника Из ДанныеЗаполнения.Услуги Цикл
НоваяСтрока = Услуги.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекСтрокаИзИсточника);
КонецЦикла;
Здесь Услуги без префикса — это табличная часть текущего (нового) документа, а ДанныеЗаполнения.Услуги — это табличная часть документа, на основании которого мы строим новый объект. Обязательно проверяйте наличие и идентичность имен колонок в обеих табличных частях.
Если вы не понимаете, что происходит в момент создания документа, воспользуйтесь простым приемом. Добавьте в начало процедуры ОбработкаЗаполнения диагностическое сообщение:
Сообщить("Тип передаваемых данных: " + ТипЗнч(ДанныеЗаполнения));
Это позволит вам сразу увидеть, передает ли платформа ссылку на документ или, возможно, структуру параметров. В сложных конфигурациях, таких как БГУ 1.0, в ДанныеЗаполнения может передаваться Структура, если ввод на основании инициирован специальной обработкой. В таком случае ваше условие ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка...") не сработает, и код заполнения будет пропущен.
Важный совет: Если вы уже начали править код, созданный конструктором, старайтесь больше не запускать конструктор для этой процедуры. Он полностью перезаписывает содержимое между своими тегами-комментариями, и вы рискуете потерять все свои исправления, включая исправленные имена переменных.