Умная маршрутизация: о сложностях интеграции с 1С (часть 2)

27.08.21

Интеграция - WEB-интеграция

В статье будет много примеров кода с комментариями работы расширения для обмена данными УТ11.4 с Яндекс.Маршрутизацией через выгрузку/загрузку EXCEL файла.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Бесплатно
Умная маршрутизация: кейс интеграции с 1С. Расширение
.cfe 494,94Kb
39
39 Скачать бесплатно
Пример заполнения EXCEL
.xlsx 15,98Kb
35
35 Скачать бесплатно

Принцип работы, какие задачи решает и кому подходит - описано в первой части статьи: Умная маршрутизация: кейс интеграции с 1С (часть 1)

Во второй части описана доработка "Рабочего места менеджера по доставке" в УТ 11.4 для обмена данными с Яндекс.Маршрутизацией.

Идея. Нам нужны 2 кнопки: “Загрузить” и “Выгрузить”

Создаём расширение, в нем обработку с тремя кнопками кода и – вуаля:

 

 

  1. Есть нажать на первую кнопку (левую зеленую) формируется готовый Excel. Его нужно подгрузить в Яндекс.Маршрутизацию.
  2. Яндекс.Маршрутизация оптимизирует маршруты водителей и возвращает Excel – Маршрутный лист с параметрами поездки. Если нажать кнопку 2, Маршрутный лист загрузится в 1С и раскидает заказы по маршрутным листам.
  3. Позже появилась кнопка 3 (верхняя длинная) «Стоимость работы водителей». Она открывает отчёт с итогами работы за день/неделю/месяц и авторасчёт зарплаты водителей.

Стоп, нужно же где-то взять список заказов, которые необходимо сегодня доставить. Вспоминаем, что в УТ это Обработки.РабочееМестоМенеджераПоДоставке.

Переносим кнопки туда.

 

Формируем Excel с заказами

 

Чтобы сформировать Excel, нужно решить 3 проблемы (по факту больше, конечно, но кто бы научил точно оценивать все проблемы до начала разработки):

 

Шаг 1. У нас база клиент-серверная, значит Excel сформируется на сервере, а сохранить его надо будет на клиенте. Тут всё стандартно:

&НаКлиенте
Процедура ЯМ_ЯМ_СохранитьВЭксельПосле(Команда)
    //Сохраняем в Эксель на клиенте
    СохранитьПрочитатьЭксельЯндексМаршрутизации("Сохранение");
КонецПроцедуры

&НаКлиенте
Процедура СохранитьПрочитатьЭксельЯндексМаршрутизации(ТипКоманды)
    //Прочитать Эксель на клиенте
    Режим = РежимДиалогаВыбораФайла[ТипКоманды]; 
    ДиалогФайла = Новый ДиалогВыбораФайла(Режим); 
    Если ТипКоманды = "Сохранение" Тогда
        ДиалогФайла.ПолноеИмяФайла = "YaRouting_" + Формат(ТекущаяДата(),"ДФ=yyyyMMdd_HHMMss"); 
    КонецЕсли;
    Фильтр = "Документ Excel (*.xlsx)|*.xlsx|";                 
    ДиалогФайла.Фильтр = Фильтр; 
    ДиалогФайла.МножественныйВыбор = Ложь; 
    ДиалогФайла.Заголовок = "Выберите файл"; 
    Если ДиалогФайла.Выбрать() Тогда 
        Если ТипКоманды = "Сохранение" Тогда
            ОднаКнига = Новый ПакетОтображаемыхДокументов;
            //Создав объект "ОднаКнига", мы можем в его состав поместить несколько табличных документов каким-то таким образом:
            ДобавитьСтраницыВКнигу(ОднаКнига);
            //А сохранить в одну книгу все это хозяйство можно так:
            ОднаКнига.Записать(ДиалогФайла.ПолноеИмяФайла, ТипФайлаПакетаОтображаемыхДокументов.XLSX);
        Иначе
            //Открытие файла
            Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ДиалогФайла.ПолноеИмяФайла));
            ПрочитатьИОбработатьФайлЯндексМаршрутизации(Адрес, ДиалогФайла.ПолноеИмяФайла);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

 

Шаг 2. Если вы посмотрели шаблон Excel Яндекс.Маршрутизации https://yandex.ru/routing/doc/vrp/concepts/example.html, то увидели, что в нём несколько страниц. Т.е. нужно сохранить не просто Excel, а сохранить в 1С многостраничный Excel.

Для этого мы на клиенте создаём: 

ОднаКнига = Новый ПакетОтображаемыхДокументов;

и затем серверной процедурой ДобавитьСтраницыВКнигу(ОднаКнига) создаём 4 отдельных Табличных документа, сохраняем их как листы книги ОднаКнига, а на клиенте - многостраничный Excel

ОднаКнига.Записать(ДиалогФайла.ПолноеИмяФайла, ТипФайлаПакетаОтображаемыхДокументов.XLSX).

Для красоты вынес код в общий модуль: и читать удобнее, и использовать повторно.

&НаСервере
Процедура ДобавитьСтраницыВКнигу(ОднаКнига)
    ЯМ_ИнтеграцияСЯндексМаршрутизацией.ДобавитьСтраницыЭкселяДляЯндексМаршрутизации(ОднаКнига, ПолучитьЗаказыНаДоставку(), УникальныйИдентификатор);
КонецПроцедуры

Основная процедура общего модуля заполняет начальные параметры и добавляет 4 страницы в книгу Excel:

Процедура ДобавитьСтраницыЭкселяДляЯндексМаршрутизации(ОднаКнига, ЗаказыНаДоставку, УникальныйИдентификатор) Экспорт
    //Определяем режим времени суток
    РежимВремени = Новый Структура;
    РежимВремени.Вставить("ТекущаяДата",    ТекущаяДата());
    РежимВремени.Вставить("СейчасВечер",     ?(Час(РежимВремени.ТекущаяДата)>= 15, Истина, Ложь)        );
    РежимВремени.Вставить("СейчасВыходной", ?(ДеньНедели(РежимВремени.ТекущаяДата)>=6, Истина, Ложь));
    РежимВремени.Вставить("Суффикс",         ?(РежимВремени.СейчасВечер, "_НОЧЬ", "_ДЕНЬ"));
    РежимВремени.Вставить("СуффиксОбщий",   ?(РежимВремени.СейчасВыходной, "_ВЫХОДНОЙ", ?(РежимВремени.СейчасВечер, "_НОЧЬ", "_ДЕНЬ")));
   
    //Добавляем страницу Опций   
    ДобавитьСтраницуВЭксель(ОднаКнига, "Orders", УникальныйИдентификатор, ЗаказыНаДоставку, РежимВремени);
    ДобавитьСтраницуВЭксель(ОднаКнига, "Vehicles", УникальныйИдентификатор,,РежимВремени);
    ДобавитьСтраницуВЭксель(ОднаКнига, "Depot", УникальныйИдентификатор,,РежимВремени);
    ДобавитьСтраницуВЭксель(ОднаКнига, "Options", УникальныйИдентификатор,,РежимВремени);
   
КонецПроцедуры

И, наконец, код добавления страниц:

&НаСервере
Процедура ДобавитьСтраницуВЭксель(ОднаКнига, НазваниеСтраницыЭксель, УникальныйИдентификатор, ЗаказыНаДоставку = Неопределено, РежимВремени)
    Элт = ОднаКнига.Состав.Добавить();
    Элт.Наименование = НазваниеСтраницыЭксель;
    Элт.Данные = ВыгрузитьТабДокВовременноеХранилищеНаСервере(НазваниеСтраницыЭксель, УникальныйИдентификатор, ЗаказыНаДоставку, РежимВремени);
КонецПроцедуры

Как вы заметили, всё довольно просто. Нужно указать название нового листа Элт.Наименование  и добавить данные  Элт.Данные.

&НаСервере
Функция ВыгрузитьТабДокВовременноеХранилищеНаСервере(НазваниеСтраницыЭксель, УникальныйИдентификатор, ЗаказыНаДоставку = Неопределено, РежимВремени)
   
    Макет = Обработки.РабочееМестоМенеджераПоДоставке.ПолучитьМакет("" + НазваниеСтраницыЭксель);
    ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
   
    ТабДок = Новый ТабличныйДокумент;
    ТабДок.Вывести(ОбластьШапка);
    ЗаполнитьСтрокиДокумента(Макет, ТабДок, НазваниеСтраницыЭксель, ЗаказыНаДоставку, РежимВремени);
   
    АдресВременногоХранилища = ПоместитьВоВременноеХранилище(ТабДок, УникальныйИдентификатор);
   
    Возврат АдресВременногоХранилища;
   
КонецФункции

 

Шаг 3. Шапки страниц с названием колонок (именно по ним Яндекс.Маршрутизация считывает значения параметров) мы храним в виде макетов и называем их как страницы в формируемом Excel. Это позволяет использовать парадигму, так называемого, самопишушегося кода

Макет = Обработки.РабочееМестоМенеджераПоДоставке.ПолучитьМакет("" + НазваниеСтраницыЭксель);

 

 

Orders

 

Vehicles

Depot

 

Options

 

Шаг 4. Самая неаккуратная процедура заполнения строки:

&НаСервере
Процедура ЗаполнитьСтрокиДокумента(Макет, ТабДок, НазваниеСтраницыЭксель, ЗаказыНаДоставку = Неопределено, РежимВремени)
    ////////////////////  "Depot"
    Если НазваниеСтраницыЭксель = "Depot" Тогда
        ПараметрыСклада = ПолучитьЗаполненныеПараметрыСтрокиСклада();
        //Ставим на вечер другой склад
        Если РежимВремени.СейчасВечер Тогда
            ПараметрыСклада.НомерСтроки = "2";
            ПараметрыСклада.НазваниеСклада = "МСК- Опт - ДОПЛАНИРОВАНИЕ";
        КонецЕсли;

        ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПараметрыСклада);

    ///////////////////  "Options"
    ИначеЕсли НазваниеСтраницыЭксель = "Options" Тогда
        ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПолучитьЗаполненныеПараметрыСтрокиОпций());
    ///////////////////  "Vehicles"   
    ИначеЕсли НазваниеСтраницыЭксель = "Vehicles" Тогда
        Машины = ПолучитьСписокМашин();
        Для Каждого Автомобиль ИЗ Машины Цикл
            ПараметрыМашины = ПолучитьЗаполненныеПараметрыСтрокиМашины();           

            ЗаполнитьЗначенияСвойств(ПараметрыМашины,Автомобиль.ТранспортноеСредство);
           
            ПараметрыМашины.ЯМ_НазваниеМашины = "" + Автомобиль.ТранспортноеСредство + " - [" + Автомобиль.Водитель + "]"; 
            ПараметрыМашины.ЯМ_ЛогинКурьера = Автомобиль.ТранспортноеСредство["ЯМ_ЛогинКурьера" + РежимВремени.Суффикс];
            ПараметрыМашины.ЯМ_ВремяНачалаИКонцаСмены = Автомобиль.ТранспортноеСредство["ЯМ_ВремяНачалаИКонцаСмены" + РежимВремени.Суффикс];
           
            ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПараметрыМашины);

        КонецЦикла;
    ///////////////////  "Orders"   
    ИначеЕсли НазваниеСтраницыЭксель = "Orders" Тогда
        Для Каждого СтрЗаказа ИЗ ЗаказыНаДоставку Цикл
            ПараметрыЗаказа = ПолучитьЗаполненныеПараметрыСтрокиЗаказов();
            УточненныеПараметрыЗаказа = ПолучитьУточненныеПараметрыЗаказа(СтрЗаказа);           

            ЗаполнитьЗначенияСвойств(ПараметрыЗаказа, УточненныеПараметрыЗаказа);           

            //Подбираем наиболее подходящее временное окно
            Если УточненныеПараметрыЗаказа.Свойство("ВременноеОкно" + РежимВремени.СуффиксОбщий) Тогда
                ПараметрыЗаказа.ВременноеОкно = УточненныеПараметрыЗаказа["ВременноеОкно" + РежимВремени.СуффиксОбщий];
            ИначеЕсли УточненныеПараметрыЗаказа.Свойство("ВременноеОкно" + РежимВремени.Суффикс) Тогда
                ПараметрыЗаказа.ВременноеОкно = УточненныеПараметрыЗаказа["ВременноеОкно" + РежимВремени.Суффикс];
            КонецЕсли;
           
            //ПараметрыМашины.ЯМ_НазваниеМашины = "" + Автомобиль.ТранспортноеСредство + " - [" + Автомобиль.Водитель + "]"; 
            //ПараметрыМашины.ЯМ_ЛогинКурьера = Автомобиль.ТранспортноеСредство.ЯМ_ЛогинКурьера_ДЕНЬ;
            //ПараметрыМашины.ЯМ_ВремяНачалаИКонцаСмены = Автомобиль.ТранспортноеСредство.ЯМ_ВремяНачалаИКонцаСмены_ДЕНЬ;
           
            ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПараметрыЗаказа);

        КонецЦикла;
    КонецЕсли;   
КонецПроцедуры

Тут мы себе помогли, сделав предзаполнение параметров процедурами:

ПолучитьЗаполненныеПараметрыСтрокиСклада()
ПолучитьЗаполненныеПараметрыСтрокиОпций()
ПолучитьЗаполненныеПараметрыСтрокиМашины()
ПолучитьЗаполненныеПараметрыСтрокиЗаказов()

Функции облегчают чтение кода, а по сути являются сохранённым результатом нашего 2-х месячного подбора параметров. Значения по умолчанию для нашей компании. Приведу их в спойлере, чтобы не загромождать статью:

&НаСервере
Процедура ЗаполнитьСтрокиДокумента(Макет, ТабДок, НазваниеСтраницыЭксель, ЗаказыНаДоставку = Неопределено, РежимВремени)
    ////////////////////  "Depot"
    Если НазваниеСтраницыЭксель = "Depot" Тогда
        ПараметрыСклада = ПолучитьЗаполненныеПараметрыСтрокиСклада();
        //Ставим на вечер другой склад
        Если РежимВремени.СейчасВечер Тогда
            ПараметрыСклада.НомерСтроки = "2";
            ПараметрыСклада.НазваниеСклада = "МСК- Опт - ДОПЛАНИРОВАНИЕ";
        КонецЕсли;

        ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПараметрыСклада);
       
    ///////////////////  "Options"
    ИначеЕсли НазваниеСтраницыЭксель = "Options" Тогда
        ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПолучитьЗаполненныеПараметрыСтрокиОпций());
    ///////////////////  "Vehicles"   
    ИначеЕсли НазваниеСтраницыЭксель = "Vehicles" Тогда
        Машины = ПолучитьСписокМашин();
        Для Каждого Автомобиль ИЗ Машины Цикл
            ПараметрыМашины = ПолучитьЗаполненныеПараметрыСтрокиМашины();
           
            ЗаполнитьЗначенияСвойств(ПараметрыМашины,Автомобиль.ТранспортноеСредство);
           
            ПараметрыМашины.ЯМ_НазваниеМашины = "" + Автомобиль.ТранспортноеСредство + " - [" + Автомобиль.Водитель + "]"; 
            ПараметрыМашины.ЯМ_ЛогинКурьера = Автомобиль.ТранспортноеСредство["ЯМ_ЛогинКурьера" + РежимВремени.Суффикс];
            ПараметрыМашины.ЯМ_ВремяНачалаИКонцаСмены = Автомобиль.ТранспортноеСредство["ЯМ_ВремяНачалаИКонцаСмены" + РежимВремени.Суффикс];
           
            ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПараметрыМашины);

        КонецЦикла;
    ///////////////////  "Orders"   
    ИначеЕсли НазваниеСтраницыЭксель = "Orders" Тогда
        Для Каждого СтрЗаказа ИЗ ЗаказыНаДоставку Цикл
            ПараметрыЗаказа = ПолучитьЗаполненныеПараметрыСтрокиЗаказов();
            УточненныеПараметрыЗаказа = ПолучитьУточненныеПараметрыЗаказа(СтрЗаказа);
           
            ЗаполнитьЗначенияСвойств(ПараметрыЗаказа, УточненныеПараметрыЗаказа);
           
            //Подбираем наиболее подходящее временное окно
            Если УточненныеПараметрыЗаказа.Свойство("ВременноеОкно" + РежимВремени.СуффиксОбщий) Тогда
                ПараметрыЗаказа.ВременноеОкно = УточненныеПараметрыЗаказа["ВременноеОкно" + РежимВремени.СуффиксОбщий];
            ИначеЕсли УточненныеПараметрыЗаказа.Свойство("ВременноеОкно" + РежимВремени.Суффикс) Тогда
                ПараметрыЗаказа.ВременноеОкно = УточненныеПараметрыЗаказа["ВременноеОкно" + РежимВремени.Суффикс];
            КонецЕсли;
           
            //ПараметрыМашины.ЯМ_НазваниеМашины = "" + Автомобиль.ТранспортноеСредство + " - [" + Автомобиль.Водитель + "]"; 
            //ПараметрыМашины.ЯМ_ЛогинКурьера = Автомобиль.ТранспортноеСредство.ЯМ_ЛогинКурьера_ДЕНЬ
            //ПараметрыМашины.ЯМ_ВремяНачалаИКонцаСмены = Автомобиль.ТранспортноеСредство.ЯМ_ВремяНачалаИКонцаСмены_ДЕНЬ;
           
            ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ПараметрыЗаказа);

        КонецЦикла;
       
    КонецЕсли;

