Ну, во-первых, 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С