Реклама на этом месте
Форум 1С
Форум 1С
Программистам. Бухгалтерам. Администраторам. Пользователям
Задай вопрос - получи решение проблемы. Без троллинга и флуда.
24 Май 2018, 05:36
МультиВход
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?
 
collapse

Автор Тема: История изменения таб. части документов  (Прочитано 3128 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн KKnD

  • *
  • Сообщений: 1
  • РЕПУТАЦИЯ: 0
  • Регистрация: 2014-10-23
  • Сайт: 
  • Профессия: Ученик 1С
Всем доброго дня.
Понадобилось фиксировать изменения табличной части документа ЗаказПокупателя.
Покопался в интернете и нашел простенький код, но никак не могу с ним справиться:

хочу, что бы у меня фиксировалась история изменений табличный части «Товары» документа «ЗаказПокупателя»
Создаем справочник “История изменений”
Для начала создал элементарный справочник “ИсторияИзменений”:
 
Справочник история изменений
Реквизиты:
Объект – ДокументСсылка, СправочникСсылка (По этому объекту в элементе справочника будет хранится история)
Табличная часть – изменения:
(тут тип значения ДокументСсылка.ЗаказПокупателя)
ДатаЗаписи – Дата (дата и время записи изменения)
(просто тип  дата состав  дата и время?)
НазваниеТабличнойЧасти – Строка (длина 50, Название табличной части по которой требуется фиксировать изменения)
(Тут тип строка и назвать ее Товары?)
ТаблицаИзменений – Строка (длина неограничена, тут будет хранится наша таблица значений)
(Тут тип строка и назвать ее ТаблицаИзменений?)
Автор – Пользователь (кто сделал изменения)
(тут тип значения СправочникиСсылка.Пользователи?)

Справочник готов, теперь необходимо поработать с его модулем, а именно:
И во всех модулях(которые ниже) вместо:
ТабличнаяЧасть – так и должна остаться? Не меняю?
НазваниеТабличнойЧасти – ставлю Товары?
1. Создать процедуру, которая будет фиксировать изменения в элементе справочника
2. Создать функции для получения предыдущего состояния табличной части, функцию для проверки изменилась ли табличная часть или нет, функцию для записи изменений
3. Создать интерфейсную часть, то есть форму списка и форму элемента справочника
Весь код модуля объекта справочника “ИсторияИзменений” приведен ниже с комментариями. Смысл обработки будет заключаться в следующем: При записи объекта мы будем фиксировать табличную часть, преобразовывать ее в таблицу значений, преобразовывать таблицу значений в строку и хранить в справочнике.

Это основная функция которую будет вызывать для записи изменения
//Фиксируются только новые и измененные строки
//Табличная часть - в эту переменную передаем табличную часть документ
//НазваниеТабличнойЧасти - название табличной части. именно по этому параметру будет искаться предыдущее значение табличной части.
//Объект - объект, в принципе может и не поднадобиться
Процедура ЗафиксироватьИзменения(ТабличнаяЧасть, НазваниеТабличнойЧасти, Объект) Экспорт	
СтараяТаблица = ПолучитьСтаруюТаблицу(НазваниеТабличнойЧасти); //Получаем старую таблицу
НоваяТаблица = ТабличнаяЧасть.Выгрузить();

Если ТипЗнч(СтараяТаблица)=Тип("ТаблицаЗначений") Тогда
//Если в новой таблице нет строк тогда просто записываем новую таблицу
Если НоваяТаблица.Количество()=0 и СтараяТаблица.Количество()>0 Тогда
ЗафиксироватьТаблицу(НоваяТаблица, НазваниеТабличнойЧасти);
ИначеЕсли НоваяТаблица.Количество()>0 и СтараяТаблица.Количество()>0 Тогда
//Надо сравнивать
Если ЕстьИзмененияВТаблицах(СтараяТаблица, НоваяТаблица) Тогда
ЗафиксироватьТаблицу(НоваяТаблица, НазваниеТабличнойЧасти);
КонецЕсли;
КонецЕсли;
Иначе
//Сравнивать не надо - это первая фиксация
//Фиксируем только если в таблице есть строки
Если НоваяТаблица.Количество()>0 Тогда
ЗафиксироватьТаблицу(НоваяТаблица, НазваниеТабличнойЧасти);
КонецЕсли;
КонецЕсли;
КонецПроцедуры

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

//Функция сравнивает две строки, которые являются предыдущим и текущим значением ТабличнойЧасти документа
Функция ЕстьИзмененияВТаблицах(СтараяТаблица, НоваяТаблица)
Если ЗначениеВСтрокуВнутр(СтараяТаблица)=ЗначениеВСтрокуВнутр(НоваяТаблица) Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции

Фиксируем изменения, а именно записываем новую табличную часть документа в элемент справочника "ИсторияИзменений"
Функция ЗафиксироватьТаблицу(ТаблицаИзменений, НазваниеТабличнойЧасти) Экспорт
НоваяСтрока = Изменения.Добавить();
НоваяСтрока.ДатаЗаписи = ТекущаяДата();
НоваяСтрока.НазваниеТабличнойЧасти = НазваниеТабличнойЧасти;
НоваяСтрока.ТаблицаИзменений = ЗначениеВСтрокуВнутр(ТаблицаИзменений);
НоваяСтрока.Автор = ПараметрыСеанса.Пользователь;
Записать();
КонецФункции


   //Это основная функция которую будет вызывать для записи изменения
//Фиксируются только новые и измененные строки
//Табличная часть - в эту переменную передаем табличную часть документ
//НазваниеТабличнойЧасти - название табличной части. именно по этому параметру будет искаться предыдущее значение табличной части.
//Объект - объект, в принципе может и не поднадобиться
Процедура ЗафиксироватьИзменения(ТабличнаяЧасть, НазваниеТабличнойЧасти, Объект) Экспорт	
СтараяТаблица = ПолучитьСтаруюТаблицу(НазваниеТабличнойЧасти); //Получаем старую таблицу
НоваяТаблица = ТабличнаяЧасть.Выгрузить();

Если ТипЗнч(СтараяТаблица)=Тип("ТаблицаЗначений") Тогда
//Если в новой таблице нет строк тогда просто записываем новую таблицу
Если НоваяТаблица.Количество()=0 и СтараяТаблица.Количество()>0 Тогда
ЗафиксироватьТаблицу(НоваяТаблица, НазваниеТабличнойЧасти);
ИначеЕсли НоваяТаблица.Количество()>0 и СтараяТаблица.Количество()>0 Тогда
//Надо сравнивать
Если ЕстьИзмененияВТаблицах(СтараяТаблица, НоваяТаблица) Тогда
ЗафиксироватьТаблицу(НоваяТаблица, НазваниеТабличнойЧасти);
КонецЕсли;
КонецЕсли;
Иначе
//Сравнивать не надо - это первая фиксация
//Фиксируем только если в таблице есть строки
Если НоваяТаблица.Количество()>0 Тогда
ЗафиксироватьТаблицу(НоваяТаблица, НазваниеТабличнойЧасти);
КонецЕсли;
КонецЕсли;
КонецПроцедуры

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

//Функция сравнивает две строки, которые являются предыдущим и текущим значением ТабличнойЧасти документа
Функция ЕстьИзмененияВТаблицах(СтараяТаблица, НоваяТаблица)
Если ЗначениеВСтрокуВнутр(СтараяТаблица)=ЗначениеВСтрокуВнутр(НоваяТаблица) Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции

Фиксируем изменения, а именно записываем новую табличную часть документа в элемент справочника "ИсторияИзменений"
Функция ЗафиксироватьТаблицу(ТаблицаИзменений, НазваниеТабличнойЧасти) Экспорт
НоваяСтрока = Изменения.Добавить();
НоваяСтрока.ДатаЗаписи = ТекущаяДата();
НоваяСтрока.НазваниеТабличнойЧасти = НазваниеТабличнойЧасти;
НоваяСтрока.ТаблицаИзменений = ЗначениеВСтрокуВнутр(ТаблицаИзменений);
НоваяСтрока.Автор = ПараметрыСеанса.Пользователь;
Записать();
КонецФункции
По сути это весь код для фиксации изменений, осталось сделать глобальную процедуру, которая будет вызываться из любого документа или справочника, а также можно дописать интерфейс, чтобы была возможность удобно смотреть историю.
Код функции указанной ниже размещаем в любом общем модуле. именно эта функция будет вызываться из модуля формы любого документа или справочника, из процедуры “ПослеЗаписи” с требуемыми параметрами.
 
Процедура ЗафиксироватьИзмененияТабличнойЧасти(ТабличнаяЧасть, НазваниеТабличнойЧасти, ОбъектСсылка) Экспорт;
Если ТабличнаяЧасть.Количество()>0 Тогда
Запрос = Новый Запрос();
ТекстЗапроса = "ВЫБРАТЬ
| ИсторияИзменений.Ссылка
|ИЗ
| Справочник.ИсторияИзменений КАК ИсторияИзменений
|ГДЕ
| ИсторияИзменений.Объект = &ОбъектСсылка";

Запрос.Текст = ТекстЗапроса;
Запрос.Параметры.Вставить("ОбъектСсылка", ОбъектСсылка);

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

СправочникИзменений.ЗафиксироватьИзменения(ТабличнаяЧасть, НазваниеТабличнойЧасти, ОбъектСсылка);
КонецЕсли;
КонецПроцедуры



Процедура ЗафиксироватьИзмененияТабличнойЧасти(ТабличнаяЧасть, НазваниеТабличнойЧасти, ОбъектСсылка) Экспорт;
Если ТабличнаяЧасть.Количество()>0 Тогда
Запрос = Новый Запрос();
ТекстЗапроса = "ВЫБРАТЬ
| ИсторияИзменений.Ссылка
|ИЗ
| Справочник.ИсторияИзменений КАК ИсторияИзменений
|ГДЕ
| ИсторияИзменений.Объект = &ОбъектСсылка";

Запрос.Текст = ТекстЗапроса;
Запрос.Параметры.Вставить("ОбъектСсылка", ОбъектСсылка);

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

СправочникИзменений.ЗафиксироватьИзменения(ТабличнаяЧасть, НазваниеТабличнойЧасти, ОбъектСсылка);
КонецЕсли;
КонецПроцедуры
Создаем форму элемента справочника “История изменений”
Рисуем форму элемента:
 
История изменений 1С
Форма элемента справочника история изменений выглядит в начальном виде именно так. В поле старые значения будут показываться предыдущие значения, а в поле новые значения… ну вы догадались. В эти поля являются табличным полями с названиями соответственно “ТаблицаСтароеЗначение” и “ТаблицаНовоеЗначение”.
А теперь код формы:
 
Процедура АнализироватьТаблицы()
Если (ТаблицаСтароеЗначение.Количество() = 0) или (ТаблицаНовоеЗначение.Количество() = 0) Тогда

Иначе
ТЗРезНовая = ТаблицаНовоеЗначение.Скопировать();
ТЗРезНовая.Очистить();
ТЗРезСтарая = ТЗРезНовая.Скопировать();
КоличествоКолонок = ТЗРезНовая.Колонки.Количество();

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

КонецЦикла;
н=н+1;
КонецЦикла;
КонецЕсли;
КонецПроцедуры

Процедура ИзмененияПриАктивизацииСтроки(Элемент)
Если Изменения.Количество() > 0 Тогда
ТаблицаНовоеЗначение = ЗначениеИзСтрокиВнутр(Элемент.ТекущиеДанные.ТаблицаИзменений);
ЭлементыФормы.ТаблицаНовоеЗначение.СоздатьКолонки();

ТаблицаСтароеЗначение = Неопределено;

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

Если ТипЗнч(ТаблицаСтароеЗначение) = Тип("ТаблицаЗначений") Тогда
ЭлементыФормы.ТаблицаСтароеЗначение.СоздатьКолонки();
КонецЕсли;
КонецЕсли;

АнализироватьТаблицы();
КонецПроцедуры



Процедура АнализироватьТаблицы()
Если (ТаблицаСтароеЗначение.Количество() = 0) или (ТаблицаНовоеЗначение.Количество() = 0) Тогда

Иначе
ТЗРезНовая = ТаблицаНовоеЗначение.Скопировать();
ТЗРезНовая.Очистить();
ТЗРезСтарая = ТЗРезНовая.Скопировать();
КоличествоКолонок = ТЗРезНовая.Колонки.Количество();

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

КонецЦикла;
н=н+1;
КонецЦикла;
КонецЕсли;
КонецПроцедуры

Процедура ИзмененияПриАктивизацииСтроки(Элемент)
Если Изменения.Количество() > 0 Тогда
ТаблицаНовоеЗначение = ЗначениеИзСтрокиВнутр(Элемент.ТекущиеДанные.ТаблицаИзменений);
ЭлементыФормы.ТаблицаНовоеЗначение.СоздатьКолонки();

ТаблицаСтароеЗначение = Неопределено;

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

Если ТипЗнч(ТаблицаСтароеЗначение) = Тип("ТаблицаЗначений") Тогда
ЭлементыФормы.ТаблицаСтароеЗначение.СоздатьКолонки();
КонецЕсли;
КонецЕсли;

АнализироватьТаблицы();
КонецПроцедуры

 
Процедура ПослеЗаписи()
 
// Попытка
ЗафиксироватьИзмененияТабличнойЧасти(Работы, "Работы", ЭтотОбъект.Ссылка);
Исключение

КонецПопытки;
КонецПроцедуры


У меня соответственно не получается вставить верные реквизиты для функции "ЗафиксироватьИзмененияТабличнойЧасти".
Если кто-то может - заполните пожалуйста код или поделитесь ссылкой...


Оффлайн Luzer1C

  • ****
  • Сообщений: 455
  • РЕПУТАЦИЯ: 57
  • КПД: 13%
  • Регистрация: 2014-02-17
  • Сайт: 
  • Профессия: Программист 1С
Знаю, что в УПП есть "Версионирование". В остальных базах - не знаю. Лучше здесь использовать стандартный механизм через регистр сведений, а не справочник.
Халамбалам.


Теги:
 

Заполнение табличной части документа табличной частью из другого документа

Автор PeaceownerРаздел Пользователям "1С - Предприятие 8"

Ответов: 1
Просмотров: 2823
Последний ответ 30 Ноя 2011, 07:10
от has
Как создать нескольких документов "расчет при увольнении" на основании кадрового документа "увольнение" как Отпуска

Автор cozuРаздел Пользователям "1С - Предприятие 8"

Ответов: 3
Просмотров: 3692
Последний ответ 21 Мар 2015, 20:24
от дфтын
Не работает структура подчиненности документов "Требование-накладная" и "Передач

Автор sv_stas_svРаздел Конфигурирование, программирование в "1С - Предприятие 8"

Ответов: 0
Просмотров: 4363
Последний ответ 10 Мар 2011, 07:36
от sv_stas_sv
В строке номер "1" табличной части "Состав набора": Не заполнено значение реквиз

Автор ХеляРаздел Пользователям "1С - Предприятие 8"

Ответов: 0
Просмотров: 7131
Последний ответ 18 Сен 2011, 16:07
от Хеля
В строке "1" табличной части "Состав набора": Не заполнено значение реквизитов Цена

Автор rusalkaРаздел Пользователям "1С - Предприятие 8"

Ответов: 0
Просмотров: 2737
Последний ответ 11 Апр 2014, 16:52
от rusalka

* Живое общение

Не устроил ответ?

Зарегистрируйся и задай свой вопрос. Живое общение приносит результат намного быстрее.


Зарегистрироваться

* Реклама

* Поиск

* Последние задачи на разработку (фриланс)

* Реклама

* Последние вакансии

* Топ 10 авторов за месяц

Геннадий ОбьГЭС Геннадий ОбьГЭС
161 Сообщений
alex0402
76 Сообщений
oleg-x
68 Сообщений
AIFrame AIFrame
61 Сообщений
buketov.av buketov.av
44 Сообщений
wise wise
39 Сообщений
KOI8-R
35 Сообщений
ilyay ilyay
29 Сообщений
Анюта17
29 Сообщений
Alter
29 Сообщений

* Кто онлайн

  • Точка Гостей: 205
  • Точка Скрытых: 0
  • Точка Пользователей: 3
  • Точка Сейчас на форуме:

* Облако тэгов

* Форум 1С с мобильного

* Инструменты

* Дополнительно

Поиск

 
SimplePortal 2.3.5 © 2008-2012, SimplePortal