Почему при загрузке из Excel время переходит в 12-часовой формат и как это исправить в 1С?

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

При импорте данных из файлов Microsoft Excel в 1С с помощью объекта ТабличныйДокумент разработчики нередко сталкиваются с ситуацией, когда время 24-часового формата (например, 13:57:12 или 19:28:18) после чтения превращается в 12-часовое значение (1:57:12 или 07:28:18). В результате теряется признак второй половины дня, что приводит к некорректной записи дат и документов.

Разберем подробнее, почему возникает такое поведение платформы, и рассмотрим проверенные способы корректного считывания времени.

Рассмотрим типовой фрагмент кода, в котором проявляется проблема:


ТабДокумент = Новый ТабличныйДокумент();
Попытка
    ТабДокумент.Прочитать(тмпИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
    ВызватьИсключение "Ошибка открытия файла Excel";
КонецПопытки;

ВсегоКолонок = ТабДокумент.ШиринаТаблицы;
ВсегоСтрок = ТабДокумент.ВысотаТаблицы;

Для НомерСтроки = 1 По ВсегоСтрок Цикл
    Для НомерКолонки = 1 По ВсегоКолонок Цикл
        // Ошибка возникает здесь: читается свойство Текст
        ЗначениеЯчейки = ТабДокумент.Область(НомерСтроки, НомерКолонки).Текст;
    КонецЦикла;
КонецЦикла;

Выясним причину ошибки. При использовании режима СпособЧтенияЗначенийТабличногоДокумента.Значение платформа считывает само типизированное значение в свойство Область.Значение, а в свойство Область.Формат переносит визуальную маску отображения ячейки из Excel. В файлах Excel для времени часто используется шаблон с двенадцатичасовым представлением (hh:mm:ss). Когда код обращается к свойству Область.Текст, 1С накладывает эту маску, из-за чего значение визуально обрезается до 12 часов.

Способ 1. Получение типизированного значения ячейки вместо текста

Проанализируем самый правильный и надежный способ. Если файл прочитан в режиме значений, необходимо обращаться напрямую к свойству Значение области ячейки, а затем при необходимости самостоятельно форматировать полученную дату с использованием заглавных букв ЧЧ (24-часовой формат):


Для НомерСтроки = 1 По ВсегоСтрок Цикл
    Для НомерКолонки = 1 По ВсегоКолонок Цикл
        Ячейка = ТабДокумент.Область(НомерСтроки, НомерКолонки);
        
        Если Ячейка.СодержитЗначение И ЗначениеЗаполнено(Ячейка.Значение) Тогда
            Если ТипЗнч(Ячейка.Значение) = Тип("Дата") Тогда
                // Форматируем дату в 24-часовой формат
                ТекстВремени = Формат(Ячейка.Значение, "ДФ=""дд.ММ.гггг ЧЧ:мм:сс""");
                ЗначениеДляЗаписи = Ячейка.Значение;
            Иначе
                ЗначениеДляЗаписи = Ячейка.Значение;
            КонецЕсли;
        Иначе
            ЗначениеДляЗаписи = СокрЛП(Ячейка.Текст);
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Способ 2. Очистка формата ячеек табличного документа

Если алгоритм построен на чтении свойства Область.Текст и переписывать логику нежелательно, можно сбросить навязанный Excel формат для всей таблицы сразу после загрузки файла:


ТабДокумент = Новый ТабличныйДокумент();
ТабДокумент.Прочитать(тмпИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);

// Сбрасываем форматирование для всех ячеек документа
ТабДокумент.Область().Формат = "";

// Теперь свойство Текст будет возвращать стандартное системное представление
Для НомерСтроки = 1 По ВсегоСтрок Цикл
    ЗначениеЯчейки = ТабДокумент.Область(НомерСтроки, 1).Текст;
КонецЦикла;

Способ 3. Переключение способа чтения на текстовый режим

Посмотрим на вариант, когда файл считывается как чистый текст без разбора внутренних типов Excel:


ТабДокумент = Новый ТабличныйДокумент();
ТабДокумент.Прочитать(тмпИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Текст);

В этом режиме платформа не пытается интерпретировать ячейки как типизированные объекты и читает строки ровно в том виде, как они отображаются в оригинальном файле.

Способ 4. Математический пересчет времени из числового формата

В ряде случаев ячейка со временем без даты может считываться в 1С как дробное число (в Excel время хранится как доля суток от 0 до 1, где 1 час равен 1/24). Разберем, как преобразовать такое число в корректную дату:


Если ТипЗнч(ЗначениеЯчейки) = Тип("Число") Тогда
    // Переводим долю суток в секунды (86400 секунд в сутках)
    ВсегоСекунд = Окр(ЗначениеЯчейки * 86400);
    
    // Получаем результирующее время
    ИтоговаяДата = Дата(1, 1, 1) + ВсегоСекунд;
    СтрокаВремени = Формат(ИтоговаяДата, "ДФ=ЧЧ:мм:сс");
КонецЕсли;

Способ 5. Быстрая загрузка через ПостроительЗапроса

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


ТабДокумент = Новый ТабличныйДокумент();
ТабДокумент.Прочитать(тмпИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);

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

ТаблицаДанных = Построитель.Результат.Выгрузить();

Полученная таблица значений будет содержать исходные значения без искажения масками строкового форматирования.

← На главную