Имя: Пароль:
1C
1С v8
Проверка номенклатуры на имеющиеся ссылки
, ,
0 LastSoldier
 
19.01.15
11:45
Всем привет! Пытаюсь создать свою первую внешнюю обработку, как сделать отбор для удаления только той номенклатуры на которую не были созданы документы в базе, КРОМЕ "Установки цен номенклатуры"
1 busy1
 
19.01.15
11:48
Запросом из регистров по котором документы делают движения. Если движений нет, запрос пустой, тогда номеклатуру удалять.
2 Rie
 
19.01.15
11:49
(2) Если вопрос о том, как проверить, какого вида документом создано движение - см. ССЫЛКА.
3 ssh2QQ6
 
19.01.15
11:49
(0) > Пытаюсь создать свою первую внешнюю обработку... для удаления

Первая обработка и сразу для удаления.
4 Cube
 
19.01.15
11:49
СП:

Глобальный контекст (Global context)
НайтиПоСсылкам (FindByRef)

Синтаксис:
НайтиПоСсылкам(<СписокСсылок>)

Параметры:
<СписокСсылок> (обязательный)
Тип: Массив.
Массив со списком ссылок на объекты, ссылки на которые нужно найти.

Возвращаемое значение:
Тип: ТаблицаЗначений.
Возвращает ссылки на найденные объекты в виде ТаблицаЗначений.
Первая колонка - исходная ссылка.
Вторая колонка - ссылка на объект, если найденная ссылка соответствует объектной таблице или значение, олицетворяющее запись необъектной таблицы.
Третья колонка - объект метаданных, которому соответствуют данные в которых найдена ссылка.

Описание:
Осуществляет поиск ссылок на объекты, переданные в параметре <СписокСсылок>.
5 LastSoldier
 
19.01.15
11:50
Запрос = Новый Запрос;
Запрос.Текст = "
   |ВЫБРАТЬ
   | Номенклатура.Ссылка
   |ИЗ
   | Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить().Выбрать();

Пока РезультатЗапроса.Следующий() Цикл
  Элемент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
  
  Если  Тогда
      
      Элемент.ПометкаУдаления = Истина;
  
  КонецЕсли;

Пока вот что я смог написать
6 LastSoldier
 
19.01.15
11:51
(3) а это плохо что первая для удаления? )) или плохой признак?))
7 Fish
 
19.01.15
11:53
(6) Это нормально. Главное, чтобы вторая не была для восстановления того, что удалила первая.
8 LastSoldier
 
19.01.15
11:57
(7) на тестовой проверим )
Мне надо отобрать только тот товар, на который в базе вообще нет никаких документов или есть только установка цен номенклатуры, остальные не трогать
9 Rie
 
19.01.15
11:57
(5) Бред. Проверку на удаление надо не в цикле делать, а непосредственно в запросе. Ну и уж если стоит задача проверить движения - то в запросе же и проверить, были ли они.
10 LastSoldier
 
19.01.15
11:58
(9) я еще не спец по запросам, только простое могу написать.
11 Rie
 
19.01.15
11:59
(8) Пройдись по метаданным. Собери те виды документов, которые могут трогать номенклатуру. Впихни в запрос.
(0) А что делать с теми, на которые были ссылки в "УстановкаЦенНоменклатуры"? Удалить - и получить битые ссылки в результате?
Кроме того, на номенклатуру могут ссылаться и объекты, не делающие движений.
12 Rie
 
19.01.15
12:00
(10) Ну так учись... Что тут ещё можно сказать?
(Насчёт проверки помеченных на удаление - в _конструкторе запросов_ содержится как бы намёк, как проверить).
13 Rie
 
19.01.15
12:01
+(12) И см. (6).
14 LastSoldier
 
19.01.15
12:03
(12) вот как раз начал учиться )
(11) мне не нужные битые ссылки.
Надо чтобы только была поставлена пометка на удаление номенклатуры и все, удалю я ее сам потом
15 hhhh
 
19.01.15
12:03
(10) в общем обработок писать не надо. Помечаешь всю номенклатуру для удаления. И запускаешь удаление помеченных объектов. Те, которых нет в документах удалятся, те, которые есть, останутся.
16 LastSoldier
 
19.01.15
12:05
(15) я уже пробовал, мне такой вариант не подходит, остается номенклатура которая есть только в документах "установка цен", а мне ее то же надо удалить, так как движения по ней вообще в базе нет
17 LastSoldier
 
19.01.15
12:07
(13) так Вы говорите, проще все то что мне надо сделать в "Запросе"? там можно и ставить пометку на удаление?
18 Rie
 
19.01.15
12:08
(16) А сами документы установки цен удалять не пробовал? А почему? Если удалишь номенклатуру, которая есть в документах установки цен - висячие ссылки пойдут. А это нехорошо.
19 LastSoldier
 
19.01.15
12:09
(18) мне их удалять нельзя, так как там есть товар используемый в базе
20 Rie
 
19.01.15
12:10
(17) Ставить - нельзя. А проверить - можно. Насчёт проверки вида документа - см. ССЫЛКА. Но! Придётся в запросе справочник Номенклатура соединить со всеми регистрами, где он встречается. И со всеми документами, где он встречается. И со всеми справочниками, где он встречается.
Это можно сделать автоматически - пробежаться по метаданным и сформировать часть текста запроса, отвечающую за соединения.
Но - см. (6). Получишь все ссылки. Потом проверишь.
21 Rie
 
19.01.15
12:11
(19) "Наш пламенный привет родным и близким. Или, говоря иными словами, родным и близким - наш пламенный привет".
Угадай, как будут выглядеть эти документы (которые удалять нельзя) после удаления номенклатуры.
Реши, что с ними делать. А уж потом занимайся удалением.
22 LastSoldier
 
19.01.15
12:23
(21) еще раз говорю мне надо сделать только пометку на удаление номенклатуры и все.
А для документов "Установка цен", у меня уже есть другая обработка которая проверяет, если номенклатура помечена на удаление, то удалить ее из установки цен и перезаписать документ. все 5 документов установки цен
23 LastSoldier
 
19.01.15
12:26
(4) Я несколько раз читал Ваше сообщение, но так ничего и не понял, в теории я примерно представляю свою задачу, а вот на практике пока еще нет
24 Cube
 
19.01.15
12:39
(23) На вот, готовый инструмент: http://files.webfile.ru/5c1f7b1359d5c08b67b2e60cb0059445

Пользоваться, примерно так: http://storage2.static.itmages.ru/i/15/0119/h_1421660274_1896596_ab2332a054.jpg

Указал тип, объекта, поставил галочку "Комментировать", нажал "Пробный поиск", на все вопросы ответил утвердительно.
25 LastSoldier
 
19.01.15
12:40
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Подскажите, я не пойму почему по этому запросу он начал с буквы "П", а потом "А"?
Или он берет первую созданную номенклатуру?
26 Rie
 
19.01.15
12:41
(25) А какая хрен разница, с какой буквы он начал?
Если надо сортировать по наименованию - так и скажи в запросе.
27 Cube
 
19.01.15
12:45
+(24) Ах да, писал сам, но давно (еще под 8.1, вроде), так что, что там и как - не помню))) Но код открыт, можешь ознакомиться.
28 LastSoldier
 
19.01.15
12:45
(24) Извините что не указал ут 11.
Готовый эт конечно хорошо, вот только бы понять как самому делать, а то все время на готовом
(26) ну я не знаю как должно быть, вот и спросил
29 LastSoldier
 
19.01.15
12:46
(27) понял, посмотрю код
30 Cube
 
19.01.15
12:47
(28) Запусти свою УТ11 на обычных формах ключом "/RunModeOrdinaryApplication" и пользуйся на здоровье
31 Rie
 
19.01.15
12:47
(25) Возьми НайтиСсылки(). Выбери из них все, которые не установка цен (а вернее, ещё и не регистр цен). Можно сначала выгрузить во временную таблицу - а затем по ней запросом пройтись.
32 LastSoldier
 
19.01.15
13:08
(25) Почему по этому запросу берет группы, мне их трогать нельзя.
33 Rie
 
19.01.15
13:10
(32)
ГДЕ
    НЕ Номенклатура.ЭтоГруппа
34 ДенисЧ
 
19.01.15
13:10
(32) а условие на группу поставить? И сортировку:
35 LastSoldier
 
19.01.15
13:13
(33) Спасибо, нашел где это в запросе надо было  выбирать
36 Serg_1960
 
19.01.15
13:18
(офф) Эх... в былые временя тут бы накидали кучу алгоритмов попоиску не используемых позиций номенклатуры и устроили состязания на тему, чей алгоритм самый быстрый...
37 LastSoldier
 
19.01.15
13:19
(31) А можно просмотреть список всех ссылок номенклатуры?


(25)
Элемент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
Элемент.НайтиСсылки();
ну так чет не работает, еще не могу понять где их смотреть.
Смотрел в РезультатЗапроса.Ссылка, так там нет установки цен
38 Rie
 
