Заполнение документа Установка цен номенклатуры в конфигурациях на обычных формах (например, Управление торговлей 10.3) — это классическая задача, которая часто ставит в тупик даже опытных разработчиков. Основная сложность заключается в том, что интерфейс документа не отображает напрямую физические табличные части. Вместо этого используется динамически строящаяся «сводная таблица». В этой статье мы разберем по шагам, как правильно реализовать загрузку данных из Excel, чтобы они не только попали в базу, но и корректно отобразились у пользователя.
Первое, что мы должны понять: документ Установка цен номенклатуры хранит данные в двух табличных частях — Товары и ТипыЦен. Однако на форме документа пользователь видит реквизит формы (обычно с именем ТаблицаЦен), который программно заполняется при открытии формы на основании данных из этих двух ТЧ. Это сделано для того, чтобы представить цены в виде удобной сетки (кросс-таблицы).
Если мы просто заполним табличную часть Товары через внешнюю обработку заполнения, форма об этом «не узнает». Она продолжит показывать старое содержимое своего внутреннего реквизита. Чтобы решить эту задачу, нам необходимо не только правильно заполнить объектные данные, но и инициировать обновление интерфейса.
Начнем с классического метода через COM-соединение. Рассмотрим процедуру инициализации, которая будет выполняться в контексте внешней обработки заполнения табличных частей.
Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПоле) Экспорт
ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогВыбора.Заголовок = "Выберите файл Excel";
ДиалогВыбора.Фильтр = "Excel (*.xls;*.xlsx)|*.xls;*.xlsx";
Если Не ДиалогВыбора.Выбрать() Тогда
Возврат;
КонецЕсли;
ИмяФайла = ДиалогВыбора.ПолноеИмяФайла;
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.WorkBooks.Open(ИмяФайла);
Исключение
Сообщить("Не удалось открыть Excel! " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Работаем с первым листом
Лист = Excel.Sheets(1);
КонецПроцедуры
Проанализируем структуру заполнения. Чтобы документ корректно провелся и отобразил данные, нам нужно соблюдать следующие правила:
Товары будет создано несколько строк.Рассмотрим пример кода для обхода строк Excel и заполнения данных:
// Предположим, ТипЦенСсылка уже выбран пользователем или определен
ТабличнаяЧастьТовары = Объект.Товары;
ТабличнаяЧастьТипыЦен = Объект.ТипыЦен;
// Проверим, есть ли наш тип цен в документе
СтрокаТипа = ТабличнаяЧастьТипыЦен.Найти(ТипЦенСсылка, "ТипЦен");
Если СтрокаТипа = Неопределено Тогда
НоваяСтрокаТипа = ТабличнаяЧастьТипыЦен.Добавить();
НоваяСтрокаТипа.ТипЦен = ТипЦенСсылка;
КонецЕсли;
КоличествоСтрок = Лист.Cells(1,1).SpecialCells(11).Row;
Для НомерСтроки = 2 По КоличествоСтрок Цикл
Артикул = СокрЛП(Лист.Cells(НомерСтроки, 1).Text);
ЦенаЗначение = Лист.Cells(НомерСтроки, 2).Value; // Используем .Value для чисел
НоменклатураСсылка = Справочники.Номенклатура.НайтиПоКоду(Артикул);
Если Не НоменклатураСсылка.Пустая() Тогда
НоваяСтрока = ТабличнаяЧастьТовары.Добавить();
НоваяСтрока.Номенклатура = НоменклатураСсылка;
НоваяСтрока.ТипЦен = ТипЦенСсылка;
НоваяСтрока.Цена = Число(ЦенаЗначение);
// Важно: берем единицу хранения остатков у номенклатуры
НоваяСтрока.ЕдиницаИзмерения = НоменклатураСсылка.ЕдиницаХраненияОстатков;
НоваяСтрока.Валюта = ТипЦенСсылка.Валюта;
КонецЕсли;
КонецЦикла;
При получении данных из Excel мы часто сталкиваемся с тем, что числа воспринимаются как строки, а коды номенклатуры — как числа в экспоненциальной форме. Выясним, как этого избежать:
.Text. Это позволит получить строковое представление именно в том виде, в котором оно написано в ячейке, без лишних знаков после запятой..Value, но обязательно оборачивать результат в функцию Число(), предварительно очистив строку от неразрывных пробелов (символ 160), которые Excel часто добавляет как разделители разрядов.Если ПустаяСтрока(Артикул) Тогда Прервать; КонецЕсли;, чтобы цикл не бежал до конца листа Excel (65536 или 1048576 строк).Как мы уже выяснили, после работы обработки заполнения табличная часть объекта заполнена, но на экране пользователя ничего не изменилось. Выясним, как заставить форму «перерисоваться».
В обычных формах 1С (8.2/8.3) нет прямого метода «ОбновитьДанныеФормы» для серверного объекта. Однако есть несколько обходных путей:
Вариант А: Запись и переоткрытие. Это самый надежный метод. В конце вашей процедуры вы вызываете Объект.Записать(). После завершения работы обработки заполнения форма документа может быть переоткрыта. Однако это не всегда удобно для пользователя.
Вариант Б: Вызов экспортного метода формы. В типовой УТ 10.3 в модуле формы документа УстановкаЦенНоменклатуры есть процедура ЗаполнитьТабличнуюЧастьЦен(). Если ваша обработка вызывается из формы, вы можете попробовать достучаться до этого метода. Но так как стандартный механизм «Заполнение ТЧ» передает только объект, лучшим решением будет использование ОповеститьОбИзменении(Тип("ДокументОбъект.УстановкаЦенНоменклатуры")).
Вариант В: Создание собственной формы в обработке. Вместо использования стандартного механизма заполнения ТЧ (кнопка «Заполнить»), создайте у своей обработки форму. На этой форме пользователь выберет файл, увидит результат в таблице, и по кнопке «Перенести в документ» вы программно заполните ТЧ документа и, если нужно, принудительно перезаполните реквизит формы ТаблицаЦен через ЭтаФорма.ВладелецФормы.
Проанализировав ситуацию, мы видим, что успешная загрузка цен требует комплексного подхода. Недостаточно просто прочитать файл — нужно понимать внутреннюю структуру хранения данных в документе. Обязательно проверяйте связку Номенклатура — ТипЦен — ЕдиницаИзмерения. Только при наличии всех трех составляющих и корректно заполненной табличной части ТипыЦен ваш документ будет готов к проведению, а цены станут актуальными в системе.