Difference between revisions of "Guide for usage of Tdbf component/ru"

From Free Pascal wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(7 intermediate revisions by 4 users not shown)
Line 12: Line 12:
 
Например, нам необходимо создать таблицу следующей структуры, если она не существует (пример взят из реальной программы):
 
Например, нам необходимо создать таблицу следующей структуры, если она не существует (пример взят из реальной программы):
  
procedure CheckAndCreate;
+
<syntaxhighlight lang=pascal>
var path : String;
+
procedure CheckAndCreate;
    TarifDbf : Tdbf;
+
var path : String;
begin
+
    TarifDbf : Tdbf;
 +
begin
 
   path:=ExtractFilePath(Application.EXEName);
 
   path:=ExtractFilePath(Application.EXEName);
 
   //Проверка существования базы данных
 
   //Проверка существования базы данных
 
   if not DirectoryExists(Path+DirectorySeparator+'Base') then  
 
   if not DirectoryExists(Path+DirectorySeparator+'Base') then  
 
         CreateDir(Path+DirectorySeparator+'Base');
 
         CreateDir(Path+DirectorySeparator+'Base');
  if not FileExists(Path+'Base'+DirectorySeparator+'tarif.dbf') then begin
+
  if not FileExists(Path+'Base'+DirectorySeparator+'tarif.dbf') then begin
 
     TarifDbf.TableLevel := 4;
 
     TarifDbf.TableLevel := 4;
 
     TarifDbf.FilePathFull := Path+'Base';
 
     TarifDbf.FilePathFull := Path+'Base';
Line 38: Line 39:
 
     TarifDbf.FieldDefs[TarifDbf.FieldDefs.Count-1].Precision := 2;//<=
 
     TarifDbf.FieldDefs[TarifDbf.FieldDefs.Count-1].Precision := 2;//<=
 
     TarifDbf.CreateTable;
 
     TarifDbf.CreateTable;
  end;
+
  end;
 
   TarifDbf.FilePathFull := Path+DirectorySeparator+'Base';
 
   TarifDbf.FilePathFull := Path+DirectorySeparator+'Base';
 
   TarifDbf.TableName := 'tarif.dbf';
 
   TarifDbf.TableName := 'tarif.dbf';
 
   TarifDbf.Active := true;
 
   TarifDbf.Active := true;
end;
+
end;
 +
</syntaxhighlight>
  
 
Обратите внимание на фрагменты кода, отмеченные <= в коментарии - только таким образом можно создать поле типа Numeric с дробной частью.
 
Обратите внимание на фрагменты кода, отмеченные <= в коментарии - только таким образом можно создать поле типа Numeric с дробной частью.
 +
 +
== Перекодировка ==
 +
У компонента Tdbf есть свойство OnTranslate. Этому свойству нужно присвоить определенную процедуру:
 +
 +
<syntaxhighlight lang=pascal>
 +
uses lconvencoding;
 +
 +
constructor TMyDbf.Create;
 +
begin
 +
  FDbf.OnTranslate:= @OnTranslate;
 +
end;
 +
 +
function TMyDbf.OnTranslate(Dbf: TDbf; Src, Dest: PChar; ToOem: Boolean): Integer;
 +
var
 +
  S: String;
 +
begin
 +
  if ToOem then
 +
    S := ConvertEncoding(Src, 'utf8', 'cp866')
 +
  else
 +
    S := ConvertEncoding(Src, 'cp866', 'utf8');
 +
  StrCopy(Dest, PChar(S));
 +
  Result := StrLen(Dest);
 +
end;
 +
</syntaxhighlight>
 +
 +
а потом после открытия для всех полей типа TStringField поставить свойству Transliterate := True:
 +
 +
<syntaxhighlight lang=pascal>
 +
FDbf.Open;
 +
for i := 0 to FDbf.Fields.Count - 1 do begin
 +
  if FDbf.Fields[i] is TStringField then
 +
    TStringField(FDbf.Fields[i]).Transliterate := True;
 +
end;
 +
</syntaxhighlight>
 +
 +
После выполнения этих действий таблица FDbf будет автоматически перекодироваться из cp866 в utf8 при открытии и из utf8 в cp866 при записи.
  
 
== Замеченные баги ==
 
== Замеченные баги ==
Line 52: Line 90:
 
1. При попытке узнать тип и размерность поля не всегда полученный результат соответствует действительности.
 
1. При попытке узнать тип и размерность поля не всегда полученный результат соответствует действительности.
  
2. При упаковке таблицы с MEMO файл MEMO "раздувается" приблизительно в 10 раз вместо того, чтобы уменьшаться.
+
2. При упаковке таблицы с MEMO файл MEMO "раздувается" приблизительно в 10 раз вместо того, чтобы уменьшаться. (в SVN версии этот баг исправили, связан с неправильным определением размера при чтении данных из поля MEMO).
  
 
3. Нет нормальной поддержки перекодировки с кодовой страницы БД в текущую локаль и обратно, что создает определенные трудности при переносе БД с одной системы в другую (напр. из DOS в Windows или Linux), поэтому приходится самому реализовывать перекодировку "на лету".
 
3. Нет нормальной поддержки перекодировки с кодовой страницы БД в текущую локаль и обратно, что создает определенные трудности при переносе БД с одной системы в другую (напр. из DOS в Windows или Linux), поэтому приходится самому реализовывать перекодировку "на лету".
 +
 +
== См. также ==
 +
*[[Example: TDbf (creating table and indexes, selecting of index)]]
  
  
 
--[[User:ViruZ|ViruZ_UA]] 14:55, 20 March 2008 (CET)
 
