При формировании отчетов или выгрузке данных из 1С в формат Excel разработчики часто сталкиваются с неприятной особенностью: лидирующие нули в таких строках, как ИНН, КПП или артикулы, бесследно исчезают. Например, значение 071111111111 превращается в число 71111111111. Это происходит потому, что Excel по умолчанию интерпретирует последовательность цифр как число и применяет к нему свои правила форматирования.
В старых релизах платформы (до 8.3.14) проблему часто решали добавлением апострофа (') перед значением, но в современных версиях (8.3.20, 8.3.21 и выше) механизмы формирования файлов .xlsx изменились, и старые «костыли» перестали работать или начали отображаться в самом файле. Рассмотрим подробнее, как победить эту проблему нативными средствами 1С.
Когда мы вызываем метод Записать() у табличного документа, платформа 1С формирует структуру файла XLSX (OpenXML). Если в макете для ячейки не задан строгий тип данных, 1С помечает ее как «Общий» (General). При открытии такого файла Excel анализирует содержимое: если он видит только цифры, он автоматически конвертирует ячейку в числовой формат. Число не может начинаться с нуля, поэтому он удаляется.
Проанализируем ситуацию: простое визуальное выравнивание в 1С (прижать влево) никак не влияет на тип данных в итоговом файле. Нам нужно явно передать информацию о том, что данное значение является строкой, а не числом.
Разберем по шагам, как настроить ячейку макета так, чтобы платформа принудительно записывала ее как текст. Это решение позволяет избежать использования тяжеловесных COM-объектов и установки Microsoft Office на сервере.
Истина.Строка. Здесь же можно ограничить длину строки, если это необходимо.Переносить или Авто, но критически важно, чтобы тип данных был зафиксирован.Теперь, когда мы будем заполнять этот параметр, платформа 1С запишет в XML-структуру файла Excel специальный тег t="s" (string). Увидев его, Excel даже не попытается преобразовать данные в число.
Иногда простого заполнения через Параметры недостаточно, особенно если вы используете метод ЗаполнитьЗначенияСвойств(), который может затирать настройки типов. В таких случаях стоит обратиться к свойству Значение конкретной области. Рассмотрим пример кода:
// Получаем область из макета
ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаДанных");
// Вместо заполнения через параметр, обращаемся к конкретной ячейке области по имени
// Предположим, ячейка с ИНН называется "ОбластьИНН"
ЯчейкаИНН = ОбластьСтрока.Область("ОбластьИНН");
// Устанавливаем тип и значение программно
ЯчейкаИНН.СодержитЗначение = Истина;
ЯчейкаИНН.ТипЗначения = Новый ОписаниеТипов("Строка");
ЯчейкаИНН.Значение = Строка(ДанныеСтроки.ИНН);
// Выводим область в результирующий табличный документ
ТабДок.Вывести(ОбластьСтрока);
Обратите внимание: мы используем ЯчейкаИНН.Значение вместо ЯчейкаИНН.Текст. Это принципиальный момент для корректного экспорта в XLSX.
Если ваш макет заполняется динамически и настройки «сбиваются», можно воспользоваться методом «сборки» строки из разных областей. Посмотрим на ситуацию, когда ИНН выводится отдельным блоком:
Для Каждого СтрокаДанных Из РезультатЗапроса Цикл
// Выводим основную часть строки (до ИНН)
ОбластьЛево = Макет.ПолучитьОбласть("Строка|Лево");
ТабДок.Вывести(ОбластьЛево);
// Выводим ячейку с ИНН с жестким типом
ОбластьИНН = Макет.ПолучитьОбласть("Строка|ЦентрИНН");
Если ОбластьИНН.ТекущаяОбласть.СодержитЗначение Тогда
// Присваиваем значение параметру, зная, что тип в макете уже "Строка"
ОбластьИНН.Параметры.ИНН = Строка(СтрокаДанных.ИНН);
КонецЕсли;
ТабДок.Присоединить(ОбластьИНН);
// Выводим остаток строки
ОбластьПраво = Макет.ПолучитьОбласть("Строка|Право");
ТабДок.Присоединить(ОбластьПраво);
КонецЦикла;
Если по каким-то причинам изменить макет невозможно, можно использовать «хитрость» с символом неразрывного пробела. В отличие от обычного пробела, он часто заставляет Excel считать всю ячейку текстовой, не меняя при этом визуальную длину строки (если пробел в конце).
// Символ(160) - это неразрывный пробел
// Добавляем его в конец значения
Область.Параметры.ИНН = Строка(Данные.ИНН) + Символ(160);
Однако стоит помнить, что при попытке дальнейшей обработки этого файла (например, загрузки в другую систему), этот невидимый символ может помешать поиску или валидации данных. Поэтому Решение 1 остается приоритетным.
Часто в обсуждениях советуют использовать Новый COMОбъект("Excel.Application"). Проанализируем, почему это плохой совет для современной разработки:
Записать().Использование свойств СодержитЗначение и ТипЗначения в самом макете 1С является «чистым» и наиболее эффективным способом решения проблемы лидирующих нулей, который поддерживается платформой на уровне формирования файлов OpenXML.