Имя: Пароль:
1C
1C 7.7
v7: Объединение одинаковых позиций.. опять =)
0 monsterZE
 
27.10.12
13:52
так исторически сложилось (специфика организации), что в одной накладной не может быть одинаковых позиций. т.е. при подборе, если такая позиция уже существует - должно спрашивать и при положительном ответе складывать количество. ну и сие было реализовано с одним "ньюаносм".. =) при подборе - никаких проблем. вся вкусность начинается, при изменении существующей строки в ТЧ документа на позицию, уже существующую в ТЧ. и тут есть ньюанс =) - если меняется любая, НЕ ПОСЛЕДНЯЯ позиция - 1с проглатывает уменьшение строк ТЧ документа.. но на последней - спотыкается и просто вылетает (т.к. позиция курсора > количества строк в документе).
раньше при подборе - вызывал одну и туже процедуру - сейчас разделил.
но вылез косяк при сортировке строк (т.к. 1с меняет товар в активной строке).. можно конечно запретить редактировать номер строки.. но мож есть какие-то более логичные решения?.. может кто сталкивался с подобным?
1 Джордж1
 
27.10.12
13:53
нифига не понял.
но можно сначала загружать ТЧ в ТЗ, там уже обрабатывать, а по окончанию подбора загружать ТЧ обратно
2 monsterZE
 
27.10.12
14:01
(1) так и есть.. и это работает, если из процедуры подбра.
но, если идет редактирование текущей строки документа - такой вариант не прокатывает.. точнее, прокатывает, как описал.
3 monsterZE
 
27.10.12
14:32
хз.. поможет, нет =)
Процедура ПриНачалеРедактированияСтроки()
   СтарТовар = Товар;
   
   ТабЧасть = СоздатьОбъект("ТаблицаЗначений");
   ТабЧасть.Очистить();
   
   ВыгрузитьТабличнуюЧасть(ТабЧасть,"НомерСтроки,Товар,Количество,Единица");
   
   ТабЧасть.НоваяКолонка("Код");
   ТабЧасть.ВыбратьСтроки();
   Пока ТабЧасть.ПолучитьСтроку()=1 Цикл
       ТабЧасть.Код = ТабЧасть.Товар.Код;
   КонецЦикла;    
КонецПроцедуры


Процедура ПриОкончанииРедактированияСтроки()
   Если СтарТовар.Код<>Товар.Код Тогда
       стр = ПолучитьПустоеЗначение();
       Если ТабЧасть.НайтиЗначение(Товар.Код,стр,"Код")=1 Тогда
           СтарКол = ТабЧасть.ПолучитьЗначение(стр,"Количество");
           СтарЕд  = ТабЧасть.ПолучитьЗначение(стр,"Единица");
           СтарСтр = ТабЧасть.ПолучитьЗначение(стр,1);
           
           Отв = Вопрос("В документе уже присутствует товар"+РазделительСтрок
                        +"["+Товар.Код+"] "+СокрЛП(Товар.Наименование)+РазделительСтрок
                        +"в строке: "+СтарСтр+РазделительСтрок
                        +"в количестве: "+СтарКол+" "+СтарЕд+РазделительСтрок
                        +"Хотите продолжить выбор?","Да+Нет");
           Если Отв = "Да" Тогда            
               СтатусВозврата(0);                
               Возврат;
           Иначе
               Товар = СтарТовар;
           КонецЕсли;
       КонецЕсли;
   КонецЕсли;
КонецПроцедуры
4 monsterZE
 
27.10.12
14:37
текущий вариант..

