Личная страничка 

Facebook Twitter Gplus RSS
Home Творчество Статьи Получение данных из внешней базы 1С
formats

Получение данных из внешней базы 1С

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

В общем, выдаю на-гора, и судите сами.

Итак, действие номер один. Прежде всего, создаем в удаленной базе удобочитаемые вьюшки и некоторые таблицы функции, которые нам понадобятся для получения данных.

Вьюшки создаются для таблиц справочников, журнала, шапок и табличных частей документов. Я использовал для этого, да и для создания таблиц и функций инструмент 1С++, потому как он распространяется бесплатно. А ставить его приходилось в фирмах, у которых не было столь мною любимого ToySQL. Хотя, используя именно библиотеку ToySQL, некоторые моменты можно значительно упростить.

Обработку запускаем на удаленной базе. Создадим для начала необходимые для работы объекты:

ЗагрузитьВнешнююКомпоненту("1CPP.dll");
МД = СоздатьОбъект("MetaDataWork");
СКЛ = СоздатьОбъект("ODBCRecordSet");
СКЛ.УстБД1С();

Теперь «рисуем» непосредственно сами вьюшки: Начнем с журнала документов.

Попытка
    СКЛ.Выполнить("DROP VIEW dbo.Журнал ");
Исключение
КонецПопытки;
стр = "CREATE VIEW dbo.Журнал
|AS
|SELECT DATE_TIME_IDDOC ДатаДок, IDDOC Ссылка, IDDOCDEF Вид, DOCNO Номер, Closed Проведен, ISMARK ПометкаУдаления
| ";
Для инд = 1 По Метаданные.ОбщийРеквизитДокумента() Цикл
    Если Метаданные.ОбщийРеквизитДокумента(инд).Сортировка = 1 Тогда
        стр = стр + ", sp"+ МД.ИДОбъекта(Метаданные.ОбщийРеквизитДокумента(инд)) + " "+
        Метаданные.ОбщийРеквизитДокумента(инд).Идентификатор;
    КонецЕсли;
КонецЦикла;
стр = стр + "
|FROM dbo._1SJOURN";
Попытка
    СКЛ.Выполнить(стр);
Исключение
    Сообщить("Не создан журнал документов...");
КонецПопытки;
Т.е. как мы видим, все реквизиты имеют теперь привычные для нас наименования и мы можем теперь обратиться к журналу документов следующим запросом: SELECT ДатаДок, Номер, Фирма, Контрагент FROM Журнал WHERE Проведен <> 0 Теперь перейдем к шапкам и табличным частям документов.
Для инд = 1 По Метаданные.Документ() Цикл
    Попытка
        СКЛ.Выполнить("DROP VIEW dbo.Док"+ Метаданные.Документ(инд).Идентификатор);
    Исключение
    КонецПопытки;
    стр = "CREATE VIEW dbo.Док"+ Метаданные.Документ(инд).Идентификатор + "
    |AS
    |SELECT IDDOC Ссылка, "+ МД.ИДОбъекта(Метаданные.Документ(инд)) + " Вид";
    Для рек = 1 По Метаданные.ОбщийРеквизитДокумента() Цикл
        Если Метаданные.ОбщийРеквизитДокумента(рек).Сортировка = 0 Тогда
            стр = стр + ", sp"+ МД.ИДОбъекта(Метаданные.ОбщийРеквизитДокумента(рек)) + " "+
            Метаданные.ОбщийРеквизитДокумента(рек).Идентификатор;
        КонецЕсли;
    КонецЦикла;
    Для рек = 1 По Метаданные.Документ(инд).РеквизитШапки() Цикл
        стр = стр + "
        |    , sp"+ МД.ИДОбъекта(Метаданные.Документ(инд).РеквизитШапки(рек)) + " "+
        Метаданные.Документ(инд).РеквизитШапки(рек).Идентификатор;
    КонецЦикла;
    стр = стр + "
    |FROM dbo.DH"+ МД.ИДОбъекта(Метаданные.Документ(инд));
    Попытка
        СКЛ.Выполнить(стр);
    Исключение
        Сообщить("Не созданы шапки документов... "+ Метаданные.Документ(инд).Идентификатор);
    КонецПопытки;

    Попытка
        СКЛ.Выполнить("DROP VIEW dbo.ТЧ"+ Метаданные.Документ(инд).Идентификатор);
    Исключение
    КонецПопытки;
    стр = "CREATE VIEW dbo.ТЧ"+ Метаданные.Документ(инд).Идентификатор + "
    |AS
    |SELECT IDDOC Ссылка, "+ МД.ИДОбъекта(Метаданные.Документ(инд)) + " Вид
    |, LINENO_ НомерСтроки";
    Для рек = 1 По Метаданные.Документ(инд).РеквизитТабличнойЧасти() Цикл
        стр = стр + "
        |    , sp"+ МД.ИДОбъекта(Метаданные.Документ(инд).РеквизитТабличнойЧасти(рек)) + " "+
         Метаданные.Документ(инд).РеквизитТабличнойЧасти(рек).Идентификатор;
    КонецЦикла;
    стр = стр + "
    |FROM dbo.DT"+ МД.ИДОбъекта(Метаданные.Документ(инд));
    Попытка
        СКЛ.Выполнить(стр);
    Исключение
        Сообщить("Не созданы табличные части документов... "+ Метаданные.Документ(инд).Идентификатор);
    КонецПопытки;
КонецЦикла;
 

Теперь мы можем смело расширить запрос по документам, вставив туда реквизиты шапок и табличных частей.


  SELECT Ж.ДатаДок
  , Ж.Номер
  , Ж.Фирма
  , Ж.Контрагент
  , Д.Валюта
  , Д.Курс
  , ТЧ.Номенклатура
  , ТЧ.Количество
  , ТЧ.Цена
  FROM Журнал Ж
  , ДокПоступлениеТоваров Д
  , ТЧПоступлениеТоваров ТЧ
  WHERE Проведен <> 0
  AND Ж.Ссылка = Д.Ссылка
  AND Ж.Ссылка = ТЧ.Ссылка
 

Маловато данных, не правда ли? Но что мы получим в результате выполнения запроса в реквизитах, являющихся ссылками на элементы справочников? Правильно: мы получим всего лишь 36-тиричный внутренний ИД объекта. И ИД это будет принадлежать совсем не нашей базе и ничего хорошего мы из него не вытянем. Поэтому создаем вьюшки на справочники и смотрим как обходить данную проблему.

  Для инд = 1 По Метаданные.Справочник() Цикл
    Попытка
        СКЛ.Выполнить("DROP VIEW dbo.Спр"+ Метаданные.Справочник(инд).Идентификатор);
    Исключение
    КонецПопытки;
    стр = "CREATE VIEW dbo.Спр"+ Метаданные.Справочник(инд).Идентификатор + "
    |AS
    |SELECT ID Ссылка
    |, ISMARK ПометкаУдаления" +
    ?(Метаданные.Справочник(инд).ДлинаКода <> 0, ", CODE Код", "") +
    ?(Метаданные.Справочник(инд).ДлинаНаименования <> 0, ", DESCR Наименование", "") +
    ", " + МД.ИДОбъекта(Метаданные.Справочник(инд)) + " Вид";
    Если СокрЛП(Метаданные.Справочник(инд).Владелец) <> "Метаданные" Тогда
        стр = стр + ", PARENTEXT Владелец";
    КонецЕсли;

    Если Метаданные.Справочник(инд).КоличествоУровней <> 1 Тогда
        стр = стр + ", PARENTID Родитель
        |, ISFOLDER ЭтоГруппа";
    КонецЕсли;

    Для рек = 1 По Метаданные.Справочник(инд).Реквизит() Цикл
        Если Метаданные.Справочник(инд).Реквизит(рек).Периодический = 1 Тогда
            Продолжить;
        КонецЕсли;
        стр = стр + "
        | , sp"+ МД.ИДОбъекта(Метаданные.Справочник(инд).Реквизит(рек)) + " "+
        Метаданные.Справочник(инд).Реквизит(рек).Идентификатор;
    КонецЦикла;
    стр = стр + "
    |FROM dbo.SC" + МД.ИДОбъекта(Метаданные.Справочник(инд));
    Попытка
        СКЛ.Выполнить(стр);
    Исключение
        Сообщить("Не созданы справочники... " + Метаданные.Справочник(инд).Идентификатор);
    КонецПопытки;
КонецЦикла;
 

И теперь меняем запрос:


  SELECT Ж.ДатаДок
  , Ж.Номер
  , СФ.Код Фирма
  , СК.Код Контрагент
  , СВ.Код Валюта
  , Д.Курс
  , СН.Код Номенклатура
  , ТЧ.Количество
  , ТЧ.Цена
  FROM Журнал Ж
  , ДокПоступлениеТоваров Д
  , ТЧПоступлениеТоваров ТЧ
  , СпрФирмы СФ
  , СпрКонтрагенты СК
  , СпрВалюты СВ
  , СпрНоменклатура СН
  WHERE Проведен <> 0
  AND Ж.Ссылка = Д.Ссылка
  AND Ж.Ссылка = ТЧ.Ссылка
  AND СВ.Ссылка = Д.Валюта
  AND СН.Ссылка = ТЧ.Номенклатура

По крайней мере, мы теперь видим коды элементов справочников, участвующих в запросе и запросто можем найти соответствия в собственной базе (а далее еще и будет информация, как получить сразу ссылку на <собственный designtimesp=22035> элемент!).

Ну и заодно соорудим вьюшки для получения констант и периодических реквизитов справочников. Думаю, они нам не помешают, хотя их получение в запросах иногда достаточно утомительное занятие.

 
// периодические значения реквизитов справочников
Попытка
    СКЛ.Выполнить("DROP VIEW dbo.Периодические");
