KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001

Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Валентин Озеров, "Советы по Delphi. Версия 1.4.3 от 1.1.2001" бесплатно, без регистрации.
Перейти на страницу:

Delphi 1

Все это я делал раньше. Я не могу вам все это показать на развернутом примере, но я дам вам идею как сделать это. Вы должны иметь таблицу, осуществляющую взаимоотношение между людьми. Если на Peter работают Jane и Simon, вы должны иметь таблицу (RELATION) с этими двумя записями.

Master

Slave ------- имена полей

Peter Jane

Peter Simon

Если George и Elisa работают на Jane, то таблица становится такой:

Master Slave ------- имена полей

Peter Jane

Peter Simon

Jane George

Jane Elisa

и так далее.

Если в таблице RELATION необходимо создать дерево, начинающееся на Peter, то нужно добавить к дереву главный узел (запись), где Master = Peter. Затем каждая дочерняя запись располагается ниже записи Master = Peter. После добавления дочерней записи вы сразу увидите, если ребенок имеет собственного ребенка. Ребенок становится теперь, вероятно, отцом, поэтому вы должны позиционировать таблицу RELATION к первой записи, где Master = child, и так далее, рекурсивно. Такой способ гарантирует построение правильного дерева.

Пример:

AddFather('Peter')

AddChild('Peter',1)


Procedure AddFather(Name: String)

Begin

 Tree.Add(Name);

End;


Procedure AddChildr(Name: String, Index:Integer)

Begin

 Relation.FindKey([Name])while RelationMaster.AsString = Name do

 Begin

  Tree.AddChild(Index,RelationSlave.AsString);

  AddChild(RelationSlave.AsString,Tree.ItemsCount);

  Relation.Next;

 End;

End;

По-моему, ошибок нет.

DBGrid и Memo-поля

Delphi 1

В обработчик события GetText TMemoField поместите следующую строку:

Text := GrabMemoAsString(TMemoField(Sender));

и поместите следующую функцию так, чтобы к ней можно было свободно обратиться:

function GrabMemoAsString(TheField : TMemoField): String;

begin

 if TheField.IsNull then Result := '' else with TBlobStream.Create(TheField, bmRead) do begin

  if Size >= 255 then begin

   Read(Result[1], 255);

   Result[0] := #255;

  end else begin

   Read(Result[1], Size);

   Result[0] := Chr(Size);

  end;

  Free;

  while Pos(#10, Result) > 0 do Result[Pos(#10, Result)] := ' ';

  while Pos(#13, Result) > 0 do Result[Pos(#13, Result] := ' ';

end;

end

Убывающий индекс

Delphi 1 

Я нашел простой способ получения убывающего индекса. В Delphi это получается очень легко и красиво: 

Table1.AddIndex('NewIndex', 'CustNo;CustName', [ixDescending]); 

Как работать из Delphi напрямую с MS ADO (Microsoft Active Data Objects)?

Nomadic отвечает:

Итак, хочу поделиться некоторыми достижениями… так на всякий случай. Если у вас вдруг потребуется сделать в своей программке доступ к базе данных, а BDE использовать будет неохота (или невозможно) – то есть довольно приятный вариант: использовать ActiveX Data Objects. Однако с их использованием есть некоторые проблемы, и одна из них это как передавать Optional параметры, которые вроде как можно не указывать. Однако, если вы работаете с ADO по-человечески, а не через тормозной IDispatch.Invoke то это превращается в головную боль. Вот как от нее избавляться: 

var

 OptionalParam: OleVariant;

 VarData: PVarData;

begin

 OptionalParam := DISP_E_PARAMNOTFOUND;

 VarData := @OptionalParam;

 VarData^.VType := varError;

после этого переменную OptionalParam можно передавать вместо неиспользуемого аргумента.

Далее, самый приятный способ получения Result sets:

Там есть масса вариантов, но как выяснилось оптимальным является следующий вариант, который позволяет получить любой желаемый вид курсора (как клиентский, так и серверный) 

var

 MyConn: _Connection;

 MyComm: _Command;

 MyRecSet: _Recordset;

 prm1: _Parameter;

begin

 MyConn := CoConnection.Create;

 MyConn.ConnectionString := 'DSN=pubs;uid=sa;pwd=;';

 MyConn.Open('', '', '', –1);

 MyCommand := CoCommand.Create;

 MyCommand.ActiveConnection := MyConn;

 MyCommand.CommandText := 'SELECT * FROM blahblah WHERE BlahID=?'

 Prm1 := MyCommand.CreateParameter('Id', adInteger.adParamInput, –1, <value>);

 MyCommand.AppendParameter(Prm1);

 MyRecSet := CoRecordSet.Create;

 MyRecSet.Open(MyCommand, OptionalParam, adOpenDynamic, adLockReadOnly, adCmdText);

…теперь можно фетчить записи. Работает шустро и классно. Меня радует. Особенно радуют серверные курсоры.

Проверялось на Delphi 3.02 + ADO 1.5 + MS SQL 6.5 sp4. Пашет как зверь.

Из вкусностей ADO – их легко можно использовать во всяких многопоточных приложениях, где BDE порой сбоит, если, конечно, ODBC драйвер грамотно сделан…

Ну и еще можно использовать для доступа к данным всяких там «нестандартных» баз типа MS Index Server или MS Active Directory Services.

В Delphi (как минимум в 4 версии) существует «константа» EmptyParam, которую можно подставлять в качестве пустого параметра. 

Как засунуть в качестве паpаметpа хpанимой пpоцедуpы стpоку длиной более 255 символов? И вообще, как использовать паpаметpы SP, если они BLOB?

Nomadic отвечает:

«Засунуть» длинную строку можно было и раньше, если написать редактируемый запрос, и воспользоваться операциями Insert/Edit.

Однако это не относится к хранимым процедурам.

В Delphi 3.0 появился новый тип параметра (TBlobField вроде) и соответственно его поддержка в BDE.

Если просто взять BDE 4.01 и выше, то работать все-равно не будет – нужна соотв. версия VCL (из Delphi 3.0 или выше). 

Дублирование набора записей

Delphi 1 

Вы можете воспользоваться вторым объектом TTable, подключенным к той же таблице, или можете вызвать метод объект TTable DisableControls, сделать изменения, и вызвать EnableControls. Для сохранения той же позиции вы можете попробовать воспользоваться закладкой. Например, так:

procedure TMyForm.MakeChanges;

var

 aBookmark: TBookmark;

begin

 Table1.DisableControls;

 aBookmark := Table.GetBookmark;

 try

  {ваш код}

 finally

  Table1.GotoBookmark(aBookmark);

  Table1.FreeBookmark(aBookmark);

  Table1.EnableControls;

 end;

end;

Как программно изменить LangDriver для таблиц dBase и Paradox?


Nomadic отвечает:

Откpываешь help и смотpишь:

……

var list:tstrings;

……

BEGIN

…….

List.Add ( 'LANGDRIVER=db866ru0 ');

……

Session.ModifyDriver( 'DBASE', List );

……

END;

Это действие я пpовожy пеpед откpытием таблицы

Ivan Sboev

(2:5049/36.15)

Это о «русификации» таблицы. В таблицах dBase и Paradox имеется байт, который определяет CodePage содержимого таблицы. Раньше он не использовался и был зарезервирован. Тебе нужно его правильно установить. Это делается через DBD Restructure table. Если хочешь программно, можешь воспользоваться следующей процедурой:

uses DbiTypes, DbiProcs, DbiErrs, DB, WinProcs, SysUtils;


procedure ChangeLangDriver( DatabaseName, TableName, LDName: string );

var

 TblExt: string;

 Database: TDatabase;

 TblDesc: CRTblDesc;

 OptDesc: FLDDesc;

 OptData: array [0..250] of Char;

 Cur: hDBICur;

 Rec: CFGDesc;

begin

 if (TableName='') or (LDName='') then raise Exception.Create('Unknown TableName or LDName');

 Database:=Session.OpenDatabase(DatabaseName);

 try

  if Database.IsSQLBased then raise Exception.Create('Function ChangeLangDriver working only with dBase or Paradox tables');

  FillChar(OptDesc, SizeOf(OptDesc), #0);

  FillChar(TblDesc, SizeOf(TblDesc), #0);

  StrCopy(OptDesc.szName, 'LANGDRIVER');

  OptDesc.iLen := Length(LDName) + 1;

  with TblDesc do

  begin

   StrPCopy(szTblName, TableName);

   TblExt := UpperCase(ExtractFileExt(TableName));

   if TblExt = 'DBF' then StrCopy(szTblType, szDbase)

   else if TblExt = '.DB' then StrCopy(szTblType, szParadox)

   else

   begin

    AnsiToOEM(StrPCopy(OptData, DatabaseName), OptData);

   if DbiOpenCfgInfoList(nil, dbiREADONLY, cfgPersistent, StrPCopy(OptData, 'DATABASES' + StrPas(OptData) + 'DB INFO')Cur) <> DBIERR_NONE then raise Exception.Create('Unknown table type');

    try

     while DbiGetNextRecord(Cur, dbiNOLOCK, @Rec, nil) <> DBIERR_EOF do if StrComp(Rec.szNodeName, 'DEFAULT DRIVER') = 0 then

     begin

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*