Доброго всем дня, меня вдохновила статья "Всё, что вы хотели знать о динамическом программировании, но боялись спросить", за что Вам огромное спасибо.
Приоритет нашей задачи: минимизация времени выполнения поиска, так как полная проверка уходит в арифметическую прогрессию.
Где я использую этот модуль? Мне была поставлена задача распределения разносортного товара на паллеты, "1" это метр кубический - объем помещающийся на паллет. У меня была мысль раскидать по объему товар 0,25 / 0,5 / 0,75 и логически складывать, 0,5 +0,5 / 0,75 + 0,25, но это породило огромное количество когда , чем дальше, тем сложнее это было.
Для моей задачи выходом стала "Ленивая динамика:" из вышеуказанной статьи.
В этом примере из статьи идет последовательное сложение строк и перебор в цикле с какого элемента начинать сложение - перебор вариантов сложения.
Я много раз переписывал и нашел предполагаю оптимальный путь. Остается та же методика последовательного сложения строк, только на каждом этапе ( ступени ) он перед следующим шагом перепроверяет попытку сложения со всеми возможными вариантами, исключая уже использованные в сложении.
Это рабочий код из моей программы, отлаженный.
Таблица000//(Таблица Значений с товаром),
Эдиал = 1; //=1 метру кубическому
КоличествоСтрокТаб = Таблица000.Количество();//количество строк
ОтклонениеВПлюс =Число("0,1");//до 1,1
ОтклонениеВМинус = Число("0,1");//до 0,9
ОптимальнаяРазница = Эдиал;//задаем максимальную разницу
ОптимальнаяСумма = 0;
//задаем 2 табличные части или можно использовать массивы, по вкусу
ОптимальнаяТаблицаСтрок = Новый ТаблицаЗначений;
ОптимальнаяТаблицаСтрок.Колонки.Добавить("НомерСтрокиП");
ТаблицаСтрок = Новый ТаблицаЗначений;
ТаблицаСтрок.Колонки.Добавить("НомерСтрокиП");
/////////////////////////////////////////////////////////////////////////////////
//Цикл от первого элемента к последнему
Для СтартСчетчик = 0 По КоличествоСтрокТаб-1 Цикл
Счетчик = СтартСчетчик;//стартовое смещение
ТаблицаСтрок.Очистить();
ТекущаяСумма = 0;
Для ТекущийСчетчик = 0 По КоличествоСтрокТаб-1 Цикл //переменная нигде
//не используется, это клон первого цикла , контроль количества повторений,
//а первый цикл только задает последовательный обход с кого начинать
Если Счетчик = КоличествоСтрокТаб Тогда //если уходим за таблицу то в начало
Счетчик = 0;
КонецЕсли;
НоваяСтрока = ТаблицаСтрок.Добавить();//постепенно наполняем таблицу
НоваяСтрока.НомерСтрокиП = Счетчик;
ТекущаяСумма = ТекущаяСумма + Таблица000[Счетчик].ОбъемТары;
//объем Количество "/" Количество помещающее на паллет
ВнутреннийСчетчик = Счетчик+1;//временная переменная
Если ВнутреннийСчетчик = КоличествоСтрокТаб Тогда
//если уходим за таблицу то в начало
ВнутреннийСчетчик = 0;
КонецЕсли;
Пока НЕ ВнутреннийСчетчик = СтартСчетчик Цикл
// с каждым углублением количество циклов сокращается
Если ТекущаяСумма > Эдиал + ОтклонениеВПлюс Тогда
//если перебор
Прервать;
КонецЕсли;
ВариантСуммы = ТекущаяСумма + Таблица000[ВнутреннийСчетчик].ОбъемТары;
Если ВариантСуммы >= Эдиал - ОтклонениеВМинус И ВариантСуммы <= Эдиал + ОтклонениеВПлюс Тогда
//если попадает сумма в наш период вычисляем разницу
РазницаСумм = ВариантСуммы - Эдиал;
Если РазницаСумм < 0 тогда //убираем минусы
РазницаСумм = РазницаСумм * -1;
КонецЕсли;
Если РазницаСумм < ОптимальнаяРазница Тогда
ОптимальнаяРазница = РазницаСумм;
ОптимальнаяСумма = ВариантСуммы;
Для Каждого Стр Из ТаблицаСтрок Цикл
//записываем цепочку индексов строк
НоваяСтрока = ОптимальнаяТаблицаСтрок.Добавить();
НоваяСтрока.НомерСтрокиП = Стр.НомерСтрокиП;
КонецЦикла;
//дополняем из временной переменной
НоваяСтрока = ОптимальнаяТаблицаСтрок.Добавить();
НоваяСтрока.НомерСтрокиП = ВнутреннийСчетчик;
Сообщить(Строка(ОптимальнаяСумма));
КонецЕсли;
КонецЕсли;
ВнутреннийСчетчик = ВнутреннийСчетчик +1;
//если уходим за таблицу то в начало
Если ВнутреннийСчетчик = КоличествоСтрокТаб Тогда
ВнутреннийСчетчик = 0;
КонецЕсли;
КонецЦикла;//Пока Цикл
Если ТекущаяСумма > Эдиал + ОтклонениеВПлюс Тогда
Прервать;
КонецЕсли;
Счетчик = Счетчик+1;
КонецЦикла;
/////////////////////////////////////////////////////////////////////////////////////
КонецЦикла;
//добавление колонок и очистка данных
ОднаТаблица = Новый ТаблицаЗначений;
ОднаТаблица = Таблица000.Скопировать();
ОднаТаблица.Очистить();
Для Каждого Стро Из ОптимальнаяТаблицаСтрок Цикл
НоваяСтрока = ОднаТаблица.Добавить();
//заполнение нужных строк
ЗаполнитьЗначенияСвойств(НоваяСтрока, Таблица000[Стро.НомерСтрокиП]);
КонецЦикла;
Расскажу о своей задаче в общем:
В самой стартовой разработке у меня много данных хранилось в переменных, что порождало сбои в программе. Но в 1с есть очень хорошее решение связка Документ - "Регистр остатков" , остается создать документ "прихода", а потом раскидывая товар по паллетам создавая "расход" мы в любую секунду запросом получаем нераспределенный остаток товара, главное только каждый раз очищать документы перед следующим распределением. Будут конкретные вопросы в комментариях, буду рад помочь.
Товары поделены на однотипности, параметры "Фасовка" и "ВидФасовки" за их определение отвечают. В "приходе" не заполняется номер паллета, а вычисляется вышеуказанным методом.
//ОбработкаПроведения(Отказ, Режим)
//Создаем документ с табличной частью, и булево переменной "Приход"
//таким образом мы понимаем что приход, а что расход
Если Приход = Истина Тогда
// регистр РегистрРаспределениеНаПаллеты Приход
Движения.РегистрРаспределениеНаПаллеты.Записывать = Истина;
Для Каждого ТекСтрокаПродукция Из Продукция Цикл
Движение = Движения.РегистрРаспределениеНаПаллеты.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Приход = Приход;
Движение.Вариант = Вариант;
Движение.Номенклатура = ТекСтрокаПродукция.Номенклатура;
Движение.Характеристика = ТекСтрокаПродукция.Характеристика;
Движение.НомерПалета = ТекСтрокаПродукция.НомерПалета;
Движение.Однотипность = ТекСтрокаПродукция.Однотипность;
Движение.Фасовка = ТекСтрокаПродукция.Фасовка;
Движение.ВидФасовки = ТекСтрокаПродукция.ВидФасовки;
Движение.ОбъемТары = ТекСтрокаПродукция.ОбъемТары;
Движение.КоличествоНаОдинПаллет = ТекСтрокаПродукция.КоличествоНаОдинПаллет;
Движение.Количество = ТекСтрокаПродукция.Количество;
Движение.Партия = ТекСтрокаПродукция.Партия;
Движение.ЕдиницаИзмерения = ТекСтрокаПродукция.ЕдиницаИзмерения;
КонецЦикла;
Иначе
// регистр РегистрРаспределениеНаПаллеты Расход
Движения.РегистрРаспределениеНаПаллеты.Записывать = Истина;
Для Каждого ТекСтрокаПродукция Из Продукция Цикл
Движение = Движения.РегистрРаспределениеНаПаллеты.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Приход = Приход;
Движение.Вариант = Вариант;
Движение.Номенклатура = ТекСтрокаПродукция.Номенклатура;
Движение.Характеристика = ТекСтрокаПродукция.Характеристика;
Движение.НомерПалета = ТекСтрокаПродукция.НомерПалета;
Движение.Однотипность = ТекСтрокаПродукция.Однотипность;
Движение.Фасовка = ТекСтрокаПродукция.Фасовка;
Движение.ВидФасовки = ТекСтрокаПродукция.ВидФасовки;
Движение.ОбъемТары = ТекСтрокаПродукция.ОбъемТары;
Движение.КоличествоНаОдинПаллет = ТекСтрокаПродукция.КоличествоНаОдинПаллет;
Движение.Количество = ТекСтрокаПродукция.Количество;
Движение.Партия = ТекСтрокаПродукция.Партия;
Движение.ЕдиницаИзмерения = ТекСтрокаПродукция.ЕдиницаИзмерения;
КонецЦикла;
КонецЕсли;
Стартовый обход документа "Приход".
&НаСервере
Функция ФункцияОбходаПрихода() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегистрРаспределениеНаПаллеты.Период,
| РегистрРаспределениеНаПаллеты.Регистратор,
| РегистрРаспределениеНаПаллеты.НомерСтроки,
| РегистрРаспределениеНаПаллеты.Активность,
| РегистрРаспределениеНаПаллеты.ВидДвижения,
| РегистрРаспределениеНаПаллеты.Приход,
| РегистрРаспределениеНаПаллеты.Вариант,
| РегистрРаспределениеНаПаллеты.Номенклатура,
| РегистрРаспределениеНаПаллеты.Характеристика,
| РегистрРаспределениеНаПаллеты.НомерПалета,
| РегистрРаспределениеНаПаллеты.Однотипность,
| РегистрРаспределениеНаПаллеты.Фасовка,
| РегистрРаспределениеНаПаллеты.ВидФасовки,
| РегистрРаспределениеНаПаллеты.ОбъемТары,
| РегистрРаспределениеНаПаллеты.КоличествоНаОдинПаллет,
| РегистрРаспределениеНаПаллеты.Партия,
| РегистрРаспределениеНаПаллеты.МоментВремени,
| РегистрРаспределениеНаПаллеты.ЕдиницаИзмерения,
| РегистрРаспределениеНаПаллеты.Количество
|ИЗ
| РегистрНакопления.РегистрРаспределениеНаПаллеты КАК РегистрРаспределениеНаПаллеты
|ГДЕ
| РегистрРаспределениеНаПаллеты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)";
Выборка = Запрос.Выполнить().Выбрать();
//Выборка.Следующий();
Возврат Выборка;
КонецФункции
Функция вычисления следующего паллета для распределения.
&НаСервере
Функция ФункцияМаксимальныйНомерПаллетаПлюсОдин() Экспорт//Следующий
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(РегистрРаспределениеНаПаллеты.НомерПалета) КАК НомерПалета
|ИЗ
| РегистрНакопления.РегистрРаспределениеНаПаллеты КАК РегистрРаспределениеНаПаллеты";
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
Если ЗначениеЗаполнено(Выборка.НомерПалета) Тогда
Возврат Выборка.НомерПалета+1;
Иначе
Возврат 1;
КонецЕсли;
КонецФункции
Далее два запроса на поиск остатков свободного товара, готового к распределению. Параметры "Начало" и "Конец" отвечают за выбираемый объем если требуется. Однотипность - число от 1 и выше.
&НаСервере
Функция ФункцияОстатковСвободныхПоОднотипности(Однотипность, Начало, Конец) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегистрРаспределениеНаПаллетыОстатки.Номенклатура,
| РегистрРаспределениеНаПаллетыОстатки.Характеристика,
| РегистрРаспределениеНаПаллетыОстатки.Однотипность КАК Однотипность,
| РегистрРаспределениеНаПаллетыОстатки.Фасовка,
| РегистрРаспределениеНаПаллетыОстатки.ВидФасовки,
| РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет,
| РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток КАК Количество,
| РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток / РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет КАК ОбъемТары,
| РегистрРаспределениеНаПаллетыОстатки.ЕдиницаИзмерения,
| РегистрРаспределениеНаПаллетыОстатки.Партия
|ИЗ
| РегистрНакопления.РегистрРаспределениеНаПаллеты.Остатки КАК РегистрРаспределениеНаПаллетыОстатки
|ГДЕ
| РегистрРаспределениеНаПаллетыОстатки.Однотипность = &Однотипность
| И РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток / РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет <= &Конец
| И РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток / РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет > &Начало
|
|УПОРЯДОЧИТЬ ПО
| ОбъемТары УБЫВ";
Запрос.УстановитьПараметр("Однотипность", Однотипность);
Запрос.УстановитьПараметр("Начало", Начало);
Запрос.УстановитьПараметр("Конец", Конец);
Результат = Запрос.Выполнить();
Возврат Результат;
КонецФункции
// по всем остаткам
&НаСервере
Функция ФункцияОстатковСвободных(Начало, Конец) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегистрРаспределениеНаПаллетыОстатки.Номенклатура,
| РегистрРаспределениеНаПаллетыОстатки.Характеристика,
| РегистрРаспределениеНаПаллетыОстатки.Однотипность КАК Однотипность,
| РегистрРаспределениеНаПаллетыОстатки.Фасовка,
| РегистрРаспределениеНаПаллетыОстатки.ВидФасовки,
| РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет,
| РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток КАК Количество,
| РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток / РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет КАК ОбъемТары,
| РегистрРаспределениеНаПаллетыОстатки.ЕдиницаИзмерения,
| РегистрРаспределениеНаПаллетыОстатки.Партия
|ИЗ
| РегистрНакопления.РегистрРаспределениеНаПаллеты.Остатки КАК РегистрРаспределениеНаПаллетыОстатки
|ГДЕ
| РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток / РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет <= &Конец
| И РегистрРаспределениеНаПаллетыОстатки.КоличествоОстаток / РегистрРаспределениеНаПаллетыОстатки.КоличествоНаОдинПаллет > &Начало
|
|УПОРЯДОЧИТЬ ПО
| ОбъемТары УБЫВ";
Запрос.УстановитьПараметр("Начало", Начало);
Запрос.УстановитьПараметр("Конец", Конец);
Результат = Запрос.Выполнить();
Возврат Результат;
КонецФункции
Функция записи документа.
НомерПалета = ФункцияМаксимальныйНомерПаллетаПлюсОдин();//вышеуказанная
ПеременнаяОбъема = 0;
//цикл по полученной таблице
Для каждого СтрокаТЗ Из ОднаТаблица Цикл
ПеременнаяОбъема = ПеременнаяОбъема + СтрокаТЗ.ОбъемТары;
Если ПеременнаяОбъема <= Число("1,05") Тогда
//////////////////////////// пока не перебор, записывать
НоваяСтрока = НовыйДокумент.Продукция.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
НоваяСтрока.НомерПалета = НомерПалета;
////////////////////////////
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
Комментарии (16)
punzik
06.01.2022 09:19+2Скажите, почему выбрано такое название переменной (константы)? Что вы имели в виду?
Эдиал = 1; //=1 метру кубическому
Это в начале первого листинга.
stone-w1987 Автор
06.01.2022 14:27Доброго дня, спасибо за вопрос, есть неполный паллет или есть переполненый паллет, а "Эдиал = 1" это оптимальное значение заполнения.
TiesP
06.01.2022 09:48+1Классно, конечно. Когда передо мной поставили подобную задачу (в типовой «Торговле 11» 1С), я не рискнул её решать на таком низком уровне с помощью алгоритмов) Просто использовал для распределения похожий типовой алгоритм, который распределяет по ячейкам (в модуле адресного хранения). При этом под «ячейками» подразумевал «паллеты».
stone-w1987 Автор
06.01.2022 14:30Доброго дня, по Вашему профилю предполагаю что Вы критик, спасибо за комментарий, он мне поможет в будущем, так как я начинающий специалист и у меня все впереди.
Уточите, там есть оптимизация укладки по ячейкам? или ручное распределение по ячейкам?
Из интернета: Ячеистый или Адресный склад – это склад, который разделяют на зоны хранения, каждая из которых предназначена для хранения определенной номенклатурной позиции.
Но у нас не для определенной номенклатуры же.
TiesP
06.01.2022 16:52+1Да, конечно, автоматически заполняет (можно выбрать из нескольких вариантов заполнения). Там это применяется, когда приходит товар и его надо распределить по ячейкам, чтобы дальше дать задание складским работникам на раскладку товара уже физически по ячейкам.
Но у нас не для определенной номенклатуры же.
А для чего? Вы же пишите в коде «Движение.Номенклатура = ТекСтрокаПродукция.Номенклатура;»
Опишу в целом, как там работает. Может вам пригодится.
Сначала нужно провести некоторые предварительные действия — заполнить разные служебные справочники. Например, для Номенклатуры добавить «Упаковки» и указать для них размеры. (это могут быть типовые размеры для разной номенклатуры). Например: коробка — ширина=0.1; высота=0.2; длина=0.5. Дальше у адресного склада создаются Ячейки и у них тоже указываются типоразмеры. Например: ширина=1.0; высота=0.8; длина=1.0. В моём случае я принимаю, что 20 ячеек — это означает 20 паллет со своими размерами. То есть это некий «виртуальный» склад, которого нет в реальности.
Дальше у нас есть список номенклатуры со своим количеством и нам надо распределить номенклатуру в эти 20 паллет. Приведу некоторые основные куски кода.кодМенеджер = Новый МенеджерВременныхТаблиц; Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = Менеджер; Запрос.Текст = "ВЫБРАТЬ | ТаблицаНоменклатурыДляЗапроса.Номенклатура КАК Номенклатура, | ТаблицаНоменклатурыДляЗапроса.Упаковка КАК Упаковка, | ТаблицаНоменклатурыДляЗапроса.Характеристика КАК Характеристика, | ТаблицаНоменклатурыДляЗапроса.Назначение КАК Назначение, | ВЫРАЗИТЬ(ТаблицаНоменклатурыДляЗапроса.Серия КАК Справочник.СерииНоменклатуры) КАК Серия, | ТаблицаНоменклатурыДляЗапроса.КоличествоУпаковок КАК КоличествоУпаковок |ПОМЕСТИТЬ ТаблицаНоменклатурыДляЗапроса |ИЗ | &Товары КАК ТаблицаНоменклатурыДляЗапроса |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ ... Запрос.УстановитьПараметр("Товары",ТаблицаКРазмещению); Запрос.УстановитьПараметр("Склад",ТекСкл); Запрос.Выполнить(); ОшибкаПроверки = Ложь; СтруктураВозврата = СкладыСервер.РазместитьТоварВЯчейках( Менеджер, ТекСкл, Справочники.СкладскиеПомещения.ПустаяСсылка(), Справочники.РабочиеУчастки.ПустаяСсылка(), Справочники.СкладскиеЯчейки.ПустаяСсылка(), ОшибкаПроверки); Менеджер.Закрыть(); тзРез = СтруктураВозврата.ТаблицаРезультатов; ЗаполнитьЯчейки(тзРез); ... тзОш = СтруктураВозврата.ТаблицаОшибок;
То есть, в итоге мы вызываем типовую функцию: «СкладыСервер.РазместитьТоварВЯчейках» и получаем в итоге «СтруктураВозврата», у которой есть таблица распределения «СтруктураВозврата.ТаблицаРезультатов» (что удалось распределить) и таблица ошибок «СтруктураВозврата.ТаблицаОшибок» (что не удалось распределить)stone-w1987 Автор
06.01.2022 20:26Спасибо за информацию для размышления.
Но у нас не для определенной номенклатуры же.
А для чего? Вы же пишите в коде «Движение.Номенклатура = ТекСтрокаПродукция.Номенклатура;»
Я имел ввиду, что можно ли разные номенклатуры хранить в одной ячейке, так как паллеты складываются из разносортного товара, Ваш метод считаем по габаритам "высота - ширина - длина", а у меня вычисляется коэффициент объема.
Из интернета: Ячеистый или Адресный склад – это склад, который разделяют на зоны хранения, каждая из которых предназначена для хранения определенной номенклатурной позиции.
Из вышеуказанного определения нет.
TiesP
06.01.2022 22:06Да, там есть разные настройки (разные стратегии распределения). Например, заполнять на 100% по объему. (или заполнять по весу). Также есть настройки для ячеек — хранить только один вид товара или хранить разные товары в одной ячейки. По сути, там тот же объем, как у вас, и используется в первом случае. Просто, возможно, еще проверяются габариты. (но я так глубоко не проверял). У вас какая конфигурация? Такое адресное хранение есть только в новых типовых, типа Торговля-11 или Комплексная-редакция 2 и т.п.
kovserg
06.01.2022 23:53Я чего-то не понимаю. Но что выдаст «рабочий и отлаженный код» если будут вот такие входные данные:
{ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 }?stone-w1987 Автор
07.01.2022 15:380.1 0.9
0.1, 0.2, 0.7
0.1, 0.2, 0.3, 0.4
......
kovserg
08.01.2022 01:391C у меня нет, поэтому попробую на lua описать:
Псевдокодfunction main(tab) one=1 n=#tab dsp=0.1 dsm=0.1 dso=one so=0 opt={} for i=1,n do j=i wrk={} cs=0.0 for k=1,n do if j==n then j=1 end table.insert(wrk,j) cs=cs+tab[j] j1=j+1 if j1>n then j1=1 end while j1~=i do if cs>one+dsp then break end sv=cs+tab[j1] if sv>=one-dsm and sv<=one+dsp then ds=sv-one if ds<0 then ds=-ds end if ds<dso then dso=ds so=sv for _,j2 in pairs(wrk) do table.insert(opt,j2) end table.insert(opt,j1) print(so) end end j1=j1+1 if j1>n then j1=1 end end if cs>one+dsp then break end j=j+1 end end print "---" for k,v in pairs(opt) do print(v,tab[v]) end end
На выходе:main { 0.1, 0.2, 0.3, 0.4, 0.5, 0.5, 0.6, 0.7, 0.8, 0.9 }
0.9
1.0
---
1 0.1
9 0.8
1 0.1
10 0.9
Может я чего накосячил, но вроде соответствует вашему коду?
OkunevPY
07.01.2022 10:28Сколько это всё выполняться будет при скажем номенклатуре 10к позиций и складских остатках более 1млн записей?
Мне кажеться даже алгоритм с википедии реализованный на любом компилируемом языке покажет большую производительность.
stone-w1987 Автор
07.01.2022 15:41Так причем тут весь склад, если Вам нужно понять сколько паллет нужно отгрузить в машину к примеру на определенный заказ.
LARII
07.01.2022 19:54Первая строка:
Таблица000//(Таблица Значений с товаром),
Работать не будет, ошибка, или это формальный параметр?
//добавление колонок и очистка данных
ОднаТаблица = Новый ТаблицаЗначений;
ОднаТаблица = Таблица000.Скопировать();Это простите что? Создаете коллекцию конструктором, потом следующей строкой создаете клон прототипом из Таблица000 в ту же переменную.
Fodin
А Вы не робкий. На Хабре выложить 1С-листинги лично я бы, наверное, не осмелился.
stone-w1987 Автор
Главное это преумножение опыта, прочитав одну статью я сделал вывод, поделился этим выводом, и узнал из комментариев еще варианты решения этой проблемы, и этому очень рад.