Исключение
КонецПопытки;
стр = "";
Для инд = 1 По Метаданные.Справочник() Цикл
    тСпр = Метаданные.Справочник(инд);
    Для чРек = 1 По тСпр.Реквизит() Цикл
        тРек = тСпр.Реквизит(чРек);
        Если тРек.Периодический = 1 Тогда
            стр = стр + ?(СтрДлина(стр) = 0, "", "
            |UNION ALL
            |");
            стр = стр +
            "select 'Спр"+ тСпр.Идентификатор + "' Справочник"+ ", '"+ тРек.Идентификатор + "
            |' Реквизит, S.ID Ссылка, C.DATE Дата, C.VALUE Значение
            |FROM SC"+ МД.ИДОбъекта(тСпр) + " S, _1SCONST C WHERE S.ID = C.OBJID";
        КонецЕсли;
    КонецЦикла;
КонецЦикла;
стр = "CREATE VIEW dbo.Периодические
|AS
|" + стр;
Попытка
    СКЛ.Выполнить(стр);
Исключение
    Сообщить("Не созданы периодические... ");
КонецПопытки;

// константы
Попытка
    СКЛ.Выполнить("DROP VIEW dbo.Константы");
Исключение
КонецПопытки;
стр = "CREATE VIEW dbo.Константы
|AS
|SELECT C1.ID ID
|        , C2.Идентификатор Идентификатор
|        , C2.Периодическая Периодическая
|        , C1.DATE Дата
|        , C1.VALUE Значение
|FROM _1SCONST C1, Конст C2
|WHERE C1.OBJID = '     0   '
|  AND C1.ID = C2.ID";
Попытка
    СКЛ.Выполнить(стр);
Исключение
    Сообщить("Не созданы константы... ");
КонецПопытки;
 

В последнем примере (создание вьюшек на константы), есть упоминание таблицы Конст — это служебная, вспомогательная таблица и формируется она следующим образом:

Попытка
    СКЛ.Выполнить("CREATE Table dbo.Конст
    |(ID Char(9), Идентификатор Char(60), Периодическая Int)");
Исключение
    Сообщить("Не создана таблица Конст");
КонецПопытки;
стр = "DELETE FROM Конст";
Попытка
    СКЛ.Выполнить(стр);
Исключение
КонецПопытки;
Для инд = 1 По Метаданные.Константа() Цикл
    тКонст = Метаданные.Константа(инд);
    Попытка
        СКЛ.Выполнить("INSERT INTO Конст (ID,Идентификатор,Периодическая)
        | VALUES ('"+ МД.ИДОбъекта(тКонст) + "','"+ тКонст.Идентификатор + "',"+ тКонст.Периодический + ")");
    Исключение
    КонецПопытки;
КонецЦикла;
 

Теперь разрешите привести пример получения периодического реквизита справочника на примере выбора курсов валют на указанную дату:


  SELECT Спр.Код
  , Пер.Значение Курс
  FROM СпрВалюты Спр
  LEFT JOIN
  (SELECT Пер.Ссылка, Пер.Значение
  FROM Периодические Пер
  WHERE Пер.Реквизит = 'Курс' AND Пер.Дата =
  (SELECT Max(Дата) FROM Периодические WHERE Пер.Ссылка = Ссылка AND Дата <=
  '20010831')
  ) Пер
  ON Спр.Ссылка = Пер.Ссылка

Как видим, нелегкое это дело, каждый раз вставлять такой кусок кода в запрос. Но т.к. это все же удаленная база, то даже объект История из библиотеки ToySQL мы не можем использовать: Есть у меня также и код для создания вьюшек на таблицы регистров (только движения), с бухитогами не занимался, в связи с отсутствием таковой необходимости. Но, я так думаю, что на основании вышеприведенных примеров вам теперь и самим будет несложно это сделать. При работе с документами и справочниками возникают еще кое-какие проблемы. Вот те, с которыми мне пришлось столкнуться и решить: 1. В некоторых таблицах вид документа или справочника храниться в 10-тичном представлении, а в некоторых в 36-тиричном. Поэтому приходится использовать пару функций для преобразования одного в другое:

 
 стр = "create FUNCTION sp_tohex(@val int, @len1 int) RETURNS varchar(9)
  |AS
  |begin
  | declare @v int;
  | declare @tval varchar(9);
  | set @v = @val;
  | set @tval = '';
  |
  | while (@v > 0)
  | begin
  | set @tval = SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',1+@v%36,1)+@tval;
  | set @v = @v/36;
  | end;
  |
  | if @tval='' set @tval='0';
  |
  | while (len(@tval) < @len1)
  | begin
  | set @tval = ' '+@tval ;
  | end;
  |
  | RETURN(@tval);
  |end";
Попытка
   СКЛ.Выполнить(стр);
Исключение
КонецПопытки;

 стр = "CREATE FUNCTION sp_toint(@val VarChar(9)) RETURNS int
  |AS
  |begin
  | declare @i int
  | declare @tval int
  | declare @v varchar(9)
  |
  | set @v = ltrim(rtrim(@val))
  | set @tval = 0
  | set @i = 0
  |
  | while @i < len(@v) + 1
  | begin
  | set @i = @i + 1
  | set @tval = @tval + (CharIndex(SubString(@v, @i, 1), '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')
  - 1)*Power(36,(len(@v) - @i))
  | end
  |
  | RETURN(@tval)
  |end";
Попытка
   СКЛ.Выполнить(стр);
Исключение
КонецПопытки;
 

2. Иногда надо получить время документа в удобоваримом виде (ЧЧ:ММ:СС):

  стр = "CREATE FUNCTION sp_gettime(@val VarChar(9)) RETURNS VarChar(8)
  |AS
  |begin
  | declare @i int
  | declare @h int
  | declare @m int
  | declare @s int
  |
  | set @i = dbo.sp_toint(@val)
  |
  | set @h = ((@i/10000) / 60) / 60
  | set @m = ((@i/10000) / 60) - @h * 60
  | set @s = (@i/10000) - (@h * 60 * 60 + @m * 60)
  |
  | RETURN( cast(@h as char(2)) + ':' + cast(@m as char(2)) + ':' + cast(@s as
  char(2)) )
  |end";
Попытка
   СКЛ.Выполнить(стр);
Исключение
КонецПопытки;
 

3. Функции получения уровня для элемента справочника и его полного кода:

Для инд = 1 По Метаданные.Справочник() Цикл
    Если Метаданные.Справочник(инд).КоличествоУровней <> 1 Тогда
        стр = "CREATE FUNCTION dbo.Уровень" + Метаданные.Справочник(инд).Идентификатор + " (@ID_36 Char(9))
        |RETURNS INT AS
        |BEGIN
        | if @ID_36 IS NULL
        | return NULL
        |
        | declare @CurLevel INT
        | declare @ParID Char(9)
        | declare @CurID Char(9)
        |
        | set @CurLevel = 0
        | set @CurID = @ID_36
        | set @ParId = '000000000'
        |
        | while @ParId <> ' 0 '
        | begin
        | select @ParId = ParentID From dbo.SC" + МД.ИДОбъекта(Метаданные.Справочник(инд)) + " Where ID = @CurID
        |
        | set @CurLevel = @CurLevel + 1
        | set @CurId = @ParID
        | end
        |
        | Return @CurLevel
        |END";
        Попытка
            СКЛ.Выполнить(стр);
        Исключение
            Сообщить("Не создана функция получения уровня для справочника: "+ Метаданные.Справочник(инд).Идентификатор);
        КонецПопытки;

        стр = "CREATE FUNCTION dbo.ПолныйКод" + Метаданные.Справочник(инд).Идентификатор + " (@ID_36 Char(9))
        |RETURNS CHAR(100) AS
        |BEGIN
        | if @ID_36 IS NULL
        | return NULL
        |
        | declare @FCode Char(100)
        | declare @CCode Char(24)
        | declare @ParID Char(9)
        | declare @CurID Char(9)
        |
        | set @FCode = ''
        | set @CurID = @ID_36
        | set @ParId = '000000000'
        |
        | while @ParId <> ' 0 '
        | begin
        | select @ParId = ParentID, @CCode = Code From dbo.SC" + МД.ИДОбъекта(Метаданные.Справочник(инд)) + " Where ID = @CurID
        |
        | if @FCode = ''
        | set @FCode = ltrim(rtrim(@CCode))
        | else
        | set @FCode = ltrim(rtrim(@CCode)) + '/' + @FCode
        |
        | set @CurId = @ParID
        | end
        |
        | Return ltrim(rtrim(@FCode))
        |END";
        Попытка
            СКЛ.Выполнить(стр);
        Исключение
            Сообщить("Не создана функция получения полного кода: "+ Метаданные.Справочник(инд).Идентификатор);
        КонецПопытки;
    КонецЕсли;
КонецЦикла;
 

4. А еще нам очень было бы неплохо иметь под рукой таблицу с перечислениями, которой, как вы знаете, с базе просто нет. Ну а раз нет, то никто нам не мешает такую таблицу создать.

Попытка
    стр = "CREATE Table dbo.Перечисления
    |(Вид char(30),Значение char(30),ID char(9))";
    СКЛ.Выполнить(стр);
Исключение
КонецПопытки;
стр = "DELETE FROM Перечисления";
Попытка
    СКЛ.Выполнить(стр);
Исключение
КонецПопытки;
Для инд = 1 По Метаданные.Перечисление() Цикл
    пер = Перечисление.ПолучитьАтрибут(Метаданные.Перечисление(инд).Идентификатор);

    Для инд1 = 1 По пер.КоличествоЗначений() Цикл
        стр = "INSERT INTO Перечисления (Вид, Значение, ID) VALUES
        | ('"+ Метаданные.Перечисление(инд).Идентификатор + "',
        | '"+ пер.ЗначениеПоНомеру(инд1).Идентификатор() + "',
        | '"+ МД.ЗначениеВСтрокуБД(пер.ЗначениеПоНомеру(инд1)) + "')";
        Попытка
            СКЛ.Выполнить(стр);
        Исключение
            Сообщить("Не созданы перечисления...");
        КонецПопытки;
    КонецЦикла;
КонецЦикла;
 

Да, еще можно создать таблицу видов для документов и справочников, видов субконто и т.д и т.п. Но это вы уж самостоятельно. Единственное, что я вам дам, так это пример запроса из «боевой» разработки. Этот запрос получает таблицу для переноса документов «ЗаявкаПокупателя» из Комплексной конфигурации в ТиС:

 
Select
'ЗаявкаПокупателя' тВид,
Left(Ж.ДатаДок, 8) ДатаДок,
dbo.sp_gettime(substring(Ж.ДатаДок,9,6)) Время,
Ж.Номер,
Ф.Код Фирма,
Ю.Код ЮрЛицо,
СпрСчета.Код БанковскийСчет,
К.Код Контрагент,
СпрДог.Код Договор,
СпрВал.Код Валюта,
Д.Курс, Д.УчитыватьНДС,
Д.СуммаВклНДС,
Д.УчитыватьНП,
Д.СуммаВклНП,
Д.СуммаВзаиморасчетов,
СпрТЦ.Код ТипЦен,
СпрСк.Код
Скидка, Д.ДатаОплаты,
Д.ДатаОтгрузки,
СпрСкл.Код Склад,
ПерВО.Значение ВидОперации,
ПерСР.Значение СпособРезервирования,
СпрНом.Код Номенклатура,
ТЧ.Количество,
ТЧ.Коэффициент,
ТЧ.Цена,
ТЧ.Сумма,
ПерНДС.Значение СтавкаНДС,
ТЧ.СуммаНДС
From
Журнал Ж,
ДокЗаявкаПокупателя Д,
ТЧЗаявкаПокупателя ТЧ,
СпрФирмы Ф,
СпрСвоиЮрЛица Ю,
СпрБанковскиеСчета СпрСчета,
СпрКонтрагенты К,
СпрДоговоры СпрДог,
СпрВалюты СпрВал,
СпрТипыЦен СпрТЦ,
СпрСкидки СпрСк,
СпрСклады СпрСкл,
СпрНоменклатура СпрНом,
Перечисления ПерВО,
Перечисления ПерСР,
Перечисления ПерНДС
where
Ж.Ссылка = Д.Ссылка
and Ж.Ссылка = ТЧ.Ссылка
and Ф.Ссылка = Ж.Фирма
and Ю.Ссылка = Ж.ЮрЛицо
and К.Ссылка = Д.Контрагент
and Д.Договор *= СпрДог.Ссылка
and Д.Валюта *= СпрВал.Ссылка
and Д.ТипЦен *= СпрТЦ.Ссылка
and Д.Скидка *= СпрСк.Ссылка
and Д.Склад *= СпрСкл.Ссылка
and ТЧ.Номенклатура *= СпрНом.Ссылка and Д.БанковскийСчет *= СпрСчета.Ссылка and ТЧ.СтавкаНДС *= ПерНДС.ID
and Д.ВидОперации *= ПерВО.ID and Д.СпособРезервирования *= ПерСР.ID 
 

Ну а на закуску — самое вкусное. Выполнив запрос, который расположен чуть выше по тексту, мы получим таблицу, по которой сможем найти все необходимые ссылки и создать документы в собственной базе. Но разве это было бы быстрее, чем большинство других способов переноса, где есть такая необходимость поиска ссылок? Нет, конечно же! Нам было бы интересно сразу получить эти самые ссылки на объекты собственной базы, потом только подставлять их и записывать вновь созданные или редактируемые документы. И такой способ есть! Решение, которое я приведу ниже, использует компоненту ToySQL.


  SELECT ExtQuery.ДатаДок
  , ExtQuery.Время
  , ExtQuery.Номер
  , [Спр1.Ссылка] Фирма
  , [Спр2.Ссылка] ЮрЛицо
  , [Спр3.Ссылка] БанковскийСчет
  , [Спр4.Ссылка] Контрагент
  , ExtQuery.Договор
  , [Спр5.Ссылка] Валюта
  , ExtQuery.Курс
  , ExtQuery.УчитыватьНДС
  , ExtQuery.СуммаВклНДС
  , ExtQuery.СуммаВзаиморасчетов
  , ExtQuery.ТипЦен
  , ExtQuery.Скидка
  , ExtQuery.ДатаОплаты
  , ExtQuery.ДатаОтгрузки
  , ExtQuery.Склад
  , ExtQuery.ВидОперации
  , ExtQuery.СпособРезервирования
  , [Спр6.Ссылка] Номенклатура
  , ExtQuery.Количество
  , ExtQuery.Коэффициент
  , ExtQuery.Цена
  , ExtQuery.Сумма
  , ExtQuery.СтавкаНДС
  , ExtQuery.СуммаНДС
  FROM
  (SELECT * FROM
  OPENQUERY(K44, 'Select Left(Ж.ДатаДок, 8) ДатаДок,
  dbo.sp_gettime(substring(Ж.ДатаДок,9,6)) Время,
  Ж.Номер,
  Ф.Код Фирма,
  Ю.Код ЮрЛицо,
  СпрСчета.Код БанковскийСчет,
  К.Код Контрагент,
  СпрДог.Код Договор,
  СпрВал.Код Валюта,
  Д.Курс,
  Д.УчитыватьНДС,
  Д.СуммаВклНДС,
  Д.УчитыватьНП,
  Д.СуммаВклНП,
  Д.СуммаВзаиморасчетов,
  СпрТЦ.Код ТипЦен,
  СпрСк.Код Скидка,
  Д.ДатаОплаты,
  Д.ДатаОтгрузки,
  СпрСкл.Код Склад,
  ПерВО.Значение ВидОперации,
  ПерСР.Значение СпособРезервирования,
  СпрНом.Код Номенклатура,
  ТЧ.Количество,
  ТЧ.Коэффициент,
  ТЧ.Цена,
  ТЧ.Сумма,
  ПерНДС.Значение СтавкаНДС,
  ТЧ.СуммаНДС

  From Журнал Ж,
  ДокЗаявкаПокупателя Д,
  ТЧЗаявкаПокупателя ТЧ,
  СпрФирмы Ф,
  СпрСвоиЮрЛица Ю,
  СпрБанковскиеСчета СпрСчета,
  СпрКонтрагенты К,
  СпрДоговоры СпрДог,
  СпрВалюты СпрВал,
  СпрТипыЦен СпрТЦ,
  СпрСкидки СпрСк,
  СпрСклады СпрСкл,
  СпрНоменклатура СпрНом,
  Перечисления ПерВО,
  Перечисления ПерСР,
  Перечисления ПерНДС

  where Ж.Ссылка = Д.Ссылка
  and Ж.Ссылка = ТЧ.Ссылка
  and Ф.Ссылка = Ж.Фирма
  and Ю.Ссылка = Ж.ЮрЛицо
  and К.Ссылка = Д.Контрагент
  and Д.Договор *= СпрДог.Ссылка
  and Д.Валюта *= СпрВал.Ссылка
  and Д.ТипЦен *= СпрТЦ.Ссылка
  and Д.Скидка *= СпрСк.Ссылка
  and Д.Склад *= СпрСкл.Ссылка
  and ТЧ.Номенклатура *= СпрНом.Ссылка
  and Д.БанковскийСчет *= СпрСчета.Ссылка
  and ТЧ.СтавкаНДС *= ПерНДС.ID
  and Д.ВидОперации *= ПерВО.ID
  and Д.СпособРезервирования *= ПерСР.ID')) ExtQuery
  , [Справочник.Фирмы] Спр1
  , [Справочник.СвоиЮрЛица] Спр2
  , [Справочник.БанковскиеСчета] Спр3
  , [Справочник.Контрагенты] Спр4
  , [Справочник.Валюты] Спр5
  , [Справочник.Номенклатура] Спр6
  WHERE ExtQuery.Фирма*=[Спр1.Код]
  AND ExtQuery.ЮрЛицо*=[Спр2.Код]
  AND ExtQuery.БанковскийСчет*=[Спр3.Код]
  AND ExtQuery.Контрагент*=[Спр4.Код]
  AND ExtQuery.Валюта*=[Спр5.Код]
  AND ExtQuery.Номенклатура*=[Спр6.Код]

Как видим, большая часть запроса нам уже известна. Что же есть его <обрамление designtimesp=22468>? Это решение построено на возможности обратиться к связанному серверу (см. sp_addlinkedserver). Хотя это может быть абсолютно любым образом полученный подзапрос. А вот уже связка с собственными объектами по каким-либо уникальным ключам (например, код для справочника) и получение готовых ссылок на объекты — это уже как раз то, что мы и хотели. Осталось только выполнить приведенный МетаЗапрос и Выгрузить результаты его выполнения в таблицу значений.  

Вот собственно и все.

 
© Вахрин Андрей Викторович
credit