• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Цикл по табличному полю...Не получается. Помогите.

  • Автор темы anivaler
  • Дата начала
A

anivaler

Помогите, пожалуйста! Мне нужно в табличном поле СписокОбслужМаршрутов пробежаться по колонке ГосНомер1 и найти повторяющиеся значения для каждого элемента колонки.
Я пишу:
ВсегоСтрок = СписокОбслужМаршрутов.Количество();
Для Каждого СтрокаМаршрута ИЗ СписокОбслужМаршрутов Цикл
Для НомерСтроки = 1 По ВсегоСтрок - 1 Цикл
СледСтрока = СписокОбслужМаршрутов.Получить(НомерСтроки).ГосНомер1;
Если СтрокаМаршрута.ГосНомер1 = СледСтрока Тогда
Сообщить (СтрокаМаршрута.ГосНомер1 + " повторяется");
КонецЕсли;
КонецЦикла;
КонецЦикла;

Так он у меня мало того, что не выводит ничего в окно служебных сообщений (хотя повторяющиеся в колонке есть), так ещё и сообщение об ошибке выдает.
Ошибка такая.

Преобразование значения к типу Число не может быть выполнено.
Сообщить (СтрокаМаршрута.ГосНомер1 + " повторяется");

Подскажите, что делать. Заранее благодарен.
 
E

evgenyatam

не знаю почему но мне в таких случаях помогает Сообщить (""+СтрокаМаршрута.ГосНомер1 + " повторяется");
 
A

anivaler

У меня теперь другая проблема. Мне из табличного поля теперь нужно сравнивать строки с тремя колонками: ГосНомер1, НР1См, КР1См.
Я сегодня целый день промучился. Не знаю, как это сделать. Т.е. нужно сравнить первую сроку со второй, с третьей, с четвёртой и т.д. Потом вторую с третьей, четвертой и т.д. Сначала вычислить есть ли повторения в колонке ГосНомер1, а если есть, то уже потом смотреть на НР1См и КР1См.
Я начал делать так. Сначала создал таблицу значений с соответствующими колонками, а затем заполнил их соответствующими значениями из табличного поля.

ТабЗнач1 = Новый ТаблицаЗначений;
ТабЗнач1.Колонки.Добавить (“НР1См”);
ТабЗнач1.Колонки.Добавить (“КР1См”);
ТабЗнач1.Колонки.Добавить (“ГосНомер1”);
Для Каждого СтрокаМаршрута Из СписокОбслужМаршрутов Цикл
НоваяСтрока1 = ТабЗнач.Добавить();
НоваяСтрока1.НР1См = СтрокаМаршрута.Маршрут.НР1См;
НоваяСтрока1.КР1См = СтрокаМаршрута.Маршрут.КР1См;
НоваяСтрока1.ГосНомер1 = СтрокаМаршрута.ГосНомер1;
КонецЦикла;

Затем сравнивал строки из табличного поля со строками табличной части.

Для Каждого СтрокаМаршрута ИЗ СписокОбслужМаршрутов Цикл
Для Каждого НоваяСтрока1 Из ТабЗнач1 Цикл
Если (СтрокаМаршрута.ГосНомер1 = НоваяСтрока1.ГосНомер1) И СтрокаМаршрута.Маршрут.НР1См >= НоваяСтрока1.НР1См) Тогда
Сообщить (Строка(НоваяСтрока1.ГосНомер1 + “участвует в нескольких маршрутах”);
КонецЕсли;
КонецЦикла;
КонецЦикла;

Но таким способом он сравнивает строку с самой собой (идентичной строкой из таблицы значений, а эти строки меня не интересуют). Подскажите как лучше сделать…Застрял на этом конкретно…
 
F

FireSTream

Подскажу красивый метод. Выгружаешь колонку в память, Вставляешь колонку "Кол-Во" которую заполняешь единичками.
После этого пользуешь метод ТаблицыЗначений "Свернуть". Колонки свертки - твой госНомер, колонка суммирования - это самое кол-во.

Потом проходишь по полученной таблице и те номера, в строках которых КОл-Во будет больше единицы будут повторяться в таблице.

Может, это помоежет. Напиши, что именно нужно сделать - будет видно точнее.
 
A

anivaler

Всё. Разобрался. Работает. Только теперь мне эту проверку нужно делать при изменении ячейки в колонке ГосНомер1 табличного поля. Первоначально все ячейки у меня пустые. Для ячейки ГосНомер1 у меня стоит поле выбора. Как только пользователь выбирает значение для любой ячейки в этой колонке - происходит моя проверка.
Как будет выглядеть процедура этого события для моей задачи?

Спасибо.
 
F

FireSTream

Примерно так
Код:
Функция ЕстьПовторения(ппТЗ,ппИмяКолонки)
ппТЗ.Колонки.Добавить("КолВоВнутр");
ппТЗ.ЗаполнитьЗначения("КолВоВнутр",1);
ппТЗ.Свернуть(ппИмяКолонки,"КолВоВнутр");

Для каждого пСтрока из ппТЗ Цикл
Если пСтрока.КолВоВнутр > 1 Тогда Возврат Истина;
КонецЦикла;

Возврат Ложь;
КонецФункции

Процедура ОбработкаИзменения(...)
пЕстьПовторения = ЕстьПовторения(тзДанные.Выгрузить(),"ГосНомер1");

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

Синтаксис естественно не проверял =). Прошу прощения за отсутсвие структурирования. Опера =)
 
A

anivaler

to FireSTream:

подожди, а на какое событие табличного поля вешать процедуру ОбработкаИзменения? или я чего-то не понял...

Там есть ВЫБОР и ВЫБОРЗНАЧЕНИЯ, причём ВЫБОРЗНАЧЕНИЯ идёт после ВЫБОР'а... Или вообще не эти мне нужны? =)
 
F

FireSTream

Смотря что тебе нужно. В твоем случае, думается, логичнее повесить ее не на ТабличноеПоле а на элемент управления в ячейке. Стандартное событие "При Изменении". (Выделяй не само ТП а ячейку в колонке нужной). Если ТЗ лепится динамически то обработчик события можно точно так же динамически налепить...
 
A

anivaler

У меня есть колонка ГосНомер1. При выборе в ней значения должна идти проверка повторения значения в НЕЙ, а если таковое повторение имеется, то проверять две другие колонки НР1См и КР1См.

Сначала я сделал так. Заполнил ВСЕ поля табличного поля. Затем прошелся по всем значениям и проверил есль ли повторяющиеся (Сначала создал таблицу значений с соответствующими колонками, а затем заполнил их соответствующими значениями из табличного поля. Затем сравнивал строки из табличного поля со строками таблицы значений). Но потом сказали сделать по-другому. Т.е. проверять на повторение ТОЛЬКО ЧТО введённое значение в ячейках колонки ГосНомер1. И вот я не знаю как лучше сделать...Подскажите...

to FireStream:

Разобрался с событием ПРИИЗМЕНЕНИИ. Скорее всего оно то мне и нужно. Но есть одна проблема. Получается, что при каждом изменении значения в ячейке колонки ГосНомер1 мне нужно созавать всё новую и новую таблицу значений, а мне нужно чтобы при первом изменении любой ячейки созалась новая ТЗ, а при изменении остальных ячеек я работал с ней (потму что в ней уже будут сохранённые значения изменённых ячеек). Это возможно сделать или в этом случае с ТЗ ничего не получится?
 
A

anivaler

У меня есть документ "РазнарядкаНаДатуГород". В нём табличная часть СписокОбслужМаршрутов. В ней реквизит Маршрут с типом СправочникиСсылка.МаршрутыГород. Как мне обратиться к значению реквизита НР1См справочника МаршрутыГород?

Вот мой пример. После слова Тогда мне нужно в колонку таблицы значений НР1См вставить значение реквизита НР1См справочника МаршрутыГород (У меня реквизит Маршрут документа РазнарядкаНаДатуГород в табличное поле не входит - так надо)


Процедура ВыборГосНомераВЯчейке(Элемент)
Если ТЗ = Неопределено Тогда
ТабЗнч = Новый ТаблицаЗначений;
ТабЗнч.Колонки.Добавить("НР1См");
ТабЗнч.Колонки.Добавить("КР1См");
ТабЗнч.Колонки.Добавить("ГосНомер1");
ТекущееЗначениеТабПоля = ЭлементыФормы.СписокОбслужМаршрутов.ТекущаяСтрока.ГосНомер1;
НайденноеЗначение = ТабЗнч.Найти(ТекущееЗначениеТабПоля, "ГосНомер1");
Если НайденноеЗначение = Неопределено Тогда
НоваяСтрокаТЗ = ТабЗнч.Добавить();
НоваяСтрокаТЗ.ГосНомер1 = ТекущееЗначениеТабПоля;
ИначеЕсли НайденноеЗначение = ТекущееЗначениеТабПоля Тогда


КонецЕсли;
КонецЕсли

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

FireSTream

Да, можно пробежаться по готовой таблице. А можно вообще ничего не делать и просто воспользоваться методом НайтиСтроки(), в качестве отбора передать Структуру(ГосНомер1). Если найдет больше одной значит есть повторения. Искать можно непосредственно в табличной части ничего не выгружая. Судя по всему оно вам подойдет больше всего. (опять же если я правильно уяснил задачу)

2)

Реквизит есть в ТаблицеЗначений но не входит в табличное поле, связанное с табличной частью?

Если так то все просто. СВойство табличного поля "ТекущиеДанные" хранит ссылку на строку табличной части. Даже если в табличном поле нет реквизита, присутствующего в Т.Ч, в Текущих данных он будет.
 
A

anivaler

Нет. Реквизит есть в табличной части, но колонки этого реквизита нет в табличном поле...
 
F

FireSTream

Он будет виден через "текущиеданные" если табличное поле связано с табличной частью.
 
A

anivaler

Всё. Нашёл. Спасибо, FireSTream.

Ещё вопрос. Как мне поставить условие, что я нахожусь в колонке ГосНомер1 табличного поля?
(Документ РазнарядкаНаДатуГород, в нём табличная часть СписокОбслуживающихМаршрутов, а в ней этот реквизит ГосНомер1)

Если ЭтаКолонка - это колонка ГосНомер1 Тогда
//действия
КонецЕсли;


???
 
F

FireSTream

Код:
тп = ЭлементыФормы.ТабличноеПоле;
Если тп.ТекущаяКолонка = тп.Колонки.ГосНомер1 Тогда ... КонецЕсли;
 
A

anivaler

Ок. Попробую. И ещё один вопрос.

У меня есть Регистр Сведений “СвободныеВодителиГород”. В нём:
Измерение – Водитель с типом СправочникСсылка.Сотрудники.
Ресурс – ВидРаботы с типом ПеречисленияСсылка.ВидыЗанятости.
Реквизиты – Бригада с типом Число, ГосНомер с типом СправочникСсылка.ГаражныеНомера

Ещё есть Перечисление “ВидыЗанятости”. В нём два значения: Выходной и Отпуск.

На свою процедуру “ВыборШофера“ вешаю событие ОбработкаВыбора для поля ввода колонки Шофер в табличной части “СписокОбслужМаршрутов”.
Мне нужно чтобы при выборе Шофера в этой колонке происходила проверка шофера – в отпуске он или у него выходной. Но я не знаю как обратиться к этим ресурсам РегистраСведений, или мне к измерению надо обращаться. Помогите…

Процедура ВыборШофера (Элемент, ВыбранноеЗначение, СтандартнаяОбработка);
Если ВыбранноеЗначение = ??? Тогда
Сообщить (Этот водитель в отпуске);
СтандартнаяОбработка = Ложь;
Иначе
// действия
КонецЕсли;
КонецПроцедуры;
 
F

FireSTream

Стоит побольше почитать про регистры сведений. В частности про способ хранения данных. Честно говоря, не совсем понимаю почему структура регистра именно такая, ну да ладно, это не важно.

Поюзай метод "СрезПоследних()". Синстаксис смотри в хелпе. Вернет тебе самые актуальные данные для шофёра. Грубо говоря делаешь срез по шофёру, регистр возвращает тебе самую свежую запись. Если таковой нет значит шофер работает. Если есть - смотришь ресурс - возвращаемой записи.

Я понятно излагаю?
 
A

anivaler

Ок. Понятно. Гляну, спасибо. Сегодня мучался с процедурой своей.

В табличном поле на полевода колонки ГосНомер1 вешаю событие “ОбработкаВыбора”. Тип реквизита ГосНомер1 – СправочникСсылка.ГаражныеНомера.
Тут есть также две колонки НР1См и КР1См. Создаю таблицу значений с такими же колонками. И обрабатываю 3 ситуации поиска в ТЗ:

1. Когда в ТЗ не найдено ВыбранноеЗначение и найдено ТекущееЗначение ячейки.
2. Когда не найдено ни то ни другое
3. Когда не найдено ТекущееЗначение (пустая ячейка) и найдено ВыбранноеЗначение

Всё работает отлично, только не знаю как обработать ситуацию, когда мы в табличном поле, в ячейке, где стоит какое-то значение жмём Очистить (крестик). Стертое значение ячейки остается в ТЗ, и при последующем выборе этого значения в табличном поле выдаёт мою ошибку: "Ошибка! Автобус: " + НайденныйГосНомер + " участвует в пересекающихся маршрутах."
Как запихнуть сюда событие Очистить вообще не представляю. Или как-то по-другому можно сделать?

[codebox]Процедура ПроверкаГосНомеров(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)

Если ТЗ = Неопределено Тогда
ТабЗнач = Новый ТаблицаЗначений;
ТабЗнач.Колонки.Добавить("НР1См");
ТабЗнач.Колонки.Добавить("КР1См");
ТабЗнач.Колонки.Добавить("ГосНомер1");
СтрокаТабЗнач = ТабЗнач.Добавить();
СтрокаТабЗнач.ГосНомер1 = ВыбранноеЗначение;
СтрокаТабЗнач.НР1См = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.Маршрут.НР1См;
СтрокаТабЗнач.КР1См = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.Маршрут.КР1См;
ТЗ = ТабЗнач;
Иначе
ТекЗначениеГосНомер1 = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.ГосНомер1;
ТекЗначениеНР1См = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.Маршрут.НР1См;
ТекЗначениеКР1См = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.Маршрут.КР1См;
//проверка изменения существующего значения в ячейке колонки ГосНомер1
//если текущее значение ячейки найдено в ТЗ и текущие значения НР1См и КР1См совпадают
//c соответствующими значениями в ТЗ, то тогда меняем это значение в ТЗ на выбранное значение
СтрокаТЗТекГосНом = ТЗ.Найти(ТекЗначениеГосНомер1, "ГосНомер1");
СтрокаТЗВыбГосНом = ТЗ.Найти(ВыбранноеЗначение, "ГосНомер1");
Если (СтрокаТЗВыбГосНом = Неопределено) И (СтрокаТЗТекГосНом <> Неопределено) Тогда
ИндСтрТЗТекГосНом = ТЗ.Индекс(СтрокаТЗТекГосНом);
ГосНомер1 = ТЗ[ИндСтрТЗТекГосНом].ГосНомер1;
НР1См = ТЗ[ИндСтрТЗТекГосНом].НР1См;
КР1См = ТЗ[ИндСтрТЗТекГосНом].КР1СМ;
Если (ТекЗначениеГосНомер1 = ГосНомер1) И (ТекЗначениеНР1См = НР1См) И (ТекЗначениеКР1См = КР1См) Тогда
ТЗ[ИндСтрТЗТекГосНом].ГосНомер1 = ВыбранноеЗначение;
КонецЕсли;
//если не найден выбранный и не найден текущий, тогда добавляем новую строку в ТЗ
ИначеЕсли (СтрокаТЗВыбГосНом = Неопределено) И (СтрокаТЗТекГосНом = Неопределено) Тогда
СтрокаТабЗнач = ТЗ.Добавить();
СтрокаТабЗнач.ГосНомер1 = ВыбранноеЗначение;
СтрокаТабЗнач.НР1См = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.Маршрут.НР1См;
СтрокаТабЗнач.КР1См = ЭлементыФормы.СписокОбслужМаршрутов.ТекущиеДанные.Маршрут.КР1См;

Иначе ИндексНайденнойСтрокиТЗ = ТЗ.Индекс(СтрокаТЗВыбГосНом);
НайденныйГосНомер = ТЗ[ИндексНайденнойСтрокиТЗ].ГосНомер1;
НР1См = ТЗ[ИндексНайденнойСтрокиТЗ].НР1См;
КР1См = ТЗ[ИндексНайденнойСтрокиТЗ].КР1См;
Если ВыбранноеЗначение = НайденныйГосНомер Тогда
Если ((НР1См > ТекЗначениеНР1См) И (НР1См < ТекЗначениеКР1См)) ИЛИ
((НР1См < ТекЗначениеНР1См) И (КР1См > ТекЗначениеНР1См)) Тогда
Сообщить ("Ошибка! Автобус: " + НайденныйГосНомер + " участвует в пересекающихся маршрутах.",СтатусСообщения.Внимание);
СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;

КонецПроцедуры[/codebox]


И объясните вот что. Пустые ячейки табличного поля хранят ПустыеСсылки. Как будет выглядеть пустаяссылка для моих пустых ячеек? (У меня документ Разнарядка, табличная часть СписокОбслужМаршрутов, реквизит ГосНомер1).

Спасибо.
 
F

FireSTream

Пустая ссылка хранится в типизированных полях ссылочного типа. Допустим у вас справочник "Гаражные номера" пустая ссылка на него - ссылка на несуществующий элемент Справочники.ГаражныеНомера.ПустаяСсылка()

Если, допустим есть ТЗ но ее колонка не типизирована то там не будет никаких пустых ссылок. будет неопределено.


По поводу задачи:
Так я и не вник в то что вы пытаетесь сделать. Тяжко думать по ночам. Может завтра подумаю. Если можете, напишите формально чего хотите добиться. Уникальности какихто полей в ТЗ или чего.
 
A

anivaler

Конкретно мне нужно следующее. При нажатии на Очистка (крестик) в любой ячейке этой колонки, мне нужно в соответсвующей колонке ТЗ это значение тоже должно удалиться. И этой ячейке ТЗ присвоено выбранное значение (если его выбрали конечно). Но я не знаю как вставить событие Очистка в событие ОбработкаВыбора...

Еще по поводу моей задачи. Я делаю следующее. Проверяю сначала Перем ТЗ. Является ли она таблицей значений. Если нет, то делаем её таблицей значений и добавляем выбранный элемент в неё.
Дальше выбираем в ТП следующий элемент. Играем с текущим и выбранным значением...
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!