Итак, мы имеем типовую БП 2.0 и нам нужно реализовать печать этикеток со штрих-кодами для номенклатуры и ОС (Основные средства). В типовой БП механизм печати штрих-кодов не предусмотрен, поэтому начнем с создания данного механизма.
Сначала заведем регистр сведений для хранения штрих-кодов «ШтрихкодыНоменклатурыИОС». В регистре будет одно измерение «Объект» (составного типа: СправочникСсылка.ОС, СправочникСсылка.Номенклатура) и ресурс Штрихкод (тип Число).
Встает вопрос, как реализовать уникальность штрих-кодов в базе и контрольную цифру (используем EAN13). Рассмотрим следующий механизм: запретим пользователям интерактивный доступ к регистру, и при добавлении нового штрих-кода будем присваивать ему значение, равное количеству записей в регистре плюс один. Тем самым сохраним уникальность штрих-кодов в пределах базы. Контрольный символ будем рассчитывать при самой печати.
Далее, пишем обработку печати этикеток (самым оптимальным видом обработки считается типовой, реализованный в УТ и Рознице, поэтому будем создавать нашу обработку по аналогии с ней). Наша обработка будет выглядеть следующим образом: пользователь выбирает сначала, какую этикетку он собирается вывести на печать: для ОС или Номенклатуры, - и в зависимости от этого будут работать различные механизмы заполнения. Также, в шапке формы укажем количество этикеток по горизонтали и вертикали на странице и отступ между ними (к ним мы еще вернемся), и отступы на странице. Реализация обработки заполнения может быть в принципе любая, какую захочет пользователь. Вот один из примеров:
Перезаполнить = Ложь;
Режим = РежимДиалогаВопрос.ДаНет;
Ответ = Вопрос("Перезаполнить таблицу?",Режим);
Перезаполнить = Ответ = КодВозвратаДиалога.Да;
Если ФлагЭтикетки Тогда
ФормаВыбора = Документы.ИнвентаризацияОС.ПолучитьФормуВыбора();
Инвертеризация = ФормаВыбора.ОткрытьМодально();
Если Инвертеризация = Неопределено Тогда
Возврат
КонецЕсли;
Запрос = новый запрос;
Запрос.Текст = "ВЫБРАТЬ
| ИнвентаризацияОСОС.ОсновноеСредство,
| ИнвентаризацияОСОС.НаличиеПоДаннымУчета КАК Количество,
| ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних.ИнвентарныйНомер,
| ИнвентаризацияОСОС.Ссылка.Организация,
| ИнвентаризацияОСОС.Ссылка.ПодразделениеОрганизации КАК Подразделение
|ИЗ
| Документ.ИнвентаризацияОС.ОС КАК ИнвентаризацияОСОС
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПервоначальныеСведенияОСБухгалтерскийУчет.СрезПоследних КАК ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних
| ПО ИнвентаризацияОСОС.ОсновноеСредство = ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних.ОсновноеСредство
|ГДЕ
| ИнвентаризацияОСОС.Ссылка = &Инвертеризация";
Запрос.УстановитьПараметр("Инвертеризация",Инвертеризация);
иначе
ФормаВыбора = Документы.ИнвентаризацияТоваровНаСкладе.ПолучитьФормуВыбора();
Инвертеризация = ФормаВыбора.ОткрытьМодально();
Если Инвертеризация = Неопределено Тогда
Возврат
КонецЕсли;
Запрос = новый запрос;
Запрос.Текст = "ВЫБРАТЬ
| ИнвентаризацияТоваровНаСкладеТовары.КоличествоУчет КАК Количество,
| ИнвентаризацияТоваровНаСкладеТовары.Номенклатура как ОсновноеСредство,
| 0 как ИнвентарныйНомер,
| NULL как Организация,
| NULL как Подразделение
|ИЗ
| Документ.ИнвентаризацияТоваровНаСкладе.Товары КАК ИнвентаризацияТоваровНаСкладеТовары
|ГДЕ
| ИнвентаризацияТоваровНаСкладеТовары.Ссылка = &Инветаризация";
Запрос.УстановитьПараметр("Инветаризация",Инвертеризация);
КонецЕсли;
Выборка = Запрос.Выполнить().Выбрать();
пока Выборка.Следующий() Цикл
Строка = ОС.Добавить();
Строка.ОсновноеСредство = Выборка.ОсновноеСредство;
Строка.Печать = Истина;
Строка.Количество = Выборка.Количество;
Строка.ИнвентарныйНомер = Выборка.ИнвентарныйНомер;
Строка.Организация = Выборка.Организация;
Строка.Подразделение = Выборка.Подразделение;
КонецЦикла;
Здесь заполнение производится на основании инвентаризации, никаких сложностей (и ничего интересного)
Переходим к самой печати этикетки. Не знаю, какая система измерения в макетах для 1С используется, но нечеловеческая это точно. Согласно моему ТЗ, заказчик подразумевал размер этикетки 64,6х33,8мм. Как его реализовать в макетах? Дело оказалось намного запутанней, чем я мог себе предположить. Но по порядку. Сначала необходимо реализовать макет. В макете сделаем нашу этикетку как нам удобно (размеры не важны). Лично я использовал для этикетки 3 столбца и 6 строк (для номенклатуры, для ОС несколько больше). И присвоим нашей этикетки область «Этикетка», также создадим 3 области: горизонтальный разрыв (целая строка), вертикальный разрыв (Столбец из 6 строк) и разрыв страницы (с заданным на нем разрывом страницы), и еще три последние строки этикетки отдадим под штрихкод, и создадим в них область «ОбластьШтрихКода» (Мы еще ее помучаем).
Переходим к непосредственной реализации печати:
ТабДок = новый ТабличныйДокумент;
Если ФлагЭтикетки Тогда
Макет = ЭтотОбъект.ПолучитьМакет("МакетОС");
ОбластьВертРазрыв = Макет.ПолучитьОбласть("ВертикальныйРазрыв");
ОбластьСтрРазрыв = Макет.ПолучитьОбласть("РазрывСтраницы");
ОблстьГоризРазрыв = Макет.ПолучитьОбласть("ГоризонтальныйРазрыв");
ОбластьВертРазрыв.Области.ВертикальныйРазрыв.ШиринаКолонки = 0.505*ОтступМеждуЭтикеткамиВертикаль;
ОблстьГоризРазрыв.Области.ГоризонтальныйРазрыв.ВысотаСтроки = 2.65*ОтступМеждуЭтикеткамиГоризонтали;
Здесь вот одна особенность: значению ОбластьВертРазрыв.Области.ВертикальныйРазрыв.ШиринаКолонки мы присваиваем отступ между этикетками по вертикали, умноженный на число 0.505. Это многострадальное число и его собрат 2.65 - коэффициенты пересчета для ширины колонки и высоты колонки для макетов в 1С. В результате получаем миллиметры. Продолжим:
ЭтикетокВСтроке = 0;
СтрокНаСтранице = 1;
Для каждого строка Из ЭтотОбъект.ОС Цикл
Если Строка.Печать Тогда
Для Счетчик = 1 По Строка.Количество Цикл
ОбластьЭтикетка = Макет.ПолучитьОбласть("Этикетка");
ОбластьЭтикетка.Области.Этикетка.ВысотаСтроки = 5.1*2.65; //Коэфициент для высоты строки 2.65;
ОбластьЭтикетка.Области.Этикетка.ШиринаКолонки = 22.23*0.505; //Коэфициент для ширины колонки 0,505;
ОбластьЭтикетка.Параметры.Наименование = Строка.ОсновноеСредство.Наименование;
ОбластьЭтикетка.Параметры.Номер = Строка.ИнвентарныйНомер;
ОбластьЭтикетка.Параметры.Организация = Строка.Организация;
ОбластьЭтикетка.Параметры.Подразделение = Строка.Подразделение;
ОбластьЭтикетка.Параметры.ЗавНомер = Строка.ОсновноеСредство.ЗаводскойНомер;
Если ЗначениеЗаполнено(Строка.ОсновноеСредство.ДатаВыпуска) Тогда
ОбластьЭтикетка.Параметры.ГодВыпуска = Год(Строка.ОсновноеСредство.ДатаВыпуска);
КонецЕсли;
Если ЭтикетокВСтроке = ЭтотОбъект.КоличествоПоГоризонтале Тогда
ТабДок.Вывести(ОблстьГоризРазрыв);
Если СтрокНаСтранице = ЭтотОбъект.КоличесвоПоВертикале Тогда
ТабДок.Вывести(ОбластьСтрРазрыв);
СтрокНаСтранице = 0;
КонецЕСли;
ТабДок.Вывести(ОбластьЭтикетка);
ЭтикетокВСтроке = 0;
СтрокНаСтранице = СтрокНаСтранице + 1;
иначе
ТабДок.Присоединить(ОбластьЭтикетка);
КонецЕсли;
ЭтикетокВСтроке = ЭтикетокВСтроке + 1;
ТабДок.Присоединить(ОбластьВертРазрыв);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Здесь идет полная реализация печати этикеток. В качестве высоты и ширины строк и столбцов еще выступают некоторые числа: они получены простым делением общей высоты или ширины этикетки на количество столбцов или строк.
Отлично, печать идет, но чего-то не хватает, правильно, штрихкода.
Для начала нам нужно установить компоненту для вывода штрихкодов (элемент ActiveX). Компонента может идти с некоторыми конфигурациями или поставляется отдельно. Называется «1С: Печать штрихкодов», устанавливается как обычная программа. Теперь необходимо вставить штрихкод в наш макет. Выбираем «Таблица» - «Рисунки»-«Вставить объект» и там ищем «1С: Печать штрихкодов». Вставили объект куда нужно, теперь можно его немного протестировать, в свойствах задать другой штрихкод, его тип, фон и многое другое.
Теперь нам необходима функция создания штрих-кода и функция поиска, а лучше все вместе где-то так:
Процедура КоманднаяПанель2ЗаполнитьШрихКоды(Кнопка)
для каждого Строка из ОС цикл
Если ЗначениеЗаполнено(Строка.ОсновноеСредство) Тогда
Запрос = новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ШтрихкодыНоменклатурыИОС.Объект,
| ШтрихкодыНоменклатурыИОС.ШтрихКод
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатурыИОС КАК ШтрихкодыНоменклатурыИОС
|ГДЕ
| ШтрихкодыНоменклатурыИОС.Объект = &Объект";
Запрос.УстановитьПараметр("Объект",Строка.ОсновноеСредство);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() ТОгда
Строка.Штрихкод = ДобавитьКонтрольныйСимвол(Выборка.ШтрихКод);
иначе
Строка.Штрихкод = ДобавитьКонтрольныйСимвол(ДобавитьШтрихКод(Строка.ОсновноеСредство));
КонецЕсли;
иначе
Сообщить("В строке "+Строка.НомерСтроки+" не заполнено ОС или номенклатура");
КонецЕсли;
КонецЦикла
КонецПроцедуры
Функция ДобавитьШтрихКод(ОбъектШтрихкода)
Запись = РегистрыСведений.ШтрихкодыНоменклатурыИОС.СоздатьМенеджерЗаписи();
Запись.Объект = ОбъектШтрихкода;
НаборЗаписей = РегистрыСведений.ШтрихкодыНоменклатурыИОС.СоздатьНаборЗаписей();
НаборЗаписей.Прочитать();
Запись.ШтрихКод = НаборЗаписей.Количество()+1;
Запись.Записать();
Возврат Запись.ШтрихКод;
КонецФункции
Здесь происходит автоматическое заполнение табличной части штрихкодами (в случае отсутствия штрихкода создается новый).
Теперь наконец-то сводим вместе наши штрихкоды и макет – это делается следующим образом:
ОбластьШтрихкод = ОбластьЭтикетка.Области.ОбластьШтрихкод;
РисунокШтрихкод = ОбластьЭтикетка.Рисунки.Штрихкод;
РисунокШтрихкод.Расположить(ОбластьШтрихкод);
ОбластьЭтикетка.Рисунки.Штрихкод.Объект.АвтоТип = Истина;
ОбластьЭтикетка.Рисунки.Штрихкод.Объект.Сообщение =Лев(строка.Штрихкод,12);
Здесь устанавливаем АвтоТип, чтобы компонента сама определила тип штрихкода, и передаем в компоненту сам штрихкод (что важно, передаем ее туда без контрольного символа).
Итак, после всех выполненных манипуляций мы получили рабочую обработку печати этикеток вместе со штрих-кодами.