Как программно заполнить дату в 1С при загрузке из Excel

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

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

Анализ проблемы: почему дата остается пустой или возникает ошибка

Разберем типичную ситуацию: вы читаете файл Excel, используя объект ТабличныйДокумент или COM-соединение, и пытаетесь записать значение в реквизит документа с типом Дата. Если вы используете свойство ТекущаяОбласть.Текст, то 1С получает строковое представление (например, "01.05.2023").

Проблема заключается в том, что тип данных Строка и тип данных Дата в 1С — это разные сущности. 1С не всегда может автоматически преобразовать строку в дату, особенно если формат строки не соответствует внутреннему стандарту (ГГГГММДДЧЧММСС). Если в табличной части вашей обработки колонка имеет тип Дата, а вы пытаетесь записать туда строку, значение просто не примется и останется пустым. Если же колонка строковая, то при попытке записать эту строку в реальный документ 1С выдаст ошибку "Поле 'Дата' не может быть пустым", так как объект документа ожидает именно дату.

Способ 1: Использование стандартного конструктора Дата()

Самый быстрый способ — это явное преобразование строки в дату с помощью встроенной функции 1С. Однако важно помнить, что функция Дата() ожидает строку в определенном формате или наличие времени. Проанализируем пример, предложенный в обсуждении:


// Предположим, в переменной ТекстИзЭксель содержится "25.12.2022"
СтрокаДанных.Дата = Дата(ТабДок.ПолучитьОбласть("R" + НомерСтроки + "C1").ТекущаяОбласть.Текст + " 00:00:00");

Добавляя " 00:00:00", мы помогаем платформе распознать строку как дату. Рассмотрим, как это выглядит в контексте цикла обхода строк Excel:


Для НомерСтроки = 2 По КоличествоСтрок Цикл
    СтрокаДанных = Объект.ДанныеФайла.Добавить();
    
    // Получаем текст из ячейки и преобразуем его
    СчитанныйТекст = ТабДок.ПолучитьОбласть("R" + Формат(НомерСтроки, "ЧГ=0") + "C" + 1).ТекущаяОбласть.Текст;
    
    Попытка
        СтрокаДанных.Дата = Дата(СчитанныйТекст + " 00:00:00");
    Исключение
        Сообщить("В строке " + НомерСтроки + " некорректный формат даты!");
        СтрокаДанных.Дата = '00010101'; // Пустая дата
    КонецПопытки;
    
    СтрокаДанных.НомерТТН = ТабДок.ПолучитьОбласть("R" + Формат(НомерСтроки, "ЧГ=0") + "C" + 2).ТекущаяОбласть.Текст;
    СтрокаДанных.Сумма = ТабДок.ПолучитьОбласть("R" + Формат(НомерСтроки, "ЧГ=0") + "C" + 3).ТекущаяОбласть.Текст;
КонецЦикла;

Важный нюанс: использование свойства ТекущаяОбласть.Текст возвращает строку именно в том виде, в котором она отображается в Excel. Если в Excel настроен формат ячейки "01-Май-23", конструктор Дата() выдаст ошибку. В таких случаях лучше использовать ТекущаяОбласть.Значение.

Способ 2: Использование свойства Значение

Если файл Excel читается через ТабличныйДокумент, мы можем попробовать получить значение сразу в типе Дата, минуя строковые преобразования. Платформа 1С при чтении файла пытается сопоставить типы ячеек Excel с типами 1С.

Рассмотрим вариант кода с использованием свойства Значение:


// Вместо .Текст используем .Значение
ЗначениеЯчейки = ТабДок.ПолучитьОбласть("R" + НомерСтроки + "C1").ТекущаяОбласть.Значение;

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

Способ 3: Универсальная функция разбора даты (Парсинг)

Иногда дата в файле может приходить в самых разных форматах: с разделителями точками, слешами или дефисами. Для таких случаев разработаем и проанализируем функцию, которая "вытаскивает" числа из строки и собирает из них дату.

Рассмотрим пример функции, которая справляется со сложными случаями:


Функция ПреобразоватьВДату(ИсхСтр)
    Стр = СокрЛП(ИсхСтр);
    // Ищем разделители
    МассивЧастей = СтрРазделить(Стр, ".,/-", Ложь);
    
    Если МассивЧастей.Количество() < 3 Тогда
        Возврат '00010101'; // Недостаточно данных для даты
    КонецЕсли;
    
    // Извлекаем день, месяц, год (предполагаем формат ДД ММ ГГГГ)
    День  = Число(МассивЧастей[0]);
    Месяц = Число(МассивЧастей[1]);
    Год   = Число(МассивЧастей[2]);
    
    // Обработка двухзначного года (например, 23 -> 2023)
    Если Год < 100 Тогда
        Год = 2000 + Год;
    КонецЕсли;
    
    Попытка
        Возврат Дата(Год, Месяц, День);
    Исключение
        Возврат '00010101';
    КонецПопытки;
КонецФункции

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

Способ 4: Особенности загрузки через COM-соединение

Если вы используете Excel.Application для чтения файла, помните, что Excel хранит даты как числа (количество дней с начала прошлого века). Выясним, как правильно обработать такое значение. Если 1С получает число (например, 44927), его нужно конвертировать следующим образом:


// Формула преобразования числа Excel в дату 1С
ЧислоИзExcel = ExcelЯчейка.Value;
Дата1С = Дата(1899, 12, 30) + (ЧислоИзExcel * 86400);

Здесь 86400 — это количество секунд в сутках. Это знание поможет вам, если стандартные методы 1С по какой-то причине не распознают формат ячейки Excel.

Рекомендации для начинающих разработчиков

Чтобы ваша загрузка работала стабильно, придерживайтесь следующих правил:

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

Проанализировав все способы, мы видим, что наиболее надежным методом для начинающего является сочетание получения значения ячейки и резервного преобразования через очищенную строку с добавлением времени. Это гарантирует, что ваш документ "Поступление товаров" всегда будет иметь корректно заполненную дату.

← На главную