Печать этикеток 1С в торговых конфигурациях — штатная функция: в УТ 11, Рознице 3.0 и УНФ 3.0 есть обработка «Печать этикеток и ценников» и справочник шаблонов с редактором. Программист нужен, когда типового шаблона мало. Ниже — шаги для пользователя, затем код: штрихкод средствами БСП, N копий по документу поступления и команда печати в расширении.
Устройство печатных форм БСП здесь не повторяется — см. статьи о печатной форме 1С, про макет печатной формы и про ПолучитьМакет.
Шаблоны хранятся в справочнике «Шаблоны этикеток и ценников». Ссылка на него — в настройках раздела продаж: «НСИ и администрирование → Настройка НСИ и разделов → Продажи», группа «Розничные продажи».

В демо-базе справочник уже заполнен: ценник и этикетка «по умолчанию», варианты для обуви, доставки, складской ячейки, серии и упаковочного листа. «Создать» открывает помощник: наименование, «Назначение» (этикетка или ценник для товаров, этикетка серии, ячейки, доставки) и «Размер ленты». «Напечатать образец» — пробная этикетка на товар из поля «Для чего».

«Изменить в редакторе» открывает шаблон как табличный документ, поля добавляются из списка доступных: товар, характеристика, упаковка, цена, остаток, штрихкод. У рисунка штрихкода свои настройки: «Тип кода», «Отображать текст», «Размер шрифта», «Угол поворота», «Уровень четкости». «Количество по горизонтали» и «Количество по вертикали» задают сетку на странице, для рулона обе цифры — 1. Для полей, которых нет в поставляемых вариантах, шаблон создают командой «Создать новый» — сразу в редакторе. Готовый шаблон открывается в том же редакторе двойным щелчком.

Шаблоны этикетки и ценника указывают в виде номенклатуры, особому товару — индивидуально в карточке, и обработка подставит их сама. Разово шаблон меняют в обработке: выделить строки → «Установить» → «Шаблон этикеток». Строка без шаблона не напечатается: «Печать» остановится с сообщением «Не выбран шаблон этикетки в строке: N». Назначьте шаблон или снимите у строки флажок «Выбран».

В документе «Приобретение товаров и услуг» выберите «Печать» → «Этикетки» (рядом — «Ценники»); непроведённый документ 1С предложит провести. Откроется обработка с товарами документа и количеством этикеток по документу. Так же этикетка в 1С:УТ печатается из «Приходного ордера на товары» и «Перемещения товаров». Нет команд «Этикетки» и «Ценники» — у пользователя нет права на обработку «Печать этикеток и ценников», это вопрос настройки прав доступа.

Без документа обработку открывают в разделе «Продажи → Сервис → Печать этикеток и ценников»: «Показать отбор» → флажки «Только со штрихкодом», «Только с ценами», «Только с остатками на складах» → «Товары → Заполнить по отбору». Товар добавляют и сканером («Найти товар по штрихкоду»), и из ТСД; товарам без кода штрихкод создаст команда «Новый штрихкод EAN13, если штрихкод не заполнен».

Количество — колонка «Кол. этикеток (шт)», правило её заполнения — под кнопкой «Показать режим заполнения»: по количеству в документе, по остаткам на складе или количество по умолчанию. С режимом «По остаткам на складе» этикеток столько, сколько товара на складе, — одно число всем выделенным строкам задаёт «Установить → Количество этикеток». Нужны только этикетки — «Установить режим печати → Печать этикеток», колонки ценников скроются. «Разбить строку» делит строку на части с разными упаковками. «Печать» формирует этикетки для просмотра, оттуда — на принтер.
Термопринтер ставят в Windows как обычный принтер с драйвером производителя, в драйвере задают размер этикетки, например 58×40 мм. Параметры печати — принтер, бумага, поля — у каждого шаблона свои, и обработка переносит их в печатную форму. Выберите в шаблоне принтер этикеток, тот же размер страницы и нулевые поля. Если размеры в драйвере, шаблоне и на ленте расходятся, принтер протягивает пустые этикетки или делит одну на две.

