Андрей Малкин где-то в 2001 Любые логические построения остаются лишь сухой теорией, пока не подтверждены работающей
моделью. В качестве такой модели я предлагаю программу, которая:
- читает MMS из выбранного пользователем MD-файла (запуская прилагаемый
Compound Extractor),
- определяет версию (7.5/7.7) для правильного преобразования данных,
- создаёт таблицы, куда помещает объекты конфигурации и их реквизиты (в том числе и внутренний
идентификатор: 64- или 36-ричный).
В качестве инструментального средства используется MS Access97. Программа поставляется в виде
файлов:
Для работы с моделью понадобятся оба файла.
Немного о реализации. Access выбран по понятным причинам: распространенность, встроенные
средства работы с данными, приличная поддержка SQL. Работать будет и на Access2000, на AcceessXP
не проверялось. При реализации во главу угла ставилась простота переноса, как на другую версию
MS Access, так в другую инструментальную среду. Отсюда эмуляция некоторых функций VB6
(Split(), Replace(), и т.п.) и некоторая потеря производительности за счет,
возможно, избыточного применения SQL. Комментариев в тексте достаточно, читайте.
Все вопросы на finsoft@saravia.ru.
В качестве шаблонов используются таблицы метаклассов (_MetaClass) и их реквизитов
(_MetaClassProps), описанных в главе III.
Таблицу метаклассов трогать не рекомендую, а вот в таблице их реквизитов можно менять поле
"OK2Convert", отвечающее за обработку того или иного реквизита, для получения более
полной информации о структуре конкретного MD-файла. Результатом является таблица
объектов (_MetaObjects) и их реквизитов (_metaObjectsProps).
Забегая вперед, скажу, что именно эти таблицы и используются в дальнейшем для построения
таблиц/запросов выборки данных из dbf-файлов базы данных V7.
Если информация в MMS не текстовая (закрыта паролем, упакована, закриптована,
и т.п.) чтение не производится.
Определившись с данными, которые надо получить, необходимо разобраться с источником данных.
Для упрощения используются DBF-версии V7, так как разница в логической
структуре данных DBF и SQL-версии практически отсутствует. Кроме этого, считается,
что данные не являются «распределенными» (в терминах V7). Разница в хранении
«распределенных» и «нераспределенных» данных
только в добавлении ко внутреннему ID документа дополнительного реквизита.
Информационную базу V7 условно можно разделить на:
- системные таблицы (1SUSERS, 1SSYSTEM, 1SDNLOCK, 1SUIDCTL)
- вспомогательные таблицы бизнес-логики/интерфейса (1SCORENT,
1SACCSEL, 1SCRDOC, 1SSBSEL, 1SSTREAM, 1STOPER)
- общие таблицы (1SBLOB, 1SCONST)
- таблицы первичных данных/итогов (1SACCS, 1SCONST, 1SBLOB, 1SENTRY, 1SJOURN,
1SOPER, CJPROP, CJxxx, CL, DHxxx, DTxxx, etc.)
Нас будут интересовать главным образом две последние группы, причём основное внимание будет
уделено именно «первичным данным» справочникам и документам.
Справочники
Начинаем со справочников: именно в этих структурах могут храниться фактически все типы данных,
кроме того, именно справочники являются базовым понятием и для некоторых других объектов
(например, для видов субконто, расчётов и т.п). В описании будут встречаться ссылки на объекты
метаданных и их реквизиты, приведенные в таблицах в предыдущих главах статьи.
Некоторые поля в таблицах содержат числовые значения в системе счисления, отличной от десятичной:
16/36/64-ричной. К наименованиям таких полей будет добавляться суффикс [int]
(internal).
Кроме этого, в качестве сокращений будут употребляться PKey (PrimaryKey) и
FKey (ForeignKey).
SCxxxx.DBF таблица справочника, где xxx
ID объекта-справочника.
"Содержит данные справочника конкретного вида. Каждый справочник
хранится в отдельном файле." [© 1С].
- ID [int] PKey таблицы, значение в 36/64-ричной
системе (в зависимости от версии V7), нумеруется с единицы. Тип Char(9).
Обращение к справочнику происходит всегда именно по ID. Справочник «отдает»
при этом обращении либо код, либо наименование (в зависимости от значения Sbcnts.ret_tip
в MMS).
- CODE код справочника. Тип всегда Char, вне
зависимости от реквизита Sbcnts.kod_tip, определенного в MMS. Длина поля
Sbcnts.kod_size
.
- DESCR наименование справочника. Тип Char. Длина
поля Sbcnts.naim_size.
- ISMARK пометка на удаление. Тип Char(1). Если
запись помечена в этом поле "*" (chr(42)). При пометке
на удаление поддерживается ссылочная целостность: все подчиненные записи (как в этой, так и
в других таблицах) также помечаются.
- VERSTAMP [int] количество изменений записи. Изменением считается
любое действие "Изменить (открыть)" + действия при изменении структуры. Появилось
в 7.7.
- ISFOLDER и PARENTID [int] поля, моделирующие
иерархическую структуру справочника. Типы, соответственно, Numeric(1,0) и Char(9).
ISFOLDER принимает значения 1 (признак группы) или 2 (признак элемента).
PARENTID ссылка (FKey) на ID записи о группе в этой же таблице.
В 7.5 эти поля присутствовали в любом справочнике, в 7.7 только в тех,
у которых Sbcnts.max_level>1.
- PARENTEXT [int] ссылка (FKey) на ID «владельца»
в другом справочнике. Тип Char(9). Владелец определяется Sbcnts.Owner_id.
Поле присутствует в 7.7 в зависимости от наличия Sbcnts.Owner_id, в 7.5
всегда.
- SPyyy эти поля полностью определяются подклассом
Sbcnts.Params.yyy=Params.ID, тип поля соответствует Params.Type, size и dec
также определяется соответствующими реквизитами. Если Params.Type=N/S/D
в поле хранятся непосредственно значения. При строковом типе и Size=0
строка неограниченной длины, хранится в 1SBLOB.DBF. Для остальных типов
в поле хранятся ссылки на значения из других таблиц или метаданных.
В случае типа=B/O/T/C/A (значения которых хранятся в таблицах), в поле SPyyy
хранится ссылка на соответствующую таблицу. Если на момент формирования структуры хранения
известен конкретный источник данных (т.е. Params.Source_Id<>0)
поле SPyyy содержит только номер записи (PKey) соответствующей таблицы (9 знаков
[int]).
Если же на момент формирования структуры хранения Params.Source_Id=0
например «справочник вообще» поле SPyyy содержит,
помимо 9-и байтового номера записи ещё и ID [int] соответствующего этой
таблице объекта метаданных (в первых 4-х байтах).
Значения для типов E/P/K не хранятся в таблицах, а выбираются
непосредственно из метаданных по своему уникальному во всей системе ID, поэтому значением
поля SPyyy является всегда является ссылка на ID [int] необходимого объекта
(хотя и размещается эта ссылка не в 4-х, а в 9-и байтах).
В случае, если Params.Type=U (значение неопределенного типа)
поле SPyyy имеет длину 23 байта и содержит в первых 2-х символах
информацию о фактически хранящемся типе значения (например N для Numeric, B1 для типа B,
E1 для типа E, и т.п.), в остальных символах аналогично предыдущему
(4+9).
Любое поле SPyyy неопределенного типа (U) сопровождается полем TSPyyy
типа Char(3), с назначением которого я не разобрался (похоже что оно всегда empty, если поле
SPyyy пусто).
При отсутствии значений в полях определенного типа они имеют вид " 0 0",
поле неопределенного типа "U"&space(22).
Всё, кроме полей неопределенного типа, присутствует и в 7.5 (только разбивка полей не
4+9, а 4+8). Полей неопределенного типа, как и полей
TSPyyy в 7.5 нет (хотя значения неопределенного присутствуют во многих таблицах).
Остался нерассмотренным ещё один реквизит поля SPyyy из Sbcnts.Params:
признак периодического поля (Params.pr_period). Значения полей, имеющих этот признак,
хранятся в файле 1SCONST.DBF, который связан с таблицами SCxxx
отношением 1:M со стороны M. Значения, имеющие структуру, описанную ранее, хранятся в поле
1SCONST.Value, номер записи справочника [int] в поле 1SCONST.OBJID,
а идентификатор справочника [int] в поле 1SCONST.ID.
Об 1SCONST, однако, чуть позже.
Документы и журналы документов
Хранение документов построено немного проще, чем справочников, хотя и здесь не без фокусов:
так, например, номера и даты документов хранятся не в таблицах документов, как это можно
предположить, а в таблице журналов.
Поэтому рассматривать документы отдельно от журналов просто бессмысленно. Вот что пишет 1С по
поводу этих таблиц:
- 1SJOURN Содержит заголовки всех документов (внутренний идентификатор, номер,
дату, время, общие реквизиты, по которым установлен отбор)
- DHxxx Содержит данные реквизитов шапки и общих реквизитов без признака
"Отбор" документа конкретного вида. Создается при наличии у документа соответствующих реквизитов.
- DTxxx Содержит данные реквизитов табличной части документа конкретного вида.
Создается при наличии у документа соответствующих реквизитов.
Понятно, что xxx ID объекта-документа (вида документа).
1SJOURN.DBF
- IDJOURNAL [int] идентификатор журнала, ID объекта класса
Journalisters, значение в 36/64-ричной системе (в зависимости от версии V7).
Тип Char(4). Определяется реквизитом Documents.Jrnl_ID. Фактически
1SJourn это «полный журнал».
- IDDOC [int] PKey документа, такой же как в DHxxx и
DTxxx. Тип Char(9). IDDOC всех документов хранятся в 1SJourn.
- IDDOCDEF [int] ссылка на ID объекта-таблицы
Documents.ID. Тип Char(4).
- APPCODE возможность документа работать с компонентами:
оперативный учет (1), расчет (2), бухучет (4) и их комбинация. Для документа
«Операция» APPCODE=20. Тип Numeric(3,0).
Возможно, существуют и другие значения. Возможность работы с различными компонентами определяется
значениями Documents.PrTrade, Documents.PrSalary, Documents.PrAccount.
- DATE дата документа. Тип Date(8).
- TIME [int] время документа в секундах(*10000) с 00:00:00.
Тип Char(6).
- DNPREFIX префикс номера документа. Тип Char(18).
- DOCNO номер документа. Тип Char. Длина поля
определяется максимальным значением Documents.DocNumSize всех объектов класса
Documents.
- CLOSED флаг закрытия/проведения документа. Тип
Numeric(1,0).
- ACTCNT счетчик действий (движения) для данного документа
(один документ может вызывать несколько движений регистра). Похоже, что связан с полями
ACTNO таблиц RAxxx и 1SCONST. Тип Numeric(6,0).
- ISMARK аналогично справочникам. Тип Сhar(1).
- ACTCNT ???.
- VERSTAMP аналогично справочникам. Тип Сhar(6).
- RFxxx флаг наличия движения по регистру "xxx".
Тип Numeric(1,0).
- SPyyy (+TSPyyy для неопределенных типов)
поля определенные, как «общие реквизиты» для всех документов (объекты класса
GenJrnlFldDef). Формирование значений в этих полях аналогично SPyyy
в таблицах справочников. В 1SJOURN включаются только те из GenJrnlFldDef,
в которых pr_otbor=1, остальные в DHyyy.
- DSzzz относится к DocumentStream.
DHxxx.DBF
Содержит реквизиты шапки документа для документа с ID=xxx, а также часть
реквизитов, определенных в конфигураторе, как «общие реквизиты для всех документов».
Связана отношением 1:1 с 1SJOURN по ключу IDDOC.
- IDDOC [int] PKey документа, из 1SJOURN и
DTxxx. Тип Char(9).
- SPyyy (+TSPyyy для неопределенных типов)
дополнительные поля определяемые:
- в Documents.HeadFields
- в Documents.TableFields, если TableFields.Col_Total=1
(для подсчета итогов по колонке)
- как «общие реквизиты для всех документов» (объекты класса GenJrnlFldDef),
у которых не установлен признак отбора (GenJrnlFldDef.pr_otbor=0); те у
которых он установлен включаются в 1SJOURN.
Тип поля определяется в Documents.HeadFields, Documents.TableFields либо в
GenJrnlFldDef.
Формирование значений в полях аналогично SPyyy в таблицах справочников (за исключением
того, что они не могут быть периодическими).
DTxxx.DBF
Содержит табличную часть документа. Связана отношением 1:M со стороны «многие»
с 1SJOURN по ключу IDDOC.
- IDDOC [int] FKey из 1SJOURN и DTxxx.
Тип Char(9).
- LINENO номер строки табличной части. Тип Numeric(4,0).
- SPyyy (+TSPyyy для неопределенных типов)
дополнительные поля, определяемые в Documents.TableFields. Тип поля определяется в
Documents.TableFields.Type. Если у документа "ууу"
TableFields.Col_Total>0, (есть итог по колонке) аналогичное
поле добавляется и в DHyyy.
Формирование значений в полях аналогично SPyyy в таблицах справочников (за исключением
того, что они не могут быть периодическими и иметь неограниченную длину).
Операции
Операции тесно связаны с предыдущим разделом и, по сути дела, являются специальным видом
документа. Из © 1С:
"1SOPER Содержит данные бухгалтерских операций (сумму,
содержание, дополнительные реквизиты). Содержит одну строку на документ, по которому создана
операция."
Таблица операция связана отношением 1:1 с 1SJOURN по
1SOPER.DOCID=1SJOURN.IDDOC.
Поля таблицы:
- DOCID [int] PKey таблицы, FKey для 1SJOURN.IDDOC.
Тип Char(9).
- DATE дата операции. Тип Date(8).
- TIME [int] время операции в секундах(*10000) с 00:00:00.
Тип Char(6).
- DESCR описание операции. Тип Char. Длина поля
определяется реквизитом Buh.OperDescrLen.
- SUM Сумма операции. Тип Numeric. Size и Dec
поля определяются реквизитами Buh.OperSumLen и Buh.OperSumDec.
- ACTIVE проводки выключены/включены. Устанавливается в "*"
(chr(42)) при выключенных проводках операции. Тип Char(1).
- SPyyy (+TSPyyy для неопределенных типов)
дополнительные поля определяемые в Buh.OperParams. Тип поля определяется в
Buh.OperParams.Type. Size и Dec там же.
Формирование значений в полях аналогично SPyyy в таблицах справочников (за
исключением того, что они не могут быть периодическими и иметь неограниченную длину).
|