Загрузка данных
&НаСервере
Процедура СоздатьGTINs()
// 1. Бэкап текущего состояния регистра
ВыгрузитьРегистрВCSV();
ТестовыйРежим = Истина; // ← поменяйте на Ложь для реальной записи
// 2. ОДИН ЗАПРОС: получаем все EAN13 (13 цифр) для всех характеристик
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Штрихкоды.Владелец КАК Номенклатура,
| Штрихкоды.Характеристика КАК Характеристика,
| Штрихкоды.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.Штрихкоды КАК Штрихкоды
|ГДЕ
| Штрихкоды.Штрихкод <> """"
| И СтрДлина(Штрихкоды.Штрихкод) = 13";
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Сообщить("Нет EAN13 штрихкодов в регистре.");
Возврат;
КонецЕсли;
Выборка = Результат.Выбрать();
// 3. Собираем структуру: ключ "НоменклатураСсылка|ХарактеристикаСсылка" → массив уникальных GTIN
СтруктураГрупп = Новый Соответствие;
Пока Выборка.Следующий() Цикл
Номенклатура = Выборка.Номенклатура;
Характеристика = Выборка.Характеристика;
Штрихкод = СокрЛП(Выборка.Штрихкод);
GTIN = "0" + Штрихкод;
Ключ = Строка(Номенклатура) + "|" + Строка(Характеристика);
Массив = СтруктураГрупп.Получить(Ключ);
Если Массив = Неопределено Тогда
Массив = Новый Массив;
СтруктураГрупп.Вставить(Ключ, Массив);
КонецЕсли;
// Добавляем, если ещё нет
Если Массив.Найти(GTIN) = Неопределено Тогда
Массив.Добавить(GTIN);
КонецЕсли;
КонецЦикла;
Если СтруктураГрупп.Количество() = 0 Тогда
Сообщить("Нет данных для обработки.");
Возврат;
КонецЕсли;
// 4. Загружаем все существующие GTIN из регистра ОписаниеGTINИС в массив (быстрая проверка)
ЗапросСущ = Новый Запрос;
ЗапросСущ.Текст = "ВЫБРАТЬ ОписаниеGTINИС.GTIN ИЗ РегистрСведений.ОписаниеGTINИС КАК ОписаниеGTINИС";
РезультатСущ = ЗапросСущ.Выполнить();
СуществующиеGTIN = Новый Массив;
Если РезультатСущ.Пустой() = Ложь Тогда
ВыборкаСущ = РезультатСущ.Выбрать();
Пока ВыборкаСущ.Следующий() Цикл
СуществующиеGTIN.Добавить(ВыборкаСущ.GTIN);
КонецЦикла;
КонецЕсли;
// 5. Подготовка переменных статистики и коллекций
КоличествоХарактеристик = 0;
КоличествоСEAN13 = 0;
КоличествоБезEAN13 = 0; // не используется, но оставим для совместимости
ВсегоУникальныхEAN13 = 0;
КоличествоУжеСуществует = 0;
КоличествоДобавленных = 0;
НаборЗаписей = РегистрыСведений.ОписаниеGTINИС.СоздатьНаборЗаписей();
СписокДобавляемых = Новый Массив; // для плоского CSV
ОтчетныеЗаписи = Новый Массив; // для группового отчёта
// 6. Основной цикл по группам
Для каждого Элемент Из СтруктураГрупп Цикл
Ключ = Элемент.Ключ;
МассивGTIN = Элемент.Значение;
КоличествоХарактеристик = КоличествоХарактеристик + 1;
КоличествоСEAN13 = КоличествоСEAN13 + 1;
ВсегоУникальныхEAN13 = ВсегоУникальныхEAN13 + МассивGTIN.Количество();
// Извлекаем ссылки из ключа
Разделитель = Найти(Ключ, "|");
СтрНоменклатура = Лев(Ключ, Разделитель - 1);
СтрХарактеристика = Сред(Ключ, Разделитель + 1);
// Преобразуем строки в ссылки (через ЗначениеИзСтрокиВнутр, но лучше так: получаем объекты из регистра)
// Мы не можем гарантировать, что строка преобразуется в ссылку, поэтому поступим иначе:
// будем хранить в структуре вместе с ключом сами ссылки. Для этого переделаем сбор данных.
// Но так как мы уже собрали структуру со строками, переделаем: создадим соответствие "ключ-структура" с ссылками.
// Это проще сделать заново в одном цикле с запросом, но мы уже его выполнили.
// Поскольку это не повлияет на производительность, переделаем сбор, чтобы сразу хранить ссылки.
КонецЦикла;
// ПЕРЕДЕЛЫВАЕМ СБОР С ССЫЛКАМИ (без дополнительных запросов)
// Выполним запрос ещё раз и сразу сохраним структуру со ссылками
Запрос2 = Новый Запрос;
Запрос2.Текст = "
|ВЫБРАТЬ
| Штрихкоды.Владелец КАК Номенклатура,
| Штрихкоды.Характеристика КАК Характеристика,
| Штрихкоды.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.Штрихкоды КАК Штрихкоды
|ГДЕ
| Штрихкоды.Штрихкод <> """"
| И СтрДлина(Штрихкоды.Штрихкод) = 13";
Результат2 = Запрос2.Выполнить();
Выборка2 = Результат2.Выбрать();
// Структура с ключом-строкой и значением-структурой с полями НоменклатураСсылка, ХарактеристикаСсылка, МассивGTIN
ГруппыСсылки = Новый Соответствие;
Пока Выборка2.Следующий() Цикл
НоменклатураСсылка = Выборка2.Номенклатура;
ХарактеристикаСсылка = Выборка2.Характеристика;
Штрихкод = СокрЛП(Выборка2.Штрихкод);
GTIN = "0" + Штрихкод;
Ключ = Строка(НоменклатураСсылка) + "|" + Строка(ХарактеристикаСсылка);
СтруктураГруппы = ГруппыСсылки.Получить(Ключ);
Если СтруктураГруппы = Неопределено Тогда
СтруктураГруппы = Новый Структура("Номенклатура, Характеристика, GTINМассив", НоменклатураСсылка, ХарактеристикаСсылка, Новый Массив);
ГруппыСсылки.Вставить(Ключ, СтруктураГруппы);
КонецЕсли;
Массив = СтруктураГруппы.GTINМассив;
Если Массив.Найти(GTIN) = Неопределено Тогда
Массив.Добавить(GTIN);
КонецЕсли;
КонецЦикла;
// 7. Теперь обходим группы со ссылками
КоличествоХарактеристик = 0;
КоличествоСEAN13 = 0;
ВсегоУникальныхEAN13 = 0;
КоличествоУжеСуществует = 0;
КоличествоДобавленных = 0;
Для каждого Элемент Из ГруппыСсылки Цикл
СтруктураГруппы = Элемент.Значение;
НоменклатураСсылка = СтруктураГруппы.Номенклатура;
ХарактеристикаСсылка = СтруктураГруппы.Характеристика;
МассивGTIN = СтруктураГруппы.GTINМассив;
КоличествоХарактеристик = КоличествоХарактеристик + 1;
КоличествоСEAN13 = КоличествоСEAN13 + 1;
ВсегоУникальныхEAN13 = ВсегоУникальныхEAN13 + МассивGTIN.Количество();
Для каждого GTIN Из МассивGTIN Цикл
// Проверяем наличие в массиве существующих (быстрый поиск)
Если СуществующиеGTIN.Найти(GTIN) <> Неопределено Тогда
КоличествоУжеСуществует = КоличествоУжеСуществует + 1;
Продолжить;
КонецЕсли;
// Добавляем в набор записей
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.GTIN = GTIN;
НоваяЗапись.ВидУпаковки = Перечисления.ВидыУпаковокИС.Потребительская;
НоваяЗапись.КоличествоПотребительскихУпаковок = 1;
КоличествоДобавленных = КоличествоДобавленных + 1;
// Для плоского списка
СтруктураЗаписи = Новый Структура;
СтруктураЗаписи.Вставить("GTIN", GTIN);
СтруктураЗаписи.Вставить("ВидУпаковки", Перечисления.ВидыУпаковокИС.Потребительская);
СтруктураЗаписи.Вставить("КоличествоПотребительскихУпаковок", 1);
СписокДобавляемых.Добавить(СтруктураЗаписи);
// Для отчёта по группам
СтруктураОтчета = Новый Структура;
СтруктураОтчета.Вставить("Номенклатура", НоменклатураСсылка.Наименование);
СтруктураОтчета.Вставить("Характеристика", ?(ХарактеристикаСсылка.Пустая(), "Без характеристики", ХарактеристикаСсылка.Наименование));
СтруктураОтчета.Вставить("GTIN", GTIN);
ОтчетныеЗаписи.Добавить(СтруктураОтчета);
КонецЦикла;
КонецЦикла;
// 8. Сохранение отчётов
Если СписокДобавляемых.Количество() > 0 Тогда
СохранитьСписокВCSV(СписокДобавляемых);
КонецЕсли;
Если ОтчетныеЗаписи.Количество() > 0 Тогда
СохранитьОтчетПоДобавленным(ОтчетныеЗаписи);
КонецЕсли;
// 9. Запись или тест
Если НаборЗаписей.Количество() > 0 Тогда
Если ТестовыйРежим Тогда
Сообщить("*** ТЕСТ: запись отключена. Будет добавлено записей: " + НаборЗаписей.Количество());
Иначе
НаборЗаписей.Записать();
Сообщить("Данные записаны. Добавлено записей: " + НаборЗаписей.Количество());
КонецЕсли;
Иначе
Сообщить("Нет новых записей для добавления.");
КонецЕсли;
// 10. Статистика
Сообщить("========== СТАТИСТИКА ==========");
Сообщить("Всего уникальных пар (Номенклатура + Характеристика): " + КоличествоХарактеристик);
Сообщить("Из них имеют хотя бы один EAN13: " + КоличествоСEAN13);
Сообщить("Всего уникальных EAN13 (преобразованных в GTIN): " + ВсегоУникальныхEAN13);
Сообщить("Из них уже существовали в регистре: " + КоличествоУжеСуществует);
Сообщить("Добавлено новых записей: " + КоличествоДобавленных);
Сообщить("=================================");
ЗаписьЖурналаРегистрации("Заполнение GTIN", УровеньЖурналаРегистрации.Информация,,
"Тест: " + ?(ТестовыйРежим, "да", "нет") + " | Добавлено: " + КоличествоДобавленных);
КонецПроцедуры
// ============================================================
// Остальные функции (бэкап, сохранение списка, отчёта) остаются без изменений.
// Они уже были приведены ранее, я включу их в финальный код.
// ============================================================
Процедура ВыгрузитьРегистрВCSV()
ИмяФайла = "F:\ОписаниеGTINИС_бэкап_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".csv";
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ОписаниеGTINИС.GTIN, ОписаниеGTINИС.ВидУпаковки, ОписаниеGTINИС.КоличествоПотребительскихУпаковок ИЗ РегистрСведений.ОписаниеGTINИС КАК ОписаниеGTINИС";
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Сообщить("Регистр пуст.");
Возврат;
КонецЕсли;
Выборка = Результат.Выбрать();
ТекстCSV = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
ТекстCSV.ЗаписатьСтроку("GTIN;ВидУпаковки;КоличествоУпаковок");
Пока Выборка.Следующий() Цикл
ТекстCSV.ЗаписатьСтроку(Выборка.GTIN + ";" + Строка(Выборка.ВидУпаковки) + ";" + Строка(Выборка.КоличествоПотребительскихУпаковок));
КонецЦикла;
ТекстCSV.Закрыть();
Сообщить("Бэкап сохранён: " + ИмяФайла);
КонецПроцедуры
Процедура СохранитьСписокВCSV(СписокЗаписей)
ИмяФайла = "F:\Добавляемые_GTIN_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".csv";
ТекстCSV = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
ТекстCSV.ЗаписатьСтроку("GTIN;ВидУпаковки;КоличествоУпаковок");
Для каждого Запись Из СписокЗаписей Цикл
ТекстCSV.ЗаписатьСтроку(Запись.GTIN + ";" + Строка(Запись.ВидУпаковки) + ";" + Строка(Запись.КоличествоПотребительскихУпаковок));
КонецЦикла;
ТекстCSV.Закрыть();
Сообщить("Список добавляемых GTIN сохранён: " + ИмяФайла);
КонецПроцедуры
Процедура СохранитьОтчетПоДобавленным(ОтчетныеЗаписи)
Если ОтчетныеЗаписи.Количество() = 0 Тогда
Сообщить("Нет данных для отчёта.");
Возврат;
КонецЕсли;
Группы = Новый Соответствие;
Для каждого Запись Из ОтчетныеЗаписи Цикл
Ключ = Запись.Номенклатура + "|" + Запись.Характеристика;
МассивGTIN = Группы.Получить(Ключ);
Если МассивGTIN = Неопределено Тогда
МассивGTIN = Новый Массив;
Группы.Вставить(Ключ, МассивGTIN);
КонецЕсли;
МассивGTIN.Добавить(Запись.GTIN);
КонецЦикла;
СтрокиДляCSV = Новый Массив;
СтрокиДляCSV.Добавить("Номенклатура;Характеристика;Добавленные штрихкоды;Количество");
Для каждого Элемент Из Группы Цикл
Ключ = Элемент.Ключ;
МассивGTIN = Элемент.Значение;
Разделитель = Найти(Ключ, "|");
Номенклатура = Лев(Ключ, Разделитель - 1);
Характеристика = Сред(Ключ, Разделитель + 1);
СписокШтрихкодов = "";
Для каждого GTIN Из МассивGTIN Цикл
Если СписокШтрихкодов = "" Тогда
СписокШтрихкодов = GTIN;
Иначе
СписокШтрихкодов = СписокШтрихкодов + ", " + GTIN;
КонецЕсли;
КонецЦикла;
Количество = МассивGTIN.Количество();
Строка = Номенклатура + ";" + Характеристика + ";" + СписокШтрихкодов + ";" + Строка(Количество);
СтрокиДляCSV.Добавить(Строка);
КонецЦикла;
ИмяФайла = "F:\Отчет_по_добавленным_GTIN_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".csv";
ТекстCSV = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
Для каждого Строка Из СтрокиДляCSV Цикл
ТекстCSV.ЗаписатьСтроку(Строка);
КонецЦикла;
ТекстCSV.Закрыть();
Сообщить("Отчёт по добавленным GTIN сохранён: " + ИмяФайла);
КонецПроцедуры
// ============================================================
// Обработчик кнопки
// ============================================================
&НаКлиенте
Процедура ВыполнитьНаКлиенте(Команда)
СоздатьGTINs();
КонецПроцедуры