19.01.15
13:22
(37) У НайтиСсылки - параметры есть. Ну и не поэлементно искать надо, а сразу массив из всех сунуть в качестве параметра.
Не РезультатЗапроса.Ссылка, а в запросе (если документы в запросе перебираешь, а не по НайтиСсылка) - Регистратор ССЫЛКА Документ.УстановкаЦенНоменклатуры.
39 LastSoldier
 
19.01.15
13:47
(38) так у меня нет поля "Регистратор", пока не пойму как его добавить
40 Cube
 
19.01.15
13:49
(36) Смысл обсасывать в 100500 раз то, что гуглится за 5 минут?
41 LastSoldier
 
19.01.15
13:52
(40) ппц, я не там искал сори
42 LastSoldier
 
19.01.15
13:55
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка,
               |    ЦеныНоменклатуры.Регистратор
               |ИЗ
               |    РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
               |        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
               |        ПО ЦеныНоменклатуры.Номенклатура = Номенклатура.Ссылка
               |ГДЕ
               |    НЕ Номенклатура.ЭтоГруппа
               |    И ЦеныНоменклатуры.Регистратор ССЫЛКА Документ.УстановкаЦенНоменклатуры
               |
               |УПОРЯДОЧИТЬ ПО
               |    Номенклатура.Наименование";
РезультатЗапроса = Запрос.Выполнить().Выбрать();


Как-то так получилось, только тут поругался "НЕ Номенклатура.ЭтоГруппа" (Но можно было игнорить)
43 Serg_1960
 
19.01.15
13:55
(40) Смысл.Не, это как бы намёк ТС :)
44 Serg_1960
 
19.01.15
13:56
Номенклатура.ЭтоГруппа = ЛОЖЬ
45 LastSoldier
 
19.01.15
14:13
Пишет неоднозначное поле "НЕ Номенклатура.ЭтоГруппа", если го удалить, то пишет  неоднозначное поле "ЦеныНоменклатуры.Номенклатура = Номенклатура.Ссылка"
46 Rie
 
19.01.15
14:14
(42) Зачем ЛЕВОЕ СОЕДИНЕНИЕ? Замени на ВНУТРЕННЕЕ.
И не майся с группой - в регистре их не будет, а если соединение - внутреннее, то и в результат запроса группы не попадут.

(44) Ошибка у него в другом - Номенклатура непонятно откуда берётся - но ли это имя таблицы (КАК), то ли имя поля (и из какой таблицы).
47 LastSoldier
 
19.01.15
14:14
неоднозначное поле "ПО ЦеныНоменклатуры.Номенклатура = Номенклатура.Ссылка"
48 Rie
 
19.01.15
14:15
(45) Всяко неоднозначное. Переименуй таблицу в спрНоменклатура, к примеру. И имена таблиц перед именами полей указывай (через точку).
49 LastSoldier
 
20.01.15
12:24
Вот я как раз и не могу понять как получить этот СписокСсылок (не для всех товаров сразу, а для каждого отдельно), для НайтиПоСсылкам(<СписокСсылок>);
50 LastSoldier
 
21.01.15
08:59
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура
               |ГДЕ
               |    НЕ Номенклатура.ЭтоГруппа
               |
               |УПОРЯДОЧИТЬ ПО
               |    Номенклатура.Наименование";
РезультатЗапроса = Запрос.Выполнить().Выбрать();

Пока РезультатЗапроса.Следующий() Цикл
     Элемент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
     МассивСсылок = Новый Массив;
     МассивСсылок.Добавить(РезультатЗапроса.Ссылка);
     ТабСсылок = НайтиПоСсылкам(МассивСсылок);
     Если ТабСсылок.Количество() >0 тогда
        
            Элемент.ПометкаУдаления = Истина;     
     КонецЕсли;
        
    
КонецЦикла;

Пока дела идут успешно, осталось обработать результаты )
51 FIXXXL
 
21.01.15
09:32
Элемент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
это лучше под
Если ТабСсылок.Количество() >0 тогда
убрать

нифиг базу без толку дергать :)
52 LastSoldier
 
22.01.15
08:47
https://yadi.sk/d/Pq4icrh9e9i2p вот, оцените внешнюю обработку и скажите замечания. Она сразу проверяется всю номенклатуру
53 LastSoldier
 
22.01.15
13:56
Только она что-то очень долго отрабатывает, можно этот как-то ускорить?
54 LastSoldier
 
