Буфер обмена 1С: скопировать и вставить программно

Дата: 19.09.2026 09:47:59
буфер обмена
СредстваБуфераОбмена
Асинх
Excel
табличная часть
COMОбъект
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Управляемые

Буфер обмена 1С долго оставался территорией обходных путей: встроенный язык не умел ни читать его, ни записывать, и программисты подключали COM-объекты Windows или прятали на форме поле HTML-документа. В платформе 8.3.24 появился штатный объект СредстваБуфераОбмена, и теперь скопировать текст в буфер обмена или вставить его оттуда можно парой строк кода. Ниже — новый способ, варианты для старых платформ и рабочий пример: вставка таблицы из Excel в табличную часть документа.

Где нужна работа с буфером обмена

Задачи, с которыми приходят чаще всего:

  • кнопка «Скопировать» рядом с номером заказа, трек-номером, ИНН или навигационной ссылкой, чтобы пользователь не выделял текст мышью;
  • загрузка списка товаров, который менеджер скопировал из Excel или из письма поставщика: артикул, количество, цена;
  • обратная операция — табличную часть документа нужно быстро перенести в Excel;
  • вставка скриншота или файла в карточку объекта без промежуточного сохранения на диск.

Одно правило действует для всех способов: буфер обмена находится на компьютере пользователя, поэтому код работы с ним выполняется только на клиенте. Серверу передают уже готовую строку. Где какой код выполняется, напоминает статья про устройство управляемой формы.

Какой способ выбрать

СпособПлатформаГде работаетКогда брать
СредстваБуфераОбмена8.3.24 и новееклиентские приложения на компьютере, включая веб-клиент; на мобильных устройствах недоступноосновной вариант для новых доработок
COM-объект htmlfileлюбая 8.3тонкий и толстый клиент под Windowsплатформу обновить нельзя, пользователи на Windows
Поле HTML-документалюбая 8.3зависит от движка поля и версиитолько поддержка чужого старого кода
Поле для ручной вставки (Ctrl+V)любая 8.3все клиентынужна загрузка таблицы, а платформа старая

Буфер обмена 1С программно: объект СредстваБуфераОбмена

В версии 8.3.24 в глобальный контекст добавлено свойство СредстваБуфераОбмена. Содержимое буфера описывает объект ЭлементБуфераОбмена — пара «формат + данные». Стандартные форматы собраны в системном перечислении СтандартныйФорматДанныхБуфераОбмена: текст, картинка, HTML. Методы чтения и записи асинхронные: их вызывают через Ждать в процедурах и функциях с модификатором Асинх (сам механизм Асинх/Ждать есть с 8.3.18). Перед обращением к буферу вызывайте СредстваБуфераОбмена.ИспользованиеДоступно(): метод вернёт Ложь там, где буфер недоступен, например в мобильном клиенте.

Что нужно для работы:

  • платформа 8.3.24 или новее на всех рабочих местах и на сервере;
  • клиентский контекст: процедуры &НаКлиенте в модуле формы, клиентские общие модули, модуль управляемого приложения.

Скопировать в буфер обмена программно

Команда формы копирует номер и дату документа. Запись вынесена в отдельную функцию, чтобы переиспользовать её в других командах. Как создать команду и вывести её кнопкой, описано в статье про команды формы.

// Модуль формы документа. Команда СкопироватьНомер. Платформа 8.3.24+.

