Никак не могу достичь цели. Вкратце нужно из ТЗ в табличную часть нового документа или уже существующего загрузить информацию. При этом не исключена повторная загрузка с исключением ранее загруженной информации. В ТЗ грубо говоря есть строки, 1 колонка - Менеджер, 2 - Идентификатор. 3 - число. В колонке Менеджер данные могут быть разные, в колонке Идентифкатор - данные разные. Нужно Взять Менеджера, проверить есть ли документ для него, если нет - создать и дальше заполнить табличную часть идентифкатором из второй колонки и числом из третьей. И так для каждой строки ТЗ.
Есть код:
таб.ВыбратьСтроки(); // таб - заполенная ТЗ с информацией Пока таб.ПолучитьСтроку() = 1 Цикл локОтчет= ""; тмпОтчет = СоздатьОбъект("Документ.Отчет"); тмпОтчет.ВыбратьДокументы(ДатаСоздания,ДатаСоздания); Пока тмпОтчет.ПолучитьДокумент() = 1 Цикл Если тмпОтчет.Менеджер = таб.Менеджер Тогда локОтчет= тмпОтчет; Прервать; КонецЕсли; КонецЦикла; Если локОтчет= "" Тогда //если не существует документа - создаем новый локОтчет= СоздатьОбъект("Документ.Отчет"); локОтчет.Новый(); локОтчет.НоваяСтрока();
//дальше заполняем первую строку документа информацией Иначе //документ уже существует локОтчет.ВыбратьСтроки(); Пока локОтчет.ПолучитьСтроку()=1 Цикл Если Число(локОтчет.Идентификатор)=СокрЛП(таб.Идентификатор) Тогда //проверяем нет ли в существующем документе строки с информацией которую загрузили ранее Продолжить; //если есть возвращаемся в начало цикла и смотрим на следующую строку КонецЕсли; локОтчет.НоваяСтрока(); //дальше заполняем строку документа информацией КонецЦикла; КонецЕсли; КонецЦикла
в итоге при первичной загрузке информации из ТЗ документы создаются изаполняются, а при повторной загрузке - вся информация задваивается. Как избежать задвоения? Заранее благодарен!
Пока тмпОтчет.ПолучитьДокумент() = 1 Цикл ТаблЗначДоков.НоваяСтрока(); ТаблЗначДоков.ДокОтчет = тмпОтчет.ТекущийДокумент(); ТаблЗначДоков.Менеджер = тмпОтчет.Менеджер; КонецЦикла;
НачатьТранзакцию(); таб.ВыбратьСтроки(); // таб - заполенная ТЗ с информацией Пока таб.ПолучитьСтроку() = 1 Цикл МенеджерВтаб = таб.Менеджер; номСтрДока = ""; Если ТаблЗначДоков.НайтиЗначение(МенеджерВтаб,номСтрДока,"Менеджер") = 1 Тогда ТаблЗначДоков.ПолучитьСтрокуПоНомеру(номСтрДока); тмпОтчет.НайтиДокумент(ТаблЗначДоков.ДокОтчет); Модифиц = 1; //Признак необходимости модификации (По умолчанию - 1) тмпОтчет.ВыбратьСтроки(); Пока тмпОтчет.ПолучитьСтроку() = 1 Цикл //Только сначала определи что здесь число или строка, типы должны быть одинаковы Если Число(тмпОтчет.Идентификатор) = Число(таб.Идентификатор) Тогда Модифиц = 0; КонецЕсли; КонецЦикла; Если Модифиц = 1 Тогда тмпОтчет.НоваяСтрока(); //заполняй следующую строку документа информацией тмпОтчет.Записать(); КонецЕсли; Иначе тмпОтчет.Новый(); тмпОтчет.Менеджер = МенеджерВтаб; тмпОтчет.НоваяСтрока(); //заполняй первую строку документа информацией тмпОтчет.Записать(); КонецЕсли; КонецЦикла; ЗафиксироватьТранзакцию();
То, что для одного человека константа, для другого - переменная. (Алан.Дж.Перлис)
тмпОтчет = СоздатьОбъект("Документ.Отчет"); локОтчет= СоздатьОбъект("Документ.Отчет"); таб.ВыбратьСтроки(); // таб - заполенная ТЗ с информацией Пока таб.ПолучитьСтроку() = 1 Цикл локОтчет=""; //или локОтчет =ПолучитьПустоеЗначение("Документ.Отчет"); тмпОтчет.ВыбратьДокументы(ДатаСоздания,ДатаСоздания); Пока тмпОтчет.ПолучитьДокумент() = 1 Цикл Если тмпОтчет.Менеджер = таб.Менеджер Тогда локОтчет.НайтиДокумент(тмпОтчет.ТекущийДОкумент()); Прервать; КонецЕсли; КонецЦикла; Если локОтчет="" Тогда //если не существует документа - создаем новый // или сравнить с пустым значением - функция ПустоеЗначение() локОтчет.Новый(); локОтчет.НоваяСтрока();
//дальше заполняем первую строку документа информацией Иначе //документ уже существует локОтчет.ВыбратьСтроки(); Пока локОтчет.ПолучитьСтроку()=1 Цикл Если Число(локОтчет.Идентификатор)=СокрЛП(таб.Идентификатор) Тогда //проверяем нет ли в существующем документе строки с информацией которую загрузили ранее Продолжить; //если есть возвращаемся в начало цикла и смотрим на следующую строку КонецЕсли; локОтчет.НоваяСтрока(); //дальше заполняем строку документа информацией КонецЦикла; КонецЕсли; КонецЦикла
Если Число(локОтчет.Идентификатор)=СокрЛП(таб.Идентификатор) Тогда
Ой, кажется Вы здесь пропустили, не заработает ) Хотя я тоже в своем коде допустил ошибку в строке Записать(), хотя возможно нужно Провести(). А здесь к автору больше вопросов, как Вы думаете Менеджер сколько раз может поторяться в его Таб ? ).
Хотя если сравнить его вариант с предложенными, то 1 С он наверное такими кодами вовсе убьет.
То, что для одного человека константа, для другого - переменная. (Алан.Дж.Перлис)
Группа: Местный
Сообщений: 298
Спасибо сказали: 98 раз
Рейтинг: 0
Цитата(salton @ 30.04.15, 20:43)
спасибо, сейчас проверю предложенный Вами варианты.
зы. Менеджер в Таб может повторяться несколько раз...
Теперь представьте вариант что "Менеджер" у Вас порядка 100 000 и информации по ним еще + по 10 шт. на каждого, итого 1 млн. строк в таб.
Смотрите глобальней, сделайте что-б в таб не попадала информация которая уже разнесена по документам.
Ваш подход и варриант реализации не совсем правильные, уж очень это все долго ! И еще, луше не перебирать сначала строки Таб, а потом документа, а сделать наоборот, перебрать Документы, потом строки Таб и только после этого произвести Запись или Проведение Документа, таким образом выиграете доп. время + еще нужно проверить существующие Документы на блокировку. (см. Блокировка(вклВыкл)). Впрочем удачи )
Цитата(Домовик @ 30.04.15, 20:56)
Sharzem, вы имеете в виду скобки присваиваются? и типа тип значения теряется? да? точно? потеряется или обнулится?
Из синтаксис помощника: Синтаксис: НайтиДокумент(<Документ>) Назначение: Найти документ по значению. Возвращает: 1 - если действие выполнено (документ найден); 0 - если действие не выполнено. Параметры: <Документ> - выражение со значением типа 'Документ'. Замечание: Метод можно использовать только для объектов, созданных функцией СоздатьОбъект.
Вот еще:
Новый() Назначение: Начать ввод нового документа. Замечание: Метод можно использовать только для объектов, созданных функцией СоздатьОбъект.
Sharzem, та что вы? действительно много чего забываю. я только не пойму о чем вы. но давайте сейчас уже не спорить. вы же помогли по вопросу. я еще чуть позже на выспанную голову посмотрю ).
Группа: Местный
Сообщений: 298
Спасибо сказали: 98 раз
Рейтинг: 0
Короче, забейте на все то что написано выше. Вот оптимальный код, в процедуру ЗаполнимДокументыИзТаб(прТаб,прНачДата, прКонДата) передайте нужные параметры, подкорректируйте процедуры в плане заполнения документа, и с Вас пиво
Процедура ОбработаемТабличнуюЧасть(прТаблЧастьДока,прТаблЗнач,прКолОтбора,прМенеджер); Для лпНомОтбора = 1 По прКолОтбора Цикл//Проходим цикл не по всей прТаблЗнач, а только по количеству в прКолОтбора лпСтрТаб = ""; прТаблЗнач.НайтиЗначение(прМенеджер,лпСтрТаб,"Менеджер"); прТаблЗнач.ПолучитьСтрокуПоНомеру(лпСтрТаб); лпИдентификатор = прТаблЗнач.Идентификатор;//Здесь нужно привести к нужному типу - "Строка" или "Число" так как в ТЧ документа Если прТаблЧастьДока.НайтиЗначение(лпИдентификатор,,"Идентификатор") = 0 Тогда//Не нашли прТаблЧастьДока.НоваяСтрока(); //Здесь заполняете прТаблЧастьДока так как в документе по идентификаторам метаданных КонецЕсли; прТаблЗнач.УдалитьСтроку();//Обязательно, что-б не попадать на 1-о и то же значение КонецЦикла; КонецПроцедуры//ОбработаемТабличнуюЧасть
//====================================================================== Процедура ЗаполнимДокументыИзТаб(прТаб,прНачДата, прКонДата)//прТаб - это Ваша таб, прНачДата, прКонДата - даты выборки документов Если ТипЗначенияСтр(прТаб) <> "ТаблицаЗначений" Тогда Предупреждение("Это не таблица значений!",5); Возврат; ИначеЕсли прТаб.КоличествоСтрок() = 0 Тогда Предупреждение("Пустая таблица значений!",5); Возврат; КонецЕсли;
//лпТаблЗначДоков (Таблица значений) - для документов которые есть в периоде, для того что-б не делать выбоку в цикле лпТаблЗначДоков = СоздатьОбъект("ТаблицаЗначений"); лпТаблЗначДоков.НоваяКолонка("ДокОтчет","Документ.Отчет"); лпТаблЗначДоков.НоваяКолонка("Менеджер","Справочник"); //Выборка документов и заполнение лпТаблЗначДоков, где лпДокОтчет - агрегатный Объект для применения команд лпДокОтчет = СоздатьОбъект("Документ.Отчет");
//лпТаблЧастьДока (Таблица значений) - для выгрузки табличной части, для того чтоб не бегать в цикле по строкам лпТаблЧастьДока = СоздатьОбъект("ТаблицаЗначений");
лпДокОтчет.ВыбратьДокументы(прНачДата, прКонДата); Пока лпДокОтчет.ПолучитьДокумент() = 1 Цикл лпТаблЗначДоков.НоваяСтрока(); лпТаблЗначДоков.ДокОтчет = лпДокОтчет.ТекущийДокумент(); лпТаблЗначДоков.Менеджер = лпДокОтчет.Менеджер; КонецЦикла; //лпТаблОтбор (Таблица значений) - для отбора по менеджерам, для того что-б не перезаписывать (перепроводить) документы в цикле лпТаблОтбор = СоздатьОбъект("ТаблицаЗначений"); лпНоваяТаб.Выгрузить(лпТаблОтбор); лпТаблОтбор.НоваяКолонка("Отбор","Число"); лпТаблОтбор.Заполнить(1,,,"Отбор"); лпТаблОтбор.Свернуть("Менеджер","Отбор"); //Теперь выберем Менеджер и конкретно по нему заполним или создадим документы лпТаблОтбор.ВыбратьСтроки(); НачатьТранзакцию(); Пока лпТаблОтбор.ПолучитьСтроку() = 1 Цикл лпМенеджер = лпТаблОтбор.Менеджер; лпКолОтбора = лпТаблОтбор.Отбор; лпСтрТаблЗначДок = ""; Если лпТаблЗначДоков.НайтиЗначение(лпМенеджер,лпСтрТаблЗначДок,"Менеджер") = 1 Тогда//Всегда на 1-го Менеджера только 1 документ лпТаблЗначДоков.ПолучитьСтрокуПоНомеру(лпСтрТаблЗначДок); лпДокОтчет.НайтиДокумент(лпТаблЗначДоков.ДокОтчет); Иначе//Документ не найден лпДокОтчет.Новый(); лпДокОтчет.Менеджер = лпМенеджер; //Еще какие там необходимые реквизиты
лпДокОтчет.УстановитьНовыйНомер(); лпДокОтчет.АвтоВремяТекущее();//или еще какое-то КонецЕсли; лпДокОтчет.ВыгрузитьТабличнуюЧасть(лпТаблЧастьДока); ОбработаемТабличнуюЧасть(лпТаблЧастьДока,лпНоваяТаб,лпКолОтбора,лпМенеджер); лпКолСтрокДока = лпДокОтчет.КоличествоСтрок(); лпКолСтрокТаблЧасть = лпТаблЧастьДока.КоличествоСтрок(); Если лпКолСтрокДока < лпКолСтрокТаблЧасть Тогда//Добавлены новые строки лпДокОтчет.ЗагрузитьТабличнуюЧасть(лпТаблЧастьДока); Если (лпДокОтчет.Блокировка(1)=1) Тогда//Проверим не блокирован ли документ лпДокОтчет.Блокировка(0); лпДокОтчет.Провести();//Или Записать() не знаю Иначе Сообщить("Заблокирован "+лпДокОтчет.Представлениевида()+" № "+лпДокОтчет.НомерДок+" от "+лпДокОтчет.ДатаДок,"!"); КонецЕсли; КонецЕсли; КонецЦикла; ЗафиксироватьТранзакцию(); КонецПроцедуры //ЗаполнимДокументыИзТаб
То, что для одного человека константа, для другого - переменная. (Алан.Дж.Перлис)
А вы что сделали ? локОтчет=СоздатьОбъект("Документ.Отчет") локОтчет="";
и далее применили локОтчет.Новый() и локОтчет.НайтиДокумент(тмпОтчет.ТекущийДОкумент());
а как "обнулить" переменную типа Документ. , не слетая с типа? и не используя в цикле СоздатьОбъект ? у меня в комментариях кода указано еще ПолучитьПустоеЗначение(). оказывается "обнуляет", но потом перепозиционировать не дает...
разве что признак нахождения существующего документа писать в другую, числову, переменную.
Группа: Местный
Сообщений: 298
Спасибо сказали: 98 раз
Рейтинг: 0
Цитата(Домовик @ 01.05.15, 9:30)
а как "обнулить" переменную типа Документ. , не слетая с типа? и не используя в цикле СоздатьОбъект ? у меня в комментариях кода указано еще ПолучитьПустоеЗначение(). оказывается "обнуляет", но потом перепозиционировать не дает...
разве что признак нахождения существующего документа писать в другую, числову, переменную.
Точнее выразиться произошло не "обнуление", а изменение типа переменной. Достаточно простого перепозиционирования с одного дока на другой, т.е. если нашли работаем с тем что нашли, нет - создаем новый не изменяя тип переменной. А так вышло что изменился агрегатный тип на "Строку" и дальше использование НайтиДокумент() или Новый() не представляет возможности. В том куске кода, который Вы применили действительно нужна еще одна переменная для установки признака (число, строка, булево - без разницы), но как Вы видели в предыдущем моем посте (хотя там применена совершенно другая конструкция) без нее можно вполне обойтись, нужно только сократить количество применений Цикл. Можно еще использовать Метка и Перейти, хоть и считается что такой подход "не для проффесионалов", но и его можно было применить в той конструкции которую предоставил автор темы.
А в принцыпе, поднятый salton вопрос, не особо заслуживает внимания, скорее больше критики. "На коленке" написали, пусть нам он простит, ответы дали по существу, а дальше пускай выбирает варриант и работает над исправлением синтаксических ошибок.
ЗЫ, Автор, если будете читать еще тему, то в Процедуре ЗаполнимДокументыИзТаб после строки:
лпДокОтчет.АвтоВремяТекущее();
нужно еще одну добавить:
лпДокОтчет.Записать();
То, что для одного человека константа, для другого - переменная. (Алан.Дж.Перлис)
1С Предприятие 8.3, 1С Предприятие 8.2, 1С Предприятие 8.1, 1С Предприятие 8.0, 1С Предприятие 7.7, Литература 1С, Общие вопросы по администрированию 1С, Методическая поддержка 1С - всё в одном месте: на Украинском 1С форуме!