Delphi: Paradox Db Field Name Issue (Spaces in Field Name)

Delphi: Paradox DB Field Name Issue (Spaces in field name)

You need to prefix the string with the table name in the query.

For example: field name is 'Street 1', table is called customers the select is:

SELECT customers."Street 1" FROM customers WHERE ...

Delphi TTable.Exists fails on Paradox table even if database tables exist

You need to separately set the DatabaseName and FileName.

Table1 := TTable.Create(whatever);
Table1.DatabaseName := ExtractDir;
Table1.TableName := ExtractFileName(filename);

(You should really get away from the BDE and Paradox files (as well as TTable). The BDE has been deprecated for more than a decade now, and may not ship in future versions of Delphi. There are serious issues with the latest versions of Windows as well.)

BDE dbidorestructure returns empty table

I got nowhere trying to correct your code even after spending several hours on it, so I started again from scratch. I think you will find that the code below correctly removes a field from a TTable while retaining the correct contents of the remaining record fields.

The DeleteField routine is a stand-alone procedure, but you should find it straightforward to integrate with your existing code. If you want to add or modify fields, I suggest that you start from Mr Sprenger's code as posted in the link. Personally, if I were you I would abandon your RestructureTable as I don't think it is salvageable, I'm afraid.

My Main form has a TTable named DestTable, a DBGrid and a Datasource connected up as you would expect. I then add the code below.

procedure TForm1.CreateTable(T : TTable);
var
AField : TField;
begin
AField := TIntegerField.Create(T);
AField.FieldName := 'Field1';
AField.DataSet := T;

AField := TStringField.Create(T);
AField.FieldName := 'Field2';
AField.DataSet := T;
AField.Size := 20;

AField := TStringField.Create(T);
AField.FieldName := 'Field3';
AField.DataSet := T;
AField.Size := 20;

T.Exclusive := True;

T.CreateTable;
T.Open;

T.InsertRecord([1, 'r1f1', 'r1f2']);
T.InsertRecord([2, 'r2f1', 'r2f2']);
T.InsertRecord([3, 'r3f1', 'r3f3']);

end;

I create and populate the table in code so that the code is self-contained and doesn't depend on any existing table.

I then add this DeleteField method:

procedure DeleteField(Table: TTable; Field: TField);
(*
based on a post by Jason Sprenge on Wed, 29 May 2002 03:00:00 GMT in
this thread http://www.delphigroups.info/2/48/359769.html
*)

type
TFieldArray = Array[0..1000] of FLDDesc;
PFieldArray = ^TFieldArray;
var
Props: CURProps;
hDb: hDBIDb;
TableDesc: CRTblDesc;
pOldFields,
pNewFields,
pCurField: pFLDDesc;
pOp, pCurOp: pCROpType;
ItrFld: Word;
i,
j : Integer;
POldFieldArray,
PNewFieldArray : PFieldArray;
OldFieldsArraySize,
NewFieldsArraySize : Integer;
begin
// Initialize the pointers...
pOldFields := nil;
pNewFields := Nil;
pOp := nil;
// Make sure the table is open exclusively so we can restructure..
if not Table.Active then
raise EDatabaseError.Create('Table must be opened '+
'to restructure');
if not Table.Exclusive then
raise EDatabaseError.Create('Table must be opened exclusively ' +
'to restructure');
// Set the cursor in physical translation mode
Check(DbiSetProp(hDBIObj(Table.Handle), curxltMODE, Ord(xltNONE)));
// Get the table properties to determine table type...
Check(DbiGetCursorProps(Table.Handle, Props));
// Make sure the table is either Paradox, dBASE or FoxPro...
if (Props.szTableType <> szPARADOX) and
(Props.szTableType <> szDBASE) and
(Props.szTableType <> szFOXPRO) then
raise EDatabaseError.Create('Field altering can only occur on '+
'Paradox, dBASE or FoxPro tables');
try
// Allocate memory for the field descriptor...
OldFieldsArraySize := Props.iFields * sizeof(FLDDesc);
NewFieldsArraySize := (Props.iFields - 1) * sizeof(FLDDesc);

pOldFields := AllocMem(OldFieldsArraySize);
pNewFields := AllocMem(NewFieldsArraySize);

// Allocate memory for the operation descriptor...
pOp := AllocMem(Props.iFields * sizeof(CROpType));
// Null out the operations (= crNOOP)...
FillChar(pOp^, Props.iFields * sizeof(CROpType), #0);
// Set the pointer to the index in the operation descriptor to put
pCurOp := pOp;
Inc(pCurOp, Field.FieldNo - 1);
pCurOp^ := crNoOp;
// Fill field descriptor with the existing field information...
Check(DbiGetFieldDescs(Table.Handle, pOldFields));
// Set pointer to the index in the field descriptor to make the
// modifications to the field
pCurField := pOldFields;
Inc(pCurField, Field.FieldNo - 1);

pCurField := pOldFields;
for ItrFld := 1 to Props.iFields do begin
pCurField^.iFldNum := ItrFld;
Inc(pCurField, 1);
end;

j := 0;
i := 0;
POldFieldArray := PFieldArray(pointer(pOldFields));
PNewFieldArray := PFieldArray(pointer(pNewFields));

for i := 0 to Table.FieldCount - 1 do begin
if Table.Fields[i] <> Field then begin
pNewFieldArray^[j] := pOldFieldArray^[i];
Inc(j);
end;
end;
// Blank out the structure...

FillChar(TableDesc, sizeof(TableDesc), #0);
// Get the database handle from the table's cursor handle...
hDb := Table.DBHandle;
// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblName, Table.TableName);
// Put the table type in the table descriptor...
StrCopy(TableDesc.szTblType, Props.szTableType);
// The following three lines are necessary when doing any field
// restructure operations on a table...

// Set the field count for the table
TableDesc.iFldCount := Props.iFields - 1{MA};
// Link the operation descriptor to the table descriptor...
TableDesc.pecrFldOp := pOp;
// Link the field descriptor to the table descriptor...
TableDesc.pFldDesc := pNewFields;
// Close the table so the restructure can complete...
Table.Close;
// Read restructure action...
Check(DbiDoRestructure(hDb, 1, @TableDesc, nil, nil, nil, False));
finally
if (pOldFields <> nil) then
FreeMem(pOldFields);
if (pNewFields <> nil) then
FreeMem(pNewFields);
if (pOp <> nil) then
FreeMem(pOp);
end;
end;

which removes a field from the table specified by its field index.

I then add

procedure TForm1.btnRestructClick(Sender: TObject);
var
AField : TField;
begin
CreateTable(DestTable);
if not DestTable.Active then
DestTable.Open;
// Select a field to be deleted
AField := DestTable.FieldByName('Field2');
DeleteField(DestTable, AField);
DestTable.Fields.Clear;
if not DestTable.Active then
DestTable.Open;
end;

Calling btnRestructClick correctly restructures the table removing Field2 and DestTable can be saved to disk with the correct structure and contents.

Error loading file with full name containing spaces in directory with delphi

Remove the double quote marks from your string. It should be:

'C:\Compartilhada\dicomserver versoes\dicomserverx\data\Genesis-1000\1.2.410.200013.1.215.1.200912141600580009_0001_000001_13061821270002.dcm'

You might use " for paths containing spaces in some situations, for instance a command interpreter. But at the API level, it is simply not needed. And indeed it is a mistake as you have discovered. The double quote character " is actually a reserved character in a file name. That is documented on MSDN:

Naming Files, Paths, and Namespaces: Naming Conventions

The following fundamental rules enable applications to create and process valid names for files and directories, regardless of the file system:

  • ...
  • Use any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:

    • The following reserved characters:

      • < (less than)
      • > (greater than)
      • : (colon)
      • " (double quote)
      • / (forward slash)
      • \ (backslash)
      • | (vertical bar or pipe)
      • ? (question mark)
      • * (asterisk)
    • ...
  • ...

In comments below you indicate that the code in the question does not reflect your actual problem. Which makes me wonder how you expect us to help. Your real problem is not the error message produced by the specific code, but that your debugging skills are letting you down. Let me try to explain how to debug a problem like this.

First of all, you are passing a file name to LoadFromFile or TFileStream.Create. These calls fail with an error that indicates that the file name is not valid.

So, when faced with that knowledge, the first step is to check the value of the file name that you are passing. Use debugging techniques to do that. Either the IDE debugger, or logging.

Once you have identified what value you are actually passing to these functions you can try to work out what is invalid about it.

To repeat, your real problem is not with the specifics, but in your debugging skills. You should take this as an opportunity to learn more about debugging. Stack Overflow is not a substitute for debugging. Learn to debug better, and your life as a programmer will become very much easier.



Related Topics



Leave a reply



Submit