Отправляет email-рассылки с помощью сервиса Sendsay

1С и электронная коммерция

  Все выпуски  

1С и электронная коммерция Доступ к данным V7 из других систем. Импорт данных. Документ




1С и электронная коммерция    Рассылка сайта Системная интеграция + 1С и
Центр милосердия, образования и творчества

Среда, 24 Сентября 2008 года (11 Сентября 2008 по ст.ст.)
Седмица 15-я по Пятидесятнице, Глас пятый


Попразднство Рождества Пресвятой Богородицы. + Перенесение мощей прпп. Сергия и Германа, Валаамских чудотворцев. Прп. Силуана Афонского (1938). Прп. Феодоры Александрийской (474-491). Мчч. Димитрия, Еванфии, жены его, и Димитриана, сына их (I). Мчч. Диодора и Дидима, Сирских. Мц. Ии (Евдокии) и 9-ти тысяч с ней в Персии (362-364). Прп. Евфросина повара (IX). Каплуновской иконы Божией Матери (1689). Мчч. Серапиона, Кронида и Леонтия, Александрийских. Прп. Пафнутия, испов., еп. в Фиваиде Египетской. Прпмц. Феодоры Вастийской, Пелопонесской. Прославление блж. Ксении, Петербургской. Прп. Дейниола, игумена Бангорского, еп. Уэльсского (584) (Кельт. и Брит.).

Доступ к данным V7 из других систем. Импорт данных. Документы.

Импорт данных из документов

 


Рекомендуемый софт
  • md2mdb v1.3b / модель приложения импорта данных (MS Access)
  • Compound Extractor / извлечение потоков из MD
  • als2html Convertor / конвертация ALS в HTML

Издатель этой статьи, а я далее буду именовать WildHare именно так, назвал эту публикацию «концептуальной». Он попал в самую точку! Исследование структуры V7, которая, в свою очередь, отражает движение абстракций, да ещё и вводит собственные – есть не что иное, как самый махровый концептуализм (представителем которого, кстати, был цитируемый мною ранее Оккам).

Для того, чтобы продолжить строительство модели доступа к системе хранения информации в V7, придётся вернуться немного назад. Итак, что получено в результате предыдущей работы? Главное, на мой взгляд, это возможность представить метаданные, описывающие хранимую информацию, в виде таблиц с которыми можно работать стандартными методами той или иной среды.

В первой (MetaObjects) хранится список объектов хранения (наименования, внутренние и десятичные идентификаторы, наименование класса). Во второй (metaObjectsProps), связанной с первой отношением 1:M – свойства (properties) каждого объекта. Функция, отдающая значение PropertyValue свойства с именем PropertyName объекта ObjectID, может тогда выглядеть примерно так:

SELECT metaObjectsProps.PropValue AS [PropertyValue] (Q1)
FROM MetaObjects INNER JOIN metaObjectsProps
ON MetaObjects.ObjKey = metaObjectsProps.ObjKey
WHERE (metaObjectsProps.PropName=[PropertyName])
AND (MetaObjects.ID=[ObjectID]);

Получить иерархию самих объектов можно с помощью ссылки на поле-родитель. Так, например, получить идентификатор объекта-родителя (Parent_ID) для объекта ObjectID можно следующим образом:

SELECT Parent.ID AS [Parent_ID] (Q2)
FROM _MetaObjects AS Child INNER
JOIN _MetaObjects AS Parent
ON Child.ParKey = Parent.ObjKey
WHERE Child.ID=[ObjectID];
а список объектов-потомков (Child_ID) так:
SELECT Child.ID AS [Child_ID] (Q3)
FROM _MetaObjects AS Child INNER
JOIN _MetaObjects AS Parent
ON Child.ParKey = Parent.ObjKey
WHERE Parent.ID= [Parent_ID];

Фактически, эти запросы и есть тот мост между метаданными (которые и определяют структуру хранения) и данными из DBF (SQL). Остаётся только надеяться, что данных из MD хватит для имитации (повторения) действий V7 при построении 1cv7.dd (dds) и использовании его в работе.

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

  • единый ключ (IDDOC) для всех таблиц 1SJOURN, DHxxx, DTxxx;
  • для таблиц 1SJOURN и DHxxx он является первичным ключом;
  • для таблиц DTxxx IDDOC выступает как foreign key;
  • таблица 1SJOURN нигде явно не выступает в отношениях 1:M со стороны M;
  • записи таблиц DTxxx уникально идентифицируются через IDDOC+ LINENO;
  • реквизиты документов не могут быть периодическими.
Файлы (таблицы) 1SOPER и 1SENTRY, в которых хранятся операции и проводки в компоненте Бухгалтерский учет, фактически являются вырожденными DHxxx и DTxxx. При организации доступ к данным этих классов будут использоваться те же методы, что и при работе с документами.

