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

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Использование Построителя отчета для быстрой выгрузки

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

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

  1. Определим границы заполненной области с помощью свойств ВысотаТаблицы и ШиринаТаблицы.
  2. Получим область ячеек, которую необходимо считать.
  3. Создадим ОписаниеИсточникаДанных на основе этой области.
  4. Используем ПостроительОтчета для получения результата.

Пример программной реализации:


// Создаем пустую таблицу значений для результата
ТабЗначений = Новый ТаблицаЗначений;

// Определяем границы документа
ПоследняяСтрока = ТабДок.ВысотаТаблицы;
ПоследняяКолонка = ТабДок.ШиринаТаблицы;

// Если таблица пустая, прерываем выполнение
Если ПоследняяСтрока = 0 Или ПоследняяКолонка = 0 Тогда
    Возврат;
КонецЕсли;

// Получаем область всех заполненных ячеек
ОбластьЯчеек = ТабДок.Область(1, 1, ПоследняяСтрока, ПоследняяКолонка);

// Описываем источник данных для построителя
ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластьЯчеек);
ИсточникДанных.Колонки.Добавить("Колонка1", , "Наименование колонки 1"); // Опционально можно настроить колонки

ПостроительОтчета = Новый ПостроительОтчета;
ПостроительОтчета.ИсточникДанных = ИсточникДанных;

// Выполняем построение и выгружаем результат в ТЗ
ПостроительОтчета.Выполнить();
ТабЗначений = ПостроительОтчета.Результат.Выгрузить();

Важное замечание: Этот метод очень быстр, однако он имеет ограничения. Если в ячейках установлены расшифровки (параметры расшифровки), ПостроительОтчета может их проигнорировать, считав только текстовые представления. Также он чувствителен к структуре заголовков.

Способ 2. Прямой обход ячеек в цикле

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

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


ТекстыЯчеек = Новый Массив;
НомерСтроки = 5; // Пример номера строки, которую нужно считать

Для к = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
    // Используем обращение по формату R1C1
    ИмяОбласти = "R" + Формат(НомерСтроки, "ЧГ=") + "C" + Формат(к, "ЧГ=");
    ТекстЗначения = СокрЛП(ТабличныйДокумент.Область(ИмяОбласти).Текст);
    ТекстыЯчеек.Добавить(ТекстЗначения);
КонецЦикла;

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


ТабДок = ЭлементыФормы.ПолеТабличногоДокумента; // Для обычных форм
ПоследняяСтрока = ТабДок.ВысотаТаблицы;
номерСтроки = 1;
НужнаяКолонка = 2; // Допустим, ищем во второй колонке

Пока номерСтроки <= ПоследняяСтрока Цикл
    Текст = ТабДок.Область(номерСтроки, НужнаяКолонка).Текст;
    
    Если СтрНайти(Текст, "Итого") > 0 Тогда
        // Нашли строку завершения данных
        Прервать;
    КонецЕсли;
    
    // Обработка данных строки...
    номерСтроки = номерСтроки + 1;
КонецЦикла;

Различие между свойствами Текст и Значение

Часто начинающие разработчики совершают ошибку, используя только свойство Текст. Давайте выясним причину, почему это не всегда правильно. Свойство Текст — это строковое представление данных, которое видит пользователь. Если в ячейке находится число "1 000,00", то Текст вернет строку с пробелом и запятой, что потребует дополнительных манипуляций для преобразования в число.

Мы рекомендуем использовать свойство Значение. Однако для этого должны быть соблюдены условия:

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

Обработка объединенных ячеек

Проанализируем ситуацию с объединенными ячейками. В 1С данные хранятся только в левой верхней ячейке объединения. Если вы программно обращаетесь к "хвосту" объединения, вы получите пустое значение. При написании алгоритма обхода следует проверять, принадлежит ли область объединению, используя свойства Область.Лево, Область.Верх и так далее. Если координаты текущей итерации цикла попадают внутрь уже обработанного блока объединения, такую ячейку следует пропускать.

Архитектурный подход: Модель данных

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

В этом случае ТабличныйДокумент выступает лишь как средство отображения (View), а все изменения в нем синхронизируются с внутренней таблицей значений. При редактировании ячейки пользователем срабатывает событие ПриИзмененииСодержимогоОбласти, и мы обновляем соответствующую строку в нашей ТЗ. При таком подходе у нас всегда есть актуальные "считанные" данные в памяти в удобном для анализа формате.

Оптимизация производительности

Важно помнить, что ТабличныйДокумент — это тяжелый объект, особенно на тонком или веб-клиенте. Если документ содержит десятки тысяч строк, прямой обход каждой ячейки на стороне клиента будет работать крайне медленно из-за постоянных вызовов между клиентом и сервером.

В таких случаях мы рекомендуем:

  1. Минимизировать количество обращений к ячейкам.
  2. Если возможно, передавать документ целиком на сервер и обрабатывать его там.
  3. Использовать метод Прочитать(), если данные загружаются из внешнего файла (Excel, MXL), так как системные методы чтения файлов работают значительно быстрее ручного перебора.

Подводя итог, выбор метода считывания зависит от ваших целей. Для простого импорта подойдет ПостроительОтчета, для сложной обработки с анализом оформления — цикл по областям, а для интерактивных инструментов — синхронизация с моделью данных.

← На главную