КонецПроцедуры

Далее мы уточняем значение параметров строки и запускаем лаконичную  ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ЗначенияПараметров).

&НаСервере
Процедура ЗаполнитьСтрокуИДобавитьТабДок(Макет, ТабДок, ЗначенияПараметров)
   
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
    ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, ЗначенияПараметров);
    ТабДок.Вывести(ОбластьСтрока);
   
КонецПроцедуры

Такой минималистичный код получился благодаря нашим ПолучитьЗаполненныеПараметры…() и тому, что мы идентично назвали параметры ячеек в макетах страниц (Проблемы шаг 3)

 

Шаг 5. Как хранить дополнительные параметры? Чтобы ускорить разработку, мы решили хранить все параметры в реквизитах Справочников. Сейчас, я бы хранил все параметры, используя стандартный механизм 1С Дополнительных Значений. Это обезопасит пользователей от потери данных, введенных в эти доп. реквизиты, например, если кто-то из сотрудников (админ, конечно, кто же ещё) снесёт расширение, а потом его опять запустит. Но было решено так:

 

 

Внешний вид карточек ТС, клиентов, склада можно посмотреть в первой части статьи - Умная маршрутизация: кейс интеграции с 1С (часть 1) 

 

Шаг 6. Но ведь нам нужны данные - список заказов. А в обработке РабочееМестоМенеджераПоДоставке этот самый список не Список, а деревоЗначений. Что ж, берём поисковик и рисуем рекурсию:

&НаСервере
Функция ПолучитьЗаказыНаДоставку()
   
    ДеревоЗнач = РеквизитФормыВЗначение("РаспоряженияНаДоставку");
    ЗаказыНаДоставку = ПолучитьПустуюТЗ();
    ОбходДереваДетально(ДеревоЗнач, ЗаказыНаДоставку);
   
    Возврат ЗаказыНаДоставку;

КонецФункции

&НаСервере
Функция ПолучитьПустуюТЗ()
   
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Распоряжение");
    ТЗ.Колонки.Добавить("Перевозчик");
    ТЗ.Колонки.Добавить("Адрес");
    ТЗ.Колонки.Добавить("Номер");
    ТЗ.Колонки.Добавить("ПолучательОтправитель");
    ТЗ.Колонки.Добавить("Вес");

    Возврат ТЗ;
   
КонецФункции

//Рекурсивная процедура
&НаСервере
Процедура ОбходДереваДетально(ПереданноеДер, ТЗ)
   
    Для Каждого СтрПолученногоДерева Из ПереданноеДер.Строки Цикл
       
        //Сообщить(СтрПолученногоДерева.Номенклатура);
        Если ЗначениеЗаполнено(СтрПолученногоДерева.Распоряжение) Тогда
            НовСтр = ТЗ.Добавить();
            ЗаполнитьЗначенияСвойств(НовСтр, СтрПолученногоДерева);
        КонецЕсли; 
       
        Если СтрПолученногоДерева.Строки.Количество()>0 Тогда           
            ОбходДереваДетально(СтрПолученногоДерева, ТЗ);           
        КонецЕсли;
       
    КонецЦикла;
   
КонецПроцедуры

Ну вот и всё! Многостраничный EXCEL с заполненными строками для Яндекс.Маршрутизации сформирован, сохранён, казалось бы, можно идти пить чай, но нет… нужно теперь загрузить ответ от Яндекс.Маршрутизации. Ну его этот чай, поехали!

 

Загружаем данные в 1С

 

Шаг 7. Теперь файл - на клиенте, а обработка - на сервере.

&НаКлиенте
Процедура ЯМ_ЯМ_ЗагрузитьМаршрутныеЛистыИзЭксельПосле(Команда)   
    СохранитьПрочитатьЭксельЯндексМаршрутизации("Открытие");
КонецПроцедуры

Процедура получилась универсальной (см. шаг 1), несколько строчек помещаем во временное хранилище и отправляем на сервер:

Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ДиалогФайла.ПолноеИмяФайла));
            ПрочитатьИОбработатьФайлЯндексМаршрутизации(Адрес, ДиалогФайла.ПолноеИмяФайла);

&НаСервере
Процедура ПрочитатьИОбработатьФайлЯндексМаршрутизации(Адрес, ИмяФайла)
       //вывод в таблицу значений
       ЯМ_ИнтеграцияСЯндексМаршрутизацией.ПрочитатьИОбработатьФайлЯндексМаршрутизации(Адрес, ИмяФайла);  
КонецПроцедуры

 

Шаг 8. Используем современные методы чтения Excel:

Процедура ПрочитатьИОбработатьФайлЯндексМаршрутизации(Адрес, ИмяФайла) Экспорт
    //Необходимо чтение файлов XLS или XLSX
    Расширение = Прав(ИмяФайла, 4);
    Расширение = СтрЗаменить(Расширение, ".", "");
   
    ФайлПриемник = ПолучитьИмяВременногоФайла(Расширение);
    ДанныеХранилища = ПолучитьИзВременногоХранилища(Адрес);
    ДанныеХранилища.Записать(ФайлПриемник);
  
    ТабДок = Новый ТабличныйДокумент;
    ТабДок.Прочитать(ФайлПриемник, СпособЧтенияЗначенийТабличногоДокумента.Значение); 
  
    //вывод в таблицу значений   
    ПЗ = Новый ПостроительЗапроса;
    //ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
    //Загружаем не весь Эксель, а только лист "Маршруты"
    ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.ПолучитьОбласть("Маршруты").Область());
    ПЗ.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
    ПЗ.ЗаполнитьНастройки();
    ПЗ.Выполнить();
   
    ТаблицаЗначений = ПЗ.Результат.Выгрузить();
    ДозаполнитьТЗДаннымиДляЗагрузки(ТаблицаЗначений);  
   
    ЗагрузитьТочкиВМаршрутныеЛисты(ТаблицаЗначений);  

