Имя: Пароль:
1C
1С v8
Подбор свободного кода справочника "Номенклатура"
0 Shade84
 
07.07.14
15:01
Как можно осуществить подбор свободного кода справочника "Номенклатура" без захвата одного и того же кода несколькими операторами, подскажите, пожалуйста?
Код для 7.7 есть, может кто адаптировать поможет?
Процедура ВводНового(ПризнКопирования)            

Спр         = СоздатьОбъект("Справочник.Номенклатура");

ФП        = СоздатьОбъект("Текст");

ТабКод      = СоздатьОбъект("ТаблицаЗначений");

ТабКод.НоваяКолонка("КодНом","Число");

Файл                  = ФС.НайтиПервыйФайл(КаталогИБ()+"*.nomer");

Пока   ПустаяСтрока(Файл) = 0 цикл

ТабКод.НоваяСтрока();

ТабКод.КодНом     = Число(СокрЛП(Лев(Файл,СтрДлина(СокрЛП(Файл))-6)));  

Файл              = ФС.НайтиСледующийФайл();

КонецЦикла;

Если ТабКод.КоличествоСтрок() > 0  Тогда  

ТабКод.ВыбратьСтроки();

Пока ТабКод.ПолучитьСтроку() = 1 Цикл

КН = Число(ТабКод.КодНом);

КонецЦикла;  

Иначе

КН = 0;

КонецЕсли;

Для К = КН + 1 ПО 99999 Цикл

Если (Спр.НайтиПоКоду(К) = 0)Тогда

Код=К;

Прервать;

КонецЕсли;

КонецЦикла;

ФП.Записать(КаталогИБ()+Код+".nomer");

//=========================================================================================================================

Процедура ПриЗаписи()  и Процедура ПриЗакрытии()

      // вставляем в конец процедур:

ФС.УдалитьФайл(КаталогИБ()+Код+".nomer");

или

Процедура ПрисвоитьНовыйКод(пКод)
    Спр=СоздатьОбъект("Справочник."+Вид());
    Для А=пКод По пКод+1000 Цикл
        Если (Спр.НайтиПоКоду(А)=1) И (Спр.ТекущийЭлемент()ТекущийЭлемент())  Тогда  
            // если такой есть и это ДРУГОЙ элемент
            Сообщить("Код " +А+" был занят","!");
            Продолжить;            
        Иначе
            Код=А;
            Записать();    
            Сообщить("Записан с кодом "+А,"i");  
            Прервать;  
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Процедура ПриЗаписи()
    ПрисвоитьНовыйКод(Число(Код));
КонецПроцедуры
1 Shade84
 
07.07.14
15:01
для 8.0 УТ 10.3
2 Shade84
 
07.07.14
15:04
это нужно, для того, чтобы занять ранее удаленные кода, а нам еще и для того, чтобы занять 10000 штук пропущенных ранее элементов
3 Shade84
 
07.07.14
15:05
Или такое не возможно?
4 Крошка Ру
 
07.07.14
15:06
Создать регистр,где хранить данные о используемых номерах и по нему проверять
5 Крошка Ру
 
07.07.14
15:07
Можно конечно и по справочнику, но по регистру - быстрее
6 Shade84
 
07.07.14
15:08
А как проверять по регистру?
и главное как новому элементу присвоить старое значение?
7 Shade84
 
07.07.14
15:08
Записать получить объект и затем изменить код?
8 Крошка Ру
 
07.07.14
15:09
(7)Вопрос: а зачем тебе использовать пропущенные номера?
9 Shade84
 
07.07.14
15:10
5 + регистр сведений нужен? А заполнять его вручную?
10 Shade84
 
07.07.14
15:10
(8) чтобы занять 10000 штук пропущенных ранее элементов
Пропустили случайно при объединении двух баз
11 Крошка Ру
 
07.07.14
15:10
(9) да погоди ты. Про регистр - это я так, шучу.
12 Крошка Ру
 
07.07.14
15:11
(10) Может перенумеровать их просто?
13 Крошка Ру
 
07.07.14
15:11
+(12) Это если не считать, что пропустили - ну хрен с ними))
14 Shade84
 
07.07.14
15:13
(13) нельзя перенумеровать :-) кода на товаре висят по ним его пробивают
15 ksupalo
 
07.07.14
15:14
Мы делали такое со счетами-фактурами, чтобы нумерация была корректной. Маска была ГГГГММДДХХХ, т.е. в один день можно было выписать 10 тыс. счетов фактур и номер был уникальный.
Выполняется поиск номера по коду только в том случае, если номер не уникальный. Если пока собирались проводить, номер кто-то занял, процедура повторялась. Проблем не было.
16 floody
 
