В статье приводятся практические примеры работы с документами в языке 1С. Рассматриваются приемы работы с объектной моделью – создание, редактирование, удаление документов, а также типовые запросы для выборки документов по различным условиям. Для удобства пользуйтесь оглавлением.
Содержание
Немного о документах
Документы – краеугольный камень в построении большинства учетных систем средствами платформы 1С Предприятие. Они предназначены преимущественно для отражения совершенных хозяйственных операций, а также для последующего просмотра и редактирования.
Виды документов, которые создаются в конфигураторе на этапе проектирования прикладного решения, в основном соответствуют своим бумажным аналогам – приходным накладным, документам продажи или актам об оказании услуг, и др. Для каждой отрасли и вида учета набор таких документов и их реквизитный состав может отличаться.
Помимо записи о произошедшей хозяйственной операции, документы используются для фиксации изменений в учетных регистрах (т.н. проведение), а также позволяют сформировать печатные формы. Вообще, спектр применения документов в платформе 1С очень обширный, и позволяет реализовывать самые различные механизмы – биллинг, учет коммунальных платежей, сложные расчеты, учет ценных бумаг и активов, и многое другое.
Документы описываются в системе 1С двумя стандартными реквизитами – Номер и Дата. Использование номера не является обязательным – можно указать длину номера 0, и в этом случае платформа отключит механизм нумерации документов. В этом случае разработчик может сам предусмотреть реквизиты для формирования представления документа и для проверки уникальности. Но на практике чаще всего номер не отключается.
Как выбрать и отсортировать документы за период в 1С 8
// Получим список всех заказов за 2021 год и отсортируем их по возрастанию даты
Запрос = Новый Запрос("ВЫБРАТЬ
| Заказ.Ссылка КАК Ссылка,
| ПРЕДСТАВЛЕНИЕ(Заказ.Ссылка) КАК ПредставлениеДокумента
|ИЗ
| Документ.Заказ КАК Заказ
|ГДЕ
| Заказ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
|
|УПОРЯДОЧИТЬ ПО
| Заказ.Дата");
Запрос.УстановитьПараметр("ДатаНачала", '20210101');
// Указать дату без уточнения времени недостаточно,
// т.к. тогда не попадут документы за последний день периода
Запрос.УстановитьПараметр("ДатаОкончания", '20211231235959');
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Сообщить("Нет документов за указанный период");
Возврат;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Для вывода информации на экран достаточно использовать представление.
Сообщить(Выборка.ПредставлениеДокумента);
КонецЦикла;
Как найти документ по номеру в 1с 8.3
Следует учитывать, что у документа должен быть не нулевой код. В случае указания интервала больше года, в результат запроса могут попасть несколько документов с одинаковым номером за разные периоды. Следует либо указывать интервалы в пределах одного календарного года, либо задать документу сплошную непериодическую нумерацию.
// найдём заказ № УТ-000001 за 2021 год
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказ.Ссылка КАК Ссылка,
| ПРЕДСТАВЛЕНИЕ(Заказ.Ссылка) КАК ПредставлениеДокумента
|ИЗ
| Документ.Заказ КАК Заказ
|ГДЕ
| Дата МЕЖДУ &ДатаНачала И &ДатаОкончания И
| Номер = &НомерДляПоиска";
Запрос.УстановитьПараметр("ДатаНачала", '20210101');
Запрос.УстановитьПараметр("ДатаОкончания", '20211231235959');
Запрос.УстановитьПараметр("НомерДляПоиска", "УТ-000001");
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДокументов = РезультатЗапроса.Выбрать();
Если ВыборкаДокументов.Следующий() Тогда
Сообщить(ВыборкаДокументов.ПредставлениеДокумента);
Иначе
Сообщить("Документ с таким номером отсутствует!");
КонецЕсли;
Как найти документы по реквизиту в 1с 8
// Найдем все заказы от покупателя "Частное лицо"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказ.Ссылка КАК Ссылка,
| ПРЕДСТАВЛЕНИЕ(Заказ.Ссылка) КАК ПредставлениеДокумента
|ИЗ
| Документ.Заказ КАК Заказ
|ГДЕ
| Покупатель = &Покупатель";
// В примере Частное лицо - предопределенный элемент справочника Контрагеты
Запрос.УстановитьПараметр("Покупатель", Справочники.Контрагенты.ЧастноеЛицо);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Сообщить("Нет документов за указанный период");
Возврат;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.ПредставлениеДокумента);
КонецЦикла;
Как выбрать все не проведенные документы, которые не помечены на удаление в 1с 8
|ГДЕ
| Заказ.Проведен = &Проведен"
Запрос.УстановитьПараметр("Проведен", Истина);
|ГДЕ
| Не Заказ.Проведен"
// найдём не проведенные и не помеченные на удаление документы заказов
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказ.Ссылка КАК Ссылка,
| ПРЕДСТАВЛЕНИЕ(Заказ.Ссылка) КАК ПредставлениеДокумента
|ИЗ
| Документ.Заказ КАК Заказ
|ГДЕ
| НЕ Заказ.Проведен
| И НЕ Заказ.ПометкаУдаления
|
|УПОРЯДОЧИТЬ ПО
| Заказ.Дата";
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Сообщить("Нет документов за указанный период");
Возврат;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.ПредставлениеДокумента);
КонецЦикла;
Как обойти (перебрать) все строки табличной части документа в 1С 8
// Переберем все строки документа Заказ с номером УТ-000001
// У документа заказ есть табличная часть Спецификация с колонками
// Товар, Количество, Сумма
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001", '20210101');
Если ЗначениеЗаполнено(НайденныйЗаказ) Тогда
Для Каждого СтрокаСпецификации Из НайденныйЗаказ.Спецификация Цикл
Сообщить(СтрШаблон("Товар % 1, количество %2 шт, сумма %3 руб.",
СтрокаСпецификации.Товар,
СтрокаСпецификации.Количество,
СтрокаСпецификации.Сумма));
КонецЦикла;
КонецЕсли;
Создание и редактирование документов в языке 1С 8
Как создать новый документ в 1С программно
// Создадим новый документ Заказ средствами языка 1С
Заказ = Документы.Заказ.СоздатьДокумент();
Заказ.Дата = ТекущаяДата();
//Далее заполним реквизиты шапки
//Здесь - вместо пустой ссылки можно передать реквизит формы, переменную и т.д.
ВыбранныйПокупатель = Справочники.Контрагенты.ПустаяСсылка();
Заказ.Покупатель = ВыбранныйПокупатель;
//Далее - заполняется табличная часть.
СтрокаТЧ = Заказ.Спецификация.Добавить();
СтрокаТЧ.Товар = Товар;
СтрокаТЧ.Количество = 10;
СтрокаТЧ.Сумма = 100;
Как записать документ в 1С 8
У всех документов в языке 1С есть метод Записать, у которого есть два необязательных параметра: РежимЗаписи и РежимПроведения. РежимПроведения имеет смысл только если мы явным образом вызываем проведение документа.
Вызов метода без параметров равносилен вызову с режимом “Запись”
Заказ.Записать();
Заказ.Записать(РежимЗаписиДокумента.Запись);
Как провести документ средствами языка 1С 8
Следует иметь в виду, что если у документа свойство Проведение установлено в значение “Запретить”, попытка записать документ с режимом записи “Проведение” приведет к ошибке.
Заказ.Записать(РежимЗаписиДокумента.Проведение);
Как отменить проведение документа в 1С 8
Заказ.Записать(РежимЗаписиДокумента.ОтменаПроведения);
Как внести изменения в документ по ссылке в 1с 8
Если нам нужно отредактировать документ, который уже записан в базу данных, чаще всего мы имеем в распоряжении ссылку на этот объект, полученную тем или иным образом. Например, ссылка может содержаться в значении реквизита формы, в переменной, или в текущих данных строки, если мы находимся в списке документов, и выделяем мышкой конкретную строку.
Ссылка позволяет считывать свойства документа, а для редактирования нужен сам объект. Для этого следует использовать метод ПолучитьОбъект().
//Найдем ссылку на заказ, используя объектную модель представления данных
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001");
// вот так можно проверить, что документ не найден в системе
Если НайденныйЗаказ.Пустая() Тогда
Сообщить("Документ отсутствует в базе");
Иначе
//Получаем документ по ссылке
ОбъектЗаказ = НайденныйЗаказ.ПолучитьОбъект();
ОбъектЗаказ.Комментарий = "Мы нашли и отредактировали существующий документ";
ОбъектЗаказ.Записать();
КонецЕсли;
Как получить пустую ссылку на документ в 1С 8
ПустаяСсылка = Документы.Заказ.ПустаяСсылка();
Как программно заблокировать документ перед изменениями в 1С 8
//Установим блокировку документа от изменения
ЗаказОбъект = НайденныйЗаказ.ПолучитьОбъект();
Попытка
//Заблокируем по ссылке
ЗаблокироватьДанныеДляРедактирования(НайденныйЗаказ);
Исключение
Сообщить("Документ уже заблокирован!";
Возврат;
КонецПопытки;
ЗаказОбъект.Комментарий = "Произвели какие-то длительные действия по изменению документа";
ЗаказОбъект.Записать();
//а разблокируем при помощи метода объекта
ЗаказОбъект.Разблокировать();
Как средствами языка 1С ввести документ на основании другого
Для полноценного ввода на основании другого документа, в дочернем документе должна быть реализована процедура ОбработкаЗаполнения, которая отвечает за алгоритм заполнения. Для связи документа-основания и дочернего документа чаще всего заводится реквизит ДокументОснование. Если связь реализуется один ко многим, как это сделано во многих типовых решениях, то для этого создается табличная часть ДокументыОснования. Ниже рассмотрен простой пример ввода счета на основании заказа.
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001");
СчетНаОсновании = Документы.Счет.СоздатьДокумент();
//Вот здесь вызывается процедура ОбработкаЗаполнения
СчетНаОсновании.Заполнить(НайденныйЗаказ);
СчетНаОсновании.Комментарий = "Документ введен программно на основании " + НайденныйЗаказ;
СчетНаОсновании.Записать();
Работа с движениями документа средствами языка 1С
Как прочитать движения документа запросом
// Прочитаем движения документа по регистру ЗаказыКлиентов при помощи запроса
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001");
Запрос = Новый Запрос("ВЫБРАТЬ
| ЗаказыКлиентов.НомерСтроки КАК НомерСтроки,
| ЗаказыКлиентов.ВидДвижения КАК ВидДвижения,
| ЗаказыКлиентов.Товар КАК Товар
| ЗаказыКлиентов.Количество КАК Количество
|ИЗ
| РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
|ГДЕ
| ЗаказыКлиентов.Регистратор = &НайденныйЗаказ");
Запрос.УстановитьПараметр("НайденныйЗаказ", НайденныйЗаказ);
Результат = Запрос.Выполнить();
// Преимущество запросов в том, что можно получать
// не все движения, а с учетом отборов, или только по некоторым полям
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(
"№ " + Выборка.НомерСтроки +
"ВидДвижения" + Выборка.ВидДвижения +
"Товар " + Выборка.Товар +
"Количество " + Выборка.Количество
);
КонецЦикла;
КонецЕсли;
Чтение и редактирование движений документа в 1С с использованием объектной модели
// Найдем и изменим движения документа по регистрам программно
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001");
// В нашем примере заказ делает движения по двум регистрам:
// регистр накопления - резервы товаров
// регистр накопления - заказы клиентов
// для редактирования движений документа используем объектный подход
// и коллекцию Движения, предварительно получив документ.
ДвиженияДокумента = НайденныйЗаказ.ПолучитьОбъект().Движения;
// в коллекции хранятся наборы записей документа в регистры
// поместим набор записей в переменную
НаборЗаписей = ДвиженияДокумента.ЗаказыКлиентов;
// Прочитаем записи из набора данных
// Если этого не сделать, то при записи набор данных заменится только новым содержимым
НаборЗаписей.Прочитать();
Для Каждого Запись Из НаборЗаписей Цикл
// выведем старые значения
Сообщить(Строка(Запись.ВидДвижения) + " " + Запись.Товар + " " + Запись.Количество);
// отредактируем запись, например укажем вид движения Расход
Запись.ВидДвижения = ВидДвиженияНакопления.Расход;
КонецЦикла;
//Добавим новую запись в набор
ЗаписьПриход = НаборЗаписей.ДобавитьПриход();
ЗаписьПриход.Товар = Справочники.Товары.НайтиПоНаименованию("Авторучка");
ЗаписьПриход.Количество = 5;
ЗаписьПриход.Период = НайденныйЗаказ.Дата;
// Удалим старые движения и вместо них запишем новые.
НаборЗаписей.Записать(Истина);
// Движения документа Заказ № УТ-000001 теперь отличаются
// от сформированных при проведении.
// Чтобы вернуть исходные движения, документ нужно перепровести
Как отредактировать проведенный документ, не меняя движений
Ситуация, обратная рассмотренной выше – нужно изменить документ, не трогая движения. Такая необходимость иногда возникает, если отчетный период закрыт, движения документов должны быть гарантировано неизменными, но в сами документы необходимо внести изменения.
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001");
ЗаказОбъект = НайденныйЗаказ.ПолучитьОбъект();
ЗаказОбъект.Комментарий = "Отредактируем документ, не трогая движения";
// В различных конфигурациях при записи объекта может быть реализованы
// алгоритмы, которые могут вызвать перепроведение.
// Чаще всего предусмотрен механизм отключения этих алгоритмов при загрузке
ЗаказОбъект.ОбменДанными.Загрузка = Истина;
// явным образом укажем, что документ необходимо только записать
ЗаказОбъект.Записать(РежимЗаписиДокумента.Запись);
Работа с формами документов средствами языка 1С 8
Открыть форму документа по ссылке
// Найдем заказ по номеру с учетом года
НайденныйЗаказ = Документы.Заказ.НайтиПоНомеру("УТ-000001",'20211231');
ПараметрыФормы = Новый Структура("Ключ", НайденныйЗаказ);
//Можно открыть форму объект по умолчанию
ОткрытьФорму(
"Документ.Заказ.ФормаОбъекта", // имя формы
ПараметрыФормы // параметры для формы
);
// Либо указать конкретную форму документа
ОткрытьФорму("Документ.Заказ.Форма.ФормаДокумента", ПараметрыФормы);
Открыть форму списка документов с отбором по реквизиту
// откроем список заказов, оставив
// только те, что от покупателя ЧастноеЛицо
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Покупатель", Справочники.Контрагенты.ЧастноеЛицо);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
ОткрытьФорму("Документ.Заказ.ФормаСписка", ПараметрыФормы);
Открыть форму выбора документа и отследить событие закрытия формы
// Чтобы отследить закрытие формы выбора, нам понадобится обработка оповещения
// Это отдельная экспортная процедура в том модуле, откуда мы вызываем открытие формы
ОповещениеОЗакрытии = Новый ОписаниеОповещения("ОбработкаВыбораДокумента",
ЭтотОбъект);
ОткрытьФорму("Документ.Заказ.ФормаВыбора",,,,,,ОповещениеОЗакрытии);
&НаКлиенте
Процедура ОбработкаВыбораДокумента(Результат, Параметры) Экспорт
Если Результат <> Неопределено Тогда
Сообщить("Был выбран документ " + Результат);
КонецЕсли;
КонецПроцедуры
Как открыть форму нового документа, созданного программно
Бывают ситуации, когда нужно создать документ, заполнить его данными, но не записывая, показать пользователю. Например, для проверки и дальнейшего редактирования. Это можно сделать при помощи следующего кода:
&НаКлиенте
Процедура ОткрытьФормуНового(Команда)
ФормаНовогоДокумента = ПолучитьФорму("Документ.Счет.ФормаОбъекта");
//Копируем объект, т.к. напрямую данные формы менять нельзя
ДанныеФормы = ФормаНовогоДокумента.Объект;
//Полученный экземпляр заполняем на сервере
ЗаполнитьНовыйДокументНаСервере(ДанныеФормы);
// Заполненные данные нужно скопировать в исходную форму
КопироватьДанныеФормы(ДанныеФормы, ФормаНовогоДокумента.Объект);
// покажем форму нового документа пользователю
ФормаНовогоДокумента.Открыть();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьНовыйДокументНаСервере(ДанныеФормы)
Счет = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.Счет"));
Счет.Дата = НачалоМесяца(ТекущаяДата());
Счет.Комментарий = "Документ создан программно, открываем без записи";
//Преобразуем объект обратно в данные формы
ЗначениеВДанныеФормы(Счет, ДанныеФормы);
КонецПроцедуры