&НаКлиенте
Асинх Процедура СкопироватьНомер(Команда)

	Текст = СтрШаблон(НСтр("ru = 'Заказ №%1 от %2'"), Объект.Номер, Формат(Объект.Дата, "ДЛФ=D"));

	Успех = Ждать ПоместитьТекстВБуферОбмена(Текст);
	Если Успех Тогда
		ПоказатьОповещениеПользователя(НСтр("ru = 'Скопировано в буфер обмена'"), , Текст);
	Иначе
		ПоказатьПредупреждение(, НСтр("ru = 'Не удалось записать в буфер обмена.'"));
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Асинх Функция ПоместитьТекстВБуферОбмена(Текст)

	Если Не СредстваБуфераОбмена.ИспользованиеДоступно() Тогда
		Возврат Ложь; // например, мобильный клиент
	КонецЕсли;

	Элементы = Новый Массив;
	Элементы.Добавить(Новый ЭлементБуфераОбмена(СтандартныйФорматДанныхБуфераОбмена.Текст, Текст));

	Попытка
		Помещено = Ждать СредстваБуфераОбмена.ПоместитьДанныеАсинх(Элементы);
	Исключение
		Возврат Ложь; // доступ запрещён браузером или буфер занят другим приложением
	КонецПопытки;

	Возврат Помещено = Истина;

КонецФункции

ПоместитьДанныеАсинх принимает массив элементов, поэтому даже один элемент кладём в массив. Метод возвращает обещание со значением Булево: Ложь — записать не удалось. В веб-клиенте отказ браузера может прийти и исключением, поэтому проверяем и результат, и ошибку. Оповещение пользователю обязательно: без него непонятно, сработала ли кнопка.

Вставить из буфера обмена текст

Чтение устроено так же: запрашиваем данные в текстовом формате и ждём результат. Команда в примере кладёт текст из буфера в комментарий документа.

&НаКлиенте
Асинх Процедура ВставитьВКомментарий(Команда)

	Текст = Ждать ТекстИзБуфераОбмена();
	Если Не ПустаяСтрока(Текст) Тогда
		Объект.Комментарий = СокрЛП(Текст);
		Модифицированность = Истина;
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Асинх Функция ТекстИзБуфераОбмена()

	Если Не СредстваБуфераОбмена.ИспользованиеДоступно() Тогда
		Возврат "";
	КонецЕсли;

	Попытка
		Результат = Ждать СредстваБуфераОбмена.ПолучитьДанныеАсинх(СтандартныйФорматДанныхБуфераОбмена.Текст);
	Исключение
		Возврат ""; // браузер не дал доступ или буфер недоступен
	КонецПопытки;

	Возврат ?(ТипЗнч(Результат) = Тип("Строка"), Результат, "");

КонецФункции

Для формата «Текст» метод возвращает строку, проверка типа страхует от буфера без текста. Пустая строка на выходе означает «текста нет или доступ не дали», различать эти случаи обычно не нужно.

Событие ПриВставкеИзБуфераОбмена и файлы

Вместе с методами в 8.3.24 появилось событие ПриВставкеИзБуфераОбмена в модуле формы и в модуле приложения. Оно срабатывает, когда пользователь вставляет в форму картинку или файлы, а на вставку обычного текста не вызывается. В параметре Значение приходит картинка или массив ссылок СсылкаНаФайл, параметр СтандартнаяОбработка позволяет отключить поведение платформы по умолчанию. Файл из буфера получают только в этом событии: из-за ограничений браузеров и операционных систем методом его не прочитать. Содержимое файла читают методами ПолучитьКакДвоичныеДанныеАсинх() и ПолучитьКакСтрокуАсинх(), которые появились у СсылкаНаФайл в той же версии. Обработчик создавайте из палитры свойств формы — конфигуратор подставит нужные параметры.

Пример: таблица из Excel в табличную часть

Вставка из буфера обмена таблицы Excel — самый востребованный сценарий. Менеджер выделяет в Excel три колонки (артикул, количество, цена), нажимает Ctrl+C, в документе жмёт «Вставить из Excel», и строки появляются в табличной части. Excel кладёт в буфер обычный текст: ячейки разделены табуляцией, строки — парой символов CR LF. Этим и пользуемся.

Пример рассчитан на форму документа с табличной частью Товары (Номенклатура, Количество, Цена, Сумма) и справочник Номенклатура с реквизитом Артикул. Создайте команду ВставитьИзExcel и выведите её в командную панель таблицы формы. Функция ТекстИзБуфераОбмена взята из предыдущего листинга.

