Part Two:
What I am trying to do is modify this procedure to change more than one
field at a time
Below is my attempt. What happen is that the *last* field I pass into the
Field Descriptor gets modified, but the earlier ones do not. I have wrapped
this into a component, so I will include the button proc that calls the
component.
procedure TForm2.SpeedButton3Click(Sender: TObject);
var
chngrec1, chngrec2:tChangeInfo;
begin
table3.open;
chngrec1 := tChangeInfo.create;
chngrec1.iType := bde.fldINT32;
Restruct.addModifyField('DistributorID',chngrec1);
chngrec2 := tChangeInfo.create;
chngrec2.iType := bde.fldINT32;
Restruct.addModifyField('EndUserID',chngrec2);
restruct.ChangeFields;
table3.open;
end;
****************************
procedure tRestructionator.ChangeFields;//(Table: TTable; Field: TField;
Rec: ChangeRec);
var
Props: CURProps;
hDb: hDBIDb;
TableDesc: CRTblDesc;
pFields: pFLDDesc;
pOp: pCROpType;
B: byte;
i : integer;
Field : tField;
ChangeRec : tChangeInfo;
begin
// Initialize the pointers...
pFields := nil; pOp := nil;
// Make sure the table is open exclusively so we can get the db handle...
if fModifyTable.Active = False then
raise EDatabaseError.Create('Table must be opened to restructure');
if fModifyTable.Exclusive = False then
raise EDatabaseError.Create('Table must be opened exclusively to
restructure');
Check(DbiSetProp(hDBIObj(fModifyTable.Handle), curxltMODE,
integer(xltNONE)));
// Get the table properties to determine table type...
Check(DbiGetCursorProps(fModifyTable.Handle, Props));
// Make sure the table is either Paradox or dBASE...
if (Props.szTableType <> szPARADOX) and (Props.szTableType <> szDBASE)
then
raise EDatabaseError.Create('Field altering can only occur on Paradox' +
' or dBASE tables');
// Allocate memory for the field descriptor...
pFields := AllocMem(fModifyTable.FieldCount * sizeof(FLDDesc));
// Allocate memory for the operation descriptor...
pOp := AllocMem(fModifyTable.FieldCount * sizeof(CROpType));
try
for i := 0 to fModifyFields.Count - 1 do
begin
ChangeRec := tChangeInfo(fModifyFields.objects[i]);
try
Field := fModifyTable.fieldByName(fModifyFields[i]);
except on e: exception do
begin
// got the field name wrong?
showmessage('Error in FieldByName: '+e.Message);
continue;
end;
end;
// Set the pointer to the index in the operation descriptor to put
// crMODIFY (This means a modification to the record is going to
happen)...
Inc(pOp, Field.Index);
pOp^ := crMODIFY;
Dec(pOp, Field.Index);
// Fill the field descriptor with the existing field information...
Check(DbiGetFieldDescs(fModifyTable.Handle, pFields));
// Set the pointer to the index in the field descriptor to make the
// modifications to the field
Inc(pFields, Field.Index);
// If the szName portion of the ChangeRec has something in it, change
it...
if StrLen(ChangeRec.szName) > 0 then
pFields^.szName := ChangeRec.szName;
// If the iType portion of the ChangeRec has something in it, change
it...
if ChangeRec.iType > 0 then
pFields^.iFldType := ChangeRec.iType;
// If the iSubType portion of the ChangeRec has something in it,
change it...
if ChangeRec.iSubType > 0 then
pFields^.iSubType := ChangeRec.iSubType;
// If the iLength portion of the ChangeRec has something in it, change
it...
if ChangeRec.iLength > 0 then
pFields^.iUnits1 := ChangeRec.iLength;
// If the iPrecision portion of the ChangeRec has something in it,
change it...
if ChangeRec.iPrecision > 0 then
pFields^.iUnits2 := ChangeRec.iPrecision;
Dec(pFields, Field.Index);
end;//for loop
for B := 1 to fModifyTable.FieldCount do begin
pFields^.iFldNum := B;
Inc(pFields, 1);
end;
Dec(pFields, fModifyTable.FieldCount);
// Blank out the structure...
FillChar(TableDesc, sizeof(TableDesc), 0);
// Get the database handle from the table's cursor handle...
Check(DbiGetObjFromObj(hDBIObj(fModifyTable.Handle),
objDATABASE, hDBIObj(hDb)));
// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblName, fModifyTable.TableName);
// Put the table type in the table descriptor...
StrPCopy(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 := fModifyTable.FieldCount;
// Link the operation descriptor to the table descriptor...
TableDesc.pecrFldOp := pOp;
// Link the field descriptor to the table descriptor...
TableDesc.pFldDesc := pFields;
// Close the table so the restructure can complete...
fModifyTable.Close;
// Call DbiDoRestructure...
Check(DbiDoRestructure(hDb, 1, @TableDesc, 'TestChanged'{nil}, nil, nil,
FALSE));
finally
if pFields <> nil then
FreeMem(pFields);
if pOp <> nil then
FreeMem(pOp);
end;
end;