Конецпроцедуры

Вот этот кусок кода мой любимый:

    //вывод в таблицу значений   
    ПЗ = Новый ПостроительЗапроса;
    //ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
    //Загружаем не весь Эксель, а только лист "Маршруты"
    ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.ПолучитьОбласть("Маршруты").Область());
    ПЗ.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
    ПЗ.ЗаполнитьНастройки();
    ПЗ.Выполнить();
    ТаблицаЗначений = ПЗ.Результат.Выгрузить();

Он подходит для любого Excel, нужно лишь подставить верное название листа. Если Excel одностраничный, то пишем так:

    ПЗ = Новый ПостроительЗапроса;
    ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабличныйДокумент.Область());
    ПЗ.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
    ПЗ.ЗаполнитьНастройки();
    ПЗ.Выполнить();
    ТаблицаЗначений = ПЗ.Результат.Выгрузить();

Т.е. на входе любой Excel, а на выходе - удобная ТаблицаЗначений, в которой колонки названы как в исходном Excel. И не нужно сопоставлять колонки по ячейкам.

 

Шаг 9. Привязываем данные из Excel к своим данным в 1С. Поэтому привожу код без пояснений, он очень персональный, и вам точно не подойдёт, но для целостной картины нужен:

Процедура ДозаполнитьТЗДаннымиДляЗагрузки(ТЗ)

    ТЗ.Колонки.Добавить("Вес");
    ТЗ.Колонки.Добавить("КлючСвязи");
    ТЗ.Колонки.Добавить("Распоряжение");
    ТЗ.Колонки.Добавить("Перевозчик");
    ТЗ.Колонки.Добавить("ПолучательОтправитель");
    ТЗ.Колонки.Добавить("Склад");
    ТЗ.Колонки.Добавить("Доставлено");
    ТЗ.Колонки.Добавить("ДоставляетсяПолностью");
    ТЗ.Колонки.Добавить("ВремяС");
    ТЗ.Колонки.Добавить("ВремяПо");
    ТЗ.Колонки.Добавить("АдресЗначенияПолей");
    ТЗ.Колонки.Добавить("ДополнительнаяИнформация");
    ТЗ.Колонки.Добавить("ИдентификаторМашиныДля1С");
   
    ПрефиксУИД = "" + Формат(ТекущаяДата(),"ДФ=ddMMyyhhmmss") + "_";
   
    Для Каждого Стр ИЗ ТЗ Цикл
        Стр.Вес = Стр.ВесЗаказа_Кг;
        Если ЗначениеЗаполнено(Стр.ИдентификаторМашины) Тогда
            Стр.ИдентификаторМашиныДля1С = СформироватьПравильныйКлюч(Стр.ИдентификаторМашины);
            Если ЗначениеЗаполнено(Стр.НомерЗаказа) И НЕ Стр.ТипТочки = "Склад" Тогда
                ГУИДНачало = СтрНайти(Стр.НомерЗаказа,"[GUID ");
                ГУИД = Сред(Стр.НомерЗаказа,ГУИДНачало + 6,36);
                НовыйGUID = Новый УникальныйИдентификатор(ГУИД);               

                //Если Стр.НомерЗаказа = "ЭПУТ-003737 - 02.10.2020 11:34:19 [GUID 8dcf91c6-03cc-11eb-9aff-c86000c31ebb]"
                //    ИЛИ Стр.НомерЗаказа = "ЭПУТ-003716 - 02.10.2020 11:34:19 [GUID 07cd4366-02f6-11eb-9aff-c86000c31ebb]" Тогда
                //    а=1;
                //КонецЕсли;
              
                ЗаказКлиента = Документы.ЗаказКлиента.ПолучитьСсылку(НовыйGUID);              

                Если СтрНайти("" + ЗаказКлиента,"Объект не найден") > 0 Тогда
                    ЗаказКлиента = Документы.ПоручениеЭкспедитору.ПолучитьСсылку(НовыйGUID);
                КонецЕсли;
               
                Если СтрНайти("" + ЗаказКлиента,"Объект не найден") > 0 Тогда
                    ЗаказКлиента = Документы.ЗаказНаПеремещение.ПолучитьСсылку(НовыйGUID);
                КонецЕсли;
               
                Если ЗначениеЗаполнено(ЗаказКлиента) Тогда
                    Стр.Распоряжение = ЗаказКлиента;
                    //Если ТипЗнч(ЗаказКлиента) = Тип("ДокументСсылка.ЗаказНаПеремещение") Тогда
                    //    Стр.Склад = ЗаказКлиента.СкладОтправитель;
                    //Иначе
                    //    Стр.Склад = ЗаказКлиента.Склад;
                    //КонецЕсли;
                    //Пока делаем для всех склад МСК-Опт
                    Стр.Склад = Справочники.Склады.НайтиПоНаименованию("МСК- Опт");
                    Стр.ПолучательОтправитель = Справочники.Партнеры.НайтиПоНаименованию(Стр.ТорговаяСеть);
                    Стр.Доставлено = Ложь;
                    Стр.ДоставляетсяПолностью = Истина;
                    Стр.Адрес = ЗаказКлиента.АдресДоставки;
                    Стр.АдресЗначенияПолей = ЗаказКлиента.АдресДоставкиЗначенияПолей;
                    Стр.ДополнительнаяИнформация = ЗаказКлиента.ДополнительнаяИнформацияПоДоставке;
                    Если ТипЗнч(ЗаказКлиента) = Тип("ДокументСсылка.ЗаказКлиента")
                        ИЛИ ТипЗнч(ЗаказКлиента) = Тип("ДокументСсылка.ЗаказНаПеремещение") Тогда
                        Стр.Перевозчик = ЗаказКлиента.ПеревозчикПартнер;
                        Если ЗначениеЗаполнено(Стр.Перевозчик) Тогда
                            Стр.Адрес = ЗаказКлиента.АдресДоставкиПеревозчика;
                            Стр.АдресЗначенияПолей = ЗаказКлиента.АдресДоставкиПеревозчикаЗначенияПолей;
                        КонецЕсли;
                    КонецЕсли;
                    //Уникальный номер связи строк
                    АдресУИД = Стр.Адрес;
                    АдресУИД = СтрЗаменить(АдресУИД," ","");
                    АдресУИД = СтрЗаменить(АдресУИД,",","");
                    АдресУИД = СтрЗаменить(АдресУИД,".","");
                    Стр.КлючСвязи = "" + ПрефиксУИД + Прав(АдресУИД, 12) + Лев(АдресУИД, 12) + Прав(АдресУИД, 12);
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

 