Печать этикеток в 1С:УНФ 3.0 и в Рознице 3.0 устроена одинаково, но не так, как в УТ.
Этикетки в 1С:Рознице и УНФ подчиняются тому же правилу размеров, что в шаге 5. Свои этикетки в 1С:УНФ делают расширением, как в УТ, но запрос из листинга придётся переписать: документы и регистры там называются иначе.
Свои этикетки 1С печатает как любую печатную форму: макет, табличный документ, команда в меню «Печать». Код нужен, если данных нет среди доступных полей, печатать надо из своего документа или конфигурации без этой обработки, количество считается по-своему (по коробам) или коды с буквами печатаются Code 128. Схема: расширение с обработкой «Расш1_ПечатьЭтикеток» и командой в документе; типовой код не меняется.
Штрихкод в табличном документе — картинка в рисунке, её рисует внешняя компонента, а в БСП компоненту обёртывает серверный общий модуль ГенерацияШтрихкода (в УТ 11.4 — БСП 3.1.5): ПараметрыГенерацииШтрихкода() возвращает структуру настроек, ИзображениеШтрихкода() — структуру с полями Результат, ДвоичныеДанные и Картинка. Сначала проверьте компоненту на своём сервере — тестовый EAN-13 без макета:
// Модуль формы обработки: проверка, что компонента штрихкода работает на сервере.
// На форме — команда «ПроверитьШтрихкод».
&НаКлиенте
Процедура ПроверитьШтрихкод(Команда)
ТабДок = ТабличныйДокументСоШтрихкодом("2000000000015");
ТабДок.Показать(НСтр("ru = 'Проверка штрихкода'"));
КонецПроцедуры
&НаСервереБезКонтекста
Функция ТабличныйДокументСоШтрихкодом(Значение)
ПараметрыШтрихкода = ГенерацияШтрихкода.ПараметрыГенерацииШтрихкода();
ПараметрыШтрихкода.Штрихкод = Значение;
ПараметрыШтрихкода.ТипКода = 1; // EAN-13
ПараметрыШтрихкода.Ширина = 400; // пиксели картинки
ПараметрыШтрихкода.Высота = 160;
Результат = ГенерацияШтрихкода.ИзображениеШтрихкода(ПараметрыШтрихкода);
Если Не Результат.Результат Или Результат.Картинка = Неопределено Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Компонента не построила штрихкод %1: проверьте значение и тип кода.'"), Значение);
КонецЕсли;
ТабДок = Новый ТабличныйДокумент;
ТабДок.Область("R1C1").Текст = НСтр("ru = 'Тестовый штрихкод'");
Рисунок = ТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
Рисунок.Расположить(ТабДок.Область("R2C1:R6C4"));
Рисунок.РазмерКартинки = РазмерКартинки.Пропорционально;
Рисунок.Линия = Новый Линия(ТипЛинииРисункаТабличногоДокумента.НетЛинии);
Рисунок.Картинка = Результат.Картинка;
Возврат ТабДок;
КонецФункции
Рисунок создан кодом — Рисунки.Добавить() и Расположить(); так же штрихкод добавляют в готовую печатную форму.
Наименование, Артикул, Характеристика.Модуль менеджера обработки целиком — печать этикеток в 1С из документа поступления со своей раскладкой. Процедуру Печать вызывает подсистема печати БСП, макет выбирается по идентификатору команды: рулон 58×40 или лист A4 с сеткой 3 × 8. Данные — из табличной части «Товары» документа «Приобретение товаров и услуг» и регистра «Штрихкоды номенклатуры» УТ 11.
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Модуль менеджера обработки Расш1_ПечатьЭтикеток (расширение УТ 11, БСП 3.1).
// Макеты «Этикетка58х40» и «ЭтикеткаНаЛисте»: область «Этикетка» с параметрами
// Наименование, Артикул, Характеристика и рисунком-картинкой «Штрихкод».
#Область ПрограммныйИнтерфейс
// Вызывается подсистемой «Печать» БСП для команд с МенеджерПечати = "Обработка.Расш1_ПечатьЭтикеток".
//
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ЭтикеткиРулон") Тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ЭтикеткиРулон",
НСтр("ru = 'Этикетки 58×40 (принтер этикеток)'"),
СформироватьЭтикетки(МассивОбъектов, "Этикетка58х40", 1, 1));
КонецЕсли;
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ЭтикеткиНаЛисте") Тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ЭтикеткиНаЛисте",
НСтр("ru = 'Этикетки на листе A4 (3 × 8)'"),
СформироватьЭтикетки(МассивОбъектов, "ЭтикеткаНаЛисте", 3, 8));
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция СформироватьЭтикетки(МассивДокументов, ИмяМакета, ВРяду, РядовНаЛисте)
МаксимумЭтикеток = 2000; // защита от опечатки в количестве
Макет = Обработки.Расш1_ПечатьЭтикеток.ПолучитьМакет(ИмяМакета);
Область = Макет.ПолучитьОбласть("Этикетка");
// Поля, размер и ориентацию страницы берём из макета.
ТабДок = Новый ТабличныйДокумент;
СвойстваЛиста = "ПолеСверху, ПолеСнизу, ПолеСлева, ПолеСправа, ОриентацияСтраницы, "
+ "РазмерСтраницы, ШиринаСтраницы, ВысотаСтраницы, АвтоМасштаб, МасштабПечати";
ЗаполнитьЗначенияСвойств(ТабДок, Макет, СвойстваЛиста);
ТабДок.КлючПараметровПечати = "Расш1_ПечатьЭтикеток_" + ИмяМакета;
КэшКартинок = Новый Соответствие;
Позиция = 0;
Выборка = ДанныеДляЭтикеток(МассивДокументов).Выбрать();
Пока Выборка.Следующий() Цикл
Копий = КоличествоКопий(Выборка.КоличествоЭтикеток);
Если Копий = 0 Тогда
Продолжить;
КонецЕсли;
Если Позиция + Копий > МаксимумЭтикеток Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Этикеток больше %1 — проверьте количество в документе.'"), МаксимумЭтикеток);
КонецЕсли;
Область.Параметры.Заполнить(Выборка);
ЗаполнитьРисункиШтрихкода(Область, Выборка.Штрихкод, КэшКартинок);
Для Номер = 1 По Копий Цикл
ВывестиЭтикетку(ТабДок, Область, Позиция, ВРяду, РядовНаЛисте);
Позиция = Позиция + 1;
КонецЦикла;
КонецЦикла;
Если Позиция = 0 Тогда
ОбщегоНазначения.СообщитьПользователю(НСтр("ru = 'В документе нет товаров для этикеток.'"));
КонецЕсли;
Возврат ТабДок;
КонецФункции
// Сетка ВРяду × РядовНаЛисте; при 1 × 1 каждая этикетка — отдельная страница.
Процедура ВывестиЭтикетку(ТабДок, Область, Позиция, ВРяду, РядовНаЛисте)
НомерНаЛисте = Позиция % (ВРяду * РядовНаЛисте);
Если Позиция > 0 И НомерНаЛисте = 0 Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
Если НомерНаЛисте % ВРяду = 0 Тогда
ТабДок.Вывести(Область); // первая в ряду
Иначе
ТабДок.Присоединить(Область); // справа от предыдущей
КонецЕсли;
КонецПроцедуры
// Имена объектов — УТ 11. Этикетка на каждую упаковку строки:
// коробки — по числу коробок, штучный товар — по штукам.
Функция ДанныеДляЭтикеток(МассивДокументов)
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Документы", МассивДокументов);
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары.Характеристика КАК Характеристика,
| Товары.Упаковка КАК Упаковка,
| СУММА(Товары.КоличествоУпаковок) КАК КоличествоЭтикеток,
| МИНИМУМ(Товары.НомерСтроки) КАК Порядок
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
| Документ.ПриобретениеТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка В (&Документы)
|
|СГРУППИРОВАТЬ ПО
| Товары.Номенклатура,
| Товары.Характеристика,
| Товары.Упаковка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Штрихкоды.Номенклатура КАК Номенклатура,
| Штрихкоды.Характеристика КАК Характеристика,
| Штрихкоды.Упаковка КАК Упаковка,
| МАКСИМУМ(Штрихкоды.Штрихкод) КАК Штрихкод
|ПОМЕСТИТЬ ВТ_Штрихкоды
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
|ГДЕ
| Штрихкоды.Номенклатура В
| (ВЫБРАТЬ
| ВТ_Товары.Номенклатура
| ИЗ
| ВТ_Товары КАК ВТ_Товары)
|
|СГРУППИРОВАТЬ ПО
| Штрихкоды.Номенклатура,
| Штрихкоды.Характеристика,
| Штрихкоды.Упаковка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_Товары.Номенклатура.Наименование КАК Наименование,
| ВТ_Товары.Номенклатура.Артикул КАК Артикул,
| ЕСТЬNULL(ВТ_Товары.Характеристика.Наименование, """") КАК Характеристика,
| ВТ_Товары.КоличествоЭтикеток КАК КоличествоЭтикеток,
| ЕСТЬNULL(ВТ_Штрихкоды.Штрихкод, """") КАК Штрихкод
|ИЗ
| ВТ_Товары КАК ВТ_Товары
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Штрихкоды КАК ВТ_Штрихкоды
| ПО ВТ_Товары.Номенклатура = ВТ_Штрихкоды.Номенклатура
| И ВТ_Товары.Характеристика = ВТ_Штрихкоды.Характеристика
| И ВТ_Товары.Упаковка = ВТ_Штрихкоды.Упаковка
|
|УПОРЯДОЧИТЬ ПО
| ВТ_Товары.Порядок";
Возврат Запрос.Выполнить();
КонецФункции
// Дробное количество (весовой товар) — одна этикетка на строку.
Функция КоличествоКопий(Количество)
Если Количество <= 0 Тогда
Возврат 0;
ИначеЕсли Количество <> Цел(Количество) Тогда
Возврат 1;
КонецЕсли;
Возврат Количество;
КонецФункции
// Рисунки, имя которых начинается с «Штрихкод», получают картинку кода.
Процедура ЗаполнитьРисункиШтрихкода(Область, Значение, КэшКартинок)
Для Каждого Рисунок Из Область.Рисунки Цикл
Если Не СтрНачинаетсяС(Рисунок.Имя, "Штрихкод") Тогда
Продолжить;
КонецЕсли;
Ключ = Значение + "|" + Рисунок.Ширина + "|" + Рисунок.Высота;
Картинка = КэшКартинок.Получить(Ключ);
Если Картинка = Неопределено Тогда
Картинка = КартинкаШтрихкода(Значение, Рисунок.Ширина, Рисунок.Высота);
КэшКартинок.Вставить(Ключ, Картинка);
КонецЕсли;
Рисунок.Картинка = Картинка;
КонецЦикла;
КонецПроцедуры
// Рисунок в макете измеряется в миллиметрах, компоненте нужны пиксели.
Функция КартинкаШтрихкода(Знач Значение, ШиринаМм, ВысотаМм)
Значение = СокрЛП(Значение);
Если ПустаяСтрока(Значение) Тогда
Возврат Новый Картинка;
КонецЕсли;
ТочекНаМиллиметр = 8; // 203 dpi; для принтера 300 dpi — 12
ПараметрыШтрихкода = ГенерацияШтрихкода.ПараметрыГенерацииШтрихкода();
ПараметрыШтрихкода.Штрихкод = Значение;
ПараметрыШтрихкода.ТипКода = ТипКодаШтрихкода(Значение);
ПараметрыШтрихкода.Ширина = Окр(ШиринаМм * ТочекНаМиллиметр);
ПараметрыШтрихкода.Высота = Окр(ВысотаМм * ТочекНаМиллиметр);
ПараметрыШтрихкода.РазмерШрифта = 3 * ТочекНаМиллиметр; // растёт вместе с картинкой
ПараметрыШтрихкода.Масштабировать = Истина;
ПараметрыШтрихкода.СохранятьПропорции = Истина;
Результат = ГенерацияШтрихкода.ИзображениеШтрихкода(ПараметрыШтрихкода);
Если Не Результат.Результат Или Результат.Картинка = Неопределено Тогда
ОбщегоНазначения.СообщитьПользователю(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось сформировать штрихкод ""%1"".'"), Значение));
Возврат Новый Картинка;
КонецЕсли;
Возврат Результат.Картинка;
КонецФункции
// Номера типов — из описания ГенерацияШтрихкода.ПараметрыГенерацииШтрихкода().
Функция ТипКодаШтрихкода(Значение)
ТипКода128 = 4; // Code 128: латиница и цифры любой длины
Длина = СтрДлина(Значение);
Если Не СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Значение)
Или Не (Длина = 8 Или Длина = 13) Тогда
Возврат ТипКода128;
КонецЕсли;
Если Не КонтрольнаяЦифраВерна(Значение) Тогда
Возврат ТипКода128; // EAN с ошибкой сканер не примет
КонецЕсли;
Возврат ?(Длина = 8, 0, 1); // 0 — EAN-8, 1 — EAN-13
КонецФункции
// Контрольная цифра EAN-8 и EAN-13: веса 3 и 1 справа налево.
Функция КонтрольнаяЦифраВерна(Код)
Длина = СтрДлина(Код);
Сумма = 0;
Для Шаг = 1 По Длина - 1 Цикл
Цифра = Число(Сред(Код, Длина - Шаг, 1));
Сумма = Сумма + Цифра * ?(Шаг % 2 = 1, 3, 1);
КонецЦикла;
Возврат (10 - Сумма % 10) % 10 = Число(Прав(Код, 1));
КонецФункции
#КонецОбласти
#КонецЕсли
Заимствуйте документ «ПриобретениеТоваровУслуг» в расширение и в модуле менеджера добавьте обработчик после типовой процедуры ДобавитьКомандыПечати. В меню «Печать» появятся две команды; после установки расширения пользователям нужно перезапустить сеанс.
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Модуль менеджера документа ПриобретениеТоваровУслуг, заимствованного в расширение.
&После("ДобавитьКомандыПечати")
Процедура Расш1_ДобавитьКомандыПечати(КомандыПечати)
Если Не ПравоДоступа("Просмотр", Метаданные.Обработки.Расш1_ПечатьЭтикеток) Тогда
Возврат;
КонецЕсли;
Расш1_ДобавитьКомандуЭтикеток(КомандыПечати, "ЭтикеткиРулон",
НСтр("ru = 'Этикетки со штрихкодом (принтер этикеток)'"), 90);
Расш1_ДобавитьКомандуЭтикеток(КомандыПечати, "ЭтикеткиНаЛисте",
НСтр("ru = 'Этикетки со штрихкодом (лист A4)'"), 91);
КонецПроцедуры
Процедура Расш1_ДобавитьКомандуЭтикеток(КомандыПечати, Идентификатор, Представление, Порядок)
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.МенеджерПечати = "Обработка.Расш1_ПечатьЭтикеток";
КомандаПечати.Идентификатор = Идентификатор;
КомандаПечати.Представление = Представление;
КомандаПечати.Порядок = Порядок;
КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;
// КомандаПечати.СразуНаПринтер = Истина; // печать без предпросмотра
КонецПроцедуры
#КонецЕсли
ПараметрыГенерацииШтрихкода() — настройки по умолчанию; номера типов — в комментарии к функции: 0 — EAN-8, 1 — EAN-13, 4 — Code 128, 11 — ITF-14, 16 — QR, 99 — автовыбор.Окр(ШиринаМм * ТочекНаМиллиметр) — рисунок в макете измеряется в миллиметрах, компоненте нужны пиксели. 8 точек на миллиметр — это 203 dpi, частое разрешение термопринтеров, для 300 dpi ставьте 12. Масштабировать и СохранятьПропорции увеличат слишком мелкую картинку до минимального размера кода, а «Растянуть» впишет её в рисунок.КонтрольнаяЦифраВерна() — контрольная цифра EAN: веса 3 и 1 справа налево. EAN-13 с ошибкой в последней цифре сканер не примет, поэтому такой код печатается как Code 128 — тот передаёт строку как есть.Область.Параметры.Заполнить(Выборка) — параметры берутся из полей выборки с теми же именами.КэшКартинок — картинка строится раз на строку, а не на каждую копию: 500 этикеток товара — один вызов компоненты.ВывестиЭтикетку() — номер на листе считается остатком от деления: первая этикетка ряда — Вывести(), следующие — Присоединить() справа, после полного листа — ВывестиГоризонтальныйРазделительСтраниц(). При сетке 1 × 1 каждая этикетка — отдельная страница, как нужно рулонному принтеру.КоличествоКопий() и МаксимумЭтикеток — дробное количество весового товара даёт одну этикетку, а опечатка «10000» в документе не уйдёт на принтер.&После("ДобавитьКомандыПечати") — команды встают после типовых. МенеджерПечати говорит БСП, чей модуль вызвать, Идентификатор приходит в НужноПечататьМакет(), а ПравоДоступа() прячет команду от тех, кому обработка недоступна.ИзображениеШтрихкода(): компонента не подключилась на сервере или не нашла графическую подсистему. Подробности — в журнале регистрации (событие «Ошибка генерации штрихкода»). Результат подключения кэшируется на сеанс: после исправления перезапустите сеанс.Результат = Ложь: значение не подходит типу кода, например в Code 128 попала кириллица.Область.Рисунки.Штрихкод, а рисунок в макете называется иначе. Перебор по началу имени, как в листинге, такой ошибки не даёт.ТочекНаМиллиметр и свойство «Растянуть».Поставьте команде СразуНаПринтер = Истина — в листинге эта строка закомментирована. Удобно, когда на приёмке принтер этикеток назначен принтером по умолчанию.
Обработка берёт цену по виду цен или по магазину, а в поступлении — закупочная. Сначала установите розничные цены документом «Установка цен номенклатуры», потом печатайте ценники.
Тем же вызовом с другим ТипКода: 16 — QR, 18–24 — варианты DataMatrix. Для QR есть и готовая ГенерацияШтрихкода.ДанныеQRКода(Строка, УровеньКоррекции, Размер) — она возвращает PNG в двоичных данных. Коды маркировки УТ печатает своими механизмами.
Тогда штрихкод строит библиотека подключаемого оборудования: МенеджерОборудованияВызовСервера.ПолучитьКартинкуШтрихкода(ПараметрыШтрихкода) с похожими параметрами. В УТ 11.4 она сама вызывает ГенерацияШтрихкода.
В обработке УТ — команда «Установить 1 шт. для каждой номенклатурной позиции из документа», в своём коде — КоличествоКопий(), возвращающая 1.
Своя этикетка, команда в документе и раскладка под конкретный принтер — небольшая доработка в расширении, но с тонкостями: права, размеры, типы кодов. Если своего программиста нет, пришлите образец этикетки и укажите, из какого документа её печатать: задачу можно разместить бесплатно, оценка тоже бесплатная, ответ — в течение рабочего дня. Подробнее — на странице доработки печатных форм.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.