При программном создании документов в современных конфигурациях 1С (таких как Бухгалтерия предприятия 3.0, ERP 2.5 или УТ 11) разработчики часто сталкиваются с неприятным эффектом: документ создается, проводится, но в интерфейсе некоторые данные (например, субконто, счета учета или расшифровки НДС) выглядят пустыми или отображаются некорректно. Выясним причину этого поведения и разберем способы решения. Если требуется автоматизировать создание счетов в «Бухгалтерии предприятия 3.0» на основании электронных писем, используется обработка для формирования документов по заказам с почты.
Рассмотрим ситуацию на примере документа ПоступлениеТоваровУслуг. Разработчик пишет код, который добавляет строку в табличную часть Услуги, заполняет номенклатуру, количество, цену и счета затрат с субконто. После записи объекта ПоступлениеОбъект.Записать() документ появляется в системе, но при открытии формы поля субконто пустые. Стоит только вручную перевыбрать номенклатуру или перезаписать документ интерактивно — данные «магическим образом» появляются.
Проанализируем ситуацию: в современных конфигурациях, построенных на базе БСП (Библиотеки стандартных подсистем), связь между основной строкой табличной части и дополнительными сведениями (которые могут храниться в скрытых колонках или других таблицах) осуществляется через техническое поле. Обычно оно называется ИдентификаторСтроки или КлючСвязи.
Важный нюанс: Платформа 1С:Предприятие самостоятельно не генерирует значения для этих полей. В интерактивном режиме (когда пользователь работает с формой) за это отвечает программный код, написанный разработчиками конфигурации в модуле формы или связанных с ней общих модулях. При программном создании документа код формы не исполняется, и поле остается равным 0 (если это число) или пустой строке.
В «Бухгалтерии предприятия 3.0» механизм отображения аналитики (субконто) на форме документа часто завязан на программную отрисовку. Система пытается сопоставить строку из таблицы услуг с данными во внутренних структурах объекта. Если ИдентификаторСтроки равен нулю, механизм связи «ломается», и форма просто не знает, какое субконто показать для данной строки, хотя в базе данных в самой табличной части значения могут присутствовать.
Проанализируем самый правильный путь. Раз мы работаем в типовой конфигурации, логично воспользоваться методами, которые уже заложили разработчики. В БСП существуют общие модули, предназначенные для работы с табличными частями. Вместо того чтобы вручную изобретать велосипед, мы можем вызвать процедуру, которая проставит идентификаторы всем строкам. Для быстрого поиска системных механизмов пригодится справочник по методам библиотеки стандартных подсистем.
Посмотрим на пример кода, который необходимо добавить перед записью документа:
// Добавляем услуги программно
Услуги = ПоступлениеОбъект.Услуги;
НоваяСтрока = Услуги.Добавить();
НоваяСтрока.Номенклатура = ВыбраннаяУслуга;
// ... заполнение остальных реквизитов ...
// Вызываем метод БСП для заполнения идентификаторов
// В разных версиях БСП имя метода может отличаться,
// но общий смысл остается прежним:
ОбщегоНазначения.ЗаполнитьУникальныеИдентификаторы(ПоступлениеОбъект.Услуги);
ПоступлениеОбъект.Записать(РежимЗаписиДокумента.Проведение);
Использование ОбщегоНазначения.ЗаполнитьУникальныеИдентификаторы гарантирует, что каждой строке будет присвоен уникальный в рамках этого документа номер, который свяжет её со всеми зависимыми данными.
Если по какой-то причине вы не хотите использовать общие модули или работаете в самописной конфигурации, разберем, как реализовать заполнение вручную. Если поле КлючСвязи (или его аналог) имеет числовой тип, нам нужно обеспечить его уникальность внутри документа.
Рассмотрим по шагам алгоритм заполнения в цикле:
СчетчикИдентификаторов = 0;
Для Каждого СтрокаТЧ Из ПоступлениеОбъект.Услуги Цикл
СчетчикИдентификаторов = СчетчикИдентификаторов + 1;
СтрокаТЧ.ИдентификаторСтроки = СчетчикИдентификаторов;
// Если в документе есть связанные таблицы (например, Акцизы или Маркировка),
// их строки должны иметь такой же идентификатор для связи
КонецЦикла;
Внимание: Если документ создается не «с нуля», а дописывается, важно сначала найти максимальный уже существующий идентификатор в таблице, чтобы не возникло дублей.
Выясним еще одну причину «пустых» полей. Иногда заполнение технических реквизитов скрыто глубоко в логике самого документа. В типовых решениях в модулях объектов часто присутствуют экспортные процедуры, такие как ЗаполнитьСчетаУчета() или ЗаполнитьРеквизитыПослеИзмененияНоменклатуры().
Проанализируем ситуацию: когда вы просто присваиваете Строка.Номенклатура = Значение, обработчик ПриИзменении, существующий в форме, не срабатывает. Поэтому счета учета и идентификаторы могут остаться пустыми. Попробуйте вызвать программно методы дозаполнения:
// Заполняем основные данные
СтрокаУслуг = ПоступлениеОбъект.Услуги.Добавить();
СтрокаУслуг.Номенклатура = НоменклатураСсылка;
// Заставляем объект рассчитать счета и ключи по своим правилам
ПоступлениеОбъект.ЗаполнитьСчетаУчета();
// Если такой метод есть в модуле объекта и он экспортный
В версии КОРП или при использовании сложного учета НДС, уникальный идентификатор строки становится критически важным для связи с таблицей НДСПредъявленный или другими регистрами сведений, которые используются для корректного формирования движений. Если идентификатор не заполнен, при проведении документа могут возникнуть ошибки или данные в регистры попадут «криво».
Разберем типичный пример правильного программного создания строки услуги:
ПоступлениеОбъект = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
ПоступлениеОбъект.Дата = ТекущаяДата();
ПоступлениеОбъект.Организация = ОрганизацияСсылка;
// ... заполнение шапки ...
Услуги = ПоступлениеОбъект.Услуги;
СтрокаУслуг = Услуги.Добавить();
СтрокаУслуг.Номенклатура = Инструмент.УслугаПовознаграждению;
СтрокаУслуг.Количество = 1;
СтрокаУслуг.Цена = СуммаАгента;
СтрокаУслуг.Сумма = СуммаАгента;
// Обязательно заполняем счета учета
СтрокаУслуг.СчетЗатрат = Инструмент.СчетЗатрат;
СтрокаУслуг.Субконто1 = Инструмент.Субконто1ДляПоступления;
// Решаем проблему идентификатора (Ключа связи)
// Если поле называется ИдентификаторСтроки:
СтрокаУслуг.ИдентификаторСтроки = Услуги.Количество();
// Или используем метод БСП, если доступен
// ОбщегоНазначения.ЗаполнитьУникальныеИдентификаторы(ПоступлениеОбъект.Услуги);
ПоступлениеОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
Для того чтобы программно созданный документ выглядел и работал так же, как интерактивный, мы должны:
ИдентификаторСтроки, КлючСвязи), так как они не заполняются платформой автоматически при добавлении строк через код.ОбщегоНазначения.ЗаполнитьУникальныеИдентификаторы), чтобы гарантировать совместимость с логикой конфигурации.Соблюдение этих правил позволит избежать проблем с отображением аналитики на формах и обеспечит корректное формирование проводок и движений по регистрам. Для поиска возможных расхождений после доработок программной логики применяется автоматическое сравнение бухгалтерских проводок между базами.