&НаКлиенте
Асинх Процедура ВставитьИзExcel(Команда)

	Текст = Ждать ТекстИзБуфераОбмена();
	Если ПустаяСтрока(Текст) Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'В буфере обмена нет текста. Выделите диапазон в Excel, нажмите Ctrl+C и повторите.'"));
		Возврат;
	КонецЕсли;

	Строки = РазобратьТекстТаблицы(Текст);
	Если Строки.Количество() = 0 Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Не найдено ни одной строки вида: артикул, количество, цена.'"));
		Возврат;
	КонецЕсли;

	НеНайдены = ЗаполнитьТоварыНаСервере(Строки);
	Если НеНайдены.Количество() > 0 Тогда
		ПоказатьПредупреждение(, СтрШаблон(НСтр("ru = 'Не найдены артикулы: %1'"), СтрСоединить(НеНайдены, ", ")));
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Функция РазобратьТекстТаблицы(Знач Текст)

	Результат = Новый Массив;
	Текст = СтрЗаменить(Текст, Символы.ВК, ""); // Excel разделяет строки парой CR LF

	Для Каждого СтрокаТекста Из СтрРазделить(Текст, Символы.ПС, Ложь) Цикл

		Ячейки = СтрРазделить(СтрокаТекста, Символы.Таб, Истина);
		Если Ячейки.Количество() < 2 Тогда
			Продолжить;
		КонецЕсли;

		Данные = Новый Структура("Артикул, Количество, Цена", "", 0, 0);
		Данные.Артикул = СокрЛП(Ячейки[0]);
		Данные.Количество = СтрокаВЧисло(Ячейки[1]);
		Если Ячейки.Количество() > 2 Тогда
			Данные.Цена = СтрокаВЧисло(Ячейки[2]);
		КонецЕсли;

		// Строка заголовков и строки без количества отсеиваются здесь
		Если ЗначениеЗаполнено(Данные.Артикул) И Данные.Количество > 0 Тогда
			Результат.Добавить(Данные);
		КонецЕсли;

	КонецЦикла;

	Возврат Результат;

КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция СтрокаВЧисло(Знач Текст)

	Текст = СтрЗаменить(Текст, " ", "");
	Текст = СтрЗаменить(Текст, Символы.НПП, ""); // разделитель разрядов из Excel
	Текст = СтрЗаменить(Текст, ",", ".");
	Если ПустаяСтрока(Текст) Тогда
		Возврат 0;
	КонецЕсли;

	Попытка
		Возврат Число(Текст);
	Исключение
		Возврат 0; // заголовок колонки или текст вместо числа
	КонецПопытки;

КонецФункции

&НаСервере
Функция ЗаполнитьТоварыНаСервере(Знач Строки)

	Артикулы = Новый Массив;
	Для Каждого Данные Из Строки Цикл
		Артикулы.Добавить(Данные.Артикул);
	КонецЦикла;

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Номенклатура.Ссылка КАК Ссылка,
	|	Номенклатура.Артикул КАК Артикул
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	Номенклатура.Артикул В (&Артикулы)
	|	И НЕ Номенклатура.ПометкаУдаления";
	Запрос.УстановитьПараметр("Артикулы", Артикулы);

	НайденныеТовары = Новый Соответствие;
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		НайденныеТовары.Вставить(ВРег(СокрЛП(Выборка.Артикул)), Выборка.Ссылка);
	КонецЦикла;

	НеНайдены = Новый Массив;
	Для Каждого Данные Из Строки Цикл

		Номенклатура = НайденныеТовары.Получить(ВРег(Данные.Артикул));
		Если Номенклатура = Неопределено Тогда
			НеНайдены.Добавить(Данные.Артикул);
			Продолжить;
		КонецЕсли;

		НоваяСтрока = Объект.Товары.Добавить();
		НоваяСтрока.Номенклатура = Номенклатура;
		НоваяСтрока.Количество = Данные.Количество;
		НоваяСтрока.Цена = Данные.Цена;
		НоваяСтрока.Сумма = Данные.Количество * Данные.Цена;

	КонецЦикла;

	Если Строки.Количество() > НеНайдены.Количество() Тогда
		Модифицированность = Истина;
	КонецЕсли;

	Возврат НеНайдены;

