Как программно полностью заполнить табличные части документов в 1С:Бухгалтерии 3.0, включая счета учета и суммы?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

При программном создании и заполнении документов в 1С:Бухгалтерии 3.0 часто возникает проблема, когда автоматически вычисляемые поля табличных частей, такие как


Сумма
,

СчетаУчета
или

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

Основные принципы программного заполнения

Прежде чем мы перейдем к конкретным решениям, давайте уясним несколько ключевых моментов. Конфигурация "Бухгалтерия предприятия 3.0" активно использует управляемые формы и разветвленную архитектуру общих модулей для реализации бизнес-логики. Многие расчеты и заполнения, которые пользователь видит "автоматически", на самом деле происходят в специальных процедурах и функциях, расположенных как на клиенте (в модулях форм), так и на сервере (в общих модулях).

При программном создании документа мы работаем напрямую с объектом документа на сервере. Это означает, что клиентские обработчики событий формы, такие как


ПриИзменении
поля

Номенклатура
или

Количество
, не вызываются. Наша задача — найти и вызвать соответствующие серверные или, при необходимости, клиентские процедуры, которые выполняют требуемые расчеты и заполнения.

Заполнение счетов учета (СчетаУчета)

Одной из наиболее частых проблем является незаполнение счетов учета в табличных частях документов. Это критически важно для корректного бухгалтерского учета. К счастью, в БП 3.0 существует мощный и универсальный механизм для этого, реализованный в общем модуле


СчетаУчетаВДокументах
.

Мы будем использовать экспортные процедуры этого общего модуля, чтобы инициировать заполнение счетов учета для нашего программно созданного документа. Модуль


СчетаУчетаВДокументах
инкапсулирует сложную логику определения счетов в зависимости от вида номенклатуры, настроек учета, вида операции и прочих параметров.

Наиболее подходящей процедурой для наших целей будет


СчетаУчетаВДокументах.Заполнить(Объект, Отбор)
. Она позволяет заполнить счета учета для всего документа или только для тех строк, где они еще не указаны.

Рассмотрим по шагам, как это сделать:

  1. Мы создаем или получаем существующий объект документа.
  2. Заполняем основные данные табличной части (номенклатура, количество, цена и т.д.).
  3. Вызываем процедуру
    
    СчетаУчетаВДокументах.Заполнить()
    
    , передавая ей объект документа и, при необходимости, структуру отбора.
  4. Записываем документ.

Вот пример серверного кода, демонстрирующий этот подход:


// Предположим, у нас есть ссылка на документ или мы только что создали новый объект
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

// --- Здесь должен быть ваш код по заполнению табличной части документа. ---
// Например, добавление строк и заполнение Номенклатуры, Количества, Цены и т.д.
//
// Пример: Добавляем строку в табличную часть "Товары"
НоваяСтрока = ДокОбъект.Товары.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("ПримерНоменклатуры");
НоваяСтрока.Количество = 10;
НоваяСтрока.Цена = 100;
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20; // Обязательно для корректного расчета НДС

// --- Конец примера заполнения табличной части ---

// Создаем структуру отбора, чтобы заполнить счета только там, где они не указаны.
// Это полезно, если документ уже частично заполнен.
Отбор = Новый Структура;
Отбор.Вставить("НеЗаполненныеРеквизиты", Истина); // Заполнять только незаполненные счета
// Можно также указать конкретные табличные части, если это необходимо
// Отбор.Вставить("ИмяТабличнойЧасти", "Товары"); 

// Вызываем универсальную процедуру для заполнения счетов учета.
// Эта процедура анализирует тип документа, хозяйственную операцию и заполняет 
// соответствующие счета (СчетУчета, СчетУчетаНДС, СчетДоходов, СчетРасходов и т.д.)
СчетаУчетаВДокументах.Заполнить(ДокОбъект, Отбор);

// После заполнения счетов обязательно записываем измененный документ.
// Если документ должен сразу быть проведенным, указываем РежимЗаписиДокумента.Проведение.
// Это также может вызвать дополнительные проверки и расчеты, специфичные для проведения.
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

Также важно отметить, что в модуле


СчетаУчетаВДокументах
существуют и другие процедуры, например,

ЗаполнитьРеквизитыПриИзменении()
(как показано в одном из сообщений форума), которая используется в обработчиках форм при изменении номенклатуры, или

