Корректировка заголовка DBF-файла, сформированного в 1С, для его связи с индексным файлом для дальнейшей работы с ним из внешних приложений (FoxPro 2.6, Visual FoxPro и пр.)


Программный код, корректирующий заголовок DBF-файла, сформированного в 1С, для его связи с индексным файлом для далнейшей работы с ним из внешних приложений (FoxPro 2.6, Visual FoxPro и пр.)

Задача: необходимо передавать некоторую информацию из 1С в DBF-формате включая индексный файл (.CDX) для дальнейшего ее использования в иных информационных подсистемах предприятия.

Проблема: ПО некоторых подсистем разработано на FoxPro 2.6 или Visual FoxPro. И как оказалось эти системы не видят индексного файла идущего в паре с DBF сформированным в 1С.

Решение: после анализа DBF-файла и изучения спецификации формата (например вот здесь: http://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm) была найдена причина, а именно то, что 1С не проставляет 28-й байт заголовка DBF-файла равным 1, что свидетельствовало бы о связке с индексным файлом.

После этого осталось лишь программно проставить целевой байт в нужное значение.

Для работы с байтами заголовка была выбрана компонента Microsoft ADODB.Stream (ссылка на описание компоненты http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms675032%28v=vs.85%29.aspx).

&НаСервере
Процедура Выгрузка()
   
//Создаем тестовый пример выгрузки данных в DBF с индексами на базе справочника «Номенклатура»
   
Путь = «E: emp»;
   
БД = Новый XBase;
   
БД.Поля.Добавить(«CODE», «S», 11);
   
БД.Поля.Добавить(«NAME», «S», 40);
   
БД.СоздатьФайл(Путь + «start.dbf», Путь + «start.cdx»);
   
БД.Индексы.Добавить(«IDXCODE», «CODE»);
   
БД.Индексы.Добавить(«IDXNAME», «NAME»);
   
ФлИБД = БД.СоздатьИндексныйФайл(Путь + «start.cdx»);
   
Выборка = Справочники.Номенклатура.ВыбратьИерархически();
    Пока
Выборка.Следующий() Цикл
       
БД.Добавить();
       
БД.CODE = Выборка.Код;
       
БД.NAME = Выборка.Наименование;
       
БД.Записать();
    КонецЦикла;
   
БД.ЗакрытьФайл();
   
//Читаем DBF-файл и корректируем 28-й байт
   
Поток = Новый COMОбъект(«ADODB.Stream»);
   
Поток.Type = 1;
   
Поток.Mode = 3;
   
Поток.Open();
   
Поток.LoadFromFile(Путь + «start.dbf»);
   
ДвоичнаяСтрока = Поток.Read(29);
   
ДвоичнаяСтрока.SetValue(28, 1);
   
Поток.Position = 0;
   
Поток.Write(ДвоичнаяСтрока);
   
Поток.SaveToFile(Путь + «start.dbf», 2);
   
Поток.Close();
 КонецПроцедуры

Вот этот несложный код корректирует 28-й байт заголовка DBF-файла и позволяет внешним приложениям увидеть и идущий в связке индексный файл.

18 Comments

  1. hogik

    (0)

    Михаил (iRounder).

    При использовании этого CDX файла другими «внешними приложениями» могут возникнуть проблемы с порядком сортировки вплоть до зацикливания функций «движения» по индексу при чтении. Про обновление такого индекса и говорить не хочется… 😉

    Т.е. рекомендуется создавать индексный файл средствами «внешнего приложения» заново, а не передавать готовый из 1С.

    Reply
  2. andrewks

    (1) hogik, полностью поддерживаю

    Reply
  3. iRounder

    (1) Вы пробовали так делать?

    У меня подобных проблем не возникло.

    Опишите, пжл, ситуацию когда вы столкнулись с подобной проблемой.

    На какой платформе формировали таким образом индексный файл и каким «внешним приложением» с ним работали.

    Reply
  4. andrewks

    (3) Вам же написали про подводные камни в ветке на мисте.

    однако в публикации о них — ни слова

    Reply
  5. iRounder

    (4) О каких подводных камнях Вы говорите? Насколько я помню там просто было предположение, что создавать сам DBF-файл через ADO проще.

    «Перечитал» мисту. Единственное, что подходит под определение «подводные камни»: Тем более, что кроме заголовка там и сортировка не полностью совпадает (для экзотических знаков).

    Никаких доводов или перечисления о каких экзотических символах речь не было. Что по Вашему я должен был быть указывать еще в публикации?

    Ну, и если Вы заметили, публикация не в виде обработки, за которые я получаю $m, а просто «дележка» опытом. Кроме применения для замены байта в DBF эта методика показывает общий принцип работы с двоичными данными, когда нужно заменить часть файла.

    Ну, и за любую критику благодарен. А если еще будут доводы или факты, которые подтвердят «глючность» метода, то я обязательно напишу об этом в описании публикации, а возможно и вообще ее закрою.

    Reply
  6. andrewks

    (5) ни в коем разе не добиваюсь закрытия публикации. наоборот, нужно больше разных тайных знаний.

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

    Reply
  7. iRounder

    (6) Так поэтому ж я и прошу примеры. Потому как в моем случае все работает 🙂

    Reply
  8. hogik

    (3)

    «Вы пробовали так делать?»(с)

    Михаил (iRounder).

    И пробовать не буду, т.к. имел «удовольствие» пялиться на исходные тексты и общаться с разработчиками. В том числе и по поводу «русификации» индексных файлов. Занимаясь вот этим: http://infostart.ru/public/14664/ И еще вот этим: http://infostart.ru/public/85748/

    Вот, читайте с 31-ого сообщения тему: http://www.forum.mista.ru/topic.php?id=434036

    А т.к. DBF-движки в 1С-продуктах сделаны на «платформе» 😉 разработчика

    http://www.codebase.com/ ,то особенности индексов для «семерки» можно распространить и на «восьмерку».

    Reply
  9. iRounder

    (8) Найду время — попробую.

    Reply
  10. iRounder

    (8) Почитал. Создал пустой справочник. Заполнил его:

    A lat
    B lat
    N lat
    O lat
    P lat
    А рус
    Б рус
    В рус
    № рус

    Показать

    Дальше по описанной в публикации методике создал индексный файл и установил в DBF 28-й байт равным 1.

    Открыл DBF-ку в Visual FoxPro.

    Далее буду приводить команды выполненные из командного окна и полученные результаты:

    SET INDEX TO start ORDER idxname
    BROWSE LAST
    —————-
    A lat
    B lat
    N lat
    O lat
    P lat
    № рус
    А рус
    Б рус
    В рус
    

    Показать

    SET FILTER TO UPPER(Name) > «Z»
    BROWSE LAST
    —————-
    № рус
    А рус
    Б рус
    В рус
    

    SET FILTER TO UPPER(Name) < «Z»
    BROWSE LAST
    —————-
    A lat
    B lat
    N lat
    O lat
    P lat
    

    Показать

    Что не так с сортировкой или что я не так делаю?

    Reply
  11. hogik

    (10)

    «… что я не так делаю?»(с)

    Всё не так. 🙂

    Михаил (iRounder).

    Даю текст на «семерке». Перепишите его на «восьмерку». Сделайте файлы.

    Выполните в FoxPro команды:

    USE d: est.dbf NOUPDATE EXCLUSIVE

    SET INDEX TO d: est.cdx

    SET ORDER TO NAME

    BROWSE LAST

    Делайте движение по списку стрелкой вниз.

    Для проверки различий «семерка»/»восьмерка» прикрепил свои файлы в тему.

    Отпишите о результатах. Обсудим … 😉

    
    Перем DBF,Кат,Ном;
    Кат=»D:»;
    DBF=СоздатьОбъект(«xBase»);
    DBF.КодоваяСтраница(0);
    DBF.ДобавитьПоле(«NAME»,»C»,1,0);
    DBF.ДобавитьПоле(«CODE»,»N»,3,0);
    DBF.ДобавитьИндекс(«NAME»,»UPPER(NAME)»,0,0,»»);
    DBF.СоздатьФайл(Кат+»Test.dbf»,Кат+»Test.cdx»);
    Для Ном=1 По 255 Цикл
    DBF.Добавить();
    DBF.NAME=Симв(Ном);
    DBF.CODE=Ном;
    DBF.Записать();
    КонецЦикла;
    DBF.ЗакрытьФайл();
    

    Показать

    Reply
  12. iRounder

    Если Симв() в 7-ке это Символ() в 8-ке, то тогда не совсем корректный пример. Эти символы форма списка не отображает и выдает ошибку (я о тонком клиенте). Поэтому, по идее, эти символы в базе могут появиться только искусственно. Если можно — то более реальный контрольный пример?

    Reply
  13. hogik

    (12)

    «эти символы в базе могут появиться только искусственно»(с)

    Не возражаю. 😉

    Заполняйте DBF только отображаемыми символами.

    Reply
  14. iRounder

    (13) Приведите реальный пример появления этих символов в базе если их сама 1С не может отобразить?

    Я ж не ради придраться — я хочу разобраться и благодарен за дискуссию.

    Reply
  15. hogik

    (14)

    «я хочу разобраться «(с)

    Михаил (iRounder).

    А мы чем занимаемся? Спокойно разбираемся.

    Вроде, уже написал в (13) сообщении. 🙁

    Организуйте цикл от пробела. Если есть символы в интервале от 0x20 до 0xFF которые не могут быть в «восьмерке», то поставьте условие-ограничение в цикле на их игнорирование.

    Reply
  16. hogik

    (14)

    Михаил (iRounder).

    Вот, сделал выгрузку DBF файла в формате SDF с использованием индекса.

    Два варианта:

    1) Сразу после создание в 1С-е.

    2) После REINDEX в Visual FoxPro.

    Можно глазами «отследить» большую разницу. 😉

    Понимаете. 😉 Если стоит задача только смотреть на файл в неком (логичном порядке) записей, то на различия можно не обращать внимание. А если требуется обрабатывать записи последовательным просмотром и/или поиском по ключу, то получим картину аналогичную примеру про запрос от Александра (orefkov). Т.е. приложение должно иметь возможность сравнивать байты в оперативной памяти аналогично порядку следования информации в индексе. Например, запрос от Александра получает последовательно в порядке индекса записи таблицы, а сравнение на «Z» применяется уже к полю самой таблицы. По индексу символ «№»<«Z», а по информации из поля «№»>»Z». И запрос прекращает просмотр таблицы. Кроме этого само движение по индексу сУБД делает сравнением на основании таблицы, которая сидит в её кишках (разная для разных программ). Т.е. не во внешней таблице «связанной» с базой данных, а не программой. Как это сделано во взрослых СУБД.

    Вот. Очень примерно — так…

    Reply
  17. iRounder

    (16) Спасибо. Буду пробовать разбираться.

    Reply
  18. Ленкина

    спасибо, возможно пригодится

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *