⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbmmemcsvstreamformat.pas

📁 kbmMemTable v5.50 (Dec. 12 2005)内存表控件
💻 PAS
📖 第 1 页 / 共 4 页
字号:
               end;
	             Result[I]:=Char(Act and 63+32);
          end;
	        Result[Len]:=Char(Act shr 6+32);
     end
     else
        Result:='';
end;

// Decode BASE64 string.
function Base64ToString(const Source:string): string;
var
   Act: Word;
   Bits,I,P,Len: Integer;
begin
     Len:=(Length(Source)*3) div 4;
     SetLength(Result,Len);
     Bits:=0;
     Act:=0;
     P:=1;
{$IFDEF DOTNET}
     for I:=1 to Length(Source) do
     begin
          Act:=Act or (Ord(Source[I])-32) shl Bits;
	        if Bits>=2 then
          begin
	             Result[P]:=Char(Act and $FF);
	             Inc(P);
	             Act:=Act shr 8;
	             Dec(Bits,2);
          end
          else
	            Inc(Bits,6);
     end;
{$ELSE}
     for I:=1 to system.Length(Source) do
     begin
          Act:=Act or (Ord(Source[I])-32) shl Bits;
	        if Bits>=2 then
          begin
	             Result[P]:=Char(Act and $FF);
	             Inc(P);
	             Act:=Act shr 8;
	             Dec(Bits,2);
          end
          else
	            Inc(Bits,6);
     end;
{$ENDIF}
end;

// Quote a string.
function QuoteString(const Source:string; Quote:char):string;
begin
     if Quote=#0 then Result:=Source
{$IFDEF DOTNET}
     else Result:=QuotedStr(Source,Quote);
{$ELSE}
     else Result:=AnsiQuotedStr(Source,Quote);
{$ENDIF}
end;

// Extract a quoted string.
function ExtractQuoteString(const Source:string; Quote:char):string;
{$IFDEF DOTNET}
var
   p:IntPtr;
   i,l,lq:integer;
begin
     p:=Marshal.StringToHGlobalAnsi(Source);
     try
       if Quote=#0 then
          Result:=Source
       else
       begin
          Result := '';
          if Source.Chars[0] <> quote then exit;
          l:= Source.Length;
          lq:=0;
          for i:=l-1 downto 0 do
          begin
               if Source.Chars[i]=quote then
               begin
                    lq:=i;
                    break;
               end;
          end;
          if lq = 0 then lq:=l-1;

          i:=0;

          while i<lq do
          begin
               if Marshal.ReadByte(p,i)<>Byte(Quote) then
               begin
                    result:=result+char(Marshal.ReadByte(p,i));
               end else
               begin
                    inc(i);
                    if i>=lq then break;
                    result:=result+char(Marshal.ReadByte(p,i));
               end;
               inc(i);
          end;
       end;
    finally
       Marshal.FreeHGlobal(p);
    end;
end;
{$ELSE}

var
   p:PChar;
begin
     p:=PChar(Source);
     if Quote=#0 then Result:=Source
     else Result:=AnsiExtractQuotedStr(p,Quote);
end;
{$ENDIF}

// TKbmCustomCSVStreamFormat
//*******************************************************************

constructor TkbmCustomCSVStreamFormat.Create(AOwner:TComponent);
begin
     inherited;
     FCSVQuote:='"';
     FCSVFieldDelimiter:=',';
     FCSVRecordDelimiter:=',';
     FCSVTrueString:='True';
     FCSVFalseString:='False';
     FsfLocalFormat:=[];
     FsfPlaceHolders:=[];
end;

function TkbmCustomCSVStreamFormat.GetVersion:string;
begin
     Result:='3.00';
end;

procedure TkbmCUstomCSVStreamFormat.Assign(Source:TPersistent);
begin
     if Source is TkbmCustomCSVStreamFormat then
     begin
          CSVQuote:=TkbmCustomCSVStreamFormat(Source).CSVQuote;
          CSVFieldDelimiter:=TkbmCustomCSVStreamFormat(Source).CSVFieldDelimiter;
          CSVRecordDelimiter:=TkbmCustomCSVStreamFormat(Source).CSVRecordDelimiter;
          CSVTrueString:=TkbmCustomCSVStreamFormat(Source).CSVTrueString;
          CSVFalseString:=TkbmCustomCSVStreamFormat(Source).CSVFalseString;
          sfLocalFormat:=TkbmCustomCSVStreamFormat(Source).sfLocalFormat;
          sfPlaceHolders:=TkbmCustomCSVStreamFormat(Source).sfPlaceHolders;
     end;
     inherited;
end;

procedure TkbmCustomCSVStreamFormat.SetCSVFieldDelimiter(Value:char);
begin
     if Value<>#0 then FCSVFieldDelimiter:=Value;
end;