ЗаполнитьПередЗаписью()
, предназначенная для вызова перед записью документа. Принципы их работы схожи, но

Заполнить()
является более общим и часто достаточным для полного заполнения.

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

Пересчет сумм и других зависимых реквизитов (Сумма, НДС)

Пересчет сумм, НДС, итогов по документу и других зависимых полей — вторая распространенная проблема. Эти поля часто рассчитываются динамически на основе


Количества
,

Цены
,

СтавкиНДС
и других параметров. При программном изменении этих значений обработчики формы, ответственные за пересчет, не срабатывают.

Здесь мы можем выделить два основных сценария работы, в зависимости от того, работаем ли мы с открытой формой документа (клиентский код) или полностью на сервере (фоновая обработка, регламентное задание):

Обработка на стороне клиента (при работе с открытой формой документа)

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


ОбработкаТабличнойЧастиКлиент
.

Метод


ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ(ТекДанные, СтруктураДействий, ДополнительныеПараметры)
предназначен именно для этой цели. Он позволяет программно "нажать" на кнопку пересчета или выполнить действия, аналогичные интерактивному изменению поля в строке табличной части.

Разберем, как мы можем его применить:

  1. Получаем текущие данные строки табличной части, которую мы изменили. Это можно сделать через элементы формы.
  2. Создаем структуру
    
    СтруктураДействий
    
    , в которой указываем, какие именно действия по пересчету нужно выполнить (например, рассчитать сумму, сумму НДС).
  3. Вызываем метод
    
    ОбработатьСтрокуТЧ
    
    .

Вот пример клиентского кода для использования этого механизма:


// Предположим, мы находимся в модуле формы документа и программно изменили строку
// В этом примере, Элементы.Товары - это элемент формы (таблица)
// Мы хотим пересчитать текущую строку, в которой изменили, например, количество или цену

// Получаем текущие данные строки табличной части.
// Если строка только что добавлена или изменена, необходимо получить к ней доступ.
// Например, если мы добавили новую строку:
// НоваяСтрокаТЧ = Элементы.Товары.ТекущиеДанные; 
// или перебираем строки:
// Для Каждого СтрокаТЧ Из Элементы.Товары.ДоступныеПоля Тогда ... КонецДля;
// В данном примере будем считать, что СтрокаТабличнойЧасти это данные строки,
// которая была изменена и требует пересчета.

// Допустим, мы изменили какие-то поля в "СтрокаТабличнойЧасти"
// СтрокаТабличнойЧасти.Количество = 5; 
// СтрокаТабличнойЧасти.Цена = 250;

// Создаем и настраиваем структуру действий, которые нужно выполнить.
// Эти параметры зависят от конкретной логики пересчета в документе.
// Чаще всего это РасчитатьСумму, РасчитатьСуммуНДС и т.п.
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("РассчитатьСумму", Истина);     // Пересчитать сумму по строке
СтруктураДействий.Вставить("РассчитатьСуммуНДС", Истина); // Пересчитать сумму НДС по строке
СтруктураДействий.Вставить("РассчитатьСуммуВсего", Истина); // Возможно, общую сумму строки
СтруктураДействий.Вставить("ПересчитатьИтоги", Истина);  // Общие итоги по документу, если необходимо

// Вызываем обработчик для текущей строки.
// ТекДанные - это данные строки табличной части (тип ДанныеФормыЭлементКоллекции).
// Неопределено - для ДополнительныеПараметры, если они не требуются.
ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ(СтрокаТабличнойЧасти, СтруктураДействий, Неопределено);

// После выполнения этих действий форма должна обновить данные и пересчитать итоги.

Важно понимать, что параметры


СтруктураДействий
могут отличаться для разных документов и даже разных табличных частей. Для определения точных параметров вам может потребоваться проанализировать код обработчиков

ПриИзменении
полей

Количество
,

Цена
или

Номенклатура
в модуле формы соответствующего документа. Обычно эти обработчики вызывают функции, которые формируют эту структуру и передают ее в

ОбработатьСтрокуТЧ
.

Обработка на стороне сервера (фоновая обработка, без открытия формы)

