Как узнать номер или имя колонки Таблицы Значений при поиске данных

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

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

Проблема метода Найти() и объект СтрокаТаблицыЗначений

Рассмотрим стандартную ситуацию: мы используем метод Найти(), чтобы отыскать ячейку с текстом "Наименование товаров". Проанализируем, что происходит в коде. Метод Результат.Найти("Значение") возвращает объект типа СтрокаТаблицыЗначений. Многие ошибочно полагают, что этого достаточно для копирования данных, но объект строки содержит значения всех колонок сразу. Чтобы понять, в каком именно «столбце» находится искомое слово, нам нужно «разрезать» эту строку по горизонтали.

Важно помнить, что к полям объекта СтрокаТаблицыЗначений можно обращаться не только по имени через точку (Строка.N1), но и по числовому индексу в квадратных скобках (Строка[0]). Именно это свойство мы будем использовать для поиска номера колонки.

Решение №1: Поиск индекса через перебор колонок в найденной строке

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


// Предположим, Результат — это наша ТаблицаЗначений с данными из Excel
ИскомоеЗначение = "Наименование товаров (работ, услуг)";
СтрокаПоиска = Результат.Найти(ИскомоеЗначение);

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

Решение №2: Поиск по конкретной строке заголовков (Best Practice)

Как правило, при загрузке из Excel заголовки всегда находятся в первой строке (индекс 0). Проанализируем ситуацию: зачем искать по всей таблице, если можно проверить только «шапку»? Это гораздо быстрее и исключает риск найти случайное совпадение в теле документа. Для загрузки в 1С:Бухгалтерию 3.0 отчетов о продажах маркетплейсов из файлов такого формата можно применить загрузку отчётов о продажах маркетплейсов в БП 3 из Excel, которая автоматически сопоставляет нужные поля.

Посмотрим на пример кода, который определяет имена колонок, перебирая только первую строку:


// Определяем нужную нам строку (обычно это самая первая строка после загрузки)
Если Результат.Количество() > 0 Тогда
    СтрокаЗаголовков = Результат[0]; 
    ИскомоеИмяКолонки = "";
    
    Для Каждого Колонка Из Результат.Колонки Цикл
        // Проверяем значение в текущей колонке первой строки
        Если СокрЛП(СтрокаЗаголовков[Колонка.Имя]) = "Наименование товаров (работ, услуг)" Тогда
            ИскомоеИмяКолонки = Колонка.Имя;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ЗначениеЗаполнено(ИскомоеИмяКолонки) Тогда
        // Теперь мы можем безопасно выгрузить данные
        ТЗ_Результат.ЗагрузитьКолонку(Результат.ВыгрузитьКолонку(ИскомоеИмяКолонки), "Наименование");
    КонецЕсли;
КонецЕсли;

Использование метаданных и метода Индекс()

Иногда требуется получить индекс колонки, уже имея объект самой колонки. В 1С для этого существует коллекция Колонки и её методы. Рассмотрим подробнее, как это работает. Если у вас есть объект колонки (например, полученный через Результат.Колонки.Найти("N1")), вы можете узнать её порядковый номер с помощью метода Индекс().

Важный нюанс: метод Индекс() принимает именно объект колонки, а не строку с её именем. Посмотрим на пример:


ОбъектКолонка = Результат.Колонки.Найти("N5");
Если ОбъектКолонка <> Неопределено Тогда
    ПорядковыйНомер = Результат.Колонки.Индекс(ОбъектКолонка);
    Сообщить("Колонка N5 имеет индекс: " + ПорядковыйНомер);
КонецЕсли;

Повышение отказоустойчивости: очистка данных и регистр

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

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


Эталон = ВРег("Наименование товаров"); // Приводим к верхнему регистру один раз
Для Каждого Кол Из Результат.Колонки Цикл
    ЗначениеЯчейки = СокрЛП(СтрокаЗаголовков[Кол.Имя]);
    Если ВРег(ЗначениеЯчейки) = Эталон Тогда
        // Точное совпадение найдено без учета пробелов и регистра
        ИмяНужнойКолонки = Кол.Имя;
    КонецЕсли;
КонецЦикла;

Продвинутый метод: Создание карты соответствия

Если в вашем Excel-файле много нужных колонок (Товар, Цена, Количество, Артикул), лучше всего один раз пройтись по первой строке и создать Структуру или Соответствие, где ключом будет название данных, а значением — реальное имя колонки в ТаблицеЗначений (N1, N2 и т.д.).

Рассмотрим этот алгоритм по шагам:

  1. Создаем пустую структуру КартаКолонок.
  2. Проходим циклом по всем колонкам первой строки файла. Если подобные файлы требуется регулярно собирать из почты или FTP, этот процесс можно автоматизировать с помощью сбора прайс-листов с почты, FTP, HTTP, их обработки и выгрузки.
  3. Если находим знакомый заголовок, записываем его в структуру.
  4. При обработке строк данных обращаемся к таблице через эту структуру. Похожий механизм сопоставления данных по произвольным полям поиска используется в переносе данных между похожими конфигурациями 1С, помогая избежать дублирования элементов.

КартаКолонок = Новый Структура;
ПерваяСтрока = Результат[0];

Для Каждого Кол Из Результат.Колонки Цикл
    ТекстЗаголовка = СокрЛП(ПерваяСтрока[Кол.Имя]);
    Если ТекстЗаголовка = "Товар" Тогда
        КартаКолонок.Вставить("Товар", Кол.Имя);
    ИначеЕсли ТекстЗаголовка = "Цена" Тогда
        КартаКолонок.Вставить("Цена", Кол.Имя);
    КонецЕсли;
КонецЦикла;

// Теперь в цикле по строкам данных (начиная со второй)
Для Ит = 1 По Результат.Количество() - 1 Цикл
    ТекСтрока = Результат[Ит];
    НоваяСтр = ТЗ_Итог.Добавить();
    // Обращаемся через карту соответствия
    НоваяСтр.Наименование = ТекСтрока[КартаКолонок.Товар];
    НоваяСтр.Цена = ТекСтрока[КартаКолонок.Цена];
КонецЦикла;

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

← На главную