Ещё раз уточним требования к методике доступа и к виду получаемых данных. Требование к методике и процессу преобразования только одно: он должен быть воспроизводим. Речь идет о том, что алгоритмы и методика доступа к данным V7 не должны использовать никаких специфических свойств системы (инструмента) преобразования. Это обязательное условие я ставлю на первое место.

Если речь идет о «Доступе к данным V7 из других систем», то этой другой системой совершенно не обязательно должен быть MS Access (он используется только для отработки технологии). Более того, совершенно необязательно, чтобы эта другая система работала под Win32! Нет никаких видимых препятствий тому, чтобы, предположим, реализовать задуманное на связке Perl+MySQL или под чем-нибудь GNU-тым.

Именно по этой причине избрана методика, при которой данные V7 будут «выгребаться» автоматически формируемыми на основе метаданных запросами. Ну а сами запросы – естественно будут написаны на «родном» языке структурированных запросов, т.е. на SQL.

Требования к данным тоже достаточно аскетичны: они должны быть представлены в виде таблиц, удовлетворяющих следующим условиям:

  1. столбцы (поля) таблиц должны иметь осмысленные наименования, по которым можно представить их содержимое;
  2. должна существовать возможность получить из системы более полную информацию (условно – комментарий) о характере данных, хранящихся в таблицах. То есть должны существовать какие-то метаданные, с нормальным механизмом доступа. Естественно – храниться они тоже должны в таблицах и быть доступны через SQL. Если бы такое было в V7, то и не было бы нужды заваривать всю эту кашу ;-).
  3. информация в таблицах должна быть представлена в не в виде ссылок на данные, а в виде непосредственно самих данных (в терминах предметной области).
Пункт (c) необходимо прокомментировать. Данные V7 хранятся лишь в частично нормализованном виде (в терминах реляционных БД). Хранение документов, о котором сказано ранее, нормализовано лишь внешне, на уровне ключей таблиц. Стоит только взглянуть на содержимое полей – и иллюзии по этому поводу исчезают. Поэтому, никакой нормализации при импорте/присоединении не будет.

Сначала размежеваться – а потом соединиться. Сначала денормализовать, а уж потом приводить к первой, второй, и т.п. нормальным формам.

Небольшие комментарии к модели. Первым делом импортируем файлы 1SJOURN, DHxxx и DTxxx. На этом этапе не рассматривается окончательная технология (импорт или присоединение таблиц). В дальнейшем будет показано какой метод и по каким причинам предпочтителен (оптимален), а пока скажу, что для разных версий системы (7.5 и 7.7) он не одинаков.

Проблемы с кодировкой, с которыми сталкиваются многие при импорте данных V7, используя Jet ISAM (dbf в OEM в 7.5 и в ANSI в 7.7), решаются изменением значения параметра DataCodePage в HKLM\Software\Microsoft\Jet\xxx\Engines\Xbase на "OEM" или "ANSI". Причем, достаточно только инициализировать драйвер с нужными значениями, дальнейшие изменения значения ключа после инициализации значения не имеют.

Список DH (DT) файлов с их именами (как в V7) получается с помощью запроса:

SELECT "DH"& Trim(ID), "DT"& Trim(ID), Sname
FROM _MetaObjects WHERE ClassName="documents";

Для формирования запросов к файлам DH (DT) нужно знать имена полей этих файлов, типы хранящихся в них данных, настоящие имена полей, и некоторую другую информацию. Эту информацию можно получить используя запросы (Q3) или в более общем виде, одним запросом типа Pivot/Transform/Rollup (в зависимости от диалекта SQL).

Для документа с ключом [DocKey] этот запрос будет выглядеть так:

TRANSFORM t1.PropValue) (Q4)
SELECT t.ID_Int, t.ID, t.Sname, t.ClassName
FROM _MetaObjects AS t
INNER JOIN _metaObjectsProps AS t1 ON t.ObjKey = t1.ObjKey
WHERE ((t.parkey=[ DocKey]) AND t.ClassName = "Head Fields"))
(OR ((t.ClassName)="GenJrnlFldDef")
GROUP BY t.ID_Int, t.ID, t.Sname, t.ClassName PIVOT t1.PropName;"

Класс GenJrnlFldDef (общие реквизиты) включен из-за того, что в нем описана часть полей таблиц DHxxx (те, у которых не установлен признак отбора). Наиболее важными значений из полученных являются:

  • id – десятичный ID поля (имя поля в таблице DHxxx = "SP"&[id]),
  • Sname – имя поля,
  • Type – тип поля,
  • Source_Id – внешний источник данных для поля нескалярного типа,
  • Size – размер поля.
В получаемых при доступе представлениях полей таблиц документа есть определенные особенности. Дело в том, что поля нескалярного типа – справочник, перечисление, счёт – должны отображаться в «правильном», содержательном виде. Но ни одна система, кроме V7, естественно, не имеет базовых типов Справочник (а уж тем более Субконто), поэтому отображаться и храниться эти значения будут в виде текста.

По-другому, думаю, и невозможно сделать по принципиальным соображениям. Если значения поля типа «определенный справочник» (справочник контрагентов, например) можно представить как множество значений, определенных на домене «организации», а поле типа «справочник сотрудников« – на домене «люди», то как быть со справочником «вообще«? Там всё смешалось, кони, люди…

Нет уже никакой предметной области. О полях типа типа «неопределенный вообще», где могут успешно сосуществовать не только объектные, но и скалярные типы, и говорить нечего. Это замечательно придумано и реализовано для реализации задач на V7, но является самым главным препятствием для решения поставленной задачи осмысленного доступа к данным. Строгости определений явно не хватает ;-).

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