07.07.14
15:15
зачем вам эти 10000 пропущенных кодов?
17 Shade84
 
07.07.14
15:16
(15) Тут наоборот нужно сначала искать меньшие от максимального кода. а если нет то присваивать следующий
18 PRO100 NigGaZ
 
07.07.14
15:16
Выбрать все коды запросом, удаляем префиксы, преобразуем в число, сортируем по возрастанию, запускаем цикл от 1 по ТЗ.Количество(), в цикле если не а = ТЗ.НомерСтроки Тогда это и есть пропущенный номер, может так...
19 Shade84
 
07.07.14
15:16
(16) уже 58000 использовали :( не хотелось бы менять разрядность
20 Крошка Ру
 
07.07.14
15:18
(19) У вас разрядность номера - 5 цифр?
21 Shade84
 
07.07.14
15:18
(18) Да, вариант хороший.
Только не знаю:
1.) как это сделать?
2.) как потом получить код, который он хочет присвоить
3.) как указать старый код элементу номенклатуры
22 Shade84
 
07.07.14
15:18
(20) да
23 Крошка Ру
 
07.07.14
15:20
(18) Выбрать ВСЕ коды, а потом их перебирать, вдруг попадется неиспользуемый? Это сильно. Да и выбирать-то придется каждый раз, когда нужно новый присвоить.
24 Shade84
 
07.07.14
15:21
(23)Может и правда регистр? сделать обход заполнить а потом из него брать?
25 Крошка Ру
 
07.07.14
15:22
(22) Раз уж пошла такая пьянка, может действительно завести регистр (на время, пока все пропущенные номера не заполнятся). Туда один раз выбрать все пропущенные номера, а потом при создании нового справочника искать номер сначала там, а уж если там нет, то добавлять новый.
26 PRO100 NigGaZ
 
07.07.14
15:24
Запрос = Новый Запрос("ВЫБРАТЬ
    Номенклатура.Код КАК Код
ИЗ
    Справочник.Номенклатура КАК Номенклатура");
ТЗ = Запрос.Выполнить().Выгрузить();
Для каждого СтрокаТЗ ИЗ ТЗ Цикл
СтрокаТЗ.Код = Число(СтрокаТЗ.Код);
КонецЦикла;
ТЗ.Сортировать("Код");
Для а = 1 По ТЗ.Количество() Цикл
Если а <> ТЗ.НомерСтроки Тогда
НужныйКод = а;
Прервать;
КонецЦикла;
27 Shade84
 
07.07.14
15:24
(25)Да :)
1.) как это сделать?
2.) как потом получить код, который он хочет присвоить
3.) как указать старый код элементу номенклатуры
28 Shade84
 
07.07.14
15:25
(26) О! Дельно. Спасибо большое
а как указать старый код элементу номенклатуры?
29 Shade84
 
07.07.14
15:26
и как получить код, который 1С хочет присвоить элементу?
30 Shade84
 
07.07.14
15:27
(25) в (26) этот код можно использовать для заполнение временного регистра :)
31 Крошка Ру
 
07.07.14
15:29
(29) метод объекта УстановитьНовыйКод()
32 Shade84
 
07.07.14
15:30
(31) спасибо :)
А старый просто перезаписываем?
33 PRO100 NigGaZ
 
07.07.14
15:31
а в объекте элемента
в этой процедуре наверное
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
(26)
Код = НужныйКод;
КонецПроцедуры
это при создании нового, по поводу производительности должен за 0,2 сек выполнить
34 Shade84
 
07.07.14
15:32
(33) Большое спасибо :-) сейчас все опробую!!!!!
35 PRO100 NigGaZ
 
07.07.14
15:33
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
(26)
Если ЭтоНовый() Тогда
  Код = НужныйКод;
КонецЕсли;
КонецПроцедуры
может даже лучше так
36 Shade84
 
07.07.14
15:35
(35) Да, так лучше!!! :)
37 Крошка Ру
 
07.07.14
15:36
(32)Смотри, по порядку:
1) Создаешь РС
2) Заполняешь его неиспользуемыми кодами в промежутке (от 00000 до максимального используемого значения для данного справочника)
3) При создании нового элемента берешь минимальный код из РС и присваиваешь его записываемому элементу. (можно руками: Элемент.Код = НашКодИзРегистра)
4) Если элемент успешно записан, удаляешь из РС использованный номер(чтоб второй раз потом его не использовать)
5) Если РС - пустой(т.е все пробелы в нумерации закончились), то новый код устанавливаешь методом УстановитьНовыйКод()
38 Крошка Ру
 