Процедура глОбъединениеКоличестваОдинаковогоТовара(Конт) Экспорт
   ВидДок = Конт.Вид();
   ПерерасчетСуммы = 0;
   
   Если (ВидДок = "ПриходнаяНал")
    или (ВидДок = "РасходнаяНал")
    или (ВидДок = "РасходнаяНОФ")
    или (ВидДок = "РасходнаяКредит")
    или (ВидДок = "ПриходнаяКредит")
    или (ВидДок = "РасходнаяРеализ")
    или (ВидДок = "ПриходнаяРеализ")
    или (ВидДок = "Счет") Тогда
       ПерерасчетСуммы = 1;
   КонецЕсли;
   
   ТабЧасть = СоздатьОбъект("ТаблицаЗначений");
   ТабЧасть.Очистить();
   
   ТабДвойников = СоздатьОбъект("ТаблицаЗначений");
   ТабДвойников.Очистить();
   
   ТабОбъединенногоТовара = СоздатьОбъект("ТаблицаЗначений");
   ТабОбъединенногоТовара.Очистить();
   ТабОбъединенногоТовара.НоваяКолонка("Код");
   ТабОбъединенногоТовара.НоваяКолонка("Колво");

   Конт.ВыгрузитьТабличнуюЧасть(ТабДвойников);  
   
   ТабДвойников.НоваяКолонка("Код");
   ТабДвойников.НоваяКолонка("Двойник");
   
   ТабДвойников.ВыбратьСтроки();
   Пока ТабДвойников.ПолучитьСтроку()=1 Цикл
       ТабДвойников.Код     = ТабДвойников.Товар.Код;
       ТабДвойников.Двойник = 1;
   КонецЦикла;    

   ТабДвойников.Выгрузить(ТабЧасть);  
   
   // проверка на коэффициент одинаковых позиций (приводим к одной ед.изм.)
   Состояние("Поиск разных ед.изм..");
   ТабДвойников.Свернуть("Код,Коэффициент","Количество,Двойник");
   ТабДвойников.Сортировать("Код");
   старКод  = "";
   старКоэф = "";
   ТабДвойников.ВыбратьСтроки();
   Пока ТабДвойников.ПолучитьСтроку()=1 Цикл
       текКод   = ТабДвойников.Код;
       текКоэф  = ТабДвойников.Коэффициент;
       текКолво = ТабДвойников.Количество;
       
       Если (ПустоеЗначение(текКод)=1) и (ПустоеЗначение(текКоэф)=1) и (ПустоеЗначение(текКолво)=1) Тогда
           Продолжить;
       КонецЕсли;
       
       Если (текКод=старКод) и (текКоэф<>старКоэф) Тогда
           ТабДвойников.Коэффициент = старКоэф;
           ТабДвойников.Количество  = текКолво*текКоэф/старКоэф;
           Если ТабДвойников.Количество<>Цел(ТабДвойников.Количество) Тогда
               Сообщить("Одинаковый товар с разными единицами измерения. Проверьте количество!");
               стр = ПолучитьПустоеЗначение();
               Если ТабЧасть.НайтиЗначение(текКод,стр,"Код")=0 Тогда
                   текНаим = "";
               Иначе
                   текНаим = Строка(ТабЧасть.ПолучитьЗначение(стр,"Товар"));
               КонецЕсли;    
               Сообщить("["+текКод+"] "+текНаим);
           КонецЕсли;
       КонецЕсли;
       старКод  = текКод;
       старКоэф = текКоэф;
   КонецЦикла;
   //-------------
   ТабДвойников.Свернуть("Код","Количество,Двойник");
   ТабДвойников.Сортировать("Двойник-");
   
   Состояние("Поиск одинаковых позиций..");

   ТабДвойников.ВыбратьСтроки();
   Пока ТабДвойников.ПолучитьСтроку()=1 Цикл
       Если ТабДвойников.Двойник=1 Тогда Прервать;    КонецЕсли;
       
       КодТовара        = ТабДвойников.Код;
       стр              = ПолучитьПустоеЗначение();
       Если ТабЧасть.НайтиЗначение(КодТовара,стр,"Код")=0 Тогда
           Предупреждение("Возникла ошибка, при проверке на двойные позиции.."+РазделительСтрок+"Не найден товар с кодом ["+КодТовара+"]");
           Возврат;
       КонецЕсли;
       Товар             = ТабЧасть.ПолучитьЗначение(стр,"Товар");
       СтароеКолвоТовара = ТабЧасть.ПолучитьЗначение(стр,"Количество");
       ЕдиницаТовара     = ТабЧасть.ПолучитьЗначение(стр,"Единица");
       НовоеКолвоТовара  = ТабДвойников.Количество;
                     
       Если (ПустоеЗначение(КодТовара)=1) и (ПустоеЗначение(Товар)=1) Тогда
           Продолжить;
       КонецЕсли;
       
       Отв = Вопрос("В документе уже присутствует товар"+РазделительСтрок
                    +"["+КодТовара+"] "+СокрЛП(Товар.Наименование)+РазделительСтрок
                    +"в количестве: "+СтароеКолвоТовара+" "+ЕдиницаТовара+РазделительСтрок
                    +"Новое количество: "+НовоеКолвоТовара+РазделительСтрок
                    +"Объединить?","Да+Нет");
       Если Отв = "Да" Тогда            
           ТабОбъединенногоТовара.НоваяСтрока();
           ТабОбъединенногоТовара.Код   = КодТовара;
           ТабОбъединенногоТовара.Колво = НовоеКолвоТовара;        
       Иначе
           ТабОбъединенногоТовара.НоваяСтрока();
           ТабОбъединенногоТовара.Код   = КодТовара;
           ТабОбъединенногоТовара.Колво = СтароеКолвоТовара;        
       КонецЕсли;
   КонецЦикла;
   Состояние("");

   // объединяем в основной тч
   ТабОбъединенногоТовара.ВыбратьСтроки();
   Пока ТабОбъединенногоТовара.ПолучитьСтроку()=1 Цикл
       Исправлено = 0;
       стр = ПолучитьПустоеЗначение();
       Пока ТабЧасть.НайтиЗначение(ТабОбъединенногоТовара.Код,стр,"Код")=1 Цикл
           Если Исправлено=0 Тогда
               ТабЧасть.УстановитьЗначение(стр,"Количество",ТабОбъединенногоТовара.Колво);
               Если ПерерасчетСуммы=1 Тогда
                   Товар      = ТабЧасть.ПолучитьЗначение(стр,"Товар");
                   НоваяСумма = ТабЧасть.ПолучитьЗначение(стр,"Цена")*ТабОбъединенногоТовара.Колво*ТабЧасть.ПолучитьЗначение(стр,"Коэффициент");
                   ТабЧасть.УстановитьЗначение(стр,"Сумма",НоваяСумма);
                   
                   Если Товар.СтавкаНДС = Перечисление.ЗначенияНДС.ОсновнаяСтавкаНДС Тогда
                       СтавкаНДС = 18;
                   ИначеЕсли Товар.СтавкаНДС = Перечисление.ЗначенияНДС.ЛьготнаяСтавкаНДС Тогда
                       СтавкаНДС = 10;
                   Иначе
                       СтавкаНДС = 0;
                   КонецЕсли;
                   НовыйНДС = НоваяСумма*СтавкаНДС/(100+СтавкаНДС);
                   ТабЧасть.УстановитьЗначение(стр,"НДС",НовыйНДС);
               КонецЕсли;
               ТабЧасть.УстановитьЗначение(стр,"Код","");
               Исправлено = 1;
           Иначе
               ТабЧасть.УдалитьСтроку(стр);
           КонецЕсли;
           стр = ПолучитьПустоеЗначение();
       КонецЦикла;
   КонецЦикла;

   Если ТабОбъединенногоТовара.КоличествоСтрок()>0 Тогда
       ТабЧасть.УдалитьКолонку("Код");
       ТабЧасть.УдалитьКолонку("Двойник");
       Конт.ЗагрузитьТабличнуюЧасть(ТабЧасть);
       Конт.АктивизироватьСтроку();
   КонецЕсли;
       