procedure TkbmCustomCSVStreamFormat.BeforeSave(ADataset:TkbmCustomMemTable);
begin
     // Check if trying to save deltas in CSV format. Not supported.
     if sfSaveDeltas in sfDeltas then
        raise EMemTableError.Create(kbmSavingDeltasBinary);

     inherited;

     // Setup standard layout for data.
     Ods:=DateSeparator;
     Oms:=DecimalSeparator;
     Ots:=TimeSeparator;
     Oths:=ThousandSeparator;
     Ocf:=CurrencyFormat;
     Onf:=NegCurrFormat;
     Osdf:=ShortDateFormat;
     Ocs:=CurrencyString;

     if not (sfSaveLocalFormat in FsfLocalFormat) then
     begin
          DateSeparator:='/';
          TimeSeparator:=':';
          ThousandSeparator:=',';
          DecimalSeparator:='.';
          ShortDateFormat:='dd/mm/yyyy';
          CurrencyString:='';
          CurrencyFormat:=0;
          NegCurrFormat:=1;
     end;
end;

procedure TkbmCustomCSVStreamFormat.AfterSave(ADataset:TkbmCustomMemTable);
begin
     // Restore locale setup.
     DateSeparator:=Ods;
     DecimalSeparator:=Oms;
     TimeSeparator:=Ots;
     ThousandSeparator:=Oths;
     CurrencyFormat:=Ocf;
     NegCurrFormat:=Onf;
     ShortDateFormat:=Osdf;
     CurrencyString:=Ocs;

     inherited;
end;

procedure TkbmCustomCSVStreamFormat.SaveDef(ADataset:TkbmCustomMemTable);
var
   i,l:integer;
   nf:integer;
   s:string;
begin
     if not (sfSaveDef in sfDef) then exit;

     // Setup flags for fields to save.
     nf:=ADataSet.Fieldcount;

{$IFNDEF CSV_FILE_1XX_COMPATIBILITY}
     // Write file version.
 {$IFDEF DOTNET}
     s:=QuoteString(kbmFileVersionMagic,FCSVQuote)+FCSVFieldDelimiter+QuoteString(IntToStr(kbmCSVFileVersion),FCSVQuote)+#13+#10;
     l:=length(s);
     WorkStream.WriteBuffer (BytesOf(s), l);
 {$ELSE}
     s:=QuoteString(PChar(kbmFileVersionMagic),FCSVQuote)+FCSVFieldDelimiter+QuoteString(IntToStr(kbmCSVFileVersion),FCSVQuote)+#13+#10;
     l:=length(s);
     WorkStream.WriteBuffer(Pointer(s)^, l);
 {$ENDIF}
{$ENDIF}

     // Write header.
{$IFDEF DOTNET}
     s:=QuoteString(kbmTableDefMagicStart,FCSVQuote)+#13+#10;
     l:=length(s);
     WorkStream.WriteBuffer(bytesOf(s), l);
{$ELSE}
     s:=QuoteString(PChar(kbmTableDefMagicStart),FCSVQuote)+#13+#10;
     l:=length(s);
     WorkStream.WriteBuffer(Pointer(s)^, l);
{$ENDIF}

     // Write fielddefinitions.
     for i:=0 to nf-1 do
     begin
          if (SaveFields[i]>=0) or (sfSavePlaceHolders in sfPlaceHolders) then
          begin
               s:=ADataSet.Fields[i].FieldName+'='+
                   FieldTypeNames[ADataSet.Fields[i].DataType]+','+
                   inttostr(ADataSet.Fields[i].Size)+','+
                   QuoteString(ADataSet.Fields[i].DisplayName,'"')+','+
                   QuoteString(ADataSet.Fields[i].EditMask,'"')+','+
                   inttostr(ADataSet.Fields[i].DisplayWidth);
               if ADataSet.Fields[i].Required then s:=s+',REQ';
               if ADataSet.Fields[i].ReadOnly then s:=s+',RO';
               if not ADataSet.Fields[i].Visible then s:=s+',INV';
               if sfSaveFieldKind in sfFieldKind then
                  s:=s+','+FieldKindNames[ord(ADataSet.Fields[i].FieldKind)]
               else
                   s:=s+','+FieldKindNames[0];
{$IFDEF LEVEL4}
               s:=s+','+QuoteString(ADataSet.Fields[i].DefaultExpression,'"');
{$ENDIF}
{$IFDEF DOTNET}
               s:=QuoteString(s,FCSVQuote)+#13+#10;
               l:=length(s);
               WorkStream.WriteBuffer(bytesOF(s), l);
{$ELSE}
               s:=QuoteString(PChar(s),FCSVQuote)+#13+#10;
               l:=length(s);
               WorkStream.WriteBuffer(Pointer(s)^, l);
{$ENDIF}
          end;
     end;

