Оцените пожалуйста моё решение (Базу прилагаю) данной задачи:
Задание 3.49
В каждом документе УчебныйДень удалите последний урок. В каждом учебном
дне должно остаться по 5 уроков.
Для выполнения этого задания создайте новую процедуру в общем модуле Сер-
верный. Перед запуском и проверкой своей программы запишите где-нибудь, ка-
кой урок должен оказаться последним в каждый из дней. Чтобы у вас была
возможность проверить правильность работы.

Правильный ли у меня ход мыслей?

```1c
    //Часть в модуле приложения

    Процедура ПриНачалеРаботыСистемы()

    УстановитьКраткийЗаголовокПриложения("Фамилия Имя");

    Серверный.УдалениеЛишнихУроков();

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

    // Часть в общем модуле "Серверный" на Сервере

    Процедура УдалениеЛишнихУроков() Экспорт
    // Гововлюсь к выбору документа
    УчебныеДни = Документы.УчебныйДень.Выбрать();

    // Начинаю выбирать документы по очереди
    Пока УчебныеДни.Следующий() Цикл
    // Получаю документ
    ДокументОбъект = УчебныеДни.ПолучитьОбъект();

    // Получаю табличную часть со строками
    ТабличнаяЧасть = ДокументОбъект.Уроки;

    // С помощью метода Получить() возвращаю Тип: Строка табличной части,
    // узнаю сколько всего строк в таблице.
    // ТабличнаяЧасть.Количество() - 1 это Индекс строки
    ПоследнийУрок = ТабличнаяЧасть.Получить(ТабличнаяЧасть.Количество() - 1);

    // Использую Свойство НомерСтроки типа Строка табличной части,
    // вычисляю Индекс последнего урока, возвращаю тип: Число
    ИндексТекСтроки = ПоследнийУрок.НомерСтроки - 1;
    Пока ИндексТекСтроки >= 5 Цикл

    // Удаляю уроки которые идут после пятого урока
    ТабличнаяЧасть.Удалить(ИндексТекСтроки);

    ИндексТекСтроки = ИндексТекСтроки - 1;

    КонецЦикла;

    ДокументОбъект.Записать();

    КонецЦикла;

    КонецПроцедуры
```
//
---
```1c
    СтрокиДляУдаления = Новый Массив;
    НомерУрока = 1;
    Для каждого Строка Из ДокументОбъект.Уроки Цикл // Табличную часть ПИШЕМ КАК ЕСТЬ
    Если НомерУрока > 5 Тогда
    СтрокиДляУдаления.Добавить(Строка);
    КонецЕсли;
    НомерУрока = НомерУрока + 1;
    КонецЦикла

    Для каждого Строка Из СтрокиДляУдаления Цикл
    ДокументОбъект.Уроки.Удалить(Строка); // УДАЛЯЕМ Строку (не по индексу!)
    КонецЦикла;
```
---
по хорошему должно быть примерно так:

```1c
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | УчебныйДеньУроки.Ссылка КАК Ссылка,
    | УчебныйДеньУроки.НомерСтроки - 1 КАК ИндексСтроки
    |ИЗ
    | Документ.УчебныйДень.Уроки КАК УчебныйДеньУроки
    |ГДЕ
    | УчебныйДеньУроки.НомерСтроки > 5
    |
    |УПОРЯДОЧИТЬ ПО
    | Ссылка,
    | ИндексСтроки УБЫВ
    |ИТОГИ ПО
    | Ссылка";

    РезультатЗапроса = Запрос.Выполнить();

    ВыборкаДокументов = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

    Пока ВыборкаДокументов.Следующий() Цикл
    ДокОбъект = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
    ДокТЧ = ДокОбъект.Уроки;
    Выборка = ВыборкаДокументов.Выбрать();
    Пока Выборка.Следующий() Цикл
    ДокТЧ.Удалить(Выборка.ИндексСтроки);
    КонецЦикла;
    ДокОбъект.Записать();
    КонецЦикла;
```

Но, раз это учебный материал, то препод не поверит, что делали самостоятельно :)

Тогда несколько советов.
1. Перед получением объекта, стоит проверить: а стоит его получать? Если там в ТЧ не более 5 строк, то и изменять документ не нужно. А получение объекта это довольно затратная операция.
2. Задача на проверку удаления из коллекции. В данном случае коллекцией выступает табличная часть документа. Если удаление делается в цикле по индексу, то настоятельно рекомендуется (общепринято) с конца.
Можно и с предварительным отбором строк и удаление полученных строк, но это может быть и затратно. Если в ТЧ 99999 строк и нужно удалить последние 10000.
---
Спасибо, до запросов ещё не дошёл.
Можете мне пожалуйста эту часть пояснить? Иделально будет если ещё напишите какие Типы возвращаются в переменные, я тогда в справке сам покапаюсь.

```1c
    Пока ВыборкаДокументов.Следующий() Цикл
    ДокОбъект = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
    ДокТЧ = ДокОбъект.Уроки;
    Выборка = ВыборкаДокументов.Выбрать();
    Пока Выборка.Следующий() Цикл
    ДокТЧ.Удалить(Выборка.ИндексСтроки);
    КонецЦикла;
    ДокОбъект.Записать();
    КонецЦикла;
```
---
ВыборкаДокументов = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
ВыборкаДокументов получает данные типа ВыборкаИзРезультатаЗапроса. Так как указываем ОбходРезультатаЗапроса.ПоГруппировкам, то получаем данные, которые указаты в ИТОГИ ПО первым, в данном случае по Ссылка. Т.е. отбираем в выборку данные по Ссылка (ссылкам на документы).
Пока ВыборкаДокументов.Следующий() Цикл
Обходим выборку, чтобы получить записи.
ДокОбъект = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
Получаем объект самого документа. Тип ДокументОбъект. Получаем у выборки по полю Ссылка в запросе саму ссылку на документ и уже у этой ссылки вызываем метод ПолучитьОбъект().
Выборка = ВыборкаДокументов.Выбрать();
У выше открытой выборки ВыборкаИзРезультатаЗапроса по Ссылка получаем вложенную выборку. Т.к. ничего не указываем в параметрах, то выборка по детальным записям. Т.е. получаем значения самих полей запроса, которые имеют значение Ссылка равное Ссылка Вышестоящей выборки.
Другими словами, получаем выборку, состоящую из значений полей из запроса по конкретной ссылке.
Получаемый тип тоже ВыборкаИзРезультатаЗапроса.
Далее так же обходим выборку и удаляем из ТЧ открытого объекта документа запись по индексу, который получаем из поля ИндексСтроки запроса.

В самом запросе ИндексСтроки получаем как НомерСтроки-1, так как НомерСтроки начинается с 1, а индексы начинаются с 0.
Отбираем только те записи, где НомерСтроки>5.
Это позволяет отбирает только индексы, на основании которых необходимо удалить строки ТЧ и не получать вообще документы, в которых условие не выполняется.
В запросе упорядочиваем ИндексСтроки УБЫВ.
Это позволяет удалять строки ТЧ по индексу с конца.
---
Вроде понял. Я правильно мыслю?

```1c
    // Этот цикл выбирает документ
    Пока ВыборкаДокументов.Следующий() Цикл
    ДокОбъект = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
    ДокТЧ = ДокОбъект.Уроки;
    Выборка = ВыборкаДокументов.Выбрать();
    // Этот цикл выбирает строки начиная с 6-ой
    Пока Выборка.Следующий() Цикл
    ДокТЧ.Удалить(Выборка.ИндексСтроки);
    КонецЦикла;
    ДокОбъект.Записать();
    КонецЦикла;
```
---
если утрированно, то да.
Строки начиная с 6-й выбираются запросом. А во вложенном цикле не отслеживается, с какой там строки начать удалять. Удаляются строки по индексу, согласно полученным данным из запроса.
---
Понял, спасибо.
---
Решение норм, работать должно. А вообще надо стараться каждую задачу решать - надежно. Более профессиональный код выглядел бы так:
1. Отобрать все строки ТЧ для удаления, (.Отбор или запросом)
2. В цикле по отобранным строкам, - удаляем их из ТЗ
Потому что в твоем решении, легко допустить ошибку. Надо всё время держать в голове что

```1c
    ТабличнаяЧасть.Количество() - 1
```
 соответствует
```1c
    ИндексТекСтроки >= 5
```
---
Спасибо. Можно пожалуйста пример такого кода?
---
```1c
    СтрокиДляУдаления = Новый Массив;
    НомерУрока = 1;
    Для каждого Строка Из ДокументОбъект.Уроки Цикл // Табличную часть ПИШЕМ КАК ЕСТЬ
    Если НомерУрока > 5 Тогда
    СтрокиДляУдаления.Добавить(Строка);
    КонецЕсли;
    НомерУрока = НомерУрока + 1;
    КонецЦикла

    Для каждого Строка Из СтрокиДляУдаления Цикл
    ДокументОбъект.Уроки.Удалить(Строка); // УДАЛЯЕМ Строку (не по индексу!)
    КонецЦикла;
```
---
А как мне так же оформить код в сообщении? Всё нашёл, теперь вопрос как удалить свой коммент?