8 апр. 2013 г.

Запись во внешний источник данных 1С

Начиная с платформы 8.2.14 в 1С появилась коллекция "Внешние источники данных". Использование объектов этой коллекции позволяет работать с внешними данными через ODBC. Стандартные механизмы платформы позволяют просматривать данные и использовать их в запросах. Тем не менее, на примере взаимодействия с SQL покажу возможность работы с внешними источниками на прямое добавление/изменение данных SQL из 1С.

Создадим для начала через консоль сервера SQL базу "test" с таблицей "assortment", строковые поля id, name, price. Сделаем ключевым поле id и внесем пару строк в таблицу. Потом создадим пустую базу 1С, в конфигураторе добавим внешний источник данных "ВнешнийSQL". На вкладке "Данные" добавим нашу таблицу. Можно ввести строку соединения, либо воспользоваться конструктором строки. В моей строке указаны явно учетная запись суперадминистратора (sa) и пароль к ней. Поскольку это сервер для тестов, вопросом безопасности можно пренебречь. Для реальной базы такого делать не стоит, либо можно завести отдельного пользователя с правами чтения/записи только на эту базу и хранить его данные.


После подключения находим в списке таблиц нашу, выбираем необходимые поля, в нашем случае все.


После добавляем формы для объекта и списка.


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


Теперь начинаем вносить изменения в формы, начнем с формы объекта. В свойствах реквизита "Объект" убираем галку "Сохраняемые данные", после этого реквизиты формы будут доступны для редактирования. Так же добавляем команду "ЗаписатьДанные" и прописываем код сохранения данных.


&НаСервере
Процедура ЗаписатьСервер()
 
 пСеанс = ВнешниеИсточникиДанных.ВнешнийSQL.ПолучитьОбщиеПараметрыСоединения();
 
 Если НЕ пСеанс.СУБД = "MSSQLServer" Тогда
  Возврат;
 КонецЕсли;
 
 ЗапросSQL = ?(Объект.Ссылка.Пустая(), ПолучитьЗапросДобавления(), ПолучитьЗапросОбновления());
 
 Connection  = Новый COMОбъект("ADODB.Connection");
 Command  = Новый COMОбъект("ADODB.Command");
 RecordSet  = Новый COMОбъект("ADODB.RecordSet");
 
 //учетка и пароль уже в строке подключения
 //иначе их необходимо добавить в строку
 Попытка
  Connection.Open(СокрЛП(пСеанс.СтрокаСоединения));
  Command.ActiveConnection   = Connection;
  Command.CommandText = ЗапросSQL;
  RecordSet = Command.Execute();
 Исключение
  Сообщить(ОписаниеОшибки());
 КонецПопытки;  

КонецПроцедуры // ЗаписатьСервер()

&НаСервере
Функция ПолучитьЗапросОбновления()
 
 мДанные = Объект.Ссылка.Метаданные();
 СтрокаПоля = "";
 СтрокаДанные = "";
 
 ДанныеОбъект = Объект.Ссылка.ПолучитьОбъект();
 
 Для Каждого мПоле Из мДанные.Поля Цикл
  Если Объект[мПоле.Имя] = ДанныеОбъект[мПоле.Имя] Тогда
   Продолжить;
  КонецЕсли;
  СтрокаДанные = СтрокаДанные + ?(ПустаяСтрока(СтрокаДанные), " SET ", ", ") + мПоле.Имя + "= '" + Объект[мПоле.Имя] + "'";
 КонецЦикла;
 
 //делаем UDPDATE по id, поскольку оно у нас ключевое
 ЗапросSQL = "UPDATE " + мДанные.ИмяВИсточникеДанных + СтрокаДанные + "WHERE (id = '" + ДанныеОбъект.id + "')";
 
 Возврат ЗапросSQL; 
 
КонецФункции

