Один из вариантов переноса данных из 1С 7.7 в 1С 8.Х


Перенос данных — это почти всегда индивидуальный подход. И крайне важно выбрать наиболее подходящий инструмент из множества доступных. Я в этой статье опишу один из вариантов.

Итак, речь пойдет о ADODB. Какие же преимущества мы можем получить используя данный вариант обмена? Во-первых — это скорость работы. Ни OLE, ни файловый обмен не дадут той скорости доступа к базам 1С 7.7, как ADODB. Во вторых — универсальность, то есть его можно применять как в 1С 7.7 (там, правда, есть более удобные механизмы 1С++), так и в 1С 8.Х, да и в принципе везде где поддерживается работа с ADODB.

Первое что нам понадобится — это создать подключение к базе 1С (я буду рассматривать вариант dbf).

Соединение = Новый COMObject("ADODB.Connection"); // Создаем соединение
Соединение.ConnectionString = "Provider=VFPOLEDB.1;Data Source="+СокрЛП(Каталог)+";Extended Properties=dBASE IV;CODEPAGE=cp1251;"; //Внимание! CODEPAGE=cp1251; работает почему-то не везде.
Попытка
Соединение.Open();
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
Соединение.Close();

Дальше нам надо создать команду.

Команда = Новый COMObject("ADODB.Command");
Команда.ActiveConnection = Соединение;

И получить данные.

Команда.CommandText = ТекстЗапроса;
РекордСет = Команда.Execute();

Обход полученных данных можно сделать как:

Пока РекордСет.Eof() = 0 Цикл
РекордСет.MoveNext();
КонецЦикла;

Но в любой бочке мёда, есть ложка дёгтя. Если в цикле Выполнить запрос, то наш «рекордсет» заполнится новыми данными. Поэтому я бы рекомендовал после запроса переносить данные в «Таблицу значений». Сделать это можно так:

Функция СоздатьТаблицу(РекордСет)
ТаблицаРезультатаЗапроса = Новый ТаблицаЗначений();
Если РекордСет.Eof() = 0 Тогда
Для ит = 0 по РекордСет.Fields.Count - 1 Цикл
ТаблицаРезультатаЗапроса.Колонки.Добавить(РекордСет.Fields(ит).Name);
КонецЦикла;
Пока РекордСет.Eof() = 0 Цикл
СтрокаТаблицы = ТаблицаРезультатаЗапроса.Добавить();
Для ит = 0 по РекордСет.Fields.Count - 1 Цикл
СтрокаТаблицы.Установить(ит, РекордСет.Fields(ит).Value);
КонецЦикла;
РекордСет.MoveNext();
КонецЦикла;
КонецЕсли;
Возврат ТаблицаРезультатаЗапроса;
КонецФункции

Сложим все вместе и посмотрим, что у нас получилось.

Функция СоздатьТаблицу(РекордСет)
ТаблицаРезультатаЗапроса = Новый ТаблицаЗначений();
Если РекордСет.Eof() = 0 Тогда
Для ит = 0 по РекордСет.Fields.Count - 1 Цикл
ТаблицаРезультатаЗапроса.Колонки.Добавить(РекордСет.Fields(ит).Name);
КонецЦикла;
Пока РекордСет.Eof() = 0 Цикл
СтрокаТаблицы = ТаблицаРезультатаЗапроса.Добавить();
Для ит = 0 по РекордСет.Fields.Count - 1 Цикл
СтрокаТаблицы.Установить(ит, РекордСет.Fields(ит).Value);
КонецЦикла;
РекордСет.MoveNext();
КонецЦикла;
КонецЕсли;
Возврат ТаблицаРезультатаЗапроса;
КонецФункции

Функция ВыполнитьЗапрос(Соединение, ТекстЗапроса)
Команда = Новый COMObject("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandText = ТекстЗапроса;
РекордСет = Команда.Execute();
Возврат РекордСет;
КонецФункции

Процедура ЗагрузитьСправочник()
Соединение = Новый COMObject("ADODB.Connection"); // Создаем соединение

Соединение.ConnectionString = "Provider=VFPOLEDB.1;Data Source="+СокрЛП(Каталог)+";Extended Properties=dBASE IV;CODEPAGE=cp1251;"; // Внимание! CODEPAGE=cp1251; работает почему-то не везде.

Попытка
Соединение.Open();
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;

ТекстЗапроса = "SELECT SC192.CODE AS Код
| , SC192.ID AS ID
| , SC192.PARENTID AS ГруппаНаименование
| , SC192.ISFOLDER AS ЭтоГруппа
| , SC192.DESCR AS Наименование
| , SC192.SP1817 AS МодельАвто
| , SC192.SP194 AS ПолноеНаименовани
| , SC192.SP195 AS ЮридическийАдрес
| , SC192.SP196 AS ПочтовыйАдрес
| , SC192.SP197 AS Телефоны
| , SC192.SP198 AS ИНН
| , SC192.SP199 AS ДокументСерия
| , SC192.SP200 AS ДокументНомер
| , SC192.SP201 AS ДокументДатаВыдач
| , SC192.SP202 AS ДокументКемВыдан
| , V1.CODE AS ВалютаВзаиморасче
| , SC192.SP210 AS НомерКарты
| , SC192.SP211 AS ГосНомер
| , SC192.SP1796 AS Скидка
| , SC192.SP1829 AS КПП
| FROM SC192
| LEFT JOIN
| SC95 AS V1 ON
| SC192.SP203 = V1.ID
| "+?(ЧастичнаяЗагрузка,"RIGHT JOIN exchange ON SC192.ID = exchange.ID AND exchange.VID = 'Контрагенты'","")+"
|";

ТаблицаРезультатаЗапроса = СоздатьТаблицу (ВыполнитьЗапрос(Соединение, ТекстЗапроса));

Для Каждого СтрокаТЧ ИЗ ТаблицаРезультатаЗапроса Цикл
...
Объект.Наименование = СтрокаТЧ.Наименование;
Объект.Код = СтрокаТЧ.ID;
...
КонецЦикла;
Соединение.Close();
КонецПроцедуры

P.S. Данный метод дает и ещё одно преимущество над остальными — это уникальный идентификатор объекта в базе 1С 7.7 («ИмяТаблицы.ID»).

 

P.P.S. Данная статья не ставила целью провести обзор T-SQL или структуры данных 1С. Все это можно найти здесь:

http://www.sql.ru/docs/mssql/tsql_ref/index.shtml

http://www.script-coding.info/v77tables.html

и т.д.

Эпилог.  В 2005 MS SQL появилась прекрасное дополнение - возможность в предложении FOR XML использовать директиву TYPE. Давайте перепишем запрос, что бы убрать лишние действия.

ТекстЗапроса = "
| SELECT (SELECT SC192.CODE AS Код
| , SC192.ID AS ID
| , SC192.PARENTID AS ГруппаНаименование
| , SC192.ISFOLDER AS ЭтоГруппа
| , SC192.DESCR AS Наименование
| , SC192.SP1817 AS МодельАвто
| , SC192.SP194 AS ПолноеНаименовани
| , SC192.SP195 AS ЮридическийАдрес
| , SC192.SP196 AS ПочтовыйАдрес
| , SC192.SP197 AS Телефоны
| , SC192.SP198 AS ИНН
| , SC192.SP199 AS ДокументСерия
| , SC192.SP200 AS ДокументНомер
| , SC192.SP201 AS ДокументДатаВыдач
| , SC192.SP202 AS ДокументКемВыдан
| , V1.CODE AS ВалютаВзаиморасче
| , SC192.SP210 AS НомерКарты
| , SC192.SP211 AS ГосНомер
| , SC192.SP1796 AS Скидка
| , SC192.SP1829 AS КПП
| FOR XML TYPE, PATCH('CatalogeObject.Номенклатура') ) AS A
| FROM SC192
| LEFT JOIN
| SC95 AS V1 ON
| SC192.SP203 = V1.ID
| "+?(ЧастичнаяЗагрузка,"RIGHT JOIN exchange ON SC192.ID = exchange.ID AND exchange.VID = 'Контрагенты'","")+"
|";

Теперь в 1С достаточно будет следующего кода:

Пока РекордСет.Eof() = 0 Цикл
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(РекордСет.Fields(0).Value);
ЗаписьXML.ПерейтиКСодержимому();
Объект = ПрочитатьXML(ЗаписьXML);
Объект.Записать();
ЧтениеXML.Закрыть();
РекордСет.MoveNext();
КонецЦикла

Файлы обработки:

-