В процессе разработки часто возникает задача загрузить данные из внешнего файла, например, с расширением .mxl или .xlsx, в ТаблицуЗначений для дальнейшей обработки. Один из распространенных подходов — использование встроенных объектов 1С. Однако, при неверном выборе объекта можно столкнуться с ошибкой «ожидается выражение "ВЫБРАТЬ"». Разберем, почему она возникает и как правильно выполнить преобразование.
Проанализируем ситуацию: разработчик пытается загрузить данные из табличного документа, используя объект ПостроительЗапроса. Код выглядит примерно так:
Построитель = Новый ПостроительЗапроса;
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать("C:\путь\к_файлу.mxl");
// Указываем область табличного документа как источник данных
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, 7));
Построитель.Выполнить(); // Здесь возникает ошибка
ТЗ = Построитель.Результат.Выгрузить();
При выполнении этого кода система выдает ошибку, связанную с языком запросов. Выясним причину. Объект ПостроительЗапроса предназначен для конструирования и выполнения запросов к базе данных. Даже если ему в качестве источника подставить табличный документ, его внутренний механизм все равно пытается построить SQL-подобный запрос. Поскольку текст запроса с ключевым словом ВЫБРАТЬ не был задан, построитель не может сформировать итоговую команду, что и приводит к ошибке.
Для таких задач следует использовать другой, более универсальный объект.
Правильным инструментом для преобразования табличных данных без написания запроса является ПостроительОтчета. Он более гибко работает с различными источниками данных, включая области табличного документа. Заменим в исходном коде всего один объект.
Рабочий пример кода:
// Создаем ТабличныйДокумент и читаем из файла
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать("C:\путь\к_файлу.mxl");
// Используем ПостроительОтчета
Построитель = Новый ПостроительОтчета;
// Указываем область с данными. Например, со строки 1, колонки 1 до конца таблицы по высоте и на 7 колонок в ширину
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, 7));
// Выполняем построение
Построитель.Выполнить();
// Выгружаем результат в ТаблицуЗначений
ТаблицаРезультат = Построитель.Результат.Выгрузить();
Этот код в большинстве случаев отработает корректно. Однако, существует важный нюанс, который может привести к ошибке даже с этим, казалось бы, верным решением.
Даже после замены объекта на ПостроительОтчета можно столкнуться с ошибкой. Самая частая причина — это структура исходного табличного документа.
Критически важный момент: для корректной работы этого метода первая строка указанной области табличного документа должна содержать заголовки колонок. Именно эти значения ПостроительОтчета использует для именования колонок в результирующей ТаблицеЗначений.
Рассмотрим частый случай. Если в вашем файле .mxl первые несколько строк пустые или содержат общую "шапку" документа, а сами заголовки таблицы начинаются, например, с 3-й или 4-й строки, то попытка считать область с первой строки ТабДок.Область(1, 1, ...) приведет к ошибке. Построитель не найдет имен для колонок и не сможет создать структуру таблицы значений.
Как исправить:
// Указываем, что данные начинаются с 4-й строки
НачальнаяСтрока = 4;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область(НачальнаяСтрока, 1, ТабДок.ВысотаТаблицы, 7));
Также стоит помнить о других особенностях:
ТаблицеЗначений, как правило, получают тип Строка. Если вам нужны числа или даты, потребуется дополнительный обход таблицы и преобразование типов.Если структура документа сложная или требуется полный контроль над процессом (например, для определения типов данных на лету), можно отказаться от построителей и реализовать загрузку через ручной перебор ячеек. Этот метод более трудоемкий, но и более надежный.
Пример реализации:
// Предполагаем, что ТабДок уже заполнен, а заголовки находятся в первой строке
ТаблицаРезультат = Новый ТаблицаЗначений;
// 1. Создаем колонки в ТаблицеЗначений на основе первой строки ТабДок
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
ИмяКолонки = СокрЛП(ТабДок.Область(1, НомерКолонки).Текст);
Если НЕ ПустаяСтрока(ИмяКолонки) Тогда
// Можно добавить логику для определения типа колонки
ТаблицаРезультат.Колонки.Добавить(ИмяКолонки);
КонецЕсли;
КонецЦикла;
// 2. Начинаем перебор со второй строки, так как первая - это заголовки
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
НоваяСтрока = ТаблицаРезультат.Добавить();
Для НомерКолонки = 1 По ТаблицаРезультат.Колонки.Количество() Цикл
// Получаем текст из ячейки и присваиваем значение
ЗначениеЯчейки = ТабДок.Область(НомерСтроки, НомерКолонки).Текст;
НоваяСтрока[НомерКолонки - 1] = ЗначениеЯчейки;
КонецЦикла;
КонецЦикла;
// Теперь в переменной ТаблицаРезультат находится заполненная таблица значений
Преимущества этого метода:
Недостаток:
ПостроителяОтчета.Таким образом, для быстрой и простой конвертации табличного документа в таблицу значений идеально подходит ПостроительОтчета, но при этом важно следить за тем, чтобы первая строка считываемой области содержала заголовки. Для более сложных и неструктурированных данных лучше использовать надежный метод ручного перебора ячеек.