07.07.14
15:37
(26)Вот этого, если честно, не понял:

Если а <> ТЗ.НомерСтроки Тогда
39 Крошка Ру
 
07.07.14
15:38
+(26) Даже, вернее, вот этого:

Для а = 1 По ТЗ.Количество() Цикл
Если а <> ТЗ.НомерСтроки Тогда
НужныйКод = а;
Прервать;
КонецЦикла;
40 Shade84
 
07.07.14
15:38
(37) Ага, понял. Щас посмотрю сколько по продолжительности код    PRO100 NigGaZ работает
41 Shade84
 
07.07.14
15:39
(39) Если код не равен отличается от числа строки то это то что нам нужно в идеале они все по порядку идут и равны
42 PRO100 NigGaZ
 
07.07.14
15:40
(38)
косяк
Если а <> ТЗ[Формат(а-1, "ЧН=; ЧГ=0")].Код Тогда
мы же сравниваем с кодом )))
43 Shade84
 
07.07.14
15:42
(42) а\га. а то говорит что поле НомерСтроки не обнаружено :)
44 Shade84
 
07.07.14
15:43
(42) {Справочник.Номенклатура.Форма.ФормаЭлемента.Форма(2982)}: Поле объекта не обнаружено (0)
Если а <> ТЗ[Формат(а-1, "ЧН=; ЧГ=0")].Код Тогда
45 PRO100 NigGaZ
 
07.07.14
15:47
Для каждого СтрокаТЗ ИЗ ТЗ Цикл
Если а <> СтрокаТЗ.Код Тогда
  НужныйКод = а;
  Прервать;
КонецЕсли;
КонецЦикла;
Код = НужныйКод;
а может так )))
46 Shade84
 
07.07.14
15:49
неее, возвращает "1" при условии что 00001 есть
47 Shade84
 
07.07.14
15:51
А значение СтрокаТЗ.Код    "1    "    Строка
тип
48 PRO100 NigGaZ
 
07.07.14
15:51
даже после преобразования в число?
49 Shade84
 
07.07.14
15:52
(45) С форматами нужно, видимо
50 Shade84
 
07.07.14
15:52
(48) да
51 hhhh
 
07.07.14
15:57
(50) может просто у тех номенклатур, которые после вбили поменять префикс. Тогда само будет браться из пропущенного диапазона..
52 Крошка Ру
 
07.07.14
15:57
Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Номенклатура.Код КАК Код
        |ИЗ
        |    Справочник.Номенклатура КАК Номенклатура
        |
        |УПОРЯДОЧИТЬ ПО
        |    Код";

    Выборка = Запрос.Выполнить().Выбрать();
    ТекНомер = 0;  СтрНомер = "00000";
    Пока Выборка.Следующий() Цикл
        Пока СтрНомер<>Выборка.Код И ТекНомер<Выборка.Количество() Цикл
            <записываем СтрНомер в регистр>
            ТекНомер = ТекНомер+1;
            СтрНомер = Формат(ТекНомер, "ЧГ=0");
            Пока СтрДлина(СтрНомер)<5 Цикл
                СтрНомер = "0"+СтрНомер;
            КонецЦикла;
        КонецЦикла;
    КонецЦикла;
53 Shade84
 
07.07.14
15:58
(51) С префиксом нельзя, их 30000 и они рабочие(ну некоторые из них)
54 Крошка Ру
 
07.07.14
15:58
+(52) Это если префиксов у кодов нет
55 Shade84
 
07.07.14
15:59
(54) префиксов нет
56 hhhh
 
07.07.14
16:01
(53) если рабочие, то сам бог велел префикс вставить.
57 Крошка Ру
 
07.07.14
16:01
(52) Вру, есть ошибка
58 Крошка Ру
 
07.07.14
16:03
Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Номенклатура.Код КАК Код
        |ИЗ
        |    Справочник.Номенклатура КАК Номенклатура
        |
        |УПОРЯДОЧИТЬ ПО
        |    Код";

    Выборка = Запрос.Выполнить().Выбрать();
    ТекНомер = 0;  СтрНомер = "00000";
    Пока Выборка.Следующий() Цикл
        Пока СтрНомер<>Выборка.Код И ТекНомер<Выборка.Количество() Цикл
            
            ТекНомер = ТекНомер+1;
            СтрНомер = Формат(ТекНомер, "ЧГ=0");
            Пока СтрДлина(СтрНомер)<5 Цикл
                СтрНомер = "0"+СтрНомер;
            КонецЦикла;
        КонецЦикла;
        ТекНомер = ТекНомер+1;
        СтрНомер = Формат(ТекНомер, "ЧГ=0");
        Пока СтрДлина(СтрНомер)<5 Цикл
            СтрНомер = "0"+СтрНомер;
        КонецЦикла;           
    КонецЦикла;
