Формирование пакетов изделий по количеству, не превышающему указанное

1. Qupkbe 18.08.23 09:26 Сейчас в теме
Приветствую!
Имеем формируемую таблицу ИсходнаяТЗ с колонками Наименование и Количество. Величина Количество произвольное, целое, неотрицательное. Содержимое ИсходнаяТЗ может быть,например, таким:

ИсходнаяТЗ
Наименование Количество

Наименование1 5
Наименование2 7
Наименование3 4
Наименование4 8
Наименование5 1
и т.п.

Требуется сформировать из ИсходнойТЗ таблицу ТЗ с колонками НомерПакета Наименование Количество так, чтобы общее количество изделий в пакете было равным переменной КоличествоВПакете. Превышающее это значение количество отдельной позиции переходит в другой пакет.
Пример: КоличествоВПакете=6

ТЗ

НомерПакета Наименование Количество

1 Наименование1 5
1 Наименование2 1
2 Наименование2 6
3 Наименование3 4
3 Наименование4 2
4 Наименование4 6
5 Наименование5 1

Может есть готовое красивое решение?
По теме из базы знаний
Найденные решения
14. user1826630 18.08.23 14:37 Сейчас в теме
(13)
Функция РаспределениеПоПакетам(Знач ИсходнаяТаблица, ОграничениеКоличестваПакета)

	ТаблицаРезультат = ИсходнаяТаблица.СкопироватьКолонки();
	ТаблицаРезультат.Колонки.Добавить("НомерПакета", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)));
	НомерТекущегоПакета = 1; КоличествоТекущегоПакета = 0;

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

			Если КоличествоТекущегоПакета = ОграничениеКоличестваПакета Тогда 
				НомерТекущегоПакета      = НомерТекущегоПакета + 1; 
				КоличествоТекущегоПакета = 0;
			КонецЕсли;
			
		КонецЦикла;            
		
	КонецЦикла;
	
	Возврат ТаблицаРезультат;
	
КонецФункции
Показать
Qupkbe; newlogin1; +2 Ответить
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. user1826630 18.08.23 10:16 Сейчас в теме
Лень самому написать 10 строк кода?
3. Qupkbe 18.08.23 11:04 Сейчас в теме
(2)То то и оно, что в 10 строк не укладываюсь. Минимум 40
4. user1826630 18.08.23 11:27 Сейчас в теме
15. user1826630 18.08.23 15:53 Сейчас в теме
(3) Вот 14 строк. Но за такой код надо бить по рукам. Куча одинаковых действий и повторяющиеся поиски по ТЗ.
	ТаблицаРезультат = ИсходнаяТаблица.СкопироватьКолонки();
	ТаблицаРезультат.Колонки.Добавить("НомерПакета", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)));
	НомерТекущегоПакета = 1; КоличествоТекущегоПакета = 0;
	Для Каждого ИсходнаяСтрока Из ИсходнаяТаблица Цикл    
		Пока ИсходнаяСтрока.Количество > 0  Цикл    
			ЗаполнитьЗначенияСвойств(ТаблицаРезультат.Добавить(), ИсходнаяСтрока);
			ТаблицаРезультат[ТаблицаРезультат.Количество()-1].НомерПакета = НомерТекущегоПакета;
			ТаблицаРезультат[ТаблицаРезультат.Количество()-1].Количество  = Мин(ОграничениеКоличестваПакета, ИсходнаяСтрока.Количество, ОграничениеКоличестваПакета - КоличествоТекущегоПакета); 
			ИсходнаяСтрока.Количество = ИсходнаяСтрока.Количество - ТаблицаРезультат[ТаблицаРезультат.Количество()-1].Количество;
			КоличествоТекущегоПакета  = КоличествоТекущегоПакета   + ТаблицаРезультат[ТаблицаРезультат.Количество()-1].Количество;
			НомерТекущегоПакета       = ?(КоличествоТекущегоПакета = ОграничениеКоличестваПакета, НомерТекущегоПакета + 1, НомерТекущегоПакета); 
			КоличествоТекущегоПакета  = ?(КоличествоТекущегоПакета = ОграничениеКоличестваПакета, 0, КоличествоТекущегоПакета);
		КонецЦикла;            
	КонецЦикла;
Показать

Могу еще на одну уменьшить...
5. newlogin1 18.08.23 12:01 Сейчас в теме
(2)Не, в 10 у меня не получилось, только в 12, покажи как в 10

Результат = Исх.Скопировать();
Результат.очистить();
Для Каждого СтрокаИсх Из Исх Цикл
	Пока Истина Цикл	
		Если СтрокаИсх.Количество = 0 Тогда Прервать; КонецЕсли;
		СтрРез = Результат.ДОбавить();
		ЗаполнитьЗначенияСвойств(СтрРез, СтрокаИсх);
		КолВоРаспр = Минимум(СтрокаИсх.Количество, КоличествоВПакете); 
		СтрРез.Количество = КолВоРаспр;
		СтрокаИсх.Количество = СтрокаИсх.Количество - КолВоРаспр;  		
	КонецЦикла;			
КонецЦикла;
Показать
6. newlogin1 18.08.23 12:14 Сейчас в теме
(5)Можно сделать 11 если меняем
Результат = Исх.Скопировать();
Результат.очистить();

на
Результат = Исх.Скопировать().очистить()

Но все равно не 10.
7. Westonline82 18.08.23 12:16 Сейчас в теме
(6) Нет колонки "НомерПакета". В 10 строк совсем никак...
8. newlogin1 18.08.23 12:24 Сейчас в теме
(7)Если я правильно понял, то получается 15, разве что вообще все в одно строку зафигачить, тогда получится. Но это уже черная магия (да и с Если я уже так сделал))
Результат = Исх.Скопировать().очистить();
Результат.Колонки.ДОбавить("пакет", Общегоназначения.Описаниетипачисло(3));
Пакет = 1;
Для Каждого СтрокаИсх Из Исх Цикл    
Пока Истина Цикл    
        Если СтрокаИсх.Количество = 0 Тогда Прервать; КонецЕсли;
        СтрРез = Результат.ДОбавить();
        ЗаполнитьЗначенияСвойств(СтрРез, СтрокаИсх);
        КолВоРаспр = Минимум(СтрокаИсх.Количество, КоличествоВПакете); 
        СтрРез.Количество = КолВоРаспр;
        СтрокаИсх.Количество = СтрокаИсх.Количество - КолВоРаспр;  
       СтрРез.Пакет = Пакет;
       Пакет = Пакет +1;        
    КонецЦикла;            
КонецЦикла;
Показать
9. user1826630 18.08.23 12:28 Сейчас в теме
(5) И где у тебя номер пакета и контроль количества в пакете?
10. newlogin1 18.08.23 12:30 Сейчас в теме
(9)
И где у тебя номер пакета
- уже исправили, опоздал)
контроль количества в пакете?
- чуть внимательнее смотри, вот эта строка
КолВоРаспр = Минимум(СтрокаИсх.Количество, КоличествоВПакете); 
11. пользователь 18.08.23 12:44
Сообщение было скрыто модератором.
...
12. newlogin1 18.08.23 12:51 Сейчас в теме
(11)Теперь увидел. Не смотрел что в пакете мы собираем всю номенклатуру, главное чтобы количество было меньше, а не отдельные. Тогда извиняюсь)
Но тогда точно не получается в 10 строк, 40 кажется не таким уж большим если на то пошло. Или у вас есть замечательная идея которая позволяет эту задачку записать в 10 строк? У меня получается чуть больше 20 с проверкой (теперь то точно ничего не забыл))
Результат = Исх.Скопировать().очистить();
	Результат.Колонки.ДОбавить("пакет", Общегоназначения.Описаниетипачисло(3));
	Пакет = 1;
	КоличествоВПакетеРаспр = 0;
	Для Каждого СтрокаИсх Из Исх Цикл    
		Пока Истина Цикл    
			Если СтрокаИсх.Количество = 0 Тогда Прервать; КонецЕсли;
			СтрРез = Результат.ДОбавить();
			ЗаполнитьЗначенияСвойств(СтрРез, СтрокаИсх);
			КолВоРаспр = Минимум(СтрокаИсх.Количество, КоличествоВПакете); 
			Если КоличествоВПакетеРаспр + КолВоРаспр > КоличествоВПакете Тогда
				КолВоРаспр = КоличествоВПакете - КоличествоВПакетеРаспр;
			КонецЕсли;
			КоличествоВПакетеРаспр = КоличествоВПакетеРаспр + КолВоРаспр;	
			СтрРез.Количество = КолВоРаспр;
			СтрокаИсх.Количество = СтрокаИсх.Количество - КолВоРаспр;  
			СтрРез.Пакет = Пакет;	
			Если КоличествоВПакетеРаспр = КоличествоВПакете Тогда 
				Пакет = Пакет +1; 
				КоличествоВПакетеРаспр = 0;
			КонецЕсли;
		КонецЦикла;            
	КонецЦикла;
Показать
13. пользователь 18.08.23 13:14
Сообщение было скрыто модератором.
...
14. user1826630 18.08.23 14:37 Сейчас в теме
(13)
Функция РаспределениеПоПакетам(Знач ИсходнаяТаблица, ОграничениеКоличестваПакета)

	ТаблицаРезультат = ИсходнаяТаблица.СкопироватьКолонки();
	ТаблицаРезультат.Колонки.Добавить("НомерПакета", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)));
	НомерТекущегоПакета = 1; КоличествоТекущегоПакета = 0;

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

			Если КоличествоТекущегоПакета = ОграничениеКоличестваПакета Тогда 
				НомерТекущегоПакета      = НомерТекущегоПакета + 1; 
				КоличествоТекущегоПакета = 0;
			КонецЕсли;
			
		КонецЦикла;            
		
	КонецЦикла;
	
	Возврат ТаблицаРезультат;
	
КонецФункции
Показать
Qupkbe; newlogin1; +2 Ответить
16. Qupkbe 22.08.23 08:54 Сейчас в теме
Благодарю за помощь newlogin1 и конечно user1826630!
Ваш код ощутимо компактнее моего
В окончательном варианте добавил переменную, в которую сохраняется значение ИсходнаяСтрока.Количество. Так как исходная таблица в моем случае не должна изменяться.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот