Страница 1 из 2
TDbf и база с сайта ЦБ РФ
Добавлено: 20.08.2010 13:21:21
qqqq1
День добрый.
Проблема в следующем - TDbf не хочет открывать поля базы данных (пустота вместо данных), если ширина поля (в структуре таблицы) превышает 20. Как получить доступ к этим полям?
Сейчас просто меняю структуру в другой программе (уменьшаю длину поля) и тогда все OK.
Например, в TDBGrid (через TDbf) пустота вместо этого столбца.
Базу беру отсюда -
http://www.cbr.ru/credit/transparent.asp (внизу страницы)
windows XP, Lazarus 0.9.28.2 / fpc 2.2.4
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 20.08.2010 15:24:12
Vadim
qqqq1У меня отображаются. Поле name_b в таблице 062010N.dbf. Длина данных (почти в начале

) - 26 символов. Все их вижу.
Картинку можете поместить со своей проблемой?
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 20.08.2010 15:50:56
qqqq1
Уточнение.
Не открываются "числовые" поля. См., например, файлы 052010_B.DBF
Структура из программы DBFNavigator:
Поле ITOGO
тип numeric
ширина 33
дроб.часть 4
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 23.08.2010 06:10:12
Vadim
qqqq1qqqq1 писал(а):Уточнение.
Не открываются "числовые" поля. См., например, файлы 052010_B.DBF
Вот это другое дело.

Я, птица-секретарь, даю справку (

):
Maximum size of numeric and float fields........ 20
Это из самого прогрессивного, на сегодняшний момент, движка обработки файлов типа DBF - Microsoft Visual FoxPro.
У TDbf движок даже рядом с микрософтовским не валялся. Отсюда и глюк - то, что выходит за пределы
предельно заданного размера не отображается.
Я думаю, ЦБР слегка погорячился с размерами этого поля.

Вы можете, перед открытием файла для просмотра, поменять тип поля на ftString с соответствующим количеством символов в длине поля. Тогда данные в поле не пропадут и будут нормально отображаться.
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 23.08.2010 10:27:01
qqqq1
Спасибо за ответ.
Но проблема остаётся.
Дело в том, что я уже пытался поменять структуру (лежит на поверхности - просто думал, что можно что-то подправить в коде, чтобы заработало) - в частности уменьшить размер поля до 20. Собственно ничего не получается - процедура RestructureTable приводит к тому, что значения у поля обрезаются справа на 8 знаков. Например, было 14 988 290 582, стало 149. Причём глюк получается, даже если не менять структуру, а просто её скопировать.
Или у меня что-то не то с кодом?
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
Dbf: TDbf;
FieldDefs: TDbfFieldDefs;
begin
Dbf := TDbf.Create(nil);
Dbf.TableName := 'C:\052010_B.DBF';
Dbf.Open;
FieldDefs := TDbfFieldDefs.Create(nil);
FieldDefs.Assign(Dbf.DbfFieldDefs);
Dbf.Close;
//FieldDefs.Items[3].FieldType:=ftString;
//FieldDefs.Items[3].Size:=20;
Dbf.RestructureTable(FieldDefs, false);
Dbf.Free;
FieldDefs.Free;
end;
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 23.08.2010 12:07:53
Vadim
qqqq1Тяжёлый случай...

Значит TDbf категорически не воспринимает всё, что выходит за пределы его компетенции. В том числе и неправильный размер поля.
Тогда можно применить дедовский способ:
Код: Выделить всё
Type
TDbfFieldR = packed record
name: array[0..10] of char;
FieldType: char;
Place: DWord;
Len: Byte;
Dec: Byte;
Flag: Byte;
AutoInc: DWord;
AutoIncStep: Byte;
Reserved: array[0..7] of Byte;
end;
procedure TForm1.FormCreate(Sender: TObject);
Var
MyFile: TFileStream;
fld: TDbfFieldR;
begin
MyFile:=TFileStream.Create('062010_b.dbf', fmOpenReadWrite);
MyFile.Seek(4*32, soFromBeginning);
MyFile.Read(fld, SizeOf(TDbfFieldR));
label1.Caption:=fld.name;
MyFile.Seek(4*32, soFromBeginning);
fld.FieldType:='C';
MyFile.Write(fld, SizeOf(TDbfFieldR));
MyFile.Free;
dbf1.Open;
end;
Коротко суть:
DBF файл состоит из заголовка файла, который имеет размер 32 байта и некоторого кол-ва заголовков полей, которые тоже имеют размер по 32 байта. Тогда мы открываем файл в стандартном потоке, пропускаем заголовок файла и заголовки трёх полей (т.к. поле ITOGO у нас четвёртое по счёту). Далее, считываем заголовок четвёртого поля в переменную, меняем тип поля, подставляя соответствующую ему букву ("C" - CHARACTER) и записываем переменную обратно в файл
на прежнее место. Закрываем файл-поток. Открываем его нашим несчастным TDbf...

Re: TDbf и база с сайта ЦБ РФ
Добавлено: 23.08.2010 14:38:58
qqqq1
Спасибо!!!
Наконец заработало.
Но. Такой код “портит” заголовок таблицы – другие программы (например, DBFNavigator - в Lazarus всё OK) отказываются после этого читать такие файлы.
Решил добавлением своего кода. Как не странно, но после изменения типа и указания нового размера – всё работает.
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
Dbf: TDbf;
FieldDefs: TDbfFieldDefs;
MyFile: TFileStream;
fld: TDbfFieldR;
begin
MyFile:=TFileStream.Create('C:\052010_B.DBF', fmOpenReadWrite);
MyFile.Seek(4*32, soFromBeginning);
MyFile.Read(fld, SizeOf(TDbfFieldR));
MyFile.Seek(4*32, soFromBeginning);
fld.FieldType:='C';
MyFile.Write(fld, SizeOf(TDbfFieldR));
MyFile.Free;
Dbf := TDbf.Create(nil);
Dbf.TableName := 'C:\052010_B.DBF';
Dbf.Open;
FieldDefs := TDbfFieldDefs.Create(nil);
FieldDefs.Assign(Dbf.DbfFieldDefs);
Dbf.Close;
FieldDefs.Items[3].FieldType:=ftFloat;
FieldDefs.Items[3].Precision:=4;
FieldDefs.Items[3].Size:=20;
Dbf.RestructureTable(FieldDefs, true);
Dbf.Free;
FieldDefs.Free;
end;
Без Вашего кода просто стирает все значения поля.
Но осталась проблема. Код создаёт копию открываемого файла. Не критично, но неприятно.
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 16.11.2010 14:49:34
Nik
Столкнулся с похожей проблемой. Имеется файл DBF, слитый из 1С. При попытке открыть силами TDbf одно из полей (NAME, типа string) считывается в корявой кодировке (сама БД в кодировке Win-1251).
С такими БД дела до сих пор иметь не приходилось, ничего типа FoxPro под рукой нет, чтобы проверить, как там откроется.
В чём там ещё может быть заморочка?
Если что, файл
здесь лежит.
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 16.11.2010 18:14:47
Vadim
Nik
Кодовая страница - это 29-ый байт заголовка. У Вас там стоит $65, что означает ср866. Для ср1251 должно стоять $C9.
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 16.11.2010 18:30:33
Nik
Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 16.11.2010 22:32:07
Padre_Mortius
А конвертить сроку из одной кодировки в другую уже не принято? Примеров на этом форуме вроде бы достаточное количество. Например,
тут можно посмотреть как это делается правильно
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 17.11.2010 09:01:01
Vadim
NikNik писал(а):Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?
Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 17.11.2010 10:23:44
Nik
Padre_Mortius писал(а):А конвертить сроку из одной кодировки в другую уже не принято? Примеров на этом форуме вроде бы достаточное количество. Например,
тут можно посмотреть как это делается правильно
Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Vadim писал(а):NikNik писал(а):Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?
Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.
Спасибо!
Re: TDbf и база с сайта ЦБ РФ
Добавлено: 17.11.2010 12:42:57
Vadim
Nik писал(а):Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Это потому что кодировка в заголовке файла стоит неправильная. Ещё один камень в огород 1С.

Re: TDbf и база с сайта ЦБ РФ
Добавлено: 17.11.2010 15:00:39
Nik
Vadim писал(а):Nik писал(а):Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Это потому что кодировка в заголовке файла стоит неправильная. Ещё один камень в огород 1С.

Это я уже понял. Подозреваю, что можно как-то настроить экспорт в 1С, но пока нет возможности пообщаться с человеком, который за это отвечает. Так что буду править своими силами