59 Shade84
 
07.07.14
16:03
(58) Пробую :-)
60 Крошка Ру
 
07.07.14
16:03
Что-то глючит при отправке

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

    Выборка = Запрос.Выполнить().Выбрать();
    ТекНомер = 0;  СтрНомер = "00000";
    Пока Выборка.Следующий() Цикл
        Пока СтрНомер<>Выборка.Код И ТекНомер<Выборка.Количество() Цикл
            <заносим СтрНомер в регистр>
            ТекНомер = ТекНомер+1;
            СтрНомер = Формат(ТекНомер, "ЧГ=0");
            Пока СтрДлина(СтрНомер)<5 Цикл
                СтрНомер = "0"+СтрНомер;
            КонецЦикла;
        КонецЦикла;
        ТекНомер = ТекНомер+1;
        СтрНомер = Формат(ТекНомер, "ЧГ=0");
        Пока СтрДлина(СтрНомер)<5 Цикл
            СтрНомер = "0"+СтрНомер;
        КонецЦикла;           
    КонецЦикла;
61 Shade84
 
07.07.14
16:13
(60) Проверяю.... Пожалуйста подождите...
:-)
62 Крошка Ру
 
07.07.14
16:21
(60) Ах, черт, и здесь ошибка))
В условии цикла ТекНомер надо не с количеством элементов выборки, а с максимальным кодом из выборки сравнивать
63 Shade84
 
07.07.14
16:21
(62) :)
А еще +1 не надо прибавлять вроде
64 Крошка Ру
 
07.07.14
16:22
Где? во внутреннем цикле или внешнем?
65 Shade84
 
07.07.14
16:22
(62) то есть как будет правильно? :)
66 Shade84
 
07.07.14
16:22
Во внутреннем
67 Shade84
 
07.07.14
16:22
это как мне кажется :)
68 Крошка Ру
 
07.07.14
16:26
(67) Нет, все нормально: ТекНомер изначально меньше Выборка.Код(или равен, но тогда сразу переходим к след коду из выборки). Поэтому, пока не сравняем ТекНомер с очередным кодом из выборки , во внутреннем цикле увеличиваем ТекНомер(и сохраняем его в регистре, т.к. в Выборке его нет). Как только сравнялся, "перескакиваем" на следующий код из Выборки и т.д., пока Выборка не закончится
69 Shade84
 
07.07.14
16:38
(68) не получается список нужных кодов попадают ненужные
00001
00005
00006
00085
00089
где 1 это существующая папка 5 - элемент, а вот 4 нету 6 папка, 84 нету 88 нету
70 Крошка Ру
 
07.07.14
16:48
(69) Первые десять кодов из справочнника покажи
71 Крошка Ру
 
07.07.14
16:48
+(70) Я надеюсь там префиксов нет?
72 Масянька
 
07.07.14
16:49
Код для 7.7:

Процедура ПоКнопкеНайтиСвободныеКоды()
    
    ТаблицаСвободныхКодов.УдалитьСтроки();
    
    ТекКод = 1;
    
    Спр = СоздатьОбъект("Справочник.Номенклатура");
    Спр.ПорядокКодов();
    
    Спр.ВыбратьЭлементы(0);
    
    Пока Спр.ПолучитьЭлемент() = 1 Цикл
        
        СправКод = Число(Спр.Код);
        
        Пока ТекКод <> СправКод Цикл
            ТаблицаСвободныхКодов.НоваяСтрока();
            ТаблицаСвободныхКодов.ФрееКод = ТекКод;
            ТаблицаСвободныхКодов.ПредКод = СправКод;
            ТекКод = ТекКод + 1;
        КонецЦикла;
        
        ТекКод = ТекКод + 1;
    
    КонецЦикла;
    
КонецПроцедуры    // ПоКнопкеСформироватьПомеченныеНаУдаление
73 Крошка Ру
 
07.07.14
16:52
(72) Один в один, только я почему-то коды как строки стал сравнивать, а не как числа))
74 Shade84
 
07.07.14
16:56
(73) А как чтобы на 8 работало? :)
75 Shade84
 
07.07.14
16:56
(73)я все таки его поменял чуть чуть щас покажу как, тогда список правильно формирует
76 Shade84
 
07.07.14
16:57
Если ЭтоНовый() Тогда
        
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Номенклатура.Код КАК Код
        |ИЗ
        |    Справочник.Номенклатура КАК Номенклатура
        |
        |УПОРЯДОЧИТЬ ПО
        |    Код";

    Выборка = Запрос.Выполнить().Выбрать();
    ТекНомер = 0;  СтрНомер = "00000";
    Пока Выборка.Следующий() Цикл
        Пока СтрНомер<>Выборка.Код И ТекНомер<Выборка.Количество() Цикл
            //<заносим СтрНомер в регистр>
            //Код = СтрНомер;
            //Сообщить(Код) ;
            //Прервать;
            ТекНомер = ТекНомер+1;
              СтрНомер = Формат(ТекНомер, "ЧГ=0");
              
              Промежут = Формат(ТекНомер-1, "ЧГ=0");
            
            Пока СтрДлина(СтрНомер)<5 Цикл
                СтрНомер = "0"+СтрНомер;
            КонецЦикла;
            
             Пока СтрДлина(Промежут)<5 Цикл
                Промежут = "0"+Промежут;
            КонецЦикла;

              Сообщить(Промежут);
              
        КонецЦикла;
        ТекНомер = ТекНомер+1;
        СтрНомер = Формат(ТекНомер, "ЧГ=0");
        Пока СтрДлина(СтрНомер)<5 Цикл
            СтрНомер = "0"+СтрНомер;
        КонецЦикла;          
    КонецЦикла;
  
  //Код = СтрНомер;
КонецЕсли;
77 Shade84
 
07.07.14
16:58
(73) Вот Промежут дает нужные значения :-)
78 Крошка Ру
 
07.07.14
17:02
(77) Ну все правильно)) Ты код посмотри. Сначала заносится в регистр СтрНомер, ПОТОМ он увеличивается на один.
В этот момент ты говоришь : Ага! А СтрНомер-1  -  это то, что нужно.
Т.е. СтрНомер+1-1 - это то что нужно))
Поставь "Сообщить(СтрНомер)" перед "ТекНомер=ТекНомер+1" и увидишь чудо))
79 Salimbek
 
07.07.14
17:02
Вместо:
             Пока СтрДлина(Промежут)<5 Цикл
                Промежут = "0"+Промежут;
            КонецЦикла;

Проще

Промежут=Прав("00000"+Промежут,5);
80 Крошка Ру
 
07.07.14
17:03
(79) Ага))
81 Shade84
 
07.07.14
17:06
(80) :-) Промежут пошел в массы :)
82 Salimbek
 
07.07.14
17:07
И вообще, я бы в ТЗ загнал все номера, потом укладываешь эту ТЗ во временную таблицу, а потом:

Выбрать Первые свНомер из ВсяТЗ
Левое соединение Справочник.Номенклатура как Номенклатура ПО ВсяТЗ.Код=Номенклатура.Код
Где Номенклатура.Код ЕСТЬ NULL
Упорядочить ПО свНомер

И все это еще бы один раз на сервер загнать, чтобы для каждого таблички не перекладывать.
83 Salimbek
 
07.07.14
17:08
...Первые 1... конечно же
84 Salimbek
 
07.07.14
17:09
и вместо свНомер -> ВсяТЗ.Код
85 Shade84
 
07.07.14
17:10
(78) О чудо!
86 Shade84
 
07.07.14
17:10
(78) Клево :))))))))
87 Shade84
 
07.07.14
17:11
(82) То есть каждый раз просматривать? Без регистра?
88 Крошка Ру
 
07.07.14
17:11
(82) Так проще, да, но больно уж большую ТЗ загружать-соединять, это уж проще тогда просто перебором в цикле отсеивать ненужные номера, как в самом начале предлагалось
89 Shade84
 
07.07.14
17:11
У меня файловая 10.3 и все на клиенте делает
90 Shade84
 
07.07.14
17:15
(88) Спасибо :-)
91 Shade84
 
07.07.14
17:16
всем спасибо :)
92 Shade84
 
07.07.14
17:18
(88) А вы в сложных запросах разбираетесь?
93 Shade84
 
07.07.14
17:22
(88) напишите, что нибудь на shade84 собака bk точка ru, пожалуйста, есть предложение
94 Salimbek
 
08.07.14
15:35
(88) Да не вопрос, создаем служебный Регистр сведений "Нумерация" с одним лишь полем "Код", которое заполняем всеми нужными числами. Потом останется только вызвать запрос:

Выбрать Первые 1 Нумерация.Код из РегистрСведений.Нумерация КАК Нумерация
Левое соединение Справочник.Номенклатура как Номенклатура ПО Нумерация.Код=Номенклатура.Код
Где Номенклатура.Код ЕСТЬ NULL
Упорядочить ПО Нумерация.Код
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.