Нередко при разработке процедур импорта данных из внешних источников возникает странное поведение системы: документ успешно создается, реквизиты заполняются, документ проводится без ошибок, а в физической таблице регистра присутствуют активные движения. Однако при формировании отчета на СКД или выполнении запроса к виртуальной таблице оборотов данные за указанный период отсутствуют. В то же время, если перепровести или вручную создать точно такой же документ в пользовательском режиме, отчет сразу видит все обороты. Разберем детально, почему это происходит и как устранить данную ошибку.
Рассмотрим типовой сценарий, в котором создается документ и формируются его проводки:
ТекДок = Документы.ПутевойЛист.СоздатьДокумент();
// Заполнение реквизитов документа из файла
ТекДок.Дата = ДатаИзФайла;
ТекДок.Организация = ВыбраннаяОрганизация;
ТекДок.Записать(РежимЗаписиДокумента.Проведение);
В модуле объекта при этом определена стандартная обработка проведения:
Движения.Износ.Записывать = Истина;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Движение = Движения.Износ.Добавить();
Движение.Период = Дата;
Движение.СерияНоменклатуры = ВыборкаДетальныеЗаписи.Агрегат;
Движение.Организация = Организация;
Движение.ТранспортноеСредство = ВыборкаДетальныеЗаписи.ТС;
Движение.Пробег = СпидометрВозвращения - СпидометрВыезда;
КонецЦикла;
Если открыть форму списка регистра или просмотреть движения через меню «Перейти», записи присутствуют, признак активности установлен в Истина. Но виртуальная таблица РегистрНакопления.Износ.Обороты возвращает пустой результат.
Выясним причину такого поведения. В файле Excel дата часто хранится в кратком формате с двухзначным обозначением года, например 01.06.17. При чтении текстового представления ячейки платформа 1С:Предприятие преобразует такое значение буквально: 17-й год первого века нашей эры (01.06.0017 00:00:00). Визуально в стандартных интерфейсных формах при формате отображения даты без четырех цифр года запись может выглядеть вполне нормально, однако в базе данных период записи равен 0017 году. В отчете же пользователь задает период за 2017 год, куда движения первого века заведомо не попадают.
Проанализируем, почему движения видны в списке регистра, но скрыты в отчетах. В платформе 1С:Предприятие для регистров накопления существуют два типа таблиц:
Период, Регистратор, НомерСтроки, Активность. Если открыть эту таблицу или построить к ней простой запрос без фильтра по дате, движения будут отображаться.(Период, Период). Если дата движения ушла в 0017 год, виртуальная таблица оставит эти записи за пределами интервала отчета.Разберем по шагам, как предотвратить искажение года при загрузке данных.
Способ 1. Использование свойства Value вместо Text при работе через COM-объект
При использовании COM-соединения с Excel (COMОбъект("Excel.Application")) обращение к свойству Ячейка.Text возвращает строку, отформатированную согласно настройкам листа. Вместо этого необходимо считывать свойство Ячейка.Value. Оно возвращает типизированное значение даты (тип OLE Date), которое автоматически транслируется платформой 1С в тип Дата с четырехзначным годом.
Способ 2. Программная нормализация двухзначного года
Если дата считывается в виде строки или разбирается вручную, реализуем функцию проверки и корректировки столетия. Посмотрим на пример такой функции:
Функция НормализоватьДату(ИсходнаяДата)
Год = Год(ИсходнаяДата);
Если Год < 100 Тогда
// Если год задан двумя цифрами, корректируем его в 2000-е года
СкорректированныйГод = ?(Год < 50, 2000 + Год, 1900 + Год);
Возврат Дата(СкорректированныйГод, Месяц(ИсходнаяДата), День(ИсходнаяДата),
Час(ИсходнаяДата), Минута(ИсходнаяДата), Секунда(ИсходнаяДата));
КонецЕсли;
Возврат ИсходнаяДата;
КонецФункции
Способ 3. Использование встроенного объекта ТабличныйДокумент
Для прямого чтения файлов XLSX на стороне сервера без использования внешних COM-библиотек рекомендуется применять встроенный механизм платформы:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
ЗначениеЯчейки = ТабДок.ПолучитьОбласть(НомерСтроки, 1).ТекущаяОбласть.Текст;
// Либо обращение к типизированному значению области
КонецЦикла;
Если созданный документ проведен, но обороты не отображаются, выполним следующие шаги диагностики:
Формат(ТекДок.Дата, "ДФ=dd.MM.yyyy HH:mm:ss"). Это позволит сразу выявить 0017 год.Активность в записях регистра равно Истина. Неактивные записи исключаются из подсчета оборотов и остатков.ТипЗнч() проверим, что в измерения записаны именно ссылки СправочникСсылка, а не примитивные строки из файла.
ТекДок.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
Применение этих правил гарантирует, что созданные программно документы будут корректно регистрировать движения, а отчеты на базе СКД и запросов отразят правильные обороты за нужный расчетный период.