26.01.15
09:46
Процедура ВыполнитьИзменениеНаСервере()

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура
               |ГДЕ
               |    НЕ Номенклатура.ЭтоГруппа
               |
               |УПОРЯДОЧИТЬ ПО
               |    Номенклатура.Наименование";
РезультатЗапроса = Запрос.Выполнить().Выбрать();

Пока РезультатЗапроса.Следующий() Цикл
     МассивСсылок = Новый Массив;
     МассивСсылок.Добавить(РезультатЗапроса.Ссылка);
     Элементов=1;
     Пока РезультатЗапроса.Следующий() Цикл
         Элементов = Элементов + 1;
         МассивСсылок.Добавить(РезультатЗапроса.Ссылка);
         Если Элементов = 100 Тогда
             Элементов=1;
             Прервать;
         КонецЕсли;
    КонецЦикла;
    ТабСсылок = НайтиПоСсылкам(МассивСсылок);
     //Если ТабСсылок.Количество() >0 тогда
          //Сч=ТабСсылок.Количество() - 1;
          Для каждого Элем ИЗ МассивСсылок цикл
             //Пока Сч>=0 Цикл
            Для Индекс=МассивСсылок.Найти(Элем) ПО Индекс=Индекс+1 цикл
                ДРегистры=ТабСсылок.Получить(Индекс).Метаданные.Синоним;
                Если (ДРегистры="Установка цен номенклатуры")
                    или (ДРегистры="Группы значений доступа")
                    или (ДРегистры="(не используется) Группы значений доступа") Тогда
                    Индекс=Индекс+1;
                Иначе
                    Прервать;
                КонецЕсли;
                //Если Сч=0 Тогда    
                //    ВыполнитьПометкуУдаления(РезультатЗапроса.Ссылка);
                //КонецЕсли;
            КонецЦикла;
        КонецЦикла;
     // Иначе
     //       ВыполнитьПометкуУдаления(РезультатЗапроса.Ссылка);
     //КонецЕсли;
КонецЦикла;
55 LastSoldier
 
26.01.15
09:48
Подскажите как сделать двойной цикл, мне надо обходить сначала по элементам массива(название номенклатуры), а потом обходить ссылки этой номенклатуры, пробовал так "Для Индекс=МассивСсылок.Найти(Элем) ПО Индекс=Индекс+1 цикл"
не работает, подскажите
56 Рэйв
 
26.01.15
09:52
(55)
Для Каждого Элемент Из ТвойМассив Цикл
    
КонецЦикла

А как ты собираешься внутри одного названия обходить ссылки?
Дубли ищешь чтоли?
57 LastSoldier
 
26.01.15
09:56
(56) ну я когда по циклу беру первый элемент (название номенклатуры), потом мне надо по другому циклу обходить его ссылки и смотреть, если они подходят под условие
ДРегистры=ТабСсылок.Получить(Индекс).Метаданные.Синоним;
                Если (ДРегистры="Установка цен номенклатуры")
                    или (ДРегистры="Группы значений доступа")
                    или (ДРегистры="(не используется) Группы значений доступа") Тогда
и других ссылок на этот элемент нету, то пометить его на удаление, а если есть другие ссылки, то перейти к следующему элементу и тд
58 LastSoldier
 
26.01.15
09:59
Процедура ВыполнитьИзменениеНаСервере()

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура
               |ГДЕ
               |    НЕ Номенклатура.ЭтоГруппа
               |
               |УПОРЯДОЧИТЬ ПО
               |    Номенклатура.Наименование";
РезультатЗапроса = Запрос.Выполнить().Выбрать();

Пока РезультатЗапроса.Следующий() Цикл
     Элемент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
     МассивСсылок = Новый Массив;
     МассивСсылок.Добавить(РезультатЗапроса.Ссылка);
     ТабСсылок = НайтиПоСсылкам(МассивСсылок);
     Если ТабСсылок.Количество() >0 тогда
          Сч=ТабСсылок.Количество() - 1;
          Пока Сч>=0 Цикл
                ДРегистры=ТабСсылок.Получить(Сч).Метаданные.Синоним;
                Если (ДРегистры="Установка цен номенклатуры")
                    или (ДРегистры="Группы значений доступа")
                    или (ДРегистры="(не используется) Группы значений доступа") Тогда
                    Сч=Сч-1;
                Иначе
                    Прервать;
                КонецЕсли;
                Если Сч=0 Тогда    
                    ВыполнитьПометкуУдаления(РезультатЗапроса.Ссылка);
                КонецЕсли;
          КонецЦикла;
     Иначе
            ВыполнитьПометкуУдаления(РезультатЗапроса.Ссылка);
     КонецЕсли;
