Как прочитать первую строку Табличного документа при выгрузке в Таблицу значений?

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

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

Почему ПостроительЗапроса игнорирует первую строку

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

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

Способ 1: Вставка технического заголовка в текущий документ

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

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


// Определяем область, которую нужно сдвинуть (вся таблица)
ОбластьДляСдвига = ТабДок.Область(1, 1, 1, ТабДок.ШиринаТаблицы);
// Вставляем пустую область, сдвигая данные вниз
ТабДок.ВставитьОбласть(ОбластьДляСдвига, ОбластьДляСдвига, ТипСмещенияТабличногоДокумента.ПоВертикали);

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

Важный нюанс: при таком подходе индексы всех строк в исходном документе изменятся. Если после загрузки вам нужно продолжать работу с тем же документом, учитывайте, что все данные «съехали» на одну строку вниз.

Способ 2: Создание временного Табличного документа (Рекомендуемый)

Проанализируем ситуацию, описанную в сообщениях форума: что делать, если документ содержит несколько именованных областей или страниц, и при вставке строк «таблица плывет»? Выясним причину: когда вы вставляете строку в начало документа внутри цикла, координаты всех последующих областей меняются. Вторая область, которая раньше начиналась с 10-й строки, теперь начинается с 11-й, но ваш цикл об этом «не знает».

Для решения этой проблемы мы применим метод создания временного объекта ТабличныйДокумент. Разберем по шагам, как это работает:

  1. Создаем новый, пустой ТабличныйДокумент.
  2. Программно формируем в нем «шапку» с уникальными именами колонок (например, «Колонка1», «Колонка2»).
  3. Выводим данные из исходного документа во временный, начиная со второй строки.
  4. Выгружаем данные из временного документа через Построитель.

Посмотрим на реализацию этого алгоритма:


// Основной ТабДок уже прочитан из файла
ТД_Временный = Новый ТабличныйДокумент;

// Генерируем заголовки колонок во временном документе
Для Сч = 1 По ТабДок.ШиринаТаблицы Цикл
    НомерКолонки = Формат(Сч, "ЧГ=0");
    ОбластьЗаголовка = ТД_Временный.Область(1, Сч);
    ОбластьЗаголовка.Текст = "Колонка_" + НомерКолонки;
КонецЦикла;

// Копируем данные из оригинала во временный документ под созданную шапку
ТД_Временный.Вывести(ТабДок);

// Работаем с временным документом
Построитель = Новый ПостроительЗапроса;
Источник = Новый ОписаниеИсточникаДанных(ТД_Временный.Область(1, 1, ТД_Временный.ВысотаТаблицы, ТД_Временный.ШиринаТаблицы));
Построитель.ИсточникДанных = Источник;
Построитель.ЗаполнитьНастройки();
Построитель.Выполнить();
ТЗ = Построитель.Результат.Выгрузить();

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

Проблема типизации данных при использовании Построителя

Рассмотрим еще один важный аспект: типизация. Когда мы используем ПостроительЗапроса, он пытается автоматически определить типы колонок на основе данных в ТабличномДокументе. Если вы назвали колонку «Колонка_1», а под ней находятся числа, Построитель может решить, что вся колонка имеет тип Число. Однако, если в какой-то строке попадется текст, это может привести к ошибке или потере данных.

Если вам критически важны типы данных, мы рекомендуем после получения ТЗ программно типизировать колонки или вовсе отказаться от Построителя в пользу прямого обхода ячеек ТабличногоДокумента в цикле:


ТЗ = Новый ТаблицаЗначений;
// Создаем колонки вручную
Для Кол = 1 По ТабДок.ШиринаТаблицы Цикл
    ТЗ.Колонки.Добавить("Колонка" + Кол);
КонецЦикла;

// Обходим строки и заполняем ТЗ
Для Стр = 1 По ТабДок.ВысотаТаблицы Цикл
    НоваяСтрока = ТЗ.Добавить();
    Для Кол = 1 По ТабДок.ШиринаТаблицы Цикл
        НоваяСтрока[Кол-1] = ТабДок.Область(Стр, Кол).Текст;
    КонецЦикла;
КонецЦикла;

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

Альтернативные способы чтения (ADO и NativeXLSX)

В завершение проанализируем ситуацию, когда источником данных является файл Excel. Если ваша задача — просто прочитать файл, минуя визуальное отображение в 1С, стоит рассмотреть технологию ADO (ActiveX Data Objects). В строке подключения к Excel через провайдер Microsoft.ACE.OLEDB можно указать параметр HDR=No. Это прямо скажет системе, что первая строка содержит данные, а не заголовки.

Для современных систем на базе Linux или при работе в облаке, где COM-объекты недоступны, рекомендуется использовать чтение XLSX как XML-архива. Это позволяет напрямую обращаться к содержимому узлов Sheet.xml, где строки пронумерованы от 1 до N, и никакие механизмы построителей не будут навязывать вам логику «заголовков».

Подведем итог: если вы используете ПостроительЗапроса, всегда добавляйте техническую строку сверху. Если вы работаете с многостраничным документом — делайте это во временном объекте ТабличныйДокумент, чтобы не нарушить структуру индексов.

← На главную