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

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

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

Базовый доступ к табличной части на форме

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


// Пример простого перебора строк на стороне сервера или клиента
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    // Выполняем действия с данными строки
    Сообщить(СтрокаТЧ.Номенклатура);
    СтрокаТЧ.Количество = СтрокаТЧ.Количество * 1.1; // Увеличим количество на 10%
КонецЦикла;

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

Анализ ошибки: «Нельзя изменять поле, содержащее объект данных формы»

Рассмотрим ситуацию, с которой столкнулся автор темы. При попытке заполнить табличную часть на сервере и передать её в качестве параметра функции возникла критическая ошибка: «Ошибка при установке значения атрибута контекста... по причине: Нельзя изменять поле, содержащее объект данных формы». Проанализируем причину возникновения этой ситуации.

Выясним причину: когда вы вызываете серверную функцию и передаете в неё Объект.ИмяТабличнойЧасти как параметр, платформа 1С передает объект типа ДанныеФормыКоллекция. Ошибка возникает в тот момент, когда внутри функции или при возврате результата система пытается перезаписать всю коллекцию целиком. В управляемом приложении коллекции данных формы являются жестко связанными структурами, и их замена (переприсваивание переменной) запрещена.

Посмотрим на ошибочный фрагмент кода:


&НаКлиенте
Процедура НачатьЗагрузку()
    // ОШИБКА: передача Объект.ЗаказНаПеремещение как последнего параметра
    Результат = ВыполнитьЗагрузкуНаСервере(..., Объект.ЗаказНаПеремещение); 
КонецПроцедуры

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

Правильная архитектура заполнения таблицы из Excel

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

Шаг 1. Подготовка данных на клиенте. Сначала мы получаем адрес временного хранения файла, который пользователь выбрал на своем компьютере.

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


&НаСервере
Процедура ЗаполнитьТаблицуНаСервере(АдресХранения)
    
    // Получаем файл из хранилища
    ДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранения);
    ПутьКФайлу = КаталогВременныхФайлов() + "upload_data.xlsx";
    ДанныеФайла.Записать(ПутьКФайлу);
    
    // Вместо использования медленного COM-объекта Excel, 
    // воспользуемся встроенным объектом ТабличныйДокумент
    ТабДок = Новый ТабличныйДокумент;
    Попытка
        ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияТабличныхДокументов.XLSX);
    Исключение
        Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // Очищаем текущую таблицу перед заполнением
    Объект.ЗаказНаПеремещение.Очистить();
    
    // Перебираем строки табличного документа
    ВсегоСтрок = ТабДок.ВысотаТаблицы;
    Для НомерСтроки = 2 По ВсегоСтрок Цикл // Начинаем со второй строки, пропуская заголовок
        
        НоваяСтрока = Объект.ЗаказНаПеремещение.Добавить();
        
        // Читаем данные из колонок
        НоменклатураНаименование = ТабДок.Область(НомерСтроки, 1).Текст;
        КоличествоСтрокой = ТабДок.Область(НомерСтроки, 2).Текст;
        
        // Поиск номенклатуры в базе
        СсылкаНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(НоменклатураНаименование);
        
        Если Не СсылкаНоменклатура.Пустая() Тогда
            НоваяСтрока.Номенклатура = СсылкаНоменклатура;
            НоваяСтрока.Количество = Число(КоличествоСтрокой);
        КонецЕсли;
        
    КонецЦикла;
    
    Сообщить("Загрузка успешно завершена. Обработано строк: " + Объект.ЗаказНаПеремещение.Количество());

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

Оптимизация производительности: использование Таблицы Значений

Проанализируем ситуацию: если в вашем файле Excel тысячи строк, прямое добавление каждой строки в Объект.ТабличнаяЧасть.Добавить() может работать медленно, так как при каждом изменении коллекция формы обновляет свое состояние. Рассмотрим более профессиональный подход — использование промежуточной ТаблицыЗначений.

Посмотрим на алгоритм ускоренной загрузки:

  1. Создаем на сервере временную Таблицу Значений с той же структурой колонок, что и у табличной части формы.
  2. Заполняем эту Таблицу Значений данными из файла (это происходит очень быстро, так как ТЗ — это чистый объект памяти без интерфейсной нагрузки).
  3. Используем метод Объект.ТабличнаяЧасть.Загрузить(ВременнаяТЗ).

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

Важные рекомендации по работе с COM-объектами

Если вы всё же используете Новый COMОбъект("Excel.Application"), как показано в примере автора темы, обязательно следуйте правилам «гигиены» кода:

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

← На главную