Правила преобразования, применяющиеся при доступе к данным:

  • поля скалярных типов типов (N,S,D) – не преобразовываются;
  • у полей типа B берется Код (Code) либо Наименование (Descr), в зависимости от установленного в конфигураторе основного представления справочника (Code_Type из таблицы metaObjectsProps) и наличия или отсутствия этих полей (в 7.7 это стало возможно);
  • поле типа Перечисление представляется наименованием (не представлением!);
  • поля типа Документ – представляются [Наименованием документа] + номер документа (из 1SJOURN);
  • у полей типа Счет берется КодСчета из 1SACCS (наименование не берется из-за обычно большого количества этих полей и длинных наименований). Хотя, наименование, конечно, более информативно и вносит меньше путаницы при обилии различных планов счетов;
  • поле типа ПланСчетов представляется своим наименованием;
  • поле типа K (вид субконто) представляется как [Наименование субконто]&[Значение субконто];
  • поля типа Календарь и ВидРасчета представляются также наименованием.
Эти правила – не догма, ничто не может помешать изменить их в дальнейшем, но на данный момент они зафиксированы.

Реализация преобразования (доступа) очень сильно зависит от версии V7 и инструмента, с помощью которого это преобразование выполняется. Смысл вышесказанного заключается в коренном отличии ключей DBF в этих версиях: если в 7.5 они 64-ричные (интересно, а как это выговорить?), то в 7.7 – 36-ричные. Первые содержат строчные буквы, вторые – нет.

Но не все из существующих сегодня систем (по крайней мере настольных) могут использовать регистрозависимые первичные ключи. По крайней мере те, которые базируются на механизме Microsoft JET – не могут. А таких среди настольных систем немало. Подробности, возможно, позже, а пока ограничичусь только замечанием, что «поля вообще» в 7.7 преобразовываются как указано выше, а в 7.5 – As Is.

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

К наименованиям полей в формируемых запросах добавляется префикс – символ, соответствующий типу поля (B,T,…): строчный в случае поля опредёленного типа, и прописной в случае неопределенного типа. Это сделано исключительно в целях наглядности и не несет никакой другой нагрузки.

Запросы формируются по одному на каждый документ и сохраняются под именем соответствующей таблицы DBF – DHxxxx. Внутри каждого запроса – стандартные конструкции SQL. Все таблицы в запросах – под alias'ами. В запросах фактически отсутствуют конструкции WHERE, и максимально (может быть, даже избыточно) применяется JOIN. Связано это как с тем, что в V7 отсутствует поддержка неопределенных значений (NULL), так и с тем, что генерацию кода для реализации левого внешнего объединения на составных ключах (типа IDDOC+OBJID) проще реализовать через LEFT JOIN + дополнительный unique key.

Кроме этого, есть некоторые отличия в реализации последовательности применения JOIN и WHERE на внешних объединениях в разных SQL-системах (по крайней мере, отличия от ANSI92 существуют).

На самом деле, сам код проще, чем его описание ;-). Вся работа с генерацией запросов собрана в одном модуле (FormQuery), импорт/присоединение таблиц – в модуле DBFWork. Советую поэкспериментировать с прилагаемым софтом, только помните что это не коммерческое изделие, производительность которого не должна опускаться ниже определенных границ, а лишь его модель, от которой требуется в первую очередь функциональность, а лишь затем производительность.

В прилагаемой версии модели, помимо разбора MD и чтения DBF, реализован экспорт прочитанной структуры метаданных в ALS-файл. Файл с именем ALSfromMDB помещается в тот каталог, откуда был прочитан соответствующий ему 1cv7.md, автоматически, сразу после чтения метаданных.


Вы можете добавить свою новость или статью по адресу (необходимо зарегистрироваться): www.anobis.ru
По вопросам размещения Ваших статей и информации в наших рассылках - пишите нам: osbekar@mail.ru
ICQ: 322770372

Подпишитесь на другие наши рассылки

Рассылки Subscribe.Ru
Секреты рекламы и создания интернет-магазинов
Скидки, подарки, призы...
1С и электронная коммерция
Серверы, сетевое оборудование, тесты, характеристики, советы
Рукопашный бой для девушек – выживание, психология, самозащита!
Милосердие. Чем ты можешь помочь ближнему.
Православные знакомства.
Здоровый образ жизни.

В избранное