--[[User:ViruZ|ViruZ_UA]] 14:55, 20 March 2008 (CET)
 +
 +
{{AutoCategory}}
 +
[[Category:FPC/ru]]
 +
[[Category:Lazarus/ru]]
 +
[[Category:Databases/ru]]
 +
[[Category:Components/ru]]
 +
[[Category:Tutorials/ru]]
 +
[[Category:FPC]]
 +
[[Category:Lazarus]]
 +
[[Category:Databases]]
 +
[[Category:Components]]
 +
[[Category:Tutorials]]

Latest revision as of 13:17, 16 February 2020

Учебник по использованию компонента Tdbf

Обзор

В этой статье я хочу описать некоторые особенности использования компонента Tdbf совместно со средой разработки Lazarus. При написании оиспользовались Free Pascal Compiler 2.2.1 /Lazarus 0.9.25, компонент Tdbf установлен по умолчанию. Примеры кода, приведенные ниже, проверены в Windows XP SP2 и Mandriva Linux 2007.1 Spring.

Документация

Я пользовался следующей документацией при изучении принципов работы с этим компонентом. Официальная документация в формате PDF доступна на SourceForge. Также мой перевод статьи по использованию этого компонента [1].

Начало - создание новой таблицы

Подробности создания таблицы описываются в статье [[2]] Я хочу уточнить некоторые особенности, с которыми мне пришлось столкнуться. Например, нам необходимо создать таблицу следующей структуры, если она не существует (пример взят из реальной программы):

procedure CheckAndCreate;
var path : String;
    TarifDbf : Tdbf;
begin
  path:=ExtractFilePath(Application.EXEName);
  //Проверка существования базы данных
  if not DirectoryExists(Path+DirectorySeparator+'Base') then 
         CreateDir(Path+DirectorySeparator+'Base');
  if not FileExists(Path+'Base'+DirectorySeparator+'tarif.dbf') then begin
    TarifDbf.TableLevel := 4;
    TarifDbf.FilePathFull := Path+'Base';
    TarifDbf.TableName := 'tarif.dbf';
    TarifDbf.FieldDefs.Add('NLZ',ftInteger,2);//[0]код учреждения
    TarifDbf.FieldDefs.Add('NOTD',ftInteger,2);//[1]код отдела
    TarifDbf.FieldDefs.Add('DOLGNOST',ftString,20);//[2]название должности
    TarifDbf.FieldDefs.Add('PERSONAL',ftInteger,2);//тип персонала
    TarifDbf.FieldDefs.Add('KODKAT',ftInteger,2);//[3]квалификацоонная категория (разряд)
    TarifDbf.FieldDefs.Add('FIO1',ftString,35);//[4]Фамилия, имя, отчество сотрудника
    TarifDbf.FieldDefs.Add('TARIFRZ',ftInteger,2);//[5]Тарификационный разряд (1..25)
    TarifDbf.FieldDefs.Add('OKLAD1',ftFloat,10);//[6]Должносной оклад по тарифному разряду
    TarifDbf.FieldDefs[TarifDbf.FieldDefs.Count-1].Precision := 2;//<=
    TarifDbf.FieldDefs.Add('DOLJA1',ftFloat,5);//[16]доля ставки
    TarifDbf.FieldDefs[TarifDbf.FieldDefs.Count-1].Precision := 2;//<=
    TarifDbf.FieldDefs.Add('FOND',ftFloat,11);//[27] месячный фонд з/п
    TarifDbf.FieldDefs[TarifDbf.FieldDefs.Count-1].Precision := 2;//<=
    TarifDbf.CreateTable;
  end;
   TarifDbf.FilePathFull := Path+DirectorySeparator+'Base';
   TarifDbf.TableName := 'tarif.dbf';
   TarifDbf.Active := true;
end;

Обратите внимание на фрагменты кода, отмеченные <= в коментарии - только таким образом можно создать поле типа Numeric с дробной частью.

Перекодировка

У компонента Tdbf есть свойство OnTranslate. Этому свойству нужно присвоить определенную процедуру:

uses lconvencoding;

constructor TMyDbf.Create;
begin
  FDbf.OnTranslate:= @OnTranslate;
end;

function TMyDbf.OnTranslate(Dbf: TDbf; Src, Dest: PChar; ToOem: Boolean): Integer;
var
  S: String;
begin
  if ToOem then
    S := ConvertEncoding(Src, 'utf8', 'cp866')
  else
    S := ConvertEncoding(Src, 'cp866', 'utf8');
  StrCopy(Dest, PChar(S));
  Result := StrLen(Dest);
end;

а потом после открытия для всех полей типа TStringField поставить свойству Transliterate := True:

FDbf.Open;
for i := 0 to FDbf.Fields.Count - 1 do begin
  if FDbf.Fields[i] is TStringField then
    TStringField(FDbf.Fields[i]).Transliterate := True;
end;

После выполнения этих действий таблица FDbf будет автоматически перекодироваться из cp866 в utf8 при открытии и из utf8 в cp866 при записи.

Замеченные баги

При использовании данного компонента я выявил несколько багов.

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

2. При упаковке таблицы с MEMO файл MEMO "раздувается" приблизительно в 10 раз вместо того, чтобы уменьшаться. (в SVN версии этот баг исправили, связан с неправильным определением размера при чтении данных из поля MEMO).

3. Нет нормальной поддержки перекодировки с кодовой страницы БД в текущую локаль и обратно, что создает определенные трудности при переносе БД с одной системы в другую (напр. из DOS в Windows или Linux), поэтому приходится самому реализовывать перекодировку "на лету".

См. также


--ViruZ_UA 14:55, 20 March 2008 (CET)