КонецФункции

Разбор ключевых мест:

  • Асинх Процедура ВставитьИзExcel — обработчик команды может быть асинхронным. Ждать приостанавливает только эту процедуру, интерфейс не блокируется.
  • СтрЗаменить(Текст, Символы.ВК, "") — без удаления возврата каретки последняя ячейка каждой строки хранит невидимый символ, и цена перестаёт распознаваться как число.
  • СтрРазделить(..., Символы.Таб, Истина) — третий параметр сохраняет пустые ячейки. Истина и так значение по умолчанию, здесь оно указано явно для читаемости. Если передать Ложь, пустая ячейка выпадет, и соседние значения сдвинутся в чужие колонки.
  • СтрокаВЧисло — убирает обычные и неразрывные пробелы (так Excel разделяет разряды) и меняет запятую на точку перед вызовом Число().
  • Количество > 0 — строки без количества пропускаются, заодно отсеивается скопированная строка заголовков.
  • Один запрос по массиву артикулов вместо НайтиПоРеквизиту в цикле: на тысяче строк это одно обращение к базе против тысячи.
  • Возврат ненайденных артикулов — пользователь видит, что не загрузилось, а не теряет строки молча.

Скопировать табличную часть в Excel

Обратная задача решается тем же форматом: собираем текст с табуляциями между ячейками и переводами строк между строками, затем кладём его в буфер. Текст удобнее формировать на сервере — там представления ссылок доступны без лишних вызовов.

&НаКлиенте
Асинх Процедура СкопироватьТоварыДляExcel(Команда)

	Текст = ТоварыКакТекстНаСервере();
	Успех = Ждать ПоместитьТекстВБуферОбмена(Текст); // функция из листинга выше
	Если Успех Тогда
		ПоказатьОповещениеПользователя(НСтр("ru = 'Товары скопированы'"), , НСтр("ru = 'Вставьте в Excel: Ctrl+V'"));
	КонецЕсли;

КонецПроцедуры

&НаСервере
Функция ТоварыКакТекстНаСервере()

	Строки = Новый Массив;
	Строки.Добавить("Номенклатура" + Символы.Таб + "Количество" + Символы.Таб + "Цена" + Символы.Таб + "Сумма");

	Для Каждого СтрокаТЧ Из Объект.Товары Цикл
		Ячейки = Новый Массив;
		Ячейки.Добавить(ОчиститьДляExcel(Строка(СтрокаТЧ.Номенклатура)));
		Ячейки.Добавить(Формат(СтрокаТЧ.Количество, "ЧН=0; ЧГ=0"));
		Ячейки.Добавить(Формат(СтрокаТЧ.Цена, "ЧДЦ=2; ЧН=0; ЧГ=0"));
		Ячейки.Добавить(Формат(СтрокаТЧ.Сумма, "ЧДЦ=2; ЧН=0; ЧГ=0"));
		Строки.Добавить(СтрСоединить(Ячейки, Символы.Таб));
	КонецЦикла;

	Возврат СтрСоединить(Строки, Символы.ВК + Символы.ПС);

КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ОчиститьДляExcel(Знач Значение)

	// Табуляция и перевод строки внутри значения сломают сетку ячеек
	Значение = СтрЗаменить(Значение, Символы.Таб, " ");
	Значение = СтрЗаменить(Значение, Символы.ВК, "");
	Значение = СтрЗаменить(Значение, Символы.ПС, " ");
	Возврат Значение;

КонецФункции

Числа выводятся без разделителя разрядов (ЧГ=0), иначе Excel может принять их за текст. Разделитель дробной части берётся из региональных установок сеанса. Для Excel с английскими региональными настройками задайте его явно параметром ЧРД=. в форматной строке.

Буфер обмена на старых платформах: COM и поле HTML

Если обновиться до 8.3.24 нельзя, остаются три пути.

COM-объект htmlfile (только Windows)

// Для платформ до 8.3.24. Тонкий и толстый клиент под Windows.

&НаКлиенте
Функция ТекстИзБуфераЧерезCOM()

	#Если ТонкийКлиент Или ТолстыйКлиентУправляемоеПриложение Или ТолстыйКлиентОбычноеПриложение Тогда
	Попытка
		ДокументHTML = Новый COMОбъект("htmlfile");
		Значение = ДокументHTML.parentWindow.clipboardData.getData("Text");
		Возврат ?(ТипЗнч(Значение) = Тип("Строка"), Значение, "");
	Исключение
		Возврат ""; // не Windows или доступ запрещён политикой
	КонецПопытки;
	#Иначе
	Возврат "";
	#КонецЕсли

КонецФункции

&НаКлиенте
Функция ПоместитьТекстВБуферЧерезCOM(Текст)

	#Если ТонкийКлиент Или ТолстыйКлиентУправляемоеПриложение Или ТолстыйКлиентОбычноеПриложение Тогда
	Попытка
		ДокументHTML = Новый COMОбъект("htmlfile");
		Возврат ДокументHTML.parentWindow.clipboardData.setData("Text", Текст) = Истина;
	Исключение
		Возврат Ложь;
	КонецПопытки;
	#Иначе
	Возврат Ложь;
	#КонецЕсли

КонецФункции

Объект htmlfile — HTML-движок из состава Windows, у его окна есть свойство clipboardData с методами чтения и записи текста. В веб-клиенте и на Linux COM-объектов нет, поэтому код закрыт инструкцией препроцессора и попыткой. Если политика безопасности на машине запрещает доступ к буферу из этого движка, функция вернёт пустую строку.

Поле HTML-документа

Второй старый приём — скрытое поле HTML-документа: в него добавляли textarea, выделяли текст и вызывали document.execCommand("copy"). Результат зависит от движка поля, версии платформы и ОС, а execCommand браузеры считают устаревшим. Для нового кода приём не годится.

Поле для ручной вставки

Самый надёжный вариант без нового API — вообще не читать буфер программно. На форму выводится поле табличного документа с включённым редактированием, пользователь вставляет в него диапазон из Excel сочетанием Ctrl+V, и данные раскладываются по ячейкам. Код читает ячейки и вызывает ту же ЗаполнитьТоварыНаСервере. Работает в любом клиенте, включая веб, и на любой версии 8.3. Если конфигурацию менять нельзя, ту же логику можно собрать в форме внешней обработки, которая создаёт или дополняет документ.

// Реквизит формы ТаблицаВставки (тип ТабличныйДокумент) выведен на форму полем.
// У поля включено свойство «Редактирование», иначе Ctrl+V в него не сработает.
// Пользователь вставляет в поле диапазон из Excel (Ctrl+V) и нажимает «Загрузить».

&НаКлиенте
Процедура ЗагрузитьИзПоляВставки(Команда)

	НеНайдены = ЗагрузитьИзПоляВставкиНаСервере();
	Если НеНайдены.Количество() > 0 Тогда
		ПоказатьПредупреждение(, СтрШаблон(НСтр("ru = 'Не найдены артикулы: %1'"), СтрСоединить(НеНайдены, ", ")));
	КонецЕсли;

КонецПроцедуры

&НаСервере
Функция ЗагрузитьИзПоляВставкиНаСервере()

	Строки = Новый Массив;
	Для НомерСтроки = 1 По ТаблицаВставки.ВысотаТаблицы Цикл

		Данные = Новый Структура("Артикул, Количество, Цена", "", 0, 0);
		Данные.Артикул = СокрЛП(ТаблицаВставки.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
		Данные.Количество = СтрокаВЧисло(ТаблицаВставки.Область(НомерСтроки, 2, НомерСтроки, 2).Текст);
		Данные.Цена = СтрокаВЧисло(ТаблицаВставки.Область(НомерСтроки, 3, НомерСтроки, 3).Текст);

		Если ЗначениеЗаполнено(Данные.Артикул) И Данные.Количество > 0 Тогда
			Строки.Добавить(Данные);
		КонецЕсли;

	КонецЦикла;

	НеНайдены = ЗаполнитьТоварыНаСервере(Строки); // функция из примера с Excel
	ТаблицаВставки.Очистить(); // повторное нажатие не задвоит строки

	Возврат НеНайдены;

КонецФункции

Типичные ошибки

  • «Переменная не определена (СредстваБуфераОбмена)» при проверке модуля. Причины: платформа ниже 8.3.24 или обращение из серверной процедуры (на сервере буфера нет). Если платформа новая, а ошибка не уходит, проверьте режим совместимости конфигурации.
  • Ждать в обычной процедуре. Модуль не компилируется: оператор Ждать допустим только в процедурах и функциях с модификатором Асинх. Асинхронной должна быть каждая процедура в цепочке, которая ждёт результат.
  • Чтение буфера при открытии формы. В веб-клиенте браузер даёт доступ к буферу в ответ на действие пользователя, только по защищённому соединению и иногда после запроса разрешения. Вызов из ПриОткрытии или обработчика ожидания закончится исключением — читайте буфер по нажатию кнопки.
  • Ячейки с переносом строки. Если в ячейке Excel есть перенос, Excel берёт её содержимое в кавычки, и простое деление по Символы.ПС рвёт такую строку на две. Для таких данных нужен разбор с учётом кавычек или вставка через поле табличного документа.
  • Потерянные ведущие нули. Артикул «00123» в числовой колонке Excel превращается в 123 ещё до копирования. Колонку в Excel нужно сделать текстовой, 1С здесь ни при чём.
  • Нет пересчётов типовой. В УТ 11, ERP и УНФ табличная часть «Товары» содержит упаковки, ставки НДС, скидки. Если заполнить только количество и цену, суммы разойдутся — после добавления строк вызывайте те же процедуры пересчёта, что использует сама форма.

Частые вопросы

Можно ли работать с буфером обмена на сервере?

Нет. Буфер принадлежит сеансу операционной системы пользователя, сервер 1С к нему доступа не имеет. На сервер передают уже прочитанный на клиенте текст.

Работает ли буфер обмена в веб-клиенте?

С 8.3.24 работает через СредстваБуфераОбмена, но с ограничениями браузера: защищённое соединение, действие пользователя, иногда запрос разрешения. COM-способ в браузере не работает. На платформах до 8.3.24 для веб-клиента остаётся поле для ручной вставки.

Почему после вставки из Excel цены стали нулями?

Обычно в ячейках остались разделители разрядов, символ валюты или возврат каретки в конце строки. Число() на такой строке падает, и функция возвращает 0. Остановитесь отладчиком в СтрокаВЧисло и посмотрите, что пришло в параметре.

Как вставить картинку из буфера обмена в 1С?

С 8.3.24 картинку получают методом ПолучитьДанныеАсинх с форматом картинки или в событии ПриВставкеИзБуфераОбмена. Затем её сохраняют в присоединённые файлы или в реквизит типа ХранилищеЗначения на сервере. На старых платформах пользователь сохраняет картинку в файл и выбирает её обычным диалогом.

Нужно ли менять режим совместимости типовой конфигурации?

Основное требование — платформа 8.3.24 или новее на клиентах и сервере. Если синтакс-контроль всё же не видит СредстваБуфераОбмена, проверьте режим совместимости. В типовой конфигурации его сами не меняйте: режим поднимает поставщик в очередном релизе, а до тех пор выручат COM под Windows или поле для ручной вставки.

Когда проще заказать

Если вставка из Excel нужна в типовой УТ, ERP или УНФ с пересчётом упаковок, НДС и скидок или часть пользователей работает на старой платформе, быстрее отдать задачу исполнителю. Такие доработки форм входят в услугу «Отчёты и обработки 1С». Опишите сценарий и разместите задачу: оценка бесплатная, ответ в течение рабочего дня.

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.