Мы часто сталкиваемся с задачей, когда необходимо получить данные из внешнего источника, например, файла Excel или результата запроса, отобразить их пользователю для выбора, а затем перенести выбранные данные в табличную часть документа. В этой статье мы подробно разберем, как реализовать этот функционал в 1С:Предприятии 8, уделив особое внимание типичным проблемам, таким как преобразование типов данных, в частности, для ссылочных полей вроде "Номенклатура".
Для начала нам необходимо получить данные и представить их пользователю в удобном для выбора виде. Как правило, для этих целей используется метод Выгрузить() для получения ТаблицыЗначений из результата запроса и метод ВыбратьСтроку() для интерактивного выбора.
Получение данных в ТаблицуЗначений.
Предположим, вы уже выполнили запрос или прочитали данные из файла Excel, и результат у вас находится в переменной типа ТаблицаЗначений. Рассмотрим пример получения данных из запроса:
// Пример получения данных из запроса
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Артикул КАК Артикул,
| ЕдиницыИзмерения.Наименование КАК ЕдиницаИзмерения,
| 1 КАК Количество,
| 0 КАК Цена,
| 0 КАК Сумма
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
| ПО Номенклатура.ЕдиницаИзмерения = ЕдиницыИзмерения.Ссылка
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();
Если данные приходят из Excel, выгрузка в ТаблицуЗначений может выглядеть иначе, но конечный объект будет тем же.
Вызов метода ВыбратьСтроку().
Метод ВыбратьСтроку() таблицы значений отображает модальное окно, позволяя пользователю выбрать одну строку.
СтрокаТЗ = ТаблицаДанных.ВыбратьСтроку();
Важно: Этот метод возвращает структуру, представляющую выбранную строку, если пользователь нажал "Выбрать" (или сделал двойной клик). Если пользователь закрыл окно без выбора (например, нажав "Отмена"), метод вернет значение Неопределено. Мы обязательно должны проверить этот случай.
Проверка результата выбора.
После вызова ТаблицаДанных.ВыбратьСтроку(), нам необходимо убедиться, что пользователь действительно выбрал строку.
Если СтрокаТЗ = Неопределено Тогда
Сообщить("Выбор строки отменен пользователем.");
Возврат;
КонецЕсли;
Теперь, когда у нас есть выбранная строка из временной таблицы значений (СтрокаТЗ), мы можем добавить новую строку в табличную часть нашего документа и заполнить ее данными.
Добавление новой строки в табличную часть.
Предположим, у вас есть документ, например, "Приходная накладная", с табличной частью "Материалы" (или "Запчасти", "Товары" — наименование может отличаться в вашей конфигурации).
СтрокаТЧ = Материалы.Добавить(); // Или Товары.Добавить(), Запчасти.Добавить()
Здесь Материалы (или другое имя) — это свойство объекта документа, которое представляет собой табличную часть.
Автоматическое заполнение совпадающих полей.
Для полей, чьи имена и типы совпадают между выбранной строкой (СтрокаТЗ) и новой строкой табличной части (СтрокаТЧ), мы можем использовать удобный метод ЗаполнитьЗначенияСвойств().
ЗаполнитьЗначенияСвойств(СтрокаТЧ, СтрокаТЗ);
Этот метод автоматически перенесет значения из СтрокаТЗ в СтрокаТЧ для всех свойств, чьи имена совпадают и типы данных совместимы. Например, "Количество", "Цена", "Сумма" обычно переносятся без проблем, если они числовые.
Одна из самых распространенных проблем, с которой мы сталкиваемся при переносе данных, — это несовпадение типов для ссылочных полей. Например, в Excel или в результате запроса "Наименование" номенклатуры может быть строкой, тогда как в табличной части документа поле "Номенклатура" имеет тип СправочникСсылка.Номенклатура. Метод ЗаполнитьЗначенияСвойств() не сможет автоматически преобразовать строку в ссылку.
Почему возникает проблема?
Как верно было замечено в обсуждении, если в табличной части документа поле Номенклатура имеет тип СправочникСсылка.Номенклатура, а в исходной ТаблицеЗначений колонка, например, Наименование, имеет тип Строка, прямое присвоение или использование ЗаполнитьЗначенияСвойств() не сработает. Системе 1С нужна не просто строка с наименованием, а ссылка на конкретный элемент справочника "Номенклатура".
Поиск элемента справочника по наименованию.
Самый распространенный способ решения этой проблемы — найти соответствующий элемент справочника по его наименованию. Для этого используется метод НайтиПоНаименованию() соответствующего справочника.
// Ищем элемент справочника Номенклатура по наименованию из выбранной строки
НайденнаяНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаТЗ.Наименование);
// Присваиваем найденную ссылку полю табличной части
Если НайденнаяНоменклатура <> Неопределено Тогда
СтрокаТЧ.Номенклатура = НайденнаяНоменклатура;
Иначе
Сообщить("Номенклатура с наименованием '" + СтрокаТЗ.Наименование + "' не найдена в справочнике!");
// Дополнительная логика: можно создать новую номенклатуру, запросить выбор у пользователя и т.д.
КонецЕсли;
Здесь СтрокаТЗ.Наименование — это строка с наименованием номенклатуры, полученная из выбранной пользователем строки временной таблицы.
Обратите внимание: Метод НайтиПоНаименованию() чувствителен к регистру и пробелам. Если в справочнике существует несколько элементов с одинаковым наименованием, он вернет первый найденный. Если элемент не найден, метод вернет Неопределено, поэтому всегда следует проверять результат поиска.
Альтернативные и более надежные способы поиска.
Если наименования могут быть не уникальными, содержать опечатки или отличаться по регистру, поиск только по наименованию может быть ненадежным. В таких случаях мы можем рассмотреть:
Поиск по коду или артикулу, если эти данные присутствуют в исходной таблице и являются уникальными.
Полнотекстовый поиск, если он настроен и требуется более гибкое сопоставление.
Создание собственного механизма сопоставления, возможно, с использованием формы выбора, если элемент не найден автоматически.
Если после всех шагов вы обнаружили, что при выборе разных строк всегда записывается одна и та же "Масло моторное" (или любой другой элемент), это указывает на ошибку в логике использования переменной, содержащей выбранную строку.
Анализ причины.
Наиболее вероятная причина — переменная, содержащая выбранную строку (СтрокаТЗ), либо не обновляется после каждого вызова ВыбратьСтроку(), либо используется статическое значение вместо динамически выбранного. Убедитесь, что поиск Справочники.Номенклатура.НайтиПоНаименованию() производится именно по данным из текущей выбранной СтрокаТЗ.
Проверка правильности использования СтрокаТЗ.
Код должен выглядеть так, чтобы после каждого вызова СтрокаТЗ = ТаблицаДанных.ВыбратьСтроку(); вы использовали поля именно этой свежеполученной структуры.
// ... (Получение ТаблицаДанных) ...
СтрокаТЗ = ТаблицаДанных.ВыбратьСтроку();
Если СтрокаТЗ <> Неопределено Тогда
СтрокаТЧ = Материалы.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаТЧ, СтрокаТЗ);
// Здесь ОБЯЗАТЕЛЬНО используем СтрокаТЗ.Наименование, а не что-либо другое
НайденнаяНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаТЗ.Наименование);
Если НайденнаяНоменклатура <> Неопределено Тогда
СтрокаТЧ.Номенклатура = НайденнаяНоменклатура;
Иначе
Сообщить("Номенклатура не найдена!");
КонецЕсли;
КонецЕсли;
Убедитесь, что нет лишних присвоений или инициализаций переменной, которая должна хранить выбранное значение, вне цикла или блока обработки выбора. Имя колонки в СтрокаТЗ также должно соответствовать ожидаемому. Например, если в ТаблицеДанных колонка называется "НаименованиеТовара", то и обращаться нужно как СтрокаТЗ.НаименованиеТовара.
Метод ВыбратьСтроку() — это быстрый и простой способ получить выбор пользователя. Однако, если требуется более сложная логика, кастомизация интерфейса или обработка дополнительных событий при выборе, мы можем использовать событие "Выбор" формы.
Создание собственной формы выбора.
Вместо вызова ВыбратьСтроку(), мы можем создать отдельную форму обработки с табличным полем.
В этой форме мы можем:
Заполнить табличное поле данными.
Настроить колонки, фильтры, сортировку.
Добавить кнопки "Выбрать", "Отмена".
Обрабатывать события табличного поля, такие как ПриДвойномКлике или Выбор, для возврата выбранной строки.
Этот подход предоставляет значительно больше контроля над пользовательским интерфейсом и логикой выбора, но требует большего объема разработки.
Возврат выбранных данных из формы.
При использовании собственной формы, выбранные данные обычно возвращаются через параметр метода ОткрытьМодально() или через свойства формы, к которым можно обратиться после ее закрытия.
Таким образом, мы рассмотрели полный цикл работы с выбором строки из таблицы значений и переносом ее данных в табличную часть документа, включая решение распространенных проблем с типами данных. Следуя этим шагам, вы сможете надежно реализовать подобный функционал в своих конфигурациях 1С.