Шаг 10. И, наконец, привязываем наши Заказы к машинам (Маршрутным листам, сформированным Яндекс.Маршрутизацией):

Процедура ЗагрузитьТочкиВМаршрутныеЛисты(ТЗ) Экспорт
   
    //Обрабатываем ТЗ
    ЗаданияНаПеревозку = НайтиВсеЗаданияНаПеревозку(ТЗ);
   
    Для Каждого ТекЗадание Из ЗаданияНаПеревозку Цикл
        Если ЗначениеЗаполнено(ТекЗадание.Значение) Тогда
           
            П = Новый Структура;
            П.Вставить("ИдентификаторМашиныДля1С",ТекЗадание.Ключ);
            НайденныеСтроки = ТЗ.НайтиСтроки(П);
           
            Если НайденныеСтроки.Количество() > 2 Тогда
                Попытка
                    //Очищаем зание перед загрузкой
                    ОбЗадание = ТекЗадание.Значение.ПолучитьОбъект();
                    ОбЗадание.Маршрут.Очистить();
                    ОбЗадание.Распоряжения.Очистить();
                    ОбЗадание.ЯМ_Км_План = 0;        
                   
                    ТЗНайденныеСтроки = ТЗ.СкопироватьКолонки();
                   
                    Для Каждого Стр Из НайденныеСтроки Цикл
                                                                       
                        //Считаем километры ЯМ_Км_План
                        Если ЗначениеЗаполнено(Стр.ДлинаПутиДоТочки_Км) Тогда
                            ОбЗадание.ЯМ_Км_План = ОбЗадание.ЯМ_Км_План + Стр.ДлинаПутиДоТочки_Км;
                            //ОбЗадание.ЯМ_Км_Факт = ОбЗадание.ЯМ_Км_Факт + Стр.ДлинаПутиДоТочки_Км;
                        КонецЕсли;
                       
                        Если Стр.ТипТочки = "Склад" Тогда
                            //Парсим время
                            Попытка
                                Если СтрНайти(Стр.ВремяПрибытияНаЗаказ_Склад,"1.") > 0 Тогда
                                    ТекДатаСтрока = "" + Формат(ОбЗадание.Дата + 24*60*60,"ДФ=yyyyMMdd");
                                    СтрВремя = СтрЗаменить(Стр.ВремяПрибытияНаЗаказ_Склад,"1.","");
                                Иначе
                                    ТекДатаСтрока = "" + Формат(ОбЗадание.Дата,"ДФ=yyyyMMdd");
                                    СтрВремя = Стр.ВремяПрибытияНаЗаказ_Склад;
                                КонецЕсли;
                                СтрВремя = СтрЗаменить(СтрВремя,":","");
   
                                ТекДата = Дата(ТекДатаСтрока + СтрВремя);
                               
                                Если Не ЗначениеЗаполнено(ОбЗадание.ДатаВремяРейсаПланС) Тогда
                                    ОбЗадание.ДатаВремяРейсаПланС      = ТекДата;
                                Иначе
                                    Если ТекДата > ОбЗадание.ДатаВремяРейсаПланС Тогда
                                        ОбЗадание.ДатаВремяРейсаПланПо = ТекДата;
                                    Иначе
                                        ОбЗадание.ДатаВремяРейсаПланПо = ОбЗадание.ДатаВремяРейсаПланС; 
                                        ОбЗадание.ДатаВремяРейсаПланС  = ТекДата;
                                    КонецЕсли;
                                КонецЕсли;
                            Исключение
                            КонецПопытки;
                        Иначе
                            //Копируем строки массива в ТЗ,чтобы потом загрузить в документ
                            НовСтр_ТЗНайденныеСтроки = ТЗНайденныеСтроки.Добавить();
                            ЗаполнитьЗначенияСвойств(ТЗНайденныеСтроки,Стр);
                            НовСтр_Маршрут         = ОбЗадание.Маршрут.Добавить();
                            ЗаполнитьЗначенияСвойств(НовСтр_Маршрут,Стр);
                           
                            НовСтр_Распоряжения = ОбЗадание.Распоряжения.Добавить();
                            ЗаполнитьЗначенияСвойств(НовСтр_Распоряжения,Стр);
                        КонецЕсли;
                    КонецЦикла;
                   
                    //ТЗНайденныеСтроки.Свернуть("Адрес,ВремяС,ВремяПо,КлючСвязи,Доставлено,АдресЗначенияПолей,ДополнительнаяИнформация","Вес");
                    //ОбЗадание.Маршрут.Загрузить(ТЗНайденныеСтроки);
                   
                    ТЗНов = ОбЗадание.Маршрут.Выгрузить();
                    ТЗНов.Свернуть("Адрес,Зона,ВремяС,ВремяПо,КлючСвязи,Доставлено,АдресЗначенияПолей,ДополнительнаяИнформация","Вес,Объем");
                    ОбЗадание.Маршрут.Загрузить(ТЗНов);
                   
                    //ОбЗадание.Статус = Перечисления.СтатусыЗаданийНаПеревозку.КПогрузке;
                    //ОбЗадание.ЯМ_ПлатимЗаЧасРаботыПередРейсом = Истина;
                    ОбЗадание.ЯМ_Час_План = (ОбЗадание.ДатаВремяРейсаПланПо - ОбЗадание.ДатаВремяРейсаПланС)/3600;
                    ОбЗадание.Записать();
                Исключение
                КонецПопытки;
            КонецЕсли

            //Заполняем документ Задание на перевозку

        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Ура. Теперь можно допить чай. Осталось нарисовать для начальника волшебную кнопку “Стоимость Работ Водителей”:

