В процессе разработки часто возникает задача предоставить пользователю возможность ручного ввода данных в табличный документ на форме с последующей программной обработкой этих данных. Это может быть импорт данных из сторонних файлов, заполнение спецификаций или расчетных таблиц. В этой статье мы подробно разберем несколько проверенных способов считывания информации, проанализируем их преимущества и недостатки, а также изучим нюансы, которые помогут избежать типичных ошибок при работе с объектом ТабличныйДокумент.
Если данные в табличном документе имеют плоскую структуру (похожи на обычную таблицу со строками и колонками без сложного оформления), наиболее эффективным и быстрым способом будет использование объекта ПостроительОтчета. Этот метод позволяет буквально в несколько строк кода преобразовать область табличного документа в ТаблицаЗначений. Для отображения полученного результата на форме можно использовать пример вывода таблицы значений с динамическим набором колонок.
Рассмотрим по шагам, как это реализовать:
ВысотаТаблицы и ШиринаТаблицы.ОписаниеИсточникаДанных на основе этой области.ПостроительОтчета для получения результата.Пример программной реализации:
// Создаем пустую таблицу значений для результата
ТабЗначений = Новый ТаблицаЗначений;
// Определяем границы документа
ПоследняяСтрока = ТабДок.ВысотаТаблицы;
ПоследняяКолонка = ТабДок.ШиринаТаблицы;
// Если таблица пустая, прерываем выполнение
Если ПоследняяСтрока = 0 Или ПоследняяКолонка = 0 Тогда
Возврат;
КонецЕсли;
// Получаем область всех заполненных ячеек
ОбластьЯчеек = ТабДок.Область(1, 1, ПоследняяСтрока, ПоследняяКолонка);
// Описываем источник данных для построителя
ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластьЯчеек);
ИсточникДанных.Колонки.Добавить("Колонка1", , "Наименование колонки 1"); // Опционально можно настроить колонки
ПостроительОтчета = Новый ПостроительОтчета;
ПостроительОтчета.ИсточникДанных = ИсточникДанных;
// Выполняем построение и выгружаем результат в ТЗ
ПостроительОтчета.Выполнить();
ТабЗначений = ПостроительОтчета.Результат.Выгрузить();
Важное замечание: Этот метод очень быстр, однако он имеет ограничения. Если в ячейках установлены расшифровки (параметры расшифровки), ПостроительОтчета может их проигнорировать, считав только текстовые представления. Также он чувствителен к структуре заголовков.
Если таблица имеет сложную структуру, содержит объединенные ячейки или вам необходимо считывать не только текст, но и дополнительные свойства (например, расшифровку или цвет фона), мы рекомендуем использовать прямой перебор ячеек. Это более трудоемкий, но максимально гибкий подход. При необходимости анализа визуальных характеристик вывода данных можно воспользоваться методикой определения того, помещается ли текст в ячейке табличного документа.
Проанализируем пример, где мы обходим колонки в определенной строке:
ТекстыЯчеек = Новый Массив;
НомерСтроки = 5; // Пример номера строки, которую нужно считать
Для к = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
// Используем обращение по формату R1C1
ИмяОбласти = "R" + Формат(НомерСтроки, "ЧГ=") + "C" + Формат(к, "ЧГ=");
ТекстЗначения = СокрЛП(ТабличныйДокумент.Область(ИмяОбласти).Текст);
ТекстыЯчеек.Добавить(ТекстЗначения);
КонецЦикла;
Разберем ситуацию, когда нам нужно найти строку с определенным заголовком и считать данные под ней. В этом случае удобно использовать цикл Пока для поиска маркера конца таблицы или нужного ключевого слова:
ТабДок = ЭлементыФормы.ПолеТабличногоДокумента; // Для обычных форм
ПоследняяСтрока = ТабДок.ВысотаТаблицы;
номерСтроки = 1;
НужнаяКолонка = 2; // Допустим, ищем во второй колонке
Пока номерСтроки <= ПоследняяСтрока Цикл
Текст = ТабДок.Область(номерСтроки, НужнаяКолонка).Текст;
Если СтрНайти(Текст, "Итого") > 0 Тогда
// Нашли строку завершения данных
Прервать;
КонецЕсли;
// Обработка данных строки...
номерСтроки = номерСтроки + 1;
КонецЦикла;
Часто начинающие разработчики совершают ошибку, используя только свойство Текст. Давайте выясним причину, почему это не всегда правильно. Свойство Текст — это строковое представление данных, которое видит пользователь. Если в ячейке находится число "1 000,00", то Текст вернет строку с пробелом и запятой, что потребует дополнительных манипуляций для преобразования в число.
Мы рекомендуем использовать свойство Значение. Однако для этого должны быть соблюдены условия:
СодержитЗначение = Истина.Число или СправочникСсылка.Номенклатура).В этом случае вы получите чистый объект данных, с которым можно сразу работать в коде.
Проанализируем ситуацию с объединенными ячейками. В 1С данные хранятся только в левой верхней ячейке объединения. Если вы программно обращаетесь к "хвосту" объединения, вы получите пустое значение. При написании алгоритма обхода следует проверять, принадлежит ли область объединению, используя свойства Область.Лево, Область.Верх и так далее. Если координаты текущей итерации цикла попадают внутрь уже обработанного блока объединения, такую ячейку следует пропускать.
Рассмотрим более продвинутый метод, который часто применяется в сложных системах. Вместо того чтобы считывать данные "по факту" из визуального компонента, мы можем построить модель в виде ТаблицаЗначений или коллекции структур.
В этом случае ТабличныйДокумент выступает лишь как средство отображения (View), а все изменения в нем синхронизируются с внутренней таблицей значений. При редактировании ячейки пользователем срабатывает событие ПриИзмененииСодержимогоОбласти, и мы обновляем соответствующую строку в нашей ТЗ. При таком подходе у нас всегда есть актуальные "считанные" данные в памяти в удобном для анализа формате.
Важно помнить, что ТабличныйДокумент — это тяжелый объект, особенно на тонком или веб-клиенте. Если документ содержит десятки тысяч строк, прямой обход каждой ячейки на стороне клиента будет работать крайне медленно из-за постоянных вызовов между клиентом и сервером.
В таких случаях мы рекомендуем:
Прочитать(), если данные загружаются из внешнего файла (Excel, MXL), так как системные методы чтения файлов работают значительно быстрее ручного перебора.Подводя итог, выбор метода считывания зависит от ваших целей. Для простого импорта подойдет ПостроительОтчета, для сложной обработки с анализом оформления — цикл по областям, а для интерактивных инструментов — синхронизация с моделью данных.