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

Тема в разделе "1C и всё что с ней связано", создана пользователем anivaler, 29 авг 2008.

  1. anivaler

    anivaler Гость

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

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

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

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

    evgenyatam Well-Known Member

    Регистрация:
    7 сен 2007
    Сообщения:
    175
    Симпатии:
    0
    не знаю почему но мне в таких случаях помогает Сообщить (""+СтрокаМаршрута.ГосНомер1 + " повторяется");
     
  3. anivaler

    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 + “участвует в нескольких маршрутах”);
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;

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

    FireSTream Гость

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

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

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

    anivaler Гость

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

    Спасибо.
     
  6. FireSTream

    FireSTream Гость

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

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

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

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

    КонецПроцедуры
    Синтаксис естественно не проверял =). Прошу прощения за отсутсвие структурирования. Опера =)
     
  7. anivaler

    anivaler Гость

    to FireSTream:

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

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

    FireSTream Гость

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

    anivaler Гость

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

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

    to FireStream:

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

    anivaler Гость

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

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


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


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

    КонецПроцедуры
     
  11. FireSTream

    FireSTream Гость

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

    2)

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

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

    anivaler Гость

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

    FireSTream Гость

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

    anivaler Гость

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

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

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


    ???
     
  15. FireSTream

    FireSTream Гость

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

    anivaler Гость

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

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

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

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

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

    FireSTream Гость

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

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

    Я понятно излагаю?
     
  18. anivaler

    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).

    Спасибо.
     
  19. FireSTream

    FireSTream Гость

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

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


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

    anivaler Гость

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

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

Поделиться этой страницей