Ну, во-первых, 1С:Предприятие 8.1 предполагает два режима работы: собственно Предприятие и Конфигуратор. Грубо говоря, парадный и служебный входы. В первом режиме штатно работают пользователи, второй режим позволяет проводить администрирование системы и заниматься её разработкой.
Информационная база 1С состоит из двух частей: конфигурация и собственно данные. Конфигурация - это, грубо говоря, метаданные, т.е. описание базы, доступных пользователю интерфейсов, отчетов и т.п. Если посмотреть на конфигурацию через Конфигуратор, то можно заметить, что она содержит описание множества загадочных сущностей: справочников, документов, отчетов, регистров накоплений и т.п. Тем не менее, за этим богатством стоит реляционная модель данных, а там, где есть реляционная модель, должен быть и какой-нибудь sql-подобный язык запросов. Тут он, к счастью, присутствует.
Конечно, никто в здравом уме не будет экспериментировать на живой, включенной в производственный процесс базе. Поэтому нужно улучить такой момент, когда с базой никто не работает, и с помощью меню Конфигуратора "Администрирование - Выгрузить информационную базу" выгрузить интересующую нас базу в файл. Затем создаем пустую базу (для этого в комплекте 1С поставляется утилита "Серверы 1С:Предприятие") и с помощью всё того же Конфигуратора через пункт "Администрирование - Загрузить информационную базу" поднимаем из файла копию интересующей нас информационной базы.
Далее задача становится интересной. Для таких дилетантов, как я, которым нельзя доверить правку конфигурации, но поработать с базой хочется, придумали специальную штуку - внешние обработки. Они представляют из себя своеобразные "программы", которые создаются в Конфигураторе, а выполняются в режиме "Предприятие". Например, при помощи внешней обработки за пару секунд можно слепить инструмент выполнения вышеупомянутых sql-подобных запросов к информационной базе.
Делается это так. В Конфигураторе через меню "Файл - Новый..." создаем внешнюю обработку. В открывшемся окне вновь созданной обработки в разделе "Формы" добавляем новую форму, устанавливаем эту форму "основной формой внешней обработки", кидаем на форму поле ввода, табличное поле и кнопку. В результате имеем три элемента интерфейса: ПолеВвода1, ТабличноеПоле1 и Кнопка1. Кроме того, с каждым элементом оказывается связана некая переменная, наименование которой совпадает с наименованием элемента.
Далее на кнопку Кнопка1 вешаем обработчик события нажатия:
Процедура Кнопка1Нажатие(Элемент)
Запрос = Новый Запрос(); // слева - переменная, справа - класс.
Запрос.Текст = ПолеВвода1; // справа - переменная, которую 1C создал автоматически вместе с полем ввода
ТабличноеПоле1 = Запрос.Выполнить().Выгрузить(); // слева - переменная, которую 1C создал вместе с табличным полем
ЭлементыФормы.ТабличноеПоле1.СоздатьКолонки();
КонецПроцедуры
Сохраняем внешнюю обработку, открываем её 1С:Предприятие, и получаем возможность выполнять запросы к информационной базе.Запросы на первый взгляд мало чем отличаются от обычных sql-запросов. Ну, двуязычные (можно писать ВЫБРАТЬ...ИЗ... или SELECT...FROM...), но это мелочи. Основное, что бросается в глаза, это работа с джойнами. То есть, если у нас, скажем, есть Документ ПутевойЛист, в котором присутствует ссылка ТранспортноеСредство на соответствующий элемент Справочника ТС, то следующие два запроса вернут один и тот же набор данных:
ВЫБРАТЬ
ПутевойЛист.ТранспортноеСредство.Номер
ИЗ
Документ.ПутевойЛист КАК ПутевойЛист
ГДЕ
ПутевойЛист.Номер = "123"
ВЫБРАТЬ
ТС.Номер
ИЗ
Документ.ПутевойЛист КАК ПутевойЛист
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ТС КАК ТС
ПО ПутевойЛист.ТранспортноеСредство = ТС.Ссылка
ГДЕ
ПутевойЛист.Номер = "123"
Кроме того, в 1С есть конструктор запросов, вызываемый из контекстного меню окна редактирования текста модуля. Т.е., скажем, при написании кода обработчика нажатия кнопки можно вызвать конструктор запроса, немного поработать мышкой и получить готовый текст запроса.
А вот dml в этой системе выглядит немного хитро. Для добавления данных в какую-то таблицу (т.е, регистр учета, справочник и т.п.) приходится сначала открыть выборку по этой таблице, потом добавить в выборку новую запись, в этой записи заполнить нужные поля, и затем выборку записать. Ну, примерно как в дельфях с их датасетами. В процессе заполнения этих самых полей, особенно в случае, когда заполняются внешние ключи на другие таблицы, полезно помнить, что все записи в 1С имеют специальный атрибут Ссылка, который позволяет поля-внешние ключи правильно заполнять.
В моем случае (путевой лист, не желавший учитываться в отчете по движению ГСМ) понадобилось добавить запись, связанную с путевым листом, в один из регистров накопления. Соответствующая процедура получилась вот такой:
Процедура Кнопка2Нажатие(Элемент)
// вытаскиваем путевой лист в переменные с префиксом ПЛ_...
Запрос_ПутевойЛист = Новый Запрос();
Запрос_ПутевойЛист.Текст =
"ВЫБРАТЬ
| ПутевойЛист.Ссылка,
| ПутевойЛист.Дата,
| ПутевойЛист.Организация,
| ПутевойЛист.ТранспортноеСредство,
| ПутевойЛист.ТранспортноеСредство.Колонна КАК Колонна,
| ПутевойЛист.Водитель1,
| Номенклатура.Ссылка КАК Топливо
|ИЗ
| Документ.ПутевойЛист КАК ПутевойЛист
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО ВЫРАЗИТЬ(Номенклатура.НаименованиеПолное КАК СТРОКА(11)) = ""Бензин АИ92""
|ГДЕ
| ПутевойЛист.Номер = ""123""
|";
РезультатЗапроса_ПутевойЛист = Запрос_ПутевойЛист.Выполнить().Выгрузить();
Для каждого Запись_ПутевойЛист из РезультатЗапроса_ПутевойЛист Цикл
ПЛ = Запись_ПутевойЛист.Ссылка;
ПЛ_Дата = Запись_ПутевойЛист.Дата;
ПЛ_Организация = Запись_ПутевойЛист.Организация;
ПЛ_Колонна = Запись_ПутевойЛист.Колонна;
ПЛ_ТранспортноеСредство = Запись_ПутевойЛист.ТранспортноеСредство;
ПЛ_Водитель = Запись_ПутевойЛист.Водитель1;
ПЛ_Топливо = Запись_ПутевойЛист.Топливо;
ПЛ_РасходПоНорме = 20.38;
ПЛ_РасходПоФакту = 20;
ПЛ_Активность = Истина;
КонецЦикла;
// открываем регистр накопления
ПЛ_Регистр = РегистрыНакопления.РасходГСМнаТС.СоздатьНаборЗаписей();
ПЛ_Регистр.Отбор.Регистратор.Установить(ПЛ);
ПЛ_Регистр.Прочитать();
// добавляем и заполняем запись в регистр накопления
НовыйРегистр = ПЛ_Регистр.Добавить();
НовыйРегистр.Период = ПЛ_Дата;
НовыйРегистр.Регистратор = ПЛ;
НовыйРегистр.Активность = ПЛ_Активность;
НовыйРегистр.Организация = ПЛ_Организация;
НовыйРегистр.Колонна = ПЛ_Колонна;
НовыйРегистр.ТС = ПЛ_ТранспортноеСредство;
НовыйРегистр.Водитель = ПЛ_Водитель;
НовыйРегистр.ГСМ = ПЛ_Топливо;
НовыйРегистр.РасходПоНорме = ПЛ_РасходПоНорме;
НовыйРегистр.РасходПоФакту = ПЛ_РасходПоФакту;
ПЛ_Регистр.Записать(Истина);
// сообщаем пользователю, что всё прошло успешно
Сообщить(ПЛ);
Сообщить("job done");
КонецПроцедуры
В общем, скажу честно, в понимании происходящего мне сильно помогло, что я однажды, сам того не подозревая, уже пытался создать нечто, подобное 1С, и, следовательно, идеология этой системы оказалась довольно знакомой (по крайней мере, азы). Остальной океан непознанного ещё плещется у порога. Затопит - будем разбираться дальше.
Использованные источники:
Как быстро вывести результат Запроса в табличный документ?
Регистры накопления в языке 1С 8.3, 8.2 (в примерах)
Особенности языка запросов 1С
Комментариев нет:
Отправить комментарий