КонецПроцедуры
5 Torquader
 
27.10.12
17:36
Почему падает 1С - понятно - при начале редактирования строки система запоминает номер строки, которая редактируется. Когда оно оканчивается, система обновляет строку в документе. Если вы число строк уменьшили, то получается, что текущая строка за пределами списка - происходит ошибка доступа к памяти.
Нужно удалять строку или до начала редактирования или после его окончания, ну или имитировать редактирование без входа в режим.
6 КонецЦикла
 
27.10.12
17:39
Было такое, он-лайн резервирование
В реальном времени в записанном или новом документе отслеживались изменения резерва (как кол-во, так и товар, удаление строки и проч.)
Все это сводилось к изменению кол-ва по позициям в собственной табличке SQL
7 monsterZE
 
27.10.12
17:52
(5) как мысль интересно, но как реализовать, например, "удаление после" - проверять по обновлению формы?
удалять до начала редактирования - тож чет не очень представляю =)
вот с эмуляцией можно что-то попробывать..

я уж хотел ничего не удалять, а просто не довать выбрать - первый пример.. но там надо тогда столбик номер_строки на редактирование запрещать.. т.к. если изменить номер, чтобы строка изменила свою позицию в списке - 1с меняет активную строку и процедура срабатывает, где не надо =)
8 Эмбеддер
 
