При организации обмена данными между базами конфигурации «Торговля и Склад 7.7 (ред. 9.2)» разработчики часто сталкиваются с ситуацией, когда при выгрузке документов и справочника номенклатуры в базу-приемник переносятся только БазоваяЕдиница и ОсновнаяЕдиница. Дополнительные единицы измерения, к которым привязаны различные штрихкоды одного и того же товара (например, разные издания книг или упаковки), в выгрузку не попадают. Попытки перенести их стандартными обработками нередко приводят к затиранию существующих данных или бесконечному дублированию строк.
Разберем детально, почему это происходит, и рассмотрим надежные способы решения данной задачи.
Проанализируем архитектуру конфигурации и механизмы типового переноса:
Единицы не имеет длины кода и наименования (код равен 0, а строковое представление формируется динамически на основе реквизита ОКЕИ и коэффициента). Стандартные механизмы синхронизации, рассчитанные на поиск по коду или наименованию, дают сбой: система не может однозначно идентифицировать элемент и либо перезаписывает первую попавшуюся запись владельца, либо бесконечно создает дубли.Инструкция), который не открывается напрямую в современных редакциях КД 2.x.Если требуется быстро передать недостающие штрихкоды и единицы без изменения глобальных правил обмена, наиболее надежный и легко контролируемый способ — создание внешней связки выгрузки и загрузки через текстовый файл (CSV). Посмотрим на реализацию этого механизма.
Формат строки файла обмена:
В файл выгружаются поля, разделенные точкой с запятой: КодНоменклатуры;Штрихкод;КодОКЕИ;Коэффициент. Если все единицы являются штучными с коэффициентом 1, достаточно передавать только код товара и штрихкод.
Алгоритм выгрузки из исходной базы:
Текст = СоздатьОбъект("Текст");
СпрН = СоздатьОбъект("Справочник.Номенклатура");
СпрЕ = СоздатьОбъект("Справочник.Единицы");
СпрН.ВыбратьЭлементы();
Пока СпрН.ПолучитьЭлемент() = 1 Цикл
Если СпрН.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
СпрЕ.ИспользоватьВладельца(СпрН.ТекущийЭлемент());
СпрЕ.ВыбратьЭлементы();
Пока СпрЕ.ПолучитьЭлемент() = 1 Цикл
ШК = СокрЛП(СпрЕ.Штрихкод);
Если ПустаяСтрока(ШК) = 0 Тогда
СтрокаВыгрузки = СокрЛП(СпрН.Код) + ";" + ШК + ";" + СокрЛП(СпрЕ.ОКЕИ.Код) + ";" + СпрЕ.Коэффициент;
Текст.ДобавитьСтроку(СтрокаВыгрузки);
КонецЕсли;
КонецЦикла;
КонецЦикла;
ПутьКФайлу = КаталогВременныхФайлов() + "barcodes_export.csv";
Текст.Записать(ПутьКФайлу);
Предупреждение("Выгрузка завершена в файл: " + ПутьКФайлу);
Алгоритм загрузки в целевую базу с контролем дублей:
Текст = СоздатьОбъект("Текст");
ПутьКФайлу = КаталогВременныхФайлов() + "barcodes_export.csv";
Если ФС.СуществуетФайл(ПутьКФайлу) = 0 Тогда
Предупреждение("Файл не найден!");
Возврат;
КонецЕсли;
Текст.Открыть(ПутьКФайлу);
СпрН = СоздатьОбъект("Справочник.Номенклатура");
СпрЕ = СоздатьОбъект("Справочник.Единицы");
СпрОКЕИ = СоздатьОбъект("Справочник.ОКЕИ");
Для НомСтр = 1 По Текст.КоличествоСтрок() Цикл
Стр = Текст.ПолучитьСтроку(НомСтр);
Стр = СтрЗаменить(Стр, ";", РазделительСтрок);
КодТовара = СокрЛП(СтрПолучитьСтроку(Стр, 1));
Штрихкод = СокрЛП(СтрПолучитьСтроку(Стр, 2));
КодОКЕИ = СокрЛП(СтрПолучитьСтроку(Стр, 3));
Коэфф = Число(СтрПолучитьСтроку(Стр, 4));
Если СпрН.НайтиПоКоду(КодТовара, 2) = 1 Тогда
Товар = СпрН.ТекущийЭлемент();
СпрЕ.ИспользоватьВладельца(Товар);
// Проверяем наличие единицы с таким штрихкодом
Найдено = 0;
СпрЕ.ВыбратьЭлементы();
Пока СпрЕ.ПолучитьЭлемент() = 1 Цикл
Если СокрЛП(СпрЕ.Штрихкод) = Штрихкод Тогда
Найдено = 1;
Прервать;
КонецЕсли;
КонецЦикла;
// Если штрихкод не найден - создаем новую единицу
Если Найдено = 0 Тогда
СпрЕ.Новый();
СпрЕ.Владелец = Товар;
СпрЕ.Штрихкод = Штрихкод;
СпрЕ.Коэффициент = ?(Коэфф = 0, 1, Коэфф);
Если СпрОКЕИ.НайтиПоКоду(КодОКЕИ, 2) = 1 Тогда
СпрЕ.ОКЕИ = СпрОКЕИ.ТекущийЭлемент();
КонецЕсли;
СпрЕ.Записать();
КонецЕсли;
КонецЕсли;
КонецЦикла;
Предупреждение("Загрузка штрихкодов успешно завершена!");
Если обмен настраивается через универсальный механизм КД 2.x (с использованием обработок MDExp.ert, V77Exp.ert и V77Imp.ert), выгрузку всех подчиненных единиц измерения настраивают внутри правила конвертации объекта (ПКО) Номенклатура.
Разберем по шагам настройку обработчиков:
Номенклатура в обработчике события «После выгрузки» прописываем программную выборку всех подчиненных элементов справочника единиц:
СпрЕд = СоздатьОбъект("Справочник.Единицы");
СпрЕд.ИспользоватьВладельца(Источник.ТекущийЭлемент());
СпрЕд.ВыбратьЭлементы();
Пока СпрЕд.ПолучитьЭлемент() = 1 Цикл
ВыгрузитьПоПравилу(СпрЕд.ТекущийЭлемент(), , , , "ЕдиницыНоменклатуры");
КонецЦикла;
ЕдиницыНоменклатуры настраиваем поля поиска. В качестве полей поиска обязательно указываем комбинацию реквизитов: Владелец + Штрихкод (либо Владелец + ОКЕИ + Коэффициент). Это исключит затирание элементов с одинаковым коэффициентом, но разными штрихкодами.При организации автоматического сохранения файлов обмена важно правильно определять рабочие каталоги операционной системы:
КаталогПользователя() возвращает путь к служебной папке пользователя внутри каталога информационной базы (...\USRDEF\ИмяПользователя\), а не путь к профилю Windows.КаталогВременныхФайлов(), которая гарантированно возвращает доступную для записи системную папку Temp.%USERPROFILE% или %APPDATA%), в коде 1С 7.7 используется обращение к COM-объекту WScript.Shell:
WshShell = СоздатьОбъект("WScript.Shell");
ПутьКПрофилю = WshShell.ExpandEnvironmentStrings("%USERPROFILE%");
КаталогДокументов = ПутьКПрофилю + "\Мои документы\";