Когда мы работаем полностью на сервере (например, в фоновой обработке, регламентном задании или из модуля менеджера объекта), клиентские модули и элементы формы нам недоступны. В этом случае подходы к пересчету сумм будут иными:

  1. Прямой расчет для простых случаев. Для простых полей, таких как
    
    Сумма = Количество * Цена
    
    , мы можем выполнить расчет напрямую в нашем серверном коде после заполнения
    
    Количества
    
    и
    
    Цены
    
    .
    
    // ... в цикле обхода строк табличной части ...
    НоваяСтрока = ДокОбъект.Товары.Добавить();
    НоваяСтрока.Номенклатура = Выборка.Номенклатура;
    НоваяСтрока.Количество = Выборка.Количество;
    НоваяСтрока.Цена = Выборка.Цена;
    НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20; // Не забываем про ставку НДС
    
    // Прямой расчет суммы
    НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
    
    // Для НДС тоже может быть прямой расчет, если логика простая,
    // например, если НДС = Сумма * СтавкаНДС / 100
    Если НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20 Тогда
        НоваяСтрока.СуммаНДС = Окр(НоваяСтрока.Сумма * 20 / 120, 2); // Пример для НДС "в том числе"
    ИначеЕсли НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.БезНДС Тогда
        НоваяСтрока.СуммаНДС = 0;
    КонецЕсли;
    
    // ... далее заполнение других полей и вызов СчетаУчетаВДокументах.Заполнить() ...
    
  2. Вызов корневых серверных процедур для сложных расчетов. Для более сложных расчетов, таких как НДС, расчет итогов по документу, или применения скидок, простой прямой расчет может быть недостаточен. В таких случаях нам придется "заглянуть" в типовую конфигурацию.

    Мы проанализируем модуль формы документа (например,

    
    МодульОбъекта
    
    или
    
    МодульМенеджера
    
    ), чтобы найти серверные функции или процедуры, которые вызываются из клиентских обработчиков. Часто эти процедуры находятся в общих модулях, связанных с документом, или в модулях менеджеров объектов документов (например,
    
    Документы.РеализацияТоваровУслуг.РассчитатьСуммы
    
    ).

    Например, для пересчета НДС в реализации может существовать серверная функция, которую вызывают из формы. Ваша задача — найти ее, изучить ее параметры и вызвать в своем серверном коде, передав объект документа и текущую строку табличной части.

    Процесс поиска выглядит так:

    1. Откроем конфигуратор.
    2. Найдем нужный документ (например, "Реализация товаров и услуг").
    3. Откроем модуль формы документа.
    4. Найдем обработчики
      
      ПриИзменении
      
      для полей
      
      Количество
      
      ,
      
      Цена
      
      ,
      
      СтавкаНДС
      
      в табличной части.
    5. Проследим, какие серверные вызовы (
      
      &НаСервере
      
      ,
      
      &НаСервереБезКонтекста
      
      ) там используются.
    6. Найдем эти серверные функции в общих модулях или модулях объектов и проанализируем их логику, чтобы понять, как их можно вызвать для нашего объекта документа.

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

Использование штатных механизмов заполнения документа

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


Заполнить()
в модуле объекта или модуле менеджера. Эта процедура может быть предназначена для заполнения документа на основании другого объекта (например, заполнение "Реализации товаров и услуг" на основании "Счета на оплату").

Хотя эта процедура не всегда решает проблему "автоматического" заполнения после прямого добавления строк, ее изучение может выявить вспомогательные методы, которые значительно упрощают задачу. Например, она может содержать вызовы к общим процедурам, которые как раз и выполняют пересчет сумм или заполнение счетов учета для всего документа.

Мы рекомендуем всегда анализировать модуль объекта и модуль менеджера документа на предмет наличия таких экспортных процедур. Возможно, они уже выполняют часть необходимой работы.

В заключение, программное заполнение табличных частей документов в 1С:Бухгалтерии 3.0 требует не простого добавления данных, но и понимания и вызова типовых механизмов конфигурации. Мы рассмотрели основные подходы: использование общего модуля


СчетаУчетаВДокументах
для счетов учета, применение

ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ
для клиентских пересчетов и прямой расчет или поиск серверных функций для работы на сервере. Всегда стремитесь использовать штатные механизмы, так как это обеспечит наибольшую стабильность и корректность работы ваших решений.

← На главную