В процессе разработки на платформе 1С часто возникает задача проанализировать или модифицировать данные в уже сформированном табличном документе. Например, найти определенное значение, выделить цветом ячейки, удовлетворяющие условию, или собрать данные из разных частей отчета. В отличие от элементов формы, у объекта ТабличныйДокумент нет готовой коллекции всех ячеек, которую можно было бы перебрать в цикле. Давайте разберем, как получить доступ к каждой ячейке и внедрить универсальный алгоритм полного перебора.
Проанализируем ситуацию: у нас есть сформированный объект ТабличныйДокумент, и нам нужно последовательно обойти все его ячейки, чтобы, например, найти текст "НужноеЗначение". Стандартный метод НайтиТекст() не всегда подходит, особенно если требуется сложная логика проверки или анализ соседних ячеек. В таких случаях лучше использовать проверенный способ программного обхода ячеек.
Самый надежный и универсальный способ обойти все ячейки — это использовать вложенные циклы. Внешний цикл будет итерировать по строкам, а внутренний — по колонкам. Для этого нам понадобятся два ключевых свойства объекта ТабличныйДокумент:
ВысотаТаблицы — возвращает общее количество строк в документе.ШиринаТаблицы — возвращает общее количество колонок.Зная общее число строк и колонок, мы можем организовать циклы от 1 до этих значений. Внутри циклов для получения доступа к конкретной ячейке используется метод Область() или ПолучитьОбласть(), которому передаются координаты — номер строки и номер колонки.
Рассмотрим по шагам, как это реализовать на практике.
ВысотаТаблицы и ШиринаТаблицы.ВысотаТаблицы.ШиринаТаблицы.НомерСтроки и НомерКолонки, мы получаем объект ячейки (типа ОбластьЯчеекТабличногоДокумента) с помощью метода ТабДок.Область(НомерСтроки, НомерКолонки).Посмотрим на пример кода, который решает исходную задачу — поиск текста в табличном документе:
Процедура НайтиЗначениеВТабличномДокументе(ТабДок)
// Получаем границы табличного документа
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;
ИскомыйТекст = "НужноеЗначение";
// Внешний цикл по строкам
Для НомерСтроки = 1 По ВсегоСтрок Цикл
// Внутренний цикл по колонкам
Для НомерКолонки = 1 По ВсегоКолонок Цикл
// Получаем область ячейки по ее координатам
Ячейка = ТабДок.Область(НомерСтроки, НомерКолонки);
// Проверяем значение в ячейке.
// Используем свойство .Текст для сравнения видимого отображения.
Если Ячейка.Текст = ИскомыйТекст Тогда
Сообщить("Найдено вхождение в строке " + НомерСтроки + ", колонке " + НомерКолонки);
// Если нужно найти только первое вхождение, можно прервать циклы.
// Для этого можно использовать оператор Возврат или систему меток.
Возврат;
КонецЕсли;
КонецЦикла; // Конец цикла по колонкам
КонецЦикла; // Конец цикла по строкам
Сообщить("Искомое значение не найдено.");
КонецПроцедуры
Этот алгоритм гарантированно проверит каждую ячейку документа. Он является основой для решения множества других, более сложных задач.
После того как мы получили объект ячейки в переменную Ячейка, мы можем не только читать ее текст, но и управлять множеством других параметров оформления. Объект ОбластьЯчеекТабличногоДокумента предоставляет доступ к оформлению и данным ячейки. Для программного вывода картинок и подписей в ячейки есть инструмент добавления факсимиле в табличный документ.
Рассмотрим самые полезные свойства:
Текст: Строковое представление данных, которое видит пользователь.Значение: Фактическое значение ячейки (может быть числом, датой, булево, в то время как Текст — это его отформатированное представление).Формат: Строка формата, применяемая к значению (например, "ДФ=dd.MM.yyyy").ЦветФона, ЦветТекста: Позволяют программно изменять цвета.Шрифт: Доступ к объекту Шрифт для изменения начертания (жирный, курсив), размера и т.д.ГоризонтальноеПоложение, ВертикальноеПоложение: Управление выравниванием текста в ячейке.Объединить(): Метод для объединения ячеек.Примечание: Текст всплывающей подсказки для ячейки.Давайте усложним наш пример. Допустим, нам нужно не просто найти значение, а выделить все ячейки, в которых числовое значение больше 1000, желтым цветом и сделать текст жирным.
Процедура ВыделитьЯчейкиПоУсловию(ТабДок)
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Ячейка = ТабДок.Область(НомерСтроки, НомерКолонки);
// Проверяем, что в ячейке содержится число
Если ТипЗнч(Ячейка.Значение) = Тип("Число") Тогда
// Проверяем условие
Если Ячейка.Значение > 1000 Тогда
// Устанавливаем цвет фона
Ячейка.ЦветФона = WebЦвета.СветлоЖелтый;
// Делаем шрифт жирным, сохраняя остальные его параметры
ТекущийШрифт = Ячейка.Шрифт;
Ячейка.Шрифт = Новый Шрифт(ТекущийШрифт, , , Истина, ТекущийШрифт.Курсив, ТекущийШрифт.Подчеркивание, ТекущийШрифт.Зачеркивание);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
// После изменения оформления нужно показать документ пользователю
ТабДок.Показать();
КонецПроцедуры
Важный момент: при изменении шрифта рекомендуется создавать новый объект Шрифт на основе существующего, чтобы не потерять другие его настройки (размер, имя и т.д.).
Полный перебор всех ячеек — мощный, но не всегда самый быстрый способ. Если табличный документ очень большой (сотни тысяч ячеек), такой перебор может занять заметное время. Рассмотрим альтернативы, которые в некоторых случаях могут быть эффективнее при обработке больших объемов данных.
НайтиТекст()Этот метод был упомянут в исходном вопросе. Он идеально подходит для простого поиска текстового значения. Его главное преимущество — высокая производительность, так как поиск выполняется на уровне платформы, что гораздо быстрее, чем перебор в цикле на языке 1С.
Метод возвращает первую найденную область или Неопределено, если ничего не найдено. Чтобы найти все вхождения, его нужно вызывать в цикле, каждый раз указывая новую область для старта поиска.
// Ищем первое вхождение
НайденнаяЯчейка = ТабДок.НайтиТекст("НужноеЗначение");
// Организуем цикл для поиска всех последующих вхождений
Пока НайденнаяЯчейка <> Неопределено Цикл
Сообщить("Текст найден в строке: " + НайденнаяЯчейка.Верх + ", колонке: " + НайденнаяЯчейка.Лево);
НайденнаяЯчейка.ЦветФона = WebЦвета.СветлоЗеленый; // Выделяем найденное
// Ищем следующее вхождение, начиная поиск со следующей ячейки
НайденнаяЯчейка = ТабДок.НайтиТекст("НужноеЗначение", НайденнаяЯчейка);
КонецЦикла;
Используйте НайтиТекст(), когда вам нужно просто найти ячейки по текстовому содержимому и не требуется анализ других свойств или сложных условий.
Если табличный документ создается на основе макета с заранее определенной структурой, можно присвоить ключевым ячейкам или областям имена. Это позволяет обращаться к ним напрямую, без перебора или поиска. Такой подход часто используется, когда разрабатывается сложная отчетность или специализированная обработка, например Контроль выручки.
В макете вы можете выделить ячейку и в палитре свойств задать ей `Имя`. После этого в коде можно обратиться к этой области через коллекцию Области.
// Предположим, в макете есть ячейка с именем "ИтогСумма"
ЯчейкаИтога = ТабДок.Области.ИтогСумма;
ЯчейкаИтога.Текст = "Всего к оплате: " + Формат(СуммаДокумента, "ЧДЦ=2");
Этот подход не решает задачу полного перебора, но является лучшей практикой для работы с документами, имеющими фиксированную структуру (например, печатные формы счетов или накладных — для этого есть редактор шаблонов печатных форм для 1С без программирования).
Таким образом, основным и самым универсальным методом для программной работы со всеми ячейками табличного документа является перебор по координатам с помощью вложенных циклов. Он дает полный контроль над каждой ячейкой, позволяя реализовывать сложную логику анализа и форматирования. В то же время, для более простых задач, таких как поиск текста, не стоит забывать о быстрых встроенных методах платформы, таких как НайтиТекст().