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

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

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

КонецЦикла;

Показать

Ну и так далее, пока не дойду до максимального итога по часам (80), но у некоторых 176, здесь бы подошел скорее всего цикл пока или счетчик, но я пока еще не разобрался.
Прикрепленные файлы:
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. homer_ 76 13.10.21 13:43 Сейчас в теме
я не понял данные в колонке "название работы" могут идти не по порядку для расчетов?
что будет если работ больше 10? Стоимость работы будет 0?
3. VID1234 74 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 74 13.10.21 18:55 Сейчас в теме
(4)Спасибо. Завтра попробую! Доброго вечера!
6. VID1234 74 13.10.21 19:01 Сейчас в теме
4)
"И что значит это "должен завершится на работе с наименьшим числом"? Числом чего? Может номером? Можете объяснить?"

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

Что-то вроде этого?"
11. VID1234 74 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 74 14.10.21 10:51 Сейчас в теме
(13)Здравствуйте а число кратности -это 4 или 8?
15. vv2 14.10.21 11:00 Сейчас в теме
это минимальное из допустимых чисел. Если по заголовку вопроса - 4, а в тексте вопроса у вас разрешено 8.
Оставьте свое сообщение
Вопросы с вознаграждением
Вакансии
Программист, аналитик, эксперт 1С
Санкт-Петербург
По совместительству

Программист 1С
Москва
зарплата от 150 000 руб. до 200 000 руб.
Полный день

Ведущий разработчик 1С
Москва
зарплата от 250 000 руб.
Полный день

Руководитель проектов 1С
Москва
зарплата от 200 000 руб.
Полный день

Программист 1С
Москва
зарплата от 150 000 руб.
Полный день