КонецЦикла;
    
КонецПроцедуры

Просто если брать так, то эта обработка отрабатывает за двое суток примерно, я так и не дождался, я хочу ускорить ее работу, добавив в массив ссылки не 1 элемента, а сразу 100 элементов
59 LastSoldier
 
27.01.15
10:17
скажите, в НайтиПоСсылкам(<СписокСсылок>, <ОбластьПоиска>, <ВключитьОбъекты>, <ИсключитьОбъекты>) , работают "ИсключитьОбъекты"? а то как не пишу, выдает ошибку

     МассивИскл = Новый Массив;
     МассивИскл.Добавить(Метаданные.Документы.Найти("УстановкаЦенНоменклатуры"));
     МассивИскл.Добавить(Метаданные.РегистрыСведений.Найти("ГруппыЗначенийДоступа"));
     МассивИскл.Добавить(Метаданные.РегистрыСведений.Найти("УдалитьГруппыЗначенийДоступа"));
     ТабСсылок = НайтиПоСсылкам(МассивЭлементов,,,МассивИскл);

Ошибка
{Форма.Форма.Форма(36)}: Ошибка при вызове метода контекста (НайтиПоСсылкам)
ТабСсылок = НайтиПоСсылкам(МассивЭлементов,,,МассивИскл);
по причине:
Несоответствие типов (параметр номер '4')
60 LastSoldier
 
27.01.15
10:21
Ут 11.1.9.66
1С Предприятие 8.3.5.1383
61 LastSoldier
 
27.01.15
14:31
Вот уже готовое решение если кому интересно


&НаСервере
Процедура ВыполнитьИзменениеНаСервере()

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура
               |ГДЕ
               |    НЕ Номенклатура.ЭтоГруппа
               |
               |УПОРЯДОЧИТЬ ПО
               |    Номенклатура.Наименование";
РезультатЗапроса = Запрос.Выполнить().Выбрать();

Пока РезультатЗапроса.Следующий() Цикл
     МассивЭлементов = Новый Массив;
     МассивЭлементов.Добавить(РезультатЗапроса.Ссылка);
     Элементов=1;
     Пока РезультатЗапроса.Следующий() Цикл
         Элементов = Элементов + 1;
         МассивЭлементов.Добавить(РезультатЗапроса.Ссылка);
         Если Элементов = 500 Тогда
             Элементов=1;
             Прервать;
         КонецЕсли;
     КонецЦикла;
     ТабСсылок = НайтиПоСсылкам(МассивЭлементов);
     Если ТабСсылок.Количество() >0 тогда
          Сч=ТабСсылок.Количество() - 1;
          Пока Сч>=0 Цикл
                ДРегистры=ТабСсылок.Получить(Сч).Метаданные.Синоним;
                Если (ДРегистры="Установка цен номенклатуры")
                    или (ДРегистры="Группы значений доступа")
                    или (ДРегистры="(не используется) Группы значений доступа") Тогда
                    ТабСсылок.Удалить(Сч);
                    Сч=Сч-1;
                Иначе
                    Сч=Сч-1;
                КонецЕсли;
            КонецЦикла;
     КонецЕсли;
     ТабСсылок.Свернуть("Ссылка");
     СчМ=МассивЭлементов.Количество() - 1;
     Пока СчМ>=0 Цикл
         СтрокаСРМ=МассивЭлементов.Получить(СчМ).Наименование;
         СчТ=ТабСсылок.Количество() - 1;
         Пока СчТ>=0 Цикл
             СтрокаСРТ=ТабСсылок.Получить(СчТ).Ссылка.Наименование;
             Если СтрокаСРМ=СтрокаСРТ Тогда
                 Прервать;
                 СчТ=-1;
             Иначе
                 СчТ=СчТ-1;
             КонецЕсли;
             Если СчТ=-1 Тогда
                 ВыполнитьПометкуУдаления(РезультатЗапроса.Ссылка);
             КонецЕсли;
         КонецЦикла;
         СчМ=СчМ-1;
     КонецЦикла;
КонецЦикла;
    
КонецПроцедуры

&НаСервере
Процедура ВыполнитьПометкуУдаления(ЭлементПометкиУдаления)
            ЭлементПометкиУдаленияОбъект = ЭлементПометкиУдаления.ПолучитьОбъект();
            ЭлементПометкиУдаленияОбъект.УстановитьПометкуУдаления(Истина);
            ЭлементПометкиУдаленияОбъект.Записать();
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьИзменение(Команда)
    ВыполнитьИзменениеНаСервере();
КонецПроцедуры