&НаКлиенте
Процедура ЯМ_ЯМ_СтоимостьРаботВодителейПосле(Команда)
    //
    ОткрытьФорму("Отчет.ЯМ_СтоимостьРаботВодителей.Форма");
КонецПроцедуры

 

Делаем отчёт о работе водителя

 

Шаг 11. Делаем запрос на СКД:

ВЫБРАТЬ
    СУММА(1) КАК ВсегоТочек,
    СУММА(ВЫБОР
            КОГДА ЗаданиеНаПеревозкуМаршрут.Доставлено
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ) КАК ДоставленоТочек,
    СУММА(ВЫБОР
            КОГДА ЗаданиеНаПеревозкуМаршрут.Доставлено
                ТОГДА 0
            ИНАЧЕ 1
        КОНЕЦ) КАК НеДоставленоТочек,
    МАКСИМУМ(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_ТарифЗаКм) КАК ЯМ_ТарифЗаКм,
    МАКСИМУМ(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_ТарифЗаТочку) КАК ЯМ_ТарифЗаТочку,
    МАКСИМУМ(ЕСТЬNULL(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_Км_План, 0)) КАК ЯМ_Км_План,
    МАКСИМУМ(ЕСТЬNULL(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_Км_Факт, 0)) КАК ЯМ_Км_Факт,
    МАКСИМУМ(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_СтоимостьРейса) КАК ЯМ_СтоимостьРейса,
    ЗаданиеНаПеревозкуМаршрут.Ссылка.ТранспортноеСредство КАК ТранспортноеСредство,
    ЗаданиеНаПеревозкуМаршрут.Ссылка.Водитель КАК Водитель,
    ЗаданиеНаПеревозкуМаршрут.Ссылка КАК ЗаданиеНаПеревозку,
    ЕСТЬNULL(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_Час_План, 0) КАК ЯМ_Час_План,
    ЕСТЬNULL(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_Час_Факт, 0) КАК ЯМ_Час_Факт
ПОМЕСТИТЬ ВТТочки
ИЗ
    Документ.ЗаданиеНаПеревозку.Маршрут КАК ЗаданиеНаПеревозкуМаршрут
ГДЕ
    ЗаданиеНаПеревозкуМаршрут.Ссылка.Дата >= &ДатаНачала
    И ЗаданиеНаПеревозкуМаршрут.Ссылка.Дата <= &ДатаОкончания
    И ЗаданиеНаПеревозкуМаршрут.Ссылка.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
    ЗаданиеНаПеревозкуМаршрут.Ссылка,
    ЗаданиеНаПеревозкуМаршрут.Ссылка.ТранспортноеСредство,
    ЗаданиеНаПеревозкуМаршрут.Ссылка.Водитель,
    ЕСТЬNULL(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_Час_Факт, 0),
    ЕСТЬNULL(ЗаданиеНаПеревозкуМаршрут.Ссылка.ЯМ_Час_План, 0)
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТТочки.ВсегоТочек КАК ВсегоТочек,
    ВТТочки.ДоставленоТочек КАК ДоставленоТочек,
    ВТТочки.НеДоставленоТочек КАК НеДоставленоТочек,
    ВТТочки.ЯМ_ТарифЗаКм КАК ЯМ_ТарифЗаКм,
    ВТТочки.ЯМ_ТарифЗаТочку КАК ЯМ_ТарифЗаТочку,
    ВТТочки.ЯМ_Км_План КАК ЯМ_Км_План,
    ВТТочки.ЯМ_Км_Факт КАК ЯМ_Км_Факт,
    ВТТочки.ЯМ_СтоимостьРейса КАК ЯМ_СтоимостьРейса,
    ВТТочки.ТранспортноеСредство КАК ТранспортноеСредство,
    ВТТочки.Водитель КАК Водитель,
    ВТТочки.ЗаданиеНаПеревозку КАК ЗаданиеНаПеревозку,
    ВТТочки.ЯМ_Час_План КАК ЯМ_Час_План,
    ВТТочки.ЯМ_Час_Факт КАК ЯМ_Час_Факт,
    ВТТочки.ЯМ_Км_План - ВТТочки.ЯМ_Км_Факт КАК Км_Разница,
    ВТТочки.ЯМ_Час_План - ВТТочки.ЯМ_Час_Факт КАК Час_Разница
ИЗ
    ВТТочки КАК ВТТочки

 

Шаг 12. Проставляем Ресурсы и Настройки:

 

 

 

Шаг 13. Отчёт готов!

 

 

