MyBaseを試してみる。(インデックスを使わずに、行の追加、挿入、削除編) REVENGE(^o^)
前回、MyBaseを試してみる。(インデックスを使わずに、行の追加、挿入、削除編)
の処理では、フィルターが使えなかったのですが、次の処理をフィルター前、挿入処理前に入れることにより、フィルターも可能になりました。でも、全く論理的ではない処理のため、使っている間に不具合が出るかも知れませんけどね(^-^)
前回の処理では、一度レコードを挿入してから、フィルター処理・解除をすると、それ以降挿入したレコードは、最後に追加されてしまいました。例えスクリーン上で、正しく表示されていたとしても、正しくファイルに書き込むことができませんでした。今回の処理では、二度目以降のフィルター処理後も正しく表示されています。FilterプロパティでもOnFilterRecordでも問題ないようです。
とりあえずレコードを挿入します。
フィルター処理します。
フィルターを解除して、再びレコードを挿入します。
フィルター処理します。
フィルターを解除しても、レコードの並びは保持されています。(^o^)/
// 挿入時、レコード位置を保持するための処理 procedure cdsUpdate(CDS: TClientDataSet); var I: Integer; Data: OleVariant; begin SaveUndoPoint(CDS); I := CDS.RecNo; Data := CDS.Data; CDS.Data := Data; CDS.RecNo := I; end;
前回の処理では、一度レコードを挿入してから、フィルター処理・解除をすると、それ以降挿入したレコードは、最後に追加されてしまいました。例えスクリーン上で、正しく表示されていたとしても、正しくファイルに書き込むことができませんでした。今回の処理では、二度目以降のフィルター処理後も正しく表示されています。FilterプロパティでもOnFilterRecordでも問題ないようです。
とりあえずレコードを挿入します。
フィルター処理します。
フィルターを解除して、再びレコードを挿入します。
フィルター処理します。
フィルターを解除しても、レコードの並びは保持されています。(^o^)/
var RecNoList: TList<Integer> // Undoに使用 SP: Integer = -1; // Undoの処理に使用 SN: Integer = 0; // サンプルデータ procedure MakeSample(DataSet: TDataSet); var F: Boolean; begin F := DataSet.Active; if not F then DataSet.Open; try // サンプルデータの追加 with DataSet do begin Appendrecord(['iPod Touch']); Appendrecord(['Zaurus C-860']); Appendrecord(['Delphi 2009 Handbook']); Appendrecord(['GEORGIA BLACK']); CheckBrowseMode; end; finally if not F then DataSet.Close; end; end; // データベースの作成 procedure CreateDB(CDS: TClientDataSet; UsingIndex: Boolean); var I: Integer; begin CDS.Close; CDS.FieldDefs.Add('ITEM',ftWideString,20); CDS.CreateDataSet; CDS.Close; for I := 0 to CDS.FieldDefs.Count - 1 do CDS.FieldDefs[I].CreateField(CDS); CDS.Open; MakeSample(CDS); end; // DataSetの有効/無効 procedure DataSetEnabled(DataSet: TDataSet; Value: Boolean); begin if Value then DataSet.EnableControls else DataSet.DisableControls; end; // SaveToFile procedure cdsSaveToFile(CDS: TClientDataSet; const FileName: String); begin if CDS.ChangeCount > 0 then CDS.MergeChangeLog; CDS.SaveToFile(FileName, dfXMLUTF8); end; // LoadFromFile procedure cdsLoadFromFile(CDS: TClientDataSet; const FileName: String); begin CDS.LoadFromFile(FileName); end; // 通し番号を返します。別に要らない処理です。 function GetSN: String; begin Inc(SN); Result := IntToStr(SN); end; // 現在の状態を保存 procedure SaveUndoPoint(CDS: TClientDataSet); begin // 変更があれば更新させます。 if CDS.ChangeCount > 0 then CDS.MergeChangeLog; SP := (CDS as TClientDataSet).SavePoint; end; // SavePointから元に戻す処理 procedure Undo(CDS: TClientDataSet); begin if SP > -1 then CDS.SavePoint := SP; SP := -1; end; // 削除されたレコードを元に戻す処理 ※コテコテ(^-^) procedure UndoDelete(CDS: TClientDataSet); var I, RC, RecNo: Integer; Delta: TClientDataSet; begin if (RecNoList.Count <> 0) and (CDS.ChangeCount > 0) then begin Delta := TClientDataSet.Create(nil); try Delta.Data := CDS.Delta; Delta.Open; Delta.Last; I := -1; RC := CDS.RecordCount; // Insertで戻す場合、最後に追加されることをあるため、この処理を行う。 cdsUpdate(CDS); //20110922 追記 procedure cdsUpdateを前に持ってきてね。 // Deltaから順番に戻していきます。 while not Delta.Bof do begin Inc(I); if I < RecNoList.Count then begin RecNo := RecNoList[I]; if RecNo > RC then begin CDS.Append; Inc(RC); end else begin CDS.RecNo := RecNo; CDS.Insert; Inc(RC); end; CDS.FieldByName('Item').AsString := Delta.FieldByName('Item').AsString; end; Delta.Prior; end; CDS.CheckBrowseMode; CDS.MergeChangeLog; RecNoList.Clear; finally Delta.Free; end; end; end; // Undo procedure cdsUndoNoIndex(CDS: TClientDataSet); begin if RecNoList.Count > 0 then UndoDelete(CDS) // 削除 else if (SP > -1) then Undo(CDS) // 追加/挿入-SavePoint else if CDS.ChangeCount > 0 then CDS.UndoLastChange(True); // 上記以外 end; // 追加 procedure cdsAppendNoIndex(CDS: TClientDataSet; Count: Integer = 1); var I: Integer; begin SaveUndoPoint(CDS); DataSetEnabled(CDS, False); try // Count分空白行を追加します。 for I := 0 to Count - 1 do begin // 追加します。 CDS.Append; CDS.FieldByName('ITEM').AsString := '追加'+ GetSN; end; CDS.CheckBrowseMode; // 今回追加した空白行の先頭レコードに移動させます。 CDS.MoveBy(1-Count); finally DataSetEnabled(CDS, True); end; end; // 挿入時、レコード位置を保持するための処理 procedure cdsUpdate(CDS: TClientDataSet); var I: Integer; Data: OleVariant; begin SaveUndoPoint(CDS); I := CDS.RecNo; Data := CDS.Data; CDS.Data := Data; CDS.RecNo := I; end; // 挿入 procedure cdsInsertNoIndex(CDS: TClientDataSet; Count: Integer = 1); var I: Integer; Data: OleVariant; begin DataSetEnabled(CDS, False); try cdsUpdate(CDS); for I := 0 to Count -1 do begin // 挿入します。 CDS.Insert; CDS.FieldByName('ITEM').AsString := '挿入'+ GetSN; end; CDS.CheckBrowseMode; finally DataSetEnabled(CDS, True); end; end; // 削除 procedure cdsDeleteNoIndex(CDS: TClientDataSet; BMList: TBookmarkList = nil); type TIntegerComparer = TComparer<Integer>; var I: Integer; begin if not Assigned(BMList) then Exit; RecNoList.Clear; SaveUndoPoint(CDS); DataSetEnabled(CDS, False); try if Assigned(BMList) and (BMList.Count > 0) then begin for I := BMList.Count -1 downto 0 do begin CDS.GotoBookmark(BMList[I]); RecNoList.Add(CDS.RecNo); CDS.Delete; end; BMList.Clear; end; // RecNoListのソート RecNoList.Sort(TComparer<Integer>.Default); finally DataSetEnabled(CDS, True); end; end; // Filter procedure cdsFiltered(CDS: TClientDataSet); begin cdsUpdate(CDS); CDS.Filtered := not CDS.Filtered; end; // OnFilterRecord - ClientDataSet1で作成しておきます。 procedure TForm1.ClientDataSet1FilterRecord(DataSet: TDataSet; var Accept: Boolean); begin Accept := AnsiPos(Edit2.Text, DataSet.FieldByName('ITEM').AsString) > 0; end; procedure TForm1.FormCreate(Sender: TObject); begin // Undo用 RecNoList:= TList<Integer>.Create; // データベースの作成 CreateDB(ClientDataSet1, False); end; procedure TForm1.FormDestroy(Sender: TObject); begin FreeAndNil(RecNoList); end; // SaveToFile procedure TForm1.SpeedButton1Click(Sender: TObject); var FileName: String; begin FileName := ExtractFilePath(Application.ExeName) + 'MyBase.cds'; cdsSaveToFile(ClientDataSet1,FileName); end; // LoadFromFile procedure TForm1.SpeedButton2Click(Sender: TObject); var FileName: String; begin FileName := ExtractFilePath(Application.ExeName) + 'MyBase.cds'; if FileExists(FileName) then cdsLoadFromFile(ClientDataSet1, FileName); end; // 追加 procedure TForm1.SpeedButton3Click(Sender: TObject); begin cdsAppendNoIndex(ClientDataSet1, StrToIntDef(Edit1.Text,1)); end; // 挿入 procedure TForm1.SpeedButton4Click(Sender: TObject); begin cdsInsertNoIndex(ClientDataSet1, StrToIntDef(Edit1.Text,1)); end; // 削除 procedure TForm1.SpeedButton5Click(Sender: TObject); begin cdsDeleteNoIndex(ClientDataSet1, DBGrid1.SelectedRows); end; // Undo procedure TForm1.SpeedButton6Click(Sender: TObject); begin cdsUndoNoIndex(ClientDataSet1); end; // Filter procedure TForm1.SpeedButton7Click(Sender: TObject); begin cdsUpdate(ClientDataset1); if not ClientDataset1.Filtered then begin case RadioGroup1.ItemIndex of 0: begin ClientDataset1.Filter := ''; ClientDataSet1.OnFilterRecord := ClientDataSet1FilterRecord; end; 1 : begin ClientDataSet1.OnFilterRecord := nil; ClientDataset1.filter := 'ITEM LIKE '+QuotedStr('%' + Edit2.Text+'%'); end; end; end; cdsFiltered(ClientDataSet1); end;
| 固定リンク