С выходом платформы 1С:Предприятие 8.3.26 многие разработчики столкнулись с неожиданным поведением механизмов, которые годами работали стабильно. Одной из таких проблем стала некорректная выгрузка данных через ПостроительЗапроса при работе с ТабличнымДокументом, полученным из файлов Excel. Суть проблемы заключается в том, что дробные числа (например, 0,003) при попадании в Результат.Выгрузить() превращаются в целые числа (в данном примере — 3), полностью теряя дробную часть и разделитель.
В этой статье мы подробно разберем, почему это происходит, проанализируем изменения в новой платформе и рассмотрим несколько способов решения данной задачи.
Рассмотрим стандартный код, который использовался автором темы для получения данных из области табличного документа:
ЧитаемаяОбласть = ТаблДок.ПолучитьОбласть(Стр.Имя);
ПЗ = Новый ПостроительЗапроса;
ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ЧитаемаяОбласть.Область);
ПЗ.ЗаполнитьНастройки;
ТЗ = ПЗ.Результат.Выгрузить;
В версиях платформы до 8.3.26 этот механизм работал корректно: система автоматически распознавала тип данных в ячейках. Однако в 8.3.26 разработчики «1С» внесли существенные корректировки в логику работы механизмов локализации. Теперь ОписаниеИсточникаДанных более строго привязывается к региональным установкам сеанса. Если в ячейке в качестве разделителя используется запятая, а система (согласно внутренним или системным настройкам) ожидает точку, алгоритм парсинга может ошибочно игнорировать разделитель и интерпретировать строку как набор цифр, приводя 0,003 к 3.
Как выяснилось в ходе обсуждения, наиболее быстрым и действенным способом является приведение всех числовых данных в Excel (или непосредственно в ТабличномДокументе перед обработкой) к формату с точкой в качестве разделителя. Если в ячейке стоит значение 0.003 вместо 0,003, построитель запроса отрабатывает верно.
Мы можем автоматизировать этот процесс программно, пройдясь по ячейкам табличного документа перед тем, как передавать его в ОписаниеИсточникаДанных. Проанализируем пример кода для такой обработки:
// Проходим по всем значимым ячейкам области
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
ТекущаяОбласть = ТабДок.Область(НомерСтроки, НомерКолонки);
// Проверяем, содержит ли текст запятую
Если Найти(ТекущаяОбласть.Текст, ",") > 0 Тогда
// Заменяем запятую на точку для корректного парсинга в 8.3.26
ТекущаяОбласть.Текст = СтрЗаменить(ТекущаяОбласть.Текст, ",", ".");
КонецЕсли;
КонецЦикла;
КонецЦикла;
После выполнения такой замены ПостроительЗапроса увидит точку и корректно сформирует колонку с типом Число, сохранив точность до третьего знака после запятой.
В платформе 8.3.26 появились расширенные возможности управления локализацией. Выясним причину конфликта в настройках системы. Необходимо проверить следующие параметры в Конфигураторе:
Попробуйте установить разделитель явно или убедиться, что настройки Excel-файла соответствуют региональным стандартам сервера 1С.
При чтении файла Excel в ТабличныйДокумент рекомендуется явно указывать способ интерпретации значений. Рассмотрим метод Прочитать():
ТабДок = Новый ТабличныйДокумент;
// Используем явное указание способа чтения
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Текст);
Если мы используем параметр СпособЧтенияЗначенийТабличногоДокумента.Значение, платформа пытается самостоятельно определить тип данных Excel. В версии 8.3.26 этот механизм может работать нестабильно. Выбрав Текст, мы получаем строковое представление, которое затем можем обработать программно (заменив разделители), прежде чем передавать в ПостроительЗапроса.
Если работа через ПостроительЗапроса и ОписаниеИсточникаДанных остается нестабильной, рассмотрим вариант прямого чтения данных через COM-объект. Этот метод не зависит от внутренних механизмов типизации ТабличногоДокумента 1С и позволяет более гибко управлять процессом получения данных.
Попытка
ExcelПриложение = Новый COMОбъект("Excel.Application");
Книга = ExcelПриложение.Workbooks.Open(ПутьКФайлу);
Лист = Книга.Sheets(1);
// Прямое чтение значения ячейки
Значение = Лист.Cells(НомерСтроки, НомерКолонки).Value;
Книга.Close(Ложь);
ExcelПриложение.Quit();
Исключение
// Обработка ошибок работы с COM
КонецПопытки;
Хотя автор вопроса отметил, что этот вариант ему менее интересен, он является наиболее надежным «обходным путем», когда штатные механизмы новой платформы содержат ошибки (баги), которые еще не исправлены в текущем релизе (патче).
Подводя итог, можно сказать, что проблема в 8.3.26 носит системный характер и связана с ужесточением правил приведения типов в зависимости от локали. Для исправления ситуации выполним следующие шаги:
"," на "." в тексте ячеек перед созданием ОписаниеИсточникаДанных.Использование ПостроителяЗапроса для парсинга Excel-файлов — это мощный и удобный инструмент, так как он позволяет сразу получить готовую ТаблицуЗначений с типизированными колонками, но в новых версиях платформы он требует более внимательного отношения к региональным настройкам данных.