Ну да, не 3 проблемы, а 13. Обычно при оценке проекта первое впечатление не врёт, поэтому… его нужно смело умножать на 3 и прибавлять ещё 2, на всякий случай. Но кто бы научил правильно считать эти эстимэйты…

 

Благодарю за ваше бесценное время!

 

 

Само расширение можно скачать из вложения к статье. Там же можно увидеть полный листинг кода.

Шаблон Excel можно взять на сайте Яндекс.Маршрутизации: https://yandex.ru/routing/doc/vrp/concepts/example.html

Там же есть описание всех параметров: https://yandex.ru/routing/doc/vrp/concepts/excel-fill-guide.html

Также во вложении к публикации шаблон с примером заполнения EXCEL, который мы после 2-х месяцев подбора выработали под потребности нашей компании (напомню, 3-5 машин, около 40 заказов в день, доставка в две смены, без выходных). 

См. также

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17886    19    22    

17

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

7200 руб.

04.05.2021    20017    13    17    

17

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14492    42    8    

18

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1523    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user612295_death4321 29.08.21 22:09 Сейчас в теме
Яндекс маршрутизация не предоставляет API ? Почему пришлось взаимодействовать через Excel ?
minotavr_x86; zqzq; Albert_2008; +3 Ответить
4. greencactus 82 02.09.21 20:42 Сейчас в теме
(1) Да, API отличный.
Но ведь Эксель же обязательно нужен в любой автоматизации :)
А если серьёзно, то у нас так настроен процесс постройки маршрутного листа - формируется Эксель - утверждается,
потом загружается в маршрутизацию другим сотрудником
формируется маршрут - если что не так прям в экселе правятся параметры (для скорости) - загружается повторно
Если всё ок - отправляется электронно водителям для загрузки в машину и обратно в 1С.
Для нас через API было сложнее на момент написания кода, сейчас всё уже работает как часы, можно и на API перейти.
Подробнее почему именно так описал в первой части статьи https://infostart.ru/1c/articles/1499581/
5. user612295_death4321 02.09.21 21:54 Сейчас в теме
(4) Понятно. Ну мы примерно так же внедряли похожую систему Maxoptra. Обкатали на экселях, далее написали подсистему.

Автоматизация транспортной логистики, тема специфическая)) У каждого логиста свой взгляд на правильный маршрут)
2. tamepjlah 3 01.09.21 05:49 Сейчас в теме
За статью, однозначно, плюс.
Глаз зацепился за фразу
Т.е. на входе любой Excel, а на выходе - удобная ТаблицаЗначений, в которой колонки названы как в исходном Excel. И не нужно сопоставлять колонки по ячейкам.

и поскольку обслуживаю несколько мелких фирм с огромными хотелками, ушел писать универсальную загрузку. И при тестировании обнаружилось, что не такой уж любой Excel может быть на входе.
1) Пытаюсь загрузить файл - файл1 (я не активно пишу комментарии, поэтому как вставить картинку в текст не знаю, пусть будут прикреплённые файлы). На строчке ПЗ.Результат.Выгрузить() получаем ошибку "Ожидается выражение "ВЫБРАТЬ""
2) Пытаюсь загрузить файл - файл2. На выходе получаем очень странную таблицу значений (файл3) со странными названиями колонок. Плюс к этому почему-то имеются дубли колонок (например _11 и _12 и _13 или _81 и _82) - стоит отметить, что в колонках 6-36 указана дата 01.01.1900 с форматом ячейки ДД.
3) Попробовал убрать объединение ячеек и в колонках 6-36 указал число. На выходе получил таблицу значений (файл4) с интересными строками _1-_9. При этом пропали данные за 1 число (на скрине этого не видно, но их нет).
Прикрепленные файлы:
3. greencactus 82 02.09.21 20:36 Сейчас в теме
(2) Клёвый комент!! 5 баллов за пробу.
_1 _2 _3 это 1С пытается сделать колонки уникальными в случае если названия колонок в первоначальном Экселе одинаковые. Или если 1С не смогла создать колонку с таким названием (например как у вас - название колонки это число, а в 1С все переменные должны начинаться с буквы или _, поэтому 1С создаёт колонки с пустым названием и добавляет к пустым названием _НомерПоПорядку)
Если шаблон Экселя одинаковый, то эти «Не правильные_Правильные» названия будут всегда одинаковыми и на них можно ссылаться.

Ещё я бы удалил первые 6 строк в вашем Экселе и строкой с названиями колонок сделал бы строку номер 7 (нижняя колонка шапки) . У меня так несколько загрузчиков запчастей из Автодока и Автопитера работают и там такие же как у вас «Не правильные» колонки.

Ещё раз спасибо за коммент - прям мёд на сердце :)
6. tamepjlah 3 03.09.21 05:44 Сейчас в теме
(3) Получается, что данный код загрузки из Excel подходит для автоматизированного обмена между базами. А если в выгрузке добавят или удалят колонку, то и наименования колонок могут измениться "неведомым" образом?
7. greencactus 82 12.11.22 02:18 Сейчас в теме
(6) Долго не заходил на инфостарт =)

Хотел написать, нет, но ты прав. Если в Экселе будет много колонок, которые не называются по человечески (Сумма, Цена, Количество остатков) то вставив в середину новую или удалив первую, названия колонок собьётся.

Если колонки с человеческими названиями, то собьются только если у тебя добавится колонка с одинаковым названием раньше твоей (Типа Номенклатура, Номенклатура, Цена, Сумма, Сумма, Сумма).

А если новые колонки будут иметь новые уникальные названия, то всё ок. Хоть добавляй, хоть удаляй, хоть местами меняй.

А для обмена между базами мне больше http-сервисы нравятся и быстрее работают и результат он-лайн =)
Оставьте свое сообщение