Как распределить часы кратно 4,8,12,16 и т.д.

1. VID1234 110 13.10.21 12:56 Сейчас в теме
Здравствуйте. Ребята подскажите пожалуйста, как мне распределить часы, я получил таблицу значений пропорционально сумме работ, в этой таблице пропорционально разбились часы, но разбились они не целым числом, а с десятыми и сотыми, а мне нужно чтобы часы были кратны 8 часам.
Как правильно написать цикл.
Я думаю так, но может лучше что-нибудь есть?
Отбор = Новый Структура();
					Отбор.Вставить("Сотрудник",Сотрудника.Сотрудник);
					СтрокаТЗ_ДоляЧасовВПроекте = ТЗ_ДоляЧасовВПроекте.НайтиСтроки(Отбор);
                                       Если СтрокаТЗ_ДоляЧасовВПроекте.Количество()= 0 Тогда Продолжить; КонецЕсли;
                                        МаксЗначение = 0;
					 Для Каждого Строки Из СтрокаТЗ_ДоляЧасовВПроекте Цикл
							Если Строки.Часы > МаксЗначение Тогда
							МаксЗначение = Строки.Часы;
						КонецЕсли;
					КонецЦикла;

 Для Каждого Строки Из СтрокаТЗ_ДоляЧасовВПроекте Цикл
							Если Строки.Часы < 8 И Строки.Часы <> МаксЗначение Тогда
							Разница = 8 - Строки.Часы;
                                                        СтрокаТЗ_ДоляЧасовВПроекте[0].Часы + Разница;
                                                        Отбор.Вставить("Часы",МаксЗначение);
					                 СтрокаСМаксимальнымЗначением = ТЗ_ДоляЧасовВПроекте.НайтиСтроки(Отбор);
						         КонецЕсли;
СтрокаСМаксимальнымЗначением[0].Часы = СтрокаСМаксимальнымЗначением[0].Часы - Разница;
//обновляем максимум
                                        
					 Для Каждого Строки Из СтрокаТЗ_ДоляЧасовВПроекте Цикл
							Если Строки.Часы > МаксЗначение Тогда
							МаксЗначение = Строки.Часы;
						КонецЕсли;
					КонецЦикла;
ИначеЕсли Если Строки.Часы > 8 И Строки.Часы < 16  Строки.Часы <> МаксЗначение Тогда
			Разница = 16 - Строки.Часы;
                                                        СтрокаТЗ_ДоляЧасовВПроекте[0].Часы + Разница;
                                                        Отбор.Вставить("Часы",МаксЗначение);
					                 СтрокаСМаксимальнымЗначением = ТЗ_ДоляЧасовВПроекте.НайтиСтроки(Отбор);
						         КонецЕсли;
СтрокаСМаксимальнымЗначением[0].Часы = СтрокаСМаксимальнымЗначением[0].Часы - Разница;
//обновляем максимум
                                        
					 Для Каждого Строки Из СтрокаТЗ_ДоляЧасовВПроекте Цикл
							Если Строки.Часы > МаксЗначение Тогда
							МаксЗначение = Строки.Часы;
						КонецЕсли;
					КонецЦикла;		
КонецЕсли;

КонецЦикла;

Показать

Ну и так далее, пока не дойду до максимального итога по часам (80), но у некоторых 176, здесь бы подошел скорее всего цикл пока или счетчик, но я пока еще не разобрался.
Прикрепленные файлы:
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. homer_ 78 13.10.21 13:43 Сейчас в теме
я не понял данные в колонке "название работы" могут идти не по порядку для расчетов?
что будет если работ больше 10? Стоимость работы будет 0?
3. VID1234 110 13.10.21 15:40 Сейчас в теме
(2Да! работ может быть и больше 10, тогда цикл должен завершится, на работе с наименьшим числом
4. Release 13.10.21 16:45 Сейчас в теме
(3) Что-то у вас какая-то путаница в коде.
Получатся массив строк, а имя переменной Строка...:
СтрокаТЗ_ДоляЧасовВПроекте = ТЗ_ДоляЧасовВПроекте.НайтиСтроки(Отбор);

Обрабатываются последовательно строки из этого массива строк, переменная строки называется Строки:
Для Каждого Строки Из СтрокаТЗ_ДоляЧасовВПроекте Цикл

Да ещё вложенные циклы с теми же переменными цикличности.

И что значит это "должен завершится на работе с наименьшим числом"? Числом чего? Может номером? Можете объяснить?

Но, если я правильно понял задачу, то можно как-то так, например:
РазницаНакопленная	= 0;
ЧасовДоступно		= ТаблицаДанных.Итог("Часы");
	
Для каждого СтрокаДанных Из ТаблицаДанных Цикл
	Если ЧасовДоступно = 0 Тогда
		Прервать;
	КонецЕсли;
		
	Часы = СтрокаДанных.Часы;
		
	ЧасыМин8			= Макс(Часы, 8);
	ЧасыВИтоге			= Мин(Цел(Макс(ЧасыМин8 - РазницаНакопленная, 8) / 8) * 8, ЧасовДоступно);
	Разница				= ЧасыМин - РазницаНакопленная;
	Разница				= ?(ЧасыВИтоге > Разница, 8 - Разница, ЧасыВИтоге - Разница);
	РазницаНакопленная	= ЧасыМин8 - Часы + Разница;
	ЧасовДоступно		= ЧасовДоступно - ЧасыВИтоге;
		
	СтрокаДанных.ЧасыВИтоге = ЧасыВИтоге;
КонецЦикла;
Показать

Нужно ещё бы потестировать, но на вашем примере работает.
Прикрепленные файлы:
5. VID1234 110 13.10.21 18:55 Сейчас в теме
(4)Спасибо. Завтра попробую! Доброго вечера!
6. VID1234 110 13.10.21 19:01 Сейчас в теме
4)
"И что значит это "должен завершится на работе с наименьшим числом"? Числом чего? Может номером? Можете объяснить?"

Допустим работ 10, но по долям попадут не все, сначала у кого доля распределения (Часы) больше, те в приоритете, как только закончилось время (80), цикл прерывается и та работа которая не попала, остается без чудесного Иванова, но есть и другие сотрудники у которых доля к этой работе больше, они и займутся ей!
7. Release 13.10.21 19:14 Сейчас в теме
(6) Так это уже совсем другая задача, если работы нужно учитывать и распределять по исполнителям и их объему в рамках общего объема.
Или вы это уже делаете при заполнении первичной таблицы данных?
8. VID1234 110 14.10.21 09:57 Сейчас в теме
(7) Это я уже сделал, у меня формируется общая таблица по всем работам и сотрудникам, с долях к той или иной работе. В этой таблице повторяются сотрудники с различными работами и их время распределено на то количество, в котором они участвуют! если у сотрудника 1 работа и 176 часов, то доля 176, если 2 работы, то у одной например 100 у другой 76 и т.п.
9. Release 14.10.21 10:03 Сейчас в теме
(8) Я это к тому писал, что если распределение уже сделано, то моё решение подойдёт. Если нет, то нужно дорабатывать или даже переписывать.
10. VID1234 110 14.10.21 10:13 Сейчас в теме
(9)Сделано, но не до конца, теперь мне бы из этой таблице проанализировать кого нужно отсеять, а кто влезет в предел по часам и по сумме.
для каждого Работа из Объект.Работы Цикл
Отбор = Новый Структура;
Отбор.Вставить("Работа", Работа.Работа);
МассивОтбора = ТаблицаДанных.НайтиСтроки(Отбор);
НакапливаемаяСумма = 0;
Для Каждого Стр Из МассивОтбора Цикл
НакапливаемаяСумма = НакапливаемаяСумма + Стр.СуммаПоСотруднику; 
Если Работа.СуммаПлана < НакапливаемаяСумма Тогда Прервать; КонецЕсли;
КонецЦикла;
конецЦикла;
Показать

Что-то вроде этого?"
11. VID1234 110 14.10.21 10:15 Сейчас в теме
(10) ну разумеется в этом цикле будет код по добавлению данных в табличную часть объекта!
12. Release 14.10.21 10:22 Сейчас в теме
(10) Ну, я возможно не совсем понял, что нужно. Но в моём примере, есть проверка на превышение. Можно добавить туда установку флага, для таких случаев:
Если ЧасовДоступно = 0 Тогда
    Превышение = Истина;

    Прервать;
КонецЕсли;

А далее обрабатывайте, как хотите.
13. vv2 14.10.21 10:23 Сейчас в теме
А попробуйте так:
1. делим часы в проекте и общую сумму часов, которую нужно распределить на число кратности
2. вызываем ОбщегоНазначенияКлиентСервер.РаспределитьСуммуПропорциональноКоэффициентам( делёнаяСуммаЧасов, массивЧасовПроекта);
3. числа из результирующего массива умножаем на число кратности.

UPD: в шаге 1 часы в поекте делить не надо
14. VID1234 110 14.10.21 10:51 Сейчас в теме
(13)Здравствуйте а число кратности -это 4 или 8?
15. vv2 14.10.21 11:00 Сейчас в теме
это минимальное из допустимых чисел. Если по заголовку вопроса - 4, а в тексте вопроса у вас разрешено 8.
Оставьте свое сообщение

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