Как программно вставить значение в табличную часть документа и обновить форму в 1С 8.3

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

В процессе разработки внешних обработок заполнения для конфигураций на управляемых формах, таких как 1С:Управление торговлей 11, программисты часто сталкиваются с задачей импорта данных из внешних файлов (Excel, CSV) напрямую в открытую форму документа. Типичный пример — документ Пересчет товаров, где необходимо быстро проставить фактическое количество по результатам инвентаризации.

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

Разбор ситуации: работа с контекстом формы-владельца

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

Проанализируем основные этапы задачи:

  1. Получение данных из файла Excel через COM-объект.
  2. Поиск номенклатуры в базе по коду или артикулу.
  3. Поиск соответствующей строки в табличной части Товары открытого документа.
  4. Изменение значения в найденной строке.
  5. Визуальное обновление формы владельца.

Ошибка при использовании метода НайтиСтроки

Одной из первых проблем, с которой сталкиваются разработчики, является неправильная обработка результата метода НайтиСтроки(). Рассмотрим фрагмент кода, который часто приводит к ошибке "Поле объекта не обнаружено":


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

// ОШИБКА: НайденноеЗначение — это МАССИВ, а не конкретная строка
НайденноеЗначение.КоличествоУпаковокФакт = ЧислоИзExcel; 

Выясним причину: метод НайтиСтроки() всегда возвращает объект типа Массив, даже если найдена всего одна строка или не найдено ничего. Чтобы изменить данные, нам необходимо проверить, содержит ли массив элементы, и обратиться к конкретному индексу (обычно [0], если номенклатура в документе не дублируется).

Реализация корректного поиска и заполнения

Рассмотрим исправленный алгоритм работы. Мы добавим проверку количества найденных строк и корректное обращение к элементам коллекции. Также важно помнить, что работа с Excel на клиенте требует осторожности при высвобождении ресурсов COM.


// Фрагмент цикла обработки строк Excel
Для СтрокаОтсчета = 2 по КоличествоСтрок Цикл
    КодТовара = Excel.Cells(СтрокаОтсчета, 4).Text;
    
    // Получаем ссылку на номенклатуру (вызов серверной функции)
    НоменклатураСсылка = ПолучитьНоменклатуруПоКоду(КодТовара);
    
    Если НоменклатураСсылка.Пустая() Тогда
        Сообщить("Товар с кодом " + КодТовара + " не найден в базе!");
        Продолжить;
    КонецЕсли;

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

    Если НайденныеСтроки.Количество() > 0 Тогда
        // Берем первую найденную строку
        ТекущаяСтрокаТЧ = НайденныеСтроки[0];
        
        // Проставляем значение из колонки Excel
        ТекущаяСтрокаТЧ.КоличествоУпаковокФакт = Число(Excel.Cells(СтрокаОтсчета, 6).Text);
        
        // Устанавливаем признак модифицированности формы, чтобы пользователь видел изменения
        ВладелецФормы.Модифицированность = Истина;
    Иначе
        Сообщить("Номенклатура " + НоменклатураСсылка + " отсутствует в документе пересчета!");
    КонецЕсли;
КонецЦикла;

Проблема обновления интерфейса (UI)

Часто после выполнения кода значения в памяти изменились, признак Модифицированность установлен, но пользователь видит на экране старые цифры. Это происходит потому, что форма-владелец не знает, что данные её объекта были изменены "извне" другой формой.

Использование метода ВладелецФормы.Прочитать() в данном случае не подходит, так как этот метод перечитывает данные из базы данных, затирая все несохраненные изменения, которые мы только что внесли в объект формы.

Правильное решение: использование глобального метода ОповеститьОбИзменении(). Рассмотрим, как это применить в финальной части кода обработки:


// Закрываем Excel и освобождаем память
Excel.Quit();
Excel = Неопределено;

// Оповещаем систему об изменении объекта, чтобы формы обновили свое содержимое
ОповеститьОбИзменении(ВладелецФормы.Объект.Ссылка);

// Закрываем текущую форму обработки заполнения
ЭтаФорма.Закрыть();

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

Оптимизация производительности: советы для больших документов

Проанализируем ситуацию, когда в документе Пересчет товаров содержатся тысячи строк. Поиск методом НайтиСтроки() внутри цикла по Excel-файлу будет работать со скоростью $O(N*M)$, что может привести к зависанию интерфейса.

Для ускорения работы рекомендуем применить следующие подходы:

  1. Предварительная индексация: Выгрузите табличную часть документа в ТаблицуЗначений на стороне сервера, добавьте индекс по колонке Номенклатура. Выполните все расчеты в этой таблице и загрузите результат обратно в объект.
  2. Минимизация вызовов сервера: Не вызывайте функцию ПолучитьНоменклатуруПоКоду в цикле. Сначала соберите все коды из Excel в массив, одним запросом получите соответствие "Код - Ссылка" на сервере, и используйте это соответствие в цикле.
  3. Отказ от COM-объекта: Если возможно, используйте встроенный объект 1С ТабличныйДокумент для чтения файлов Excel (.xlsx). Метод Прочитать() работает быстрее и стабильнее на серверной стороне, не требуя установленного Microsoft Office на компьютере или сервере.

Важные нюансы УТ 11

В конфигурации 1С:Управление торговлей 11 документ Пересчет товаров имеет свои особенности. Например, если вы меняете КоличествоУпаковокФакт, в документе могут быть завязаны события, рассчитывающие отклонения (излишки и недостатки). При программном изменении реквизита "напрямую" через объект формы эти обработчики могут не сработать.

Поэтому в идеале стоит вызывать типовые процедуры пересчета из модулей конфигурации, если они доступны для вызова. Однако для простых задач заполнения фактических данных связки НайтиСтроки() + ОповеститьОбИзменении() обычно достаточно для корректной работы пользователя.

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

← На главную