&НаСервере
Функция ПолучитьЗапросДобавления()
 
 мДанные = Объект.Ссылка.Метаданные();
 СтрокаПоля = "";
 СтрокаДанные = "";
 
 Для Каждого мПоле Из мДанные.Поля Цикл
  СтрокаПоля = СтрокаПоля + ?(ПустаяСтрока(СтрокаПоля), " (", ", ") + мПоле.Имя;
  СтрокаДанные = СтрокаДанные + ?(ПустаяСтрока(СтрокаДанные), " VALUES (", ", ") + "'" + Объект[мПоле.Имя] + "'";
 КонецЦикла;
 
 СтрокаПоля = СтрокаПоля + ")";
 СтрокаДанные = СтрокаДанные + ")";
 ЗапросSQL = "INSERT INTO " + мДанные.ИмяВИсточникеДанных + СтрокаПоля + СтрокаДанные;
 
 Возврат ЗапросSQL; 
 
КонецФункции

&НаКлиенте
Процедура ЗаписатьДанные(Команда)
 
 ЗаписатьСервер();
 //делаем оповещение для списка, поскольку он автоматически не обновляется
 Оповестить("ОбновитьВнешнийИсточникДанных");
 
КонецПроцедуры
 
Теперь в форме списка на панель вешаем команду "Добавить" и добавляем обработку оповещения.

&НаКлиенте
Процедура Добавить(Команда)

 ОткрытьФорму("ВнешнийИсточникДанных.ВнешнийSQL.Таблица.dbo_assortment.ФормаОбъекта");
 
КонецПроцедуры

&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
 
 Если ИмяСобытия = "ОбновитьВнешнийИсточникДанных" Тогда
  Элементы.Список.Обновить();
 КонецЕсли;
 
КонецПроцедуры 

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

22 комментария:

  1. Извините, но как добавить автонумерацию? У меня мало опыта работы с SQL, а по-работе нужен такой вариант с передачей данных и автонумерацию.

    ОтветитьУдалить
    Ответы
    1. Для автонумерации строк следует создать колонку с типом int и свойством IDENTITY (http://msdn.microsoft.com/ru-ru/library/ms186775.aspx)
      Если создавать через дизайнер, то эту колонку можно выбрать в свойстве "Identity Column" таблицы.

      Пример скрипта создания таблицы:
      CREATE TABLE [dbo].[assortiment](
      [id] [nchar](10) NOT NULL,
      [name] [nvarchar](max) NOT NULL,
      [price] [numeric](18, 2) NULL,
      [tabn] [int] IDENTITY(1,1) NOT NULL)

      При выполнении INSERT поле tabn указывать не надо.
      use test
      insert into assortiment (id, name, price) values ('02', 'tovar', '55')

      Удалить
    2. ЗапросSQL = ? Как примерно должен выглядеть ?

      Удалить
  2. СПАСИБО!!!!! все получилось, написано все кратко и понятно.

    ОтветитьУдалить
    Ответы
    1. Пожалуйста :) с новыми возможностями внешних источников можно ознакомиться здесь http://start1c.blogspot.ru/2014/02/1_12.html

      Удалить
  3. А вот у меня вопрос, если мне нужно из 1с (из табличной части) в sql перекинуть определенные данные... как мне в этом случае быть?

    ОтветитьУдалить
    Ответы
    1. Генерация запроса для каждой строки - не наш метод.
      Необходимо залить в запрос всю таблицу, либо бить на пакеты. Примеры http://start1c.blogspot.ru/2012/09/qlikview-1-1-ii.html, http://start1c.blogspot.ru/2012/10/1-qlikview.html.

      Удалить
    2. Спасибо за ответ!!! Но я решила свою проблему сама... У меня был отчет (обычные табульки сотрудников) - в модуле объекта находились все данные и я не могла перекинуть в модуль формы... Я думала уже использовать и таблицу значений, и временная таблица и так далее... но потом я вспомнила, что есть табличная часть в самом отчете... И я передала в табличную часть все мои данные. И с Модуля формы, я уже передала данные в БД SQL.

      Удалить
  4. Интересная и полезная статья, НО возник вопрос по поводу отображения данных из ВИД на форме списка:
    — стандартная форма выводится пустой, но поиск по ней срабатывает,
    — динамический список не срабатывает.
    Не подскажете, в чем может быть проблема?
    ВИД — база SQL.

    ОтветитьУдалить
    Ответы
    1. Нет, на вскидку не подскажу. Всегда проблем со списком внешних источников не было. Попробуйте ради интереса в настройках форм источника убрать ссылки на формы списка и посмотреть как отработает автогенерируемая форма.

      Удалить
    2. Самое интересное, если при подключении не ставить галочку у поля oid, то все открывается хорошо.

      Удалить
  5. Спасибо АВТОРУ!!!! Два дня бился с ВнешнимиИсточникамиДанных. Решил идти старым проверенным путем. Пол часа на адаптацию кода и ВУАЛЯ!!! Еще раз спасибо!

    ОтветитьУдалить
  6. Михаил, подскажите пожалуйста, как во внешние источники подключить базу noSQL?
    Поставил odbc driver, 1с-ка драйвер видит, но не подключает, пишет, не удалось создать строку подключения, возможно база не поддерживает параметры подключения.

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

    ОтветитьУдалить
    Ответы
    1. Андрей, а какую noSQL используете?
      Навскидку, в конфигураторе необходимо прописать строку соединения руками без использования конструктора.
      Например, при использовании создании источника с использованием ODBC Microsoft Text Driver 1С также видит драйвер, но конструктор строки не работает. Но если прописать строку подключения руками Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=c:\temp\1c_odbc, то подключение произойдет.

      Удалить
    2. Как я могу узнать у себя, какая там версия noSQL?

      Пока не знаю.
      Опишу, что имею.
      Значит знакомые попросили написать выгрузку телефонов сразу в программу для рассылки смс.
      Называется она вот так "SMS AIR Sender" (https : // prostor-sms . ru /)
      Устанавливается в программ файл, а свои данные хранит тут: "C:\Users\Andrew\AppData\Roaming\Sender.3086999DA79CAED26B786A9BA0713452E9AC8766.1\Local Store".
      В папке есть файлик "AIRSender5.db".
      Открыть я его могу программой SQLiteStudio-3.1.1
      Программа показывает версию SQLite 3. Вот принскрин http://prntscr.com/e3bl1t

      Поскольку я делаю первые шаги в этом направлении (подключение и использование Внешних источников данных), многое не понятно и не получается.
      Потому прошу помощи.
      Подскажите, что именно нужно вписать, что бы подключиться к файлу?

      Удалить
    3. Попробуй варианты
      https://www.connectionstrings.com/sqlite3-odbc-driver/
      https://www.connectionstrings.com/sqlite/

      Удалить
    4. Михаил спасибо, все получилось.
      Вот принстскрин подключенных таблиц из SQLite базы http://prntscr.com/e3g16g
      Путь прописал к файлу такой
      (
      DRIVER=SQLite3 ODBC Driver;Database=D:\Documents and Settings\Admin\Application Data\Sender.3086453DA79CAED38B796A9BA3120432E0AC2716.1\Local Store\AIRSender5.db;LongNames=0;Timeout=1000;NoTXN=0;
      SyncPragma=NORMAL;StepAPI=0;
      )

      Удалить
  7. Здраствуйте. А не подскажите пожалуйста, как сделать сихронизацию внешнего источника и справочника? Необходимо из sql постоянно данные в 1с кидать в справочники и изменять, если были изменения. Пришел к варианту с внешним источником, но не знаю как сихронизировать теперь их?

    ОтветитьУдалить
  8. Привет.
    В общих чертах, синхронизацию 1С с данными внешних источников делал следующим образом:
    - в таблицу ВИ добавлялась колонка с отметкой о синхронизации (булево, дата/время - на выбор)
    - при обновлении данных со стороны sql отметка сбрасывалась
    - регламентное задание 1С искало в таблице ВИ строки с пустой отметкой о синхронизации и выполняла необходимые процедуры синхронизации с установкой отметки в обработанных строках ВИ.

    ОтветитьУдалить