TDbf и база с сайта ЦБ РФ
Модератор: Модераторы
TDbf и база с сайта ЦБ РФ
День добрый.
Проблема в следующем - TDbf не хочет открывать поля базы данных (пустота вместо данных), если ширина поля (в структуре таблицы) превышает 20. Как получить доступ к этим полям?
Сейчас просто меняю структуру в другой программе (уменьшаю длину поля) и тогда все OK.
Например, в TDBGrid (через TDbf) пустота вместо этого столбца.
Базу беру отсюда - http://www.cbr.ru/credit/transparent.asp (внизу страницы)
windows XP, Lazarus 0.9.28.2 / fpc 2.2.4
Проблема в следующем - TDbf не хочет открывать поля базы данных (пустота вместо данных), если ширина поля (в структуре таблицы) превышает 20. Как получить доступ к этим полям?
Сейчас просто меняю структуру в другой программе (уменьшаю длину поля) и тогда все OK.
Например, в TDBGrid (через TDbf) пустота вместо этого столбца.
Базу беру отсюда - http://www.cbr.ru/credit/transparent.asp (внизу страницы)
windows XP, Lazarus 0.9.28.2 / fpc 2.2.4
qqqq1
У меня отображаются. Поле name_b в таблице 062010N.dbf. Длина данных (почти в начале
) - 26 символов. Все их вижу.
Картинку можете поместить со своей проблемой?
У меня отображаются. Поле name_b в таблице 062010N.dbf. Длина данных (почти в начале
Картинку можете поместить со своей проблемой?
Уточнение.
Не открываются "числовые" поля. См., например, файлы 052010_B.DBF
Структура из программы DBFNavigator:
Поле ITOGO
тип numeric
ширина 33
дроб.часть 4
Не открываются "числовые" поля. См., например, файлы 052010_B.DBF
Структура из программы DBFNavigator:
Поле ITOGO
тип numeric
ширина 33
дроб.часть 4
qqqq1
Вот это другое дело.
Я, птица-секретарь, даю справку (
):
Это из самого прогрессивного, на сегодняшний момент, движка обработки файлов типа DBF - Microsoft Visual FoxPro.
У TDbf движок даже рядом с микрософтовским не валялся. Отсюда и глюк - то, что выходит за пределы предельно заданного размера не отображается.
Я думаю, ЦБР слегка погорячился с размерами этого поля.
Вы можете, перед открытием файла для просмотра, поменять тип поля на ftString с соответствующим количеством символов в длине поля. Тогда данные в поле не пропадут и будут нормально отображаться.
qqqq1 писал(а):Уточнение.
Не открываются "числовые" поля. См., например, файлы 052010_B.DBF
Вот это другое дело.
Я, птица-секретарь, даю справку (
Maximum size of numeric and float fields........ 20
Это из самого прогрессивного, на сегодняшний момент, движка обработки файлов типа DBF - Microsoft Visual FoxPro.
У TDbf движок даже рядом с микрософтовским не валялся. Отсюда и глюк - то, что выходит за пределы предельно заданного размера не отображается.
Я думаю, ЦБР слегка погорячился с размерами этого поля.
Спасибо за ответ.
Но проблема остаётся.
Дело в том, что я уже пытался поменять структуру (лежит на поверхности - просто думал, что можно что-то подправить в коде, чтобы заработало) - в частности уменьшить размер поля до 20. Собственно ничего не получается - процедура RestructureTable приводит к тому, что значения у поля обрезаются справа на 8 знаков. Например, было 14 988 290 582, стало 149. Причём глюк получается, даже если не менять структуру, а просто её скопировать.
Или у меня что-то не то с кодом?
Но проблема остаётся.
Дело в том, что я уже пытался поменять структуру (лежит на поверхности - просто думал, что можно что-то подправить в коде, чтобы заработало) - в частности уменьшить размер поля до 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;
qqqq1
Тяжёлый случай...
Значит TDbf категорически не воспринимает всё, что выходит за пределы его компетенции. В том числе и неправильный размер поля.
Тогда можно применить дедовский способ:
Коротко суть:
DBF файл состоит из заголовка файла, который имеет размер 32 байта и некоторого кол-ва заголовков полей, которые тоже имеют размер по 32 байта. Тогда мы открываем файл в стандартном потоке, пропускаем заголовок файла и заголовки трёх полей (т.к. поле ITOGO у нас четвёртое по счёту). Далее, считываем заголовок четвёртого поля в переменную, меняем тип поля, подставляя соответствующую ему букву ("C" - CHARACTER) и записываем переменную обратно в файл на прежнее место. Закрываем файл-поток. Открываем его нашим несчастным 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...
Спасибо!!!
Наконец заработало.
Но. Такой код “портит” заголовок таблицы – другие программы (например, DBFNavigator - в Lazarus всё OK) отказываются после этого читать такие файлы.
Решил добавлением своего кода. Как не странно, но после изменения типа и указания нового размера – всё работает.
Без Вашего кода просто стирает все значения поля.
Но осталась проблема. Код создаёт копию открываемого файла. Не критично, но неприятно.
Наконец заработало.
Но. Такой код “портит” заголовок таблицы – другие программы (например, 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;
Без Вашего кода просто стирает все значения поля.
Но осталась проблема. Код создаёт копию открываемого файла. Не критично, но неприятно.
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
Столкнулся с похожей проблемой. Имеется файл DBF, слитый из 1С. При попытке открыть силами TDbf одно из полей (NAME, типа string) считывается в корявой кодировке (сама БД в кодировке Win-1251).
С такими БД дела до сих пор иметь не приходилось, ничего типа FoxPro под рукой нет, чтобы проверить, как там откроется.
В чём там ещё может быть заморочка?
Если что, файл здесь лежит.
С такими БД дела до сих пор иметь не приходилось, ничего типа FoxPro под рукой нет, чтобы проверить, как там откроется.
В чём там ещё может быть заморочка?
Если что, файл здесь лежит.
Nik
Кодовая страница - это 29-ый байт заголовка. У Вас там стоит $65, что означает ср866. Для ср1251 должно стоять $C9.
Кодовая страница - это 29-ый байт заголовка. У Вас там стоит $65, что означает ср866. Для ср1251 должно стоять $C9.
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
А конвертить сроку из одной кодировки в другую уже не принято? Примеров на этом форуме вроде бы достаточное количество. Например, тут можно посмотреть как это делается правильно
Nik
Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.
Nik писал(а):Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?
Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
Padre_Mortius писал(а):А конвертить сроку из одной кодировки в другую уже не принято? Примеров на этом форуме вроде бы достаточное количество. Например, тут можно посмотреть как это делается правильно
Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Vadim писал(а):NikNik писал(а):Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?
Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.
Спасибо!
Nik писал(а):Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Это потому что кодировка в заголовке файла стоит неправильная. Ещё один камень в огород 1С.
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
Vadim писал(а):Nik писал(а):Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Это потому что кодировка в заголовке файла стоит неправильная. Ещё один камень в огород 1С.
Это я уже понял. Подозреваю, что можно как-то настроить экспорт в 1С, но пока нет возможности пообщаться с человеком, который за это отвечает. Так что буду править своими силами
