Как правильно загрузить время из Excel в 1С, если вместо "ЧЧ:ММ" вы получаете число?

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

При работе с внешними данными, особенно при импорте информации из файлов Excel в систему 1С, разработчики часто сталкиваются с нестандартным поведением при попытке загрузить временные значения. Одной из наиболее распространенных проблем является ситуация, когда время, ожидаемое в формате "ЧЧ:ММ" (например, "9:00"), при считывании из ячейки Excel с помощью COM-объекта внезапно преобразуется в десятичное число (например, 0,375). Эта особенность Excel может поставить в тупик, но, как мы выясним, имеет вполне логичное объяснение и несколько эффективных решений.

Мы подробно рассмотрим, почему Excel так хранит и передает время, и предоставим несколько методов для его корректной загрузки в поля 1С с типом "Дата" и составом "Время".

Почему Excel возвращает число вместо времени?

Прежде чем углубляться в решения, давайте выясним причину такого поведения. Excel хранит даты и время как числовое значение. Полная дата представляет собой количество дней, прошедших с определенной базовой даты (обычно 1 января 1900 года). Время же хранится как доля суток. То есть, если 9:00 утра — это 9 часов из 24, то в десятичном представлении это будет 9/24 = 0,375. Если бы это было 12:00, то это было бы 12/24 = 0,5, и так далее. Это объясняет, почему вы получаете 0,375 вместо "9:00", когда пытаетесь прочитать значение ячейки Excel напрямую через свойство Value.

Итак, когда вы используете конструкцию типа Строка(Лист.Cells(сч, 3).Value), вы фактически запрашиваете числовое значение ячейки и затем пытаетесь преобразовать его в строку, что приводит к получению строкового представления этого числа ("0,375"). Наша задача — либо получить время в его строковом виде сразу, либо правильно преобразовать числовое представление.

Метод 1: Чтение значения ячейки Excel как текста (.Text)

Наиболее простой и часто рекомендуемый способ решить эту проблему — это считывать значение ячейки Excel не как число (.Value), а как текст (.Text). Если ячейка в Excel отформатирована как время (например, "ЧЧ:ММ"), то при чтении ее свойства Text вы получите строковое представление времени точно так, как оно отображается в Excel.

  1. Получаем строковое представление времени: Мы используем свойство .Text для прямого чтения отформатированного значения ячейки.
  2. Разбираем строку: Полученная строка (например, "9:00" или "09:00") легко разделяется на часы и минуты по символу двоеточия.
  3. Преобразуем в числовые значения: Каждую часть (часы и минуты) мы преобразуем в число.
  4. Создаем объект "Дата" в 1С: Используем функцию Дата(), указав минимальные значения для года, месяца и дня (например, 1, 1, 1), так как для полей с типом "Время" в 1С важна только временная часть.

Давайте посмотрим на пример кода, который демонстрирует этот подход:


// Предположим, что "Лист" - это COM-объект листа Excel
// и "сч" - это текущий номер строки.
// В данном примере мы считываем значение из 3-й колонки.

// 1. Получаем строковое представление времени из ячейки Excel
ЗначениеЯчейкиСтрока = Лист.Cells(сч, 3).Text; // Например, получаем "9:00" или "09:00"

// 2. Проверяем, что строка не пустая, чтобы избежать ошибок
Если ЗначениеЯчейкиСтрока <> "" Тогда

    // 3. Разделяем строку по символу двоеточия для получения часов и минут
    МассивЧастейВремени = СтрРазделить(ЗначениеЯчейкиСтрока, ":");

    // 4. Проверяем, что получили две части (часы и минуты)
    Если МассивЧастейВремени.Количество() = 2 Тогда

        // 5. Преобразуем строковые части в числа
        Часы = Число(МассивЧастейВремени[0]);
        Минуты = Число(МассивЧастейВремени[1]);
        
        // 6. Создаем значение типа "Дата" в 1С, указывая только время
        // Год, месяц и день устанавливаем на минимальные значения, так как нам нужна только временная часть.
        ВремяДля1С = Дата(1, 1, 1, Часы, Минуты, 0); // Результат: Дата, например, 01.01.0001 9:00:00

        // Теперь переменная ВремяДля1С содержит корректное значение времени,
        // которое можно присвоить полю в таблице 1С.
        Сообщить("Успешно загружено время: " + ВремяДля1С);

    Иначе
        // Обработка ситуации, если формат строки некорректен (например, "9" или "9:00:00")
        Сообщить("Ошибка: Некорректный формат времени в ячейке '" + ЗначениеЯчейкиСтрока + "'. Ожидался 'Ч:ММ' или 'ЧЧ:ММ'.");
    КонецЕсли;

Иначе
    Сообщить("Предупреждение: Ячейка со временем пуста.");
КонецЕсли;

Этот метод является предпочтительным, поскольку он полагается на то, как Excel отображает данные, что часто соответствует нашим ожиданиям.

Метод 2: Преобразование числового значения Excel во время 1С

В некоторых случаях, возможно, вы уже получили числовое значение из Excel (например, через .Value), или по какой-то причине ячейка не отформатирована как время, и .Text возвращает то же число. В такой ситуации нам потребуется выполнить математические преобразования, чтобы получить часы, минуты и секунды из доли суток.

Мы выяснили, что Excel хранит время как долю дня. В одном дне ровно 24 часа, или 86400 секунд (24 * 60 * 60). Следовательно, чтобы получить общее количество секунд, прошедших от начала суток, нам нужно умножить числовое значение из Excel на 86400.

  1. Получаем числовое значение: Мы считываем значение ячейки через свойство .Value.
  2. Вычисляем общее количество секунд: Умножаем полученное число на 86400.
  3. Выделяем часы, минуты и секунды: Используем целочисленное деление и операцию взятия остатка (модуль) для извлечения отдельных компонентов времени.
  4. Создаем объект "Дата" в 1С: Аналогично предыдущему методу, используем функцию Дата() с минимальными значениями даты.

Рассмотрим пример кода для этого метода:


// Предположим, что "Лист" - это COM-объект листа Excel
// и "сч" - это текущий номер строки.
// В данном примере мы считываем значение из 3-й колонки.

// 1. Получаем числовое значение времени из ячейки Excel
ЗначениеЯчейкиЧисло = Лист.Cells(сч, 3).Value; // Например, получаем 0.375

// 2. Проверяем, что полученное значение является числом
Если ТипЗнч(ЗначениеЯчейкиЧисло) = Тип("Число") Тогда

    // 3. Вычисляем общее количество секунд от начала суток
    // Умножаем долю суток на общее количество секунд в сутках (24 * 60 * 60 = 86400)
    ОбщееКоличествоСекунд = Цел(ЗначениеЯчейкиЧисло * 86400); // 0.375 * 86400 = 32400 секунд

    // 4. Выделяем часы: общее количество секунд / количество секунд в часе (3600)
    Часы = Цел(ОбщееКоличествоСекунд / 3600); // 32400 / 3600 = 9

    // 5. Выделяем минуты: остаток от деления на 3600, затем делим на количество секунд в минуте (60)
    Минуты = Цел((ОбщееКоличествоСекунд % 3600) / 60); // (32400 % 3600 = 0) / 60 = 0

    // 6. Выделяем секунды: остаток от деления на 60
    Секунды = ОбщееКоличествоСекунд % 60; // 0 % 60 = 0

    // 7. Создаем значение типа "Дата" в 1С, указывая вычисленные часы, минуты и секунды
    ВремяДля1С = Дата(1, 1, 1, Часы, Минуты, Секунды); // Результат: Дата, например, 01.01.0001 9:00:00

    Сообщить("Успешно загружено время: " + ВремяДля1С);

Иначе
    Сообщить("Ошибка: Значение в ячейке не является числом или пустым.");
КонецЕсли;

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

Метод 3: Использование "Табличного документа" 1С для загрузки данных из Excel

Хотя прямое взаимодействие с COM-объектами Excel через Лист.Cells(...) является рабочим решением, в разработке на платформе 1С зачастую более надежным и производительным подходом является использование встроенного объекта "Табличный документ" 1С (ТабличныйДокумент). Этот метод особенно актуален в клиент-серверном режиме, где прямой доступ к COM-объектам на сервере может быть ограничен или вообще невозможен.

Объект ТабличныйДокумент в 1С предоставляет удобные функции для чтения данных из файлов Excel с помощью метода Прочитать(). При чтении через "Табличный документ" система 1С часто уже сама пытается интерпретировать и форматировать значения ячеек. Это означает, что если ячейка в Excel содержит время и отформатирована соответствующим образом, то при чтении ее значения через ТабличныйДокумент.Область(Строка, Колонка).Значение или ТабличныйДокумент.Область(Строка, Колонка).Текст, вы с высокой вероятностью получите уже корректное строковое или даже датовое представление времени.

  1. Создаем объект "Табличный документ": Инициализируем новый экземпляр ТабличныйДокумент.
  2. Загружаем данные из Excel: Используем метод Прочитать(), указывая путь к файлу Excel.
  3. Считываем значения: После загрузки мы можем обращаться к ячейкам как к областям табличного документа и получать их значения или текстовое представление.
  4. Обрабатываем полученные значения: В зависимости от того, что возвращает .Значение или .Текст, мы применяем один из вышеописанных методов (либо парсим строку, либо преобразуем число).

Вот как может выглядеть упрощенный пример использования "Табличного документа":


// 1. Создаем новый объект "ТабличныйДокумент"
ТабДок = Новый ТабличныйДокумент;

// 2. Указываем путь к файлу Excel, который нужно загрузить
ПутьКФайлуExcel = "C:\МоиДокументы\ВремяРаботы.xlsx"; // Замените на фактический путь

Попытка
    // 3. Загружаем данные из файла Excel
    ТабДок.Прочитать(ПутьКФайлуExcel);

    // Предположим, время находится в колонке 3, начиная со строки 2
    Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл

        // 4. Считываем значение ячейки. Часто ТабличныйДокумент уже предоставляет текст.
        // Мы можем попробовать получить как текст, так и значение.
        ЗначениеЯчейки = ТабДок.Область(НомерСтроки, 3).Значение; // Попробуем получить значение напрямую
        ТекстЯчейки = ТабДок.Область(НомерСтроки, 3).Текст;       // Если Значение не подошло, берем текст

        ВремяДля1С = Неопределено;

        // Если Значение уже вернуло Дату/Время (иногда бывает)
        Если ТипЗнч(ЗначениеЯчейки) = Тип("Дата") Тогда
            ВремяДля1С = ЗначениеЯчейки;
            Сообщить("Время загружено как Дата (ТабличныйДокумент.Значение): " + ВремяДля1С);

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

        // Если Значение не подошло, но Текст содержит "ЧЧ:ММ"
        ИначеЕсли ТекстЯчейки <> "" И СтрНайти(ТекстЯчейки, ":") > 0 Тогда
            // Применяем метод 1 для парсинга строки
            МассивЧастейВремени = СтрРазделить(ТекстЯчейки, ":");
            Если МассивЧастейВремени.Количество() = 2 Тогда
                Часы = Число(МассивЧастейВремени[0]);
                Минуты = Число(МассивЧастейВремени[1]);
                ВремяДля1С = Дата(1, 1, 1, Часы, Минуты, 0);
                Сообщить("Время загружено как Строка (ТабличныйДокумент.Текст), преобразовано: " + ВремяДля1С);
            Иначе
                Сообщить("Ошибка обработки времени в строке " + НомерСтроки + ": Некорректный текстовый формат '" + ТекстЯчейки + "'");
            КонецЕсли;

        Иначе
            Сообщить("Предупреждение в строке " + НомерСтроки + ": Не удалось определить формат времени для значения '" + Строка(ЗначениеЯчейки) + "' / текста '" + ТекстЯчейки + "'");
        КонецЕсли;

        // Здесь вы можете использовать ВремяДля1С для записи в вашу таблицу 1С
        // Например: НоваяСтрокаТаблицы.ПолеВремя = ВремяДля1С;

    КонецЦикла;

Исключение
    Сообщить("Ошибка при чтении файла Excel: " + ОписаниеОшибки());
КонецПопытки;

Мы видим, что использование "Табличного документа" позволяет унифицировать процесс загрузки и, в зависимости от того, как 1С интерпретирует данные, применить соответствующий метод преобразования.

Выводы и рекомендации

Как мы проанализировали, проблема загрузки времени из Excel в 1С, когда Excel возвращает десятичное число, имеет четкое объяснение в способе хранения времени в Excel. Мы рассмотрели три основных подхода к решению этой задачи:

  1. Прямое чтение текстового значения (.Text): Это наиболее простой и предпочтительный метод, когда ячейка Excel отформатирована как время. Он позволяет получить строковое представление "ЧЧ:ММ" и затем легко разобрать его.
  2. Преобразование числового значения (.Value): Если вы получаете числовое значение (долю суток), этот метод позволяет точно вычислить часы, минуты и секунды и создать объект "Дата" в 1С.
  3. Использование "Табличного документа" 1С: Этот подход является более универсальным и рекомендованным для работы с файлами Excel, так как он обеспечивает большую стабильность и гибкость, а также позволяет системе 1С самостоятельно интерпретировать некоторые данные, сокращая объем ручной обработки.

Выбирая метод, всегда начинайте с попытки получить текстовое представление, если это возможно. Если нет, или если вы имеете дело с неформатированными числовыми значениями, используйте математическое преобразование. Для масштабных или регулярных загрузок отдавайте предпочтение "Табличному документу" 1С. Эти подходы помогут вам успешно загружать временные значения из Excel и корректно отображать их в вашей базе 1С.

← На главную