27.10.12
18:20
тема такая была с полгода назад, глюк платформы. точнее не скажу
9 КонецЦикла
 
27.10.12
18:33
(7) Извраты это все
А как другие пользователи увидят, что резерв освободился из-за замены товара?
Иначе это все твое "на лету" теряет смысл
А если теряет смысл, то можно в спокойной обстановке по факту записи документа сравнивать с тем что было при его открытии
10 Torquader
 
27.10.12
18:42
А в чём проблема - в ПриНачалеРедактированияСтроки ставим отмену редактирования, а также делаем, что хотим - то есть показываем пользователю форму для подбора, но только одного значения. После подбора, если строка "скукожилась", то она просто делается пустой (очищаем все поля).
А вот при записи мы пустые строки просто удаляем.
Если же делается добавление строки, то вместо новой строки подставляется "пустая".
В общем-то, достаточно несильный геморрой из-за каких-то граблей в платформе.
11 monsterZE
 
27.10.12
20:33
(9) Сорри, из поста понял только первую строчку. =)
(10) вобщем надо попробывать варианты, чтобы устроило всех..
а я расчитывал на уже готовое решение 8-D
12 ADirks
 
28.10.12
10:56
Ещё можно в ПриОкончании  запускать таймер, миллисекунд на 50 скажем, и там уже всё сворачивать.
Ещё можно переделать всю ТЧ на ТабличноеПоле, и там уж делай что хочешь.
13 Torquader
 
28.10.12
12:48
(12) В семёрке табличное поле - это таблица значений на форме - для её редактирования прямых методов нет - нужно или внешние компоненты использовать или на каждое редактирование писать отдельные диалоги, правда, есть огромное преимущество - не бывает строки в режиме редактирования, как у табличной или многострочной части.
14 ADirks
 
28.10.12
13:12
(13) А в семёрке + 1С++   ТабличноеПоле - это ТабличноеПоле, с возможностью редактирования
15 monsterZE
 
30.10.12
13:37
Вобщем переделал я, по совету Torquader. И вот оно! =)
..Но фак! В ПриНачалеРедактированияСтроки() нет ид поля, по которому кликнул юзверь. Возможно его как-нибудь получить? Дабы остались возможности редактировать количество и ед.изм..
Процедура ПриНачалеРедактированияСтроки()
   СтатусВозврата(0);
   СтарТовар = Товар;
   ОткрытьПодбор("Справочник.Товары","ДляПодбора",Контекст,0,СтарТовар);
   УстановитьЗначениеВПодборе("Склад",Склад);
КонецПроцедуры

Процедура ОбработкаПодбора(Выб)
   
   ПроверкаВыделенныхПозицийТовара(Выб);
   
   Если ПустоеЗначение(СтарТовар)=0 Тогда
       Если СтарТовар.Код = Выб.Код Тогда
           Возврат;
       КонецЕсли;
       
       СтарТовар = ПолучитьПустоеЗначение();
       Товар     = Выб;
   Иначе
       ЗапросКоличестваВПодборе(Контекст,Режим,Выб);
   КонецЕсли;
   
   УстанЦеныРасх(Контекст);
   Выч_суммы_накл(Контекст);
   АктивизироватьСтроку();          
   
   глОбъединениеКоличестваОдинаковогоТовара(Контекст);
16 Torquader
 
30.10.12
13:42
Форма.АктивныйЭлемент() скажет вам про того, кого начали править.
17 monsterZE
 
30.10.12
13:44
(16) благодарю! =)
18 monsterZE
 
30.10.12
15:32
вот еще одну шляпу получил.. тестируясь =)
если при выборе элемента (товара) - поменять его реквизит (например цену) и выбрать, то в обработке подбора в Выб - измененный реквизит видно сразу, а присваивая его табличной части дока - имеем реквизит до обновления.
это если товар один и тот-же. если товары разные - все гуд.
19 monsterZE
 
30.10.12
15:45
Процедура ОбработкаПодбора(Выб)
   ПроверкаВыделенныхПозицийТовара(Выб);
   Сообщить("лок выб "+Выб.Опт_Цена);
   
   Если ПустоеЗначение(СтарТовар)=0 Тогда
       Если СтарТовар.Код = Выб.Код Тогда
           Товар = Выб;
           Сообщить("лок тов "+Товар.Опт_Цена);

выводятся разные сообщения
20 Ёпрст
 
30.10.12
15:52
Нихрена не понял, что не работает и чем штатный подбор не угодил, который умеет сам учитывать "одинаковые" строки
21 Ёпрст
 
30.10.12
15:52
.?
22 Torquader
 
30.10.12
15:59
(18) Так это старые грабли - кеширование называется, и оно в 1С реализовано не совсем верно.
Точнее, как реквизит в табличной части узнает, что его копию кто-то поменял ?
Делай позиционирование на элементе и читай все данные на момент позиционирования.
23 monsterZE
 
30.10.12
16:09
(22) т.е. создавать справочник и найти элемент?
24 monsterZE
 
30.10.12
16:09
(20) =) штатного подбора нет - это конфа с версии 5.3 что-ли.... некро короче =)
25 monsterZE
 
30.10.12
16:13
(20) поясняю =)
в ТЧ дока есть строка с товаром - из документа меняем реквизит этого товара и вводим его (редактирование строки)
и если товар остался "стрый" 1с не обновляет его реквизиты до второго клика..
т.е. дабл ентер на строке =) хер знает как еще описать
26 monsterZE
 
30.10.12
16:14
в (19) выводятся разные сообщения о цене
вот что не работает =)
27 monsterZE
 
30.10.12
16:25
получается - если поменять реквизит элемента тч при редактировании строки - он обновится сразу
а, если поменять из подбора - через некоторое время.. =)
28 Ёпрст
 
30.10.12
16:27
(27) через время опроса периода БД, если быть точнее.
А так, в типовых есть что-то типа глОбновитьКарточкуРеквизита..
не помню точное название, грубо - после изменения нужно заново в базе найти объект и поиметь его свойства
29 monsterZE
 
30.10.12
16:28
гы гы гы =) поборол так

Товар = ПолучитьПустоеЗначение();
Товар = Выб;
30 monsterZE
 
30.10.12
16:29
Процедура ОбработкаПодбора(Выб)
   
   ПроверкаВыделенныхПозицийТовара(Выб);
   
   Сообщить("лок выб "+Выб.Опт_Цена);
   
   Если ПустоеЗначение(СтарТовар)=0 Тогда
       Если СтарТовар.Код = Выб.Код Тогда
           Товар = ПолучитьПустоеЗначение();
           Товар = Выб;
           Сообщить("лок тов "+Товар.Опт_Цена);
           УстанЦеныРасх(Контекст);
           СтарТовар = ПолучитьПустоеЗначение();
           Возврат;
       КонецЕсли;
       СтарТовар = ПолучитьПустоеЗначение();
       Товар     = Выб;
   Иначе
       ЗапросКоличестваВПодборе(Контекст,Режим,Выб);
   КонецЕсли;
   
   УстанЦеныРасх(Контекст);
   //Выч_суммы_накл(Контекст);
   АктивизироватьСтроку();          
   
   глОбъединениеКоличестваОдинаковогоТовара(Контекст);
   ОткрытьФормуМодально("Обработка.ВосстановлениеПослеАварии_ЗаписьРеквизитовВФайл",Контекст);
   
КонецПроцедуры
31 Torquader
 
30.10.12
18:59
(29) Тоже способ.
А разве просто присвоение значения не меняет атрибуты, или в случае выбора того же просто выбор не происходит ?
32 monsterZE
 
31.10.12
10:32
(31) смотрел отладчиком - получается так:
если элемент тот-же самый - присвоение его "не обновляет" (до второго раза)
если элемент другой - отрабатывает на ура (при первом)
33 monsterZE
 
31.10.12
10:36
к (32) но это именно при подборе
если меняем реквизиты и отрабатывают стандартные ПриНачалеРедактированияСтроки()
то реквизиты в ТЧ обновляются (с первого раза)