📄 kbmmemcsvstreamformat.pas
字号:
end;
procedure TkbmCustomCSVStreamFormat.DetermineLoadFieldIDs(ADataset:TkbmCustomMemTable; AList:TStringList; Situation:TkbmDetermineLoadFieldsSituation);
var
s:string;
null:boolean;
begin
// Dont try to get fields display names if def not yet loaded.
if (Situation<>dlfAfterLoadDef) or (Line='') or (sfLoadNoHeader in sfNoHeader) then
begin
inherited;
exit;
end;
// Determine which fields is present in the stream.
// Line has already been populated by LoadDef.
with TkbmProtCustomMemTable(ADataSet) do
begin
AList.Clear;
lptr:=PChar(Line);
while (lptr<elptr) do
begin
// Get DisplayName for field.
s:=GetWord(null);
AList.Add(s);
end;
end;
end;
procedure TkbmCUstomCSVStreamFormat.DetermineLoadFieldIndex(ADataset:TkbmCustomMemTable; ID:string; FieldCount:integer; OrigIndex:integer; var NewIndex:integer; Situation:TkbmDetermineLoadFieldsSituation);
var
i:integer;
s:string;
begin
// If determined not to load field, dont.
if (Situation<>dlfAfterLoadDef) then exit;
// Dont want to worry about case.
s:=UpperCase(ID);
// Find Field index in dataset
for i:=0 to ADataset.FieldCount-1 do
begin
if (UpperCase(ADataset.Fields[i].DisplayName)=s) then
begin
NewIndex:=i;
exit;
end;
end;
NewIndex:=-1;
end;
procedure TkbmCustomCSVStreamFormat.LoadDef(ADataset:TkbmCustomMemTable);
var
ld:boolean;
i:integer;
slist:TStringList;
DuringTableDef,DuringIndexDef:boolean;
null:boolean;
FName,KName,TName,DName,EMask,DExpr:string;
FSize,DSize:integer;
REQ,RO,INV,CASEIN,{$IFNDEF LEVEL3}NONMT,{$ENDIF}DESC,UNIQ:boolean;
FT:TFieldType;
FK:TFieldKind;
FFields:string;
ioptions:TIndexOptions;
begin
if (StreamSize = 0) then exit;
ld:=sfLoadDef in sfDef;
with TkbmProtCustomMemTable(ADataSet) do
begin
// Read all definition lines in CSV format.
slist:=TStringList.Create;
DuringTableDef:=false;
DuringIndexDef:=false;
try
while true do
begin
GetLine;
if Line='' then break;
// Read magic words if any.
Word:=GetWord(null);
{$IFNDEF CSV_FILE_1XX_COMPATIBILITY}
if Word=kbmFileVersionMagic then
begin
Word:=GetWord(null);
// FileVersion:=StrToInt(Word);
continue;
end
else
{$ENDIF}
if Word=kbmTableDefMagicStart then
begin
DuringTableDef:=true;
if ld then
begin
Close;
FieldDefs.clear;
DeleteTable;
end;
continue;
end
// End of table definition?
else if Word=kbmTableDefMagicEnd then
begin
DuringTableDef:=false;
Open;
continue;
end
// Start of index definitions?
else if Word=kbmIndexDefMagicStart then
begin
if ld then
begin
DestroyIndexes;
IndexDefs.Clear;
end;
DuringIndexDef:=true;
continue;
end
// End of index definitions?
else if Word=kbmIndexDefMagicEnd then
begin
DuringIndexDef:=false;
if ld then CreateIndexes;
continue;
end;
// If not during table definitions then its the header. Break.
if not DuringTableDef then break;
// If its an index definition.
if DuringIndexDef then
begin
if ld then
begin
Line:=ExtractQuoteString(Line,FCSVQuote);
i:=pos('=',Line);
slist.CommaText:=copy(Line,i+1,length(Line));
FName:=copy(Line,1,i-1);
FFields:=slist.Strings[0];
DName:=slist.Strings[1];
CASEIN:=pos(',CASE',Line)<>0;
{$IFNDEF LEVEL3}
NONMT:=pos(',NONMT',Line)<>0;
{$ENDIF}
DESC:=pos(',DESC',Line)<>0;
UNIQ:=pos(',UNIQ',Line)<>0;
// Add field definition.
ioptions:=[];
if CASEIN then ioptions:=ioptions+[ixCaseInSensitive];
if DESC then ioptions:=ioptions+[ixDescending];
if UNIQ then ioptions:=ioptions+[ixUnique];
{$IFNDEF LEVEL3}
if NONMT then ioptions:=ioptions+[ixNonMaintained];
with IndexDefs.AddIndexDef do
begin
Name:=FName;
Fields:=FFields;
Options:=ioptions;
DisplayName:=DName;
end;
{$ELSE}
IndexDefs.Add(FName,FFields,ioptions);
{$ENDIF}
end;
continue;
end;
// Otherwise its a field definition. Break the line apart.
if ld then
begin
Line:=ExtractQuoteString(Line,FCSVQuote);
i:=pos('=',Line);
slist.CommaText:=copy(Line,i+1,length(Line));
FName:=copy(Line,1,i-1);
TName:=slist.Strings[0];
FSize:=strtoint(slist.Strings[1]);
DName:=slist.Strings[2];
EMask:=slist.Strings[3];
DSize:=strtoint(slist.Strings[4]);
REQ:=pos(',REQ',Line)<>0;
RO:=pos(',RO',Line)<>0;
INV:=pos(',INV',Line)<>0;
i:=slist.Count;
DExpr:='';
if i>6 then
begin
DExpr:=slist.Strings[i-1];
dec(i);
end;
if i>5 then
KName:=slist.Strings[i-1]
else
KName:=FieldKindNames[0]; // fkData.
// Find fieldtype from fieldtypename.
for i:=0 to ord(High(FieldTypeNames)) do
if FieldTypeNames[TFieldType(i)]=TName then break;
FT:=TFieldType(i);
if not (FT in kbmSupportedFieldTypes) then
raise EMemTableError.Create(Format(kbmUnknownFieldErr1+kbmUnknownFieldErr2,[TName,Word]));
// Check if autoinc field in stream, use data from stream.
if FT=ftAutoInc then
SetIgnoreAutoIncPopulation(ADataset,true);
// If fieldkind specified, find fieldkind.
FK:=fkData;
for i:=0 to ord(High(FieldKindNames)) do
if FieldKindNames[i]=KName then
begin
FK:=TFieldKind(i);
break;
end;
// Add field definition.
FieldDefs.Add(FName,FT,FSize,REQ);
// Setup other properties.
i:=FieldDefs.IndexOf(FName);
with FieldDefs.Items[i].CreateField(ADataset) do
begin
FieldKind:=FK;
DisplayLabel:=DName;
EditMask:=EMask;
ReadOnly:=RO;
DisplayWidth:=DSize;
{$IFDEF LEVEL4}
DefaultExpression:=DExpr;
{$ENDIF}
Visible:=not INV;
end;
end;
end;
finally
slist.free;
end;
end;
FDefLoaded:=true;
end;
procedure TkbmCustomCSVStreamFormat.LoadData(ADataset:TkbmCustomMemTable);
var
i,j:integer;
nf:integer;
null:boolean;
s:string;
Accept:boolean;
LoadLine:boolean;
begin
if (StreamSize = 0) then exit;
if not (sfLoadData in sfData) then exit;
// Check if data line already loaded.
LoadLine:=not (sfLoadNoHeader in sfNoHeader);
lptr:=PChar(Line); // Make sure word pointer is at start of line.
with TkbmProtCustomMemTable(ADataSet) do
begin
ResetAutoInc;
// Read all lines in CSV format.
FLoadCount:=0;
FLoadedCompletely:=true;
while true do
begin
if (FLoadLimit>0) and (FLoadCount>=FLoadLimit) then
begin
FLoadedCompletely:=false;
break;
end;
if LoadLine then GetLine;
LoadLine:=true;
if Line='' then break;
append;
i:=0;
{$IFDEF LEVEL4}
nf:=length(LoadFields);
{$ELSE}
nf:=LoadFieldsCount;
{$ENDIF}
while (lptr<elptr) and (i<nf) do
begin
j:=LoadFields[i];
s:=GetWord(null);
if j>=0 then
begin
if not (sfLoadFieldKind in sfFieldKind) then
begin
if Fields[j].FieldKind<>fkData then
begin
inc(i);
continue;
end;
end;
if assigned(FOnFormatLoadField) then
FOnFormatLoadField(self,Fields[j],null,s);
if null then
Fields[j].Clear
else if Fields[j].DataType in kbmStringTypes then
Fields[j].AsString:=CodedStringToString(s)
else if Fields[j].DataType in kbmBinaryTypes then
Fields[j].AsString:=Base64ToString(s)
else if Fields[j].DataType = ftBoolean then
with TBooleanField(Fields[j]) do
begin
if s=FCSVTrueString then
Value:=true
else
Value:=false;
end
else
Fields[j].AsString:=s;
if Assigned(OnLoadField) then OnLoadField(ADataSet,j,Fields[j]);
end;
inc(i);
end;
Accept:=true;
if Assigned(OnLoadRecord) then OnLoadRecord(ADataset,Accept);
if Accept then
begin
Post;
inc(FLoadCount);
end
else
Cancel;
end;
end;
end;
// -----------------------------------------------------------------------------------
// Registration for Delphi 3 / C++ Builder 3
// -----------------------------------------------------------------------------------
{$ifdef LEVEL3}
procedure Register;
begin
RegisterComponents('kbmMemTable', [TkbmCSVStreamFormat]);
end;
{$endif}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -