gifts2017

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

Опубликовал Михаил Шумский (iRounder) в раздел Обмен - Обмен через DBF

Программный код, корректирующий заголовок 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:\temp\";
   
БД = Новый 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-файла и позволяет внешним приложениям увидеть и идущий в связке индексный файл.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Владимир (hogik) 18.03.13 17:09
(0)
Михаил (iRounder).
При использовании этого CDX файла другими "внешними приложениями" могут возникнуть проблемы с порядком сортировки вплоть до зацикливания функций "движения" по индексу при чтении. Про обновление такого индекса и говорить не хочется... ;-)
Т.е. рекомендуется создавать индексный файл средствами "внешнего приложения" заново, а не передавать готовый из 1С.
Vladal; Ёпрст; andrewks; +3 Ответить 2
2. andrewks 18.03.13 17:18
(1) hogik, полностью поддерживаю
3. Михаил Шумский (iRounder) 18.03.13 17:43
(1) Вы пробовали так делать?

У меня подобных проблем не возникло.
Опишите, пжл, ситуацию когда вы столкнулись с подобной проблемой.
На какой платформе формировали таким образом индексный файл и каким "внешним приложением" с ним работали.
4. andrewks 18.03.13 18:26
(3) iRounder, Вам же написали про подводные камни в ветке на мисте.
однако в публикации о них - ни слова
5. Михаил Шумский (iRounder) 18.03.13 19:14
(4) О каких подводных камнях Вы говорите? Насколько я помню там просто было предположение, что создавать сам DBF-файл через ADO проще.

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

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

Ну, и за любую критику благодарен. А если еще будут доводы или факты, которые подтвердят "глючность" метода, то я обязательно напишу об этом в описании публикации, а возможно и вообще ее закрою.
6. andrewks 18.03.13 19:53
(5) iRounder, ни в коем разе не добиваюсь закрытия публикации. наоборот, нужно больше разных тайных знаний.

просто в данном случае, мне кажется, нельзя утверждать о полной совместимости индексного файла, созданного 1с, с любыми сторонними приложениями.
7. Михаил Шумский (iRounder) 18.03.13 20:02
(6) Так поэтому ж я и прошу примеры. Потому как в моем случае все работает :)
8. Владимир (hogik) 18.03.13 20:59
(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/ ,то особенности индексов для "семерки" можно распространить и на "восьмерку".
9. Михаил Шумский (iRounder) 18.03.13 21:05
(8) Найду время - попробую.
10. Михаил Шумский (iRounder) 19.03.13 15:19
(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
...Показать Скрыть


Что не так с сортировкой или что я не так делаю?
11. Владимир (hogik) 19.03.13 20:04
(10)
"... что я не так делаю?"(с)
Всё не так. :-)
Михаил (iRounder).
Даю текст на "семерке". Перепишите его на "восьмерку". Сделайте файлы.
Выполните в FoxPro команды:
USE d:\test.dbf NOUPDATE EXCLUSIVE
SET INDEX TO d:\test.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.ЗакрытьФайл();
...Показать Скрыть
Прикрепленные файлы:
Test.zip
12. Михаил Шумский (iRounder) 19.03.13 20:16
Если Симв() в 7-ке это Символ() в 8-ке, то тогда не совсем корректный пример. Эти символы форма списка не отображает и выдает ошибку (я о тонком клиенте). Поэтому, по идее, эти символы в базе могут появиться только искусственно. Если можно - то более реальный контрольный пример?
13. Владимир (hogik) 19.03.13 20:23
(12)
"эти символы в базе могут появиться только искусственно"(с)
Не возражаю. ;-)
Заполняйте DBF только отображаемыми символами.
14. Михаил Шумский (iRounder) 19.03.13 20:56
(13) Приведите реальный пример появления этих символов в базе если их сама 1С не может отобразить?
Я ж не ради придраться - я хочу разобраться и благодарен за дискуссию.
15. Владимир (hogik) 19.03.13 21:58
(14)
"я хочу разобраться "(с)
Михаил (iRounder).
А мы чем занимаемся? Спокойно разбираемся.
Вроде, уже написал в (13) сообщении. :-(
Организуйте цикл от пробела. Если есть символы в интервале от 0x20 до 0xFF которые не могут быть в "восьмерке", то поставьте условие-ограничение в цикле на их игнорирование.
16. Владимир (hogik) 19.03.13 23:07
(14)
Михаил (iRounder).
Вот, сделал выгрузку DBF файла в формате SDF с использованием индекса.
Два варианта:
1) Сразу после создание в 1С-е.
2) После REINDEX в Visual FoxPro.
Можно глазами "отследить" большую разницу. ;-)
Понимаете. ;-) Если стоит задача только смотреть на файл в неком (логичном порядке) записей, то на различия можно не обращать внимание. А если требуется обрабатывать записи последовательным просмотром и/или поиском по ключу, то получим картину аналогичную примеру про запрос от Александра (orefkov). Т.е. приложение должно иметь возможность сравнивать байты в оперативной памяти аналогично порядку следования информации в индексе. Например, запрос от Александра получает последовательно в порядке индекса записи таблицы, а сравнение на "Z" применяется уже к полю самой таблицы. По индексу символ "№"<"Z", а по информации из поля "№">"Z". И запрос прекращает просмотр таблицы. Кроме этого само движение по индексу сУБД делает сравнением на основании таблицы, которая сидит в её кишках (разная для разных программ). Т.е. не во внешней таблице "связанной" с базой данных, а не программой. Как это сделано во взрослых СУБД.
Вот. Очень примерно - так...
Прикрепленные файлы:
Test.zip
17. Михаил Шумский (iRounder) 20.03.13 09:43
(16) Спасибо. Буду пробовать разбираться.
18. Лена (Ленкина) 17.05.13 11:44
спасибо, возможно пригодится
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа