Задача кратко:
Дан файл с данными (*.xlsx). В новой информационной базе создайте необходимые объекты конфигурации для автоматической загрузки данных файла в информационную базу.
Краткое решение:
- Считаем, что информация в файле – справочная, поэтому в конфигураторе создаем справочник подходящей структуры, вспомогательные справочники и перечисления;
- Функцию загрузки добавим на форму списка основного справочника.
- Затем программно:
- Выбираем файл через диалог,
- Читаем данные файла в табличный документ,
- В цикле для каждой строки табличного документа создаем новый элемент справочника и записываем его.
Дана таблица Excel с данными об электротоварах (см. рис.1., таблицу). В новой информационной базе создайте необходимые объекты конфигурации для автоматической загрузки данных файла в информационную базу.
Рисунок 1 Данные файла
Решение:
- Обнаруживаем, что:
- В файле справочные данные о Товарах. Значит, создадим справочник Товары (или Номенклатура)
- Колонка Наименование в таблице объединяет несколько столбцов (1-4), поэтому нам надо читать данные из 1-го (Наименование), затем из 5-го (Артикул), из 6-го (Шт/уп), из 7-го (Штрихкод), из 8-го цену, из 9-го (Минимальный заказа), из 10-го (Вид товара), из 11-го (Сборка), из 12-го (После ремонта), 14-го (Дата ремонта)
- Во всех колонках, кроме 6й, 8й, 9й и 13й содержатся данные в текстовом формате.
- Максимальная длина текста в колонке Наименование составляет 200 символов, а это больше, чем максимальная длина стандартного реквизита Наименование справочников в 1С, поэтому придется в справочнике Товары создать дополнительный реквизит «ПолноеНаименование» (Строка, длина 200)
Рисунок 2 Определение длины наименования
Рисунок 3 Длина наименования рассчитана для всех строк
-
- Аналогично определяем максимальную длину значений в колонке Артикул (18 символов), поэтому реквизиту Артикул справочника Товары установим тип Строка, длина 25 (на всякий случай).
- ШтукВУпаковке – Число, точность 0
- Штрихкод - тип строка, длина 13 символов.
- Цена – Число, точность 2
- МинЗаказ – Число, точность 0
- Значения в колонке Вид товара повторяются и теоретически могут быть добавлены новые виды товаров. Поэтому создадим справочник ВидыТоваров, а реквизиту ВидТовара в справочнике Товары установим тип СправочникСсылка.ВидыТоваров
- В колонке Сборка видим 3 варианта значений: сборка не требуется, сборка потребителем и сборка квалифицированным персоналом. На мой взгляд, этот ряд трудно продолжить, поэтому для этих значений создадим перечисление ВидСборки, а реквизиту Сборка в справочнике Товары установим тип ПеречислениеСсылка.ВидСборки
- В колонке После ремонта значение да или нет. Поэтому можно реквизиту ПослеРемонта справочника Товары установить тип Булево (в таком смысле, что да=Истина, а нет = Ложь)
- Колонка Ремонт содержит дату ремонта, поэтому тип реквизита Ремонт в справочнике Товары будет Дата.
Рисунок 4 Структура данных такая получилась в итоге
- Создаем форму списка справочника Товары (выбираем все необходимые реквизиты для отображения данных),
- добавляем команду ЗагрузитьДанные и перетаскиваем ее на панель формы,
- определяем действие команды (Создаем процедуру на клиенте и на сервере), см.рис.5:
Рисунок 5 Определяем действие команды
- Когда пользователь нажмет на кнопку «Загрузить данные», должен открыться диалог для выбора файла. Будем использовать объект ДиалогВыбораФайла (он очень хорошо описан в Синтакс-помощнике).
Рисунок 6 Настраиваем диалог выбора файла
&НаКлиенте
Процедура ЗагрузитьДанные(Команда)
Диалог= Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл с данными";
Диалог.ПредварительныйПросмотр = Истина;
Диалог.МножественныйВыбор=Ложь;
Диалог.Фильтр="Формат Excel (*.xls;*.xlsx)|*.xls;*.xlsx|";
Если Диалог.Выбрать() Тогда
ЗагрузитьДанныеНаСервере(Диалог.ПолноеИмяФайла);
Иначе
Сообщить("Файл не выбран. Загрузка невозможна!");
Возврат;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьДанныеНаСервере(ИмяФайла)
КонецПроцедуры
После корректировки кода для открытия диалога, обновим конфигурацию базы данных (F7).
Проверим, как работает выбор диалога в пользовательском режиме (F5).
Но! Получим сообщение об ошибке: «Использование синхронных методов на клиенте запрещено!»
Чтобы все заработало, разрешим в свойствах конфигурации использовать синхронные методы.
Рисунок 7 Разрешаем использовать синхронные методы
&НаСервере
Процедура ЗагрузитьДанныеНаСервере(ИмяФайла)
//Создаем новый табличный документ:
ТабДок=Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);//читаем все данные табличного документа как текст
КоличествоСтрок=ТабДок.ВысотаТаблицы;//определяем количество строк в таблице
Для НомерСтроки=2 По КоличествоСтрок Цикл
//Читаем наименование из 1й колонки строки с номером НомерСтроки:
НаименованиеИзТабДок=ТабДок.Область(НомерСтроки,1,НомерСтроки,1).Текст;
//Ищем прочитанное наименование в справочнике Товары:
ТоварСсылка=Справочники.Товары.НайтиПоНаименованию(НаименованиеИзТабДок);
//Если не нашли, создаем новый элемент, иначе не делаем ничего:
Если ТоварСсылка.Пустая() Тогда
НовыйТовар=Справочники.Товары.СоздатьЭлемент();
НовыйТовар.ПолноеНаименование=НаименованиеИзТабДок;//заполняем строковый реквизит
НовыйТовар.Наименование=НаименованиеИзТабДок;//заполняем строковый реквизит
НовыйТовар.Артикул=ТабДок.Область(НомерСтроки,5,НомерСтроки,5).Текст;//заполняем строковый реквизит
НовыйТовар.ШтукВУпаковке=ТабДок.Область(НомерСтроки,6,НомерСтроки,6).Текст;//реквизит типа Число, но все ок
НовыйТовар.ШтрихКод=ТабДок.Область(НомерСтроки,7,НомерСтроки,7).Текст;
НовыйТовар.Цена=ТабДок.Область(НомерСтроки,8,НомерСтроки,8).Текст;//реквизит типа Число, но все ок
НовыйТовар.МинЗаказ=ТабДок.Область(НомерСтроки,9,НомерСтроки,9).Текст;//реквизит типа Число, но все ок
//Подбираем вид товара из справочника ВидТовара:
//1. Читаем вид товара из 10й колонки табличного документа:
ВидТовараИзТабДок= ТабДок.Область(НомерСтроки,10,НомерСтроки,10).Текст;
//2. Ищем наименование в справочнике ВидТовара:
ВидТовараСсылка=Справочники.ВидТовара.НайтиПоНаименованию(ВидТовараИзТабДок);
//3. Если не нашли, создаем новый вид товара:
Если ВидТовараСсылка.Пустая() Тогда
НовыйВидТовара=Справочники.ВидТовара.СоздатьЭлемент(); //3.1.создаем новый вид товара
НовыйВидТовара.Наименование=ВидТовараИзТабДок;
НовыйВидТовара.Записать(); //3.2.записываем его в базу
ВидТовараСсылка=НовыйВидТовара.Ссылка;//3.3.запоминаем ссылку на новый вид товара
КонецЕсли;
НовыйТовар.ВидТовара=ВидТовараСсылка;//записываем ссылку в реквизит товара
//Читаем текстовое значение из табличного документа:
ВидСборкиИзТабДок=ТабДок.Область(НомерСтроки,11,НомерСтроки,11).Текст;
//Подбираем для текста из табличного документа значение перечисления:
Если ВидСборкиИзТабДок= "Не требуется" Тогда
НовыйТовар.Сборка=Перечисления.ВидСборки.НеТребуется;
ИначеЕсли ВидСборкиИзТабДок= "Сборка квалифицированным персоналом" Тогда
НовыйТовар.Сборка=Перечисления.ВидСборки.СборкаКвалифицированнымПерсоналом;
ИначеЕсли ВидСборкиИзТабДок= "Сборка потребителем" Тогда
НовыйТовар.Сборка=Перечисления.ВидСборки.СборкаПотребителем;
КонецЕсли;
ПослеРемонтаИзТабДок=ТабДок.Область(НомерСтроки,12,НомерСтроки,12).Текст;
// Это выражение <ПослеРемонтаИзТабДок="да"> будет иметь значение либо Истина, либо Ложь,
// поэтому и реквизит нового товара получит соответствующее значение:
НовыйТовар.ПослеРемонта=ПослеРемонтаИзТабДок="да";
//читаем дату как текст (строку) из табличного документа:
ДатаРемонтаИзТабДок=ТабДок.Область(НомерСтроки,13,НомерСтроки,13).Текст;
Если ДатаРемонтаИзТабДок<>"" Тогда //если дата - не пустая строка
// преобразуем строку в дату за 2 шага:
МассивЧастиДаты=СтрРазделить(ДатаРемонтаИзТабДок,".");// 1 шаг. Строковую дату (день, месяц, год) преобразуем в массив
//2 шаг.Соберем дату по кусочкам в правильном порядке (год, месяц. день) и запишем в реквизит:
НовыйТовар.Ремонт=Дата(МассивЧастиДаты[2],МассивЧастиДаты[1],МассивЧастиДаты[0]);
КонецЕсли;
НовыйТовар.Записать();//запишем новый наш товар
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Рисунок 7-8 Процедура ЗагрузитьДаныеНаСервере()
Проверяем в пользовательском режиме (F5). Вручную обновляем справочник Товары (F5).
Итак, задача решена и вроде все работает.
&НаКлиенте
Процедура ЗагрузитьДанные(Команда)
Диалог= Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл с данными";
Диалог.ПредварительныйПросмотр = Истина;
Диалог.МножественныйВыбор=Ложь;
Диалог.Фильтр="Формат Excel (*.xls;*.xlsx)|*.xls;*.xlsx|";
Если Диалог.Выбрать() Тогда
ЗагрузитьДанныеНаСервере(Диалог.ПолноеИмяФайла);
Иначе
Сообщить("Файл не выбран. Загрузка невозможна!");
Возврат;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьДанныеНаСервере(ИмяФайла)
//Создаем новый табличный документ:
ТабДок=Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);//читаем все данные табличного документа как текст
КоличесвтоСтрок=ТабДок.ВысотаТаблицы;//определяем количество строк в таблице
Для НомерСтроки=2 По КоличесвтоСтрок Цикл
//Читаем наименование из 1й (нужной) колонки строки с номером НомерСтроки:
НаименованиеИзТабДок=ТабДок.Область(НомерСтроки,1,НомерСтроки,1).Текст;
//Ищем прочитанное наименование в справочнике Товары:
ТоварСсылка=Справочники.Товары.НайтиПоНаименованию(НаименованиеИзТабДок);
//Если не нашли, создаем новый элемент, иначе не делаем ничего:
Если ТоварСсылка.Пустая() Тогда
НовыйТовар=Справочники.Товары.СоздатьЭлемент();
// Реквизитам нового элемента справочника присвоить значения:
// Ести тип реквизита простой (строка, число), можно присвоить напрямую данные из ТАбДок:
НовыйТовар.Наименование=НаименованиеИзТабДок;//заполняем строковый реквизит
НовыйТовар.Цена=ТабДок.Область(НомерСтроки,8,НомерСтроки,8).Текст;//реквизит типа Число, но все ок
//Если тип реквизита Дата:
//читаем ее как текст и преобразовываем с помощью СтрРазделить() и Дата():
//читаем дату как текст (строку) из табличного документа:
ДатаРемонтаИзТабДок=ТабДок.Область(НомерСтроки,13,НомерСтроки,13).Текст;
Если ДатаРемонтаИзТабДок<>"" Тогда //если дата - не пустая строка
МассивЧастиДаты=СтрРазделить(ДатаРемонтаИзТабДок,".");
НовыйТовар.Ремонт=Дата(МассивЧастиДаты[2],МассивЧастиДаты[1],МассивЧастиДаты[0]);
КонецЕсли;
//Если тип реквизита Булево, можно так:
ПослеРемонтаИзТабДок=ТабДок.Область(НомерСтроки,12,НомерСтроки,12).Текст;
НовыйТовар.ПослеРемонта=ПослеРемонтаИзТабДок="да";
//Если тип реквизита - Ссылка на перечисление:
//Читаем текстовое значение из табличного документа:
ВидСборкиИзТабДок=ТабДок.Область(НомерСтроки,11,НомерСтроки,11).Текст;
//Подбираем для строки из табличного документа значение перечисления:
Если ВидСборкиИзТабДок= "Не требуется" Тогда
НовыйТовар.Сборка=Перечисления.ВидСборки.НеТребуется;
ИначеЕсли ВидСборкиИзТабДок= "Сборка квалифицированным персоналом" Тогда
НовыйТовар.Сборка=Перечисления.ВидСборки.СборкаКвалифицированнымПерсоналом;
ИначеЕсли ВидСборкиИзТабДок= "Сборка потребителем" Тогда
НовыйТовар.Сборка=Перечисления.ВидСборки.СборкаПотребителем;
КонецЕсли;
//Если тип реквизита - Ссылка на справочник:
//1. Читаем вид товара из 10й(нужной) колонки табличного документа:
ВидТовараИзТабДок= ТабДок.Область(НомерСтроки,10,НомерСтроки,10).Текст;
//2. Ищем наименование в справочнике ВидТовара:
ВидТовараСсылка=Справочники.ВидТовара.НайтиПоНаименованию(ВидТовараИзТабДок);
//3. Если не нашли, создаем новый вид товара:
Если ВидТовараСсылка.Пустая() Тогда
НовыйВидТовара=Справочники.ВидТовара.СоздатьЭлемент(); //3.1.создаем новый вид товара
НовыйВидТовара.Наименование=ВидТовараИзТабДок;
НовыйВидТовара.Записать(); //3.2.записываем его в базу
ВидТовараСсылка=НовыйВидТовара.Ссылка;//3.3.запоминаем ссылку на новый вид товара
КонецЕсли;
НовыйТовар.ВидТовара=ВидТовараСсылка;//записываем ссылку в реквизит товара
НовыйТовар.Записать();//запишем новый наш товар
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Что можно улучшить?
- Использование асинхронных методов
- Использовать запрос вместо НайтиПоНаименованию
- Автоматически обновлять справочник
- Обновлять данные справочника при повторной загрузке
- Загрузку данных в клиент-серверной базе
Но это, надеюсь, в следующих сериях...