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