{$IFNDEF CSV_FILE_1XX_COMPATIBILITY}
     // Check if to write index definitions.
     if sfSaveIndexDef in sfIndexDef then
     begin
          // Write header.
 {$IFDEF DOTNET}
          s:=QuoteString(kbmIndexDefMagicStart,FCSVQuote)+#13+#10;
          l:=length(s);
          WorkStream.WriteBuffer(bytesOf(s),l);
 {$ELSE}
          s:=QuoteString(PChar(kbmIndexDefMagicStart),FCSVQuote)+#13+#10;
          l:=length(s);
          WorkStream.WriteBuffer(Pointer(s)^, l);
 {$ENDIF}

          // Write indexdefinitions.
          for i:=0 to ADataSet.IndexDefs.count-1 do
              with ADataSet.IndexDefs.Items[i] do
              begin
                   s:=Name+'='+
                      QuoteString(Fields,FCSVQuote)+','+
 {$IFDEF LEVEL3}
                      Name;
 {$ELSE}
                      QuoteString(DisplayName,FCSVQuote);
 {$ENDIF}
                   if ixDescending in Options then s:=s+',DESC';
                   if ixCaseInsensitive in Options then s:=s+',CASE';
 {$IFNDEF LEVEL3}
                   if ixNonMaintained in Options then s:=s+',NONMT';
 {$ENDIF}
                   if ixUnique in Options then s:=s+',UNIQ';
 {$IFDEF DOTNET}
                   s:=QuoteString(s,FCSVQuote)+#13+#10;
                   l:=length(s);
                   WorkStream.WriteBuffer(bytesOf(s),l);
 {$ELSE}
                   s:=QuoteString(PChar(s),FCSVQuote)+#13+#10;
                   l:=length(s);
                   WorkStream.WriteBuffer(Pointer(s)^,l);
 {$ENDIF}
              end;

          // Write footer.
 {$IFDEF DOTNET}
          s:=QuoteString(kbmIndexDefMagicEnd,FCSVQuote)+#13+#10;
          l:=length(s);
          WorkStream.WriteBuffer(BytesOf(s),l);
 {$ELSE}
          s:=QuoteString(PChar(kbmIndexDefMagicEnd),FCSVQuote)+#13+#10;
          l:=length(s);
          WorkStream.WriteBuffer(Pointer(s)^,l);
 {$ENDIF}
     end;
{$ENDIF}

     // Write footer.
{$IFDEF DOTNET}
     s:=QuoteString(kbmTableDefMagicEnd,FCSVQuote)+#13+#10;
     l:=length(s);
     WorkStream.WriteBuffer(BytesOf(s), l);
{$ELSE}
     s:=QuoteString(PChar(kbmTableDefMagicEnd),FCSVQuote)+#13+#10;
     l:=length(s);
     WorkStream.WriteBuffer(Pointer(s)^, l);
{$ENDIF}
end;

procedure TkbmCustomCSVStreamFormat.SaveData(ADataset:TkbmCustomMemTable);
var
   i,j,l:integer;
   nf:integer;
   s,s1,a:string;
   Accept:boolean;
   null:boolean;
begin
     ADataSet.SaveCount := 0;

     // Setup flags for fields to save.
     nf:=ADataSet.Fieldcount;

     // Save header.
     if not (sfSaveNoHeader in sfNoHeader) then
     begin
          // Write all field display names in CSV format.
          s:='';
          a:='';
          for i:=0 to nf-1 do
          begin
               if (SaveFields[i]>=0) or (sfSavePlaceHolders in sfPlaceHolders) then
               begin

{$IFDEF DOTNET}
                    s:=s+a+QuoteString(ADataSet.Fields[i].DisplayName,FCSVQuote);
{$ELSE}
                    s:=s+a+QuoteString(PChar(ADataSet.Fields[i].DisplayName),FCSVQuote);
{$ENDIF}
                    a:=FCSVFieldDelimiter;
               end;
          end;
          if FCSVRecordDelimiter <> #0 then s:=s+FCSVRecordDelimiter;
          s:=s+#13+#10;
          l:=length(s);
{$IFDEF DOTNET}
          WorkStream.Write(bytesOf(s), l);
{$ELSE}
          WorkStream.Write(Pointer(s)^, l);
{$ENDIF}

     end;

     // Write all records in CSV format ordered by current index.
     if sfSaveData in sfData then
     begin
          try
             ADataSet.SavedCompletely := True;

             for j:=0 to ADataSet.CurIndex.References.Count-1 do
             begin
                  // Check if to save more.
                  if (ADataSet.SaveLimit>0) and (ADataSet.SaveCount>=ADataSet.SaveLimit) then
                  begin
                       ADataSet.SavedCompletely:=false;
                       break;
                  end;

                  // Check if to invoke progress event if any.
                  if (j mod 100)=0 then ADataSet.Progress(trunc((j/ADataSet.CurIndex.References.count)*100),mtpcSave);

                  // Setup which record to work on.
                  ADataSet.OverrideActiveRecordBuffer:=PkbmRecord(ADataSet.CurIndex.References.Items[j]);
                  if ADataSet.OverrideActiveRecordBuffer=nil then continue;

                  // Calculate fields.
                  ADataSet.__ClearCalcFields({$IFNDEF DOTNET}PChar(ADataSet.OverrideActiveRecordBuffer){$ELSE}ADataSet.OverrideActiveRecordBuffer{$ENDIF});
                  ADataSet.__GetCalcFields({$IFNDEF DOTNET}PChar(ADataSet.OverrideActiveRecordBuffer){$ELSE}ADataSet.OverrideActiveRecordBuffer{$ENDIF});

                  // Check filter of record.
                  Accept:=ADataSet.FilterRecord(ADataSet.OverrideActiveRecordBuffer,false);
                  if not Accept then continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -