Marco Web Center

[an error occurred while processing this directive]

Home: Code Repository: Mastering Delphi 6

Chapter 14 - Project CdsDelta

Project Structure

CdsDelta.dpr
program CdsDelta;

uses
  Forms,
  CdsDeltaForm in 'CdsDeltaForm.pas' {FormCds},
  CdsDeltaDm in 'CdsDeltaDm.pas' {DmCds: TDataModule},
  Reconc in 'Reconc.pas' {ReconcileErrorForm};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TDmCds, DmCds);
  Application.CreateForm(TFormCds, FormCds);
  Application.Run;
end.
CdsDeltaForm.pas
unit CdsDeltaForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Db, DBClient, Grids, DBGrids, StdCtrls, ExtCtrls, ComCtrls, MConnect,
  MidasCon;

type
  TFormCds = class(TForm)
    DataSource1: TDataSource;
    Panel1: TPanel;
    ButtonUpdate: TButton;
    ButtonDelta: TButton;
    ButtonUndo: TButton;
    PageControl1: TPageControl;
    TabSheetData: TTabSheet;
    TabSheetDelta: TTabSheet;
    DBGrid2: TDBGrid;
    DataSource2: TDataSource;
    DBGrid1: TDBGrid;
    procedure ButtonUpdateClick(Sender: TObject);
    procedure ButtonDeltaClick(Sender: TObject);
    procedure ButtonUndoClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormCds: TFormCds;

implementation

{$R *.DFM}

uses
  TypInfo, Reconc, CdsDeltaDm;

procedure TFormCds.ButtonUpdateClick(Sender: TObject);
begin
  DmCds.cdsEmployee.ApplyUpdates (-1);
  // activate data and hide delta
  PageControl1.ActivePage := TabSheetData;
  TabSheetDelta.TabVisible := False;
end;

procedure TFormCds.ButtonDeltaClick(Sender: TObject);
begin
  if DmCds.cdsEmployee.ChangeCount > 0 then
  begin
    DmCds.cdsDelta.Data := DmCds.cdsEmployee.Delta;
    DmCds.cdsDelta.Open;
    // activate delta
    TabSheetDelta.TabVisible := True;
    PageControl1.ActivePage := TabSheetDelta;
  end
  else
  begin
    TabSheetDelta.TabVisible := False;
    ShowMessage ('No udpates in log');
  end;
end;

procedure TFormCds.ButtonUndoClick(Sender: TObject);
begin
  DmCds.cdsEmployee.UndoLastChange (True);
end;

procedure TFormCds.FormCreate(Sender: TObject);
begin
  DmCds.cdsEmployee.Open;
  TabSheetDelta.TabVisible := False;
end;

procedure TFormCds.PageControl1Change(Sender: TObject);
begin
  if PageControl1.ActivePage = TabSheetDelta then
    if DmCds.cdsEmployee.ChangeCount > 0 then
      DmCds.cdsDelta.Data := DmCds.cdsEmployee.Delta
    else
    begin
      TabSheetDelta.TabVisible := False;
      PageControl1.ActivePage := TabSheetData;
    end;
end;

end.
CdsDeltaDm.pas
unit CdsDeltaDm;

interface

uses
  SysUtils, Classes, FMTBcd, DBXpress, DB, SqlExpr, DBClient, Provider;

type
  TDmCds = class(TDataModule)
    cdsEmployee: TClientDataSet;
    cdsDelta: TClientDataSet;
    SQLConnection: TSQLConnection;
    EmplData: TSQLDataSet;
    EmplProvider: TDataSetProvider;
    cdsDeltaStatus: TStringField;
    cdsEmployeeStatus: TStringField;
    cdsEmployeeDEPT_NO: TStringField;
    cdsEmployeeEMP_NO: TSmallintField;
    cdsEmployeeFIRST_NAME: TStringField;
    cdsEmployeeLAST_NAME: TStringField;
    cdsEmployeeSALARY: TBCDField;
    cdsEmployeePHONE_EXT: TStringField;
    cdsDeltaDEPT_NO: TStringField;
    cdsDeltaEMP_NO: TSmallintField;
    cdsDeltaFIRST_NAME: TStringField;
    cdsDeltaLAST_NAME: TStringField;
    cdsDeltaSALARY: TBCDField;
    cdsDeltaPHONE_EXT: TStringField;
    procedure CalcStatusField(DataSet: TDataSet);
    procedure cdsEmployeeReconcileError(DataSet: TCustomClientDataSet;
      E: EReconcileError; UpdateKind: TUpdateKind;
      var Action: TReconcileAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DmCds: TDmCds;

implementation

{$R *.dfm}

uses
  TypInfo, Reconc;

procedure TDmCds.CalcStatusField(DataSet: TDataSet);
begin
  DataSet.FieldByName('Status').AsString :=
    GetEnumName (TypeInfo(TUpdateStatus),
      Integer ((DataSet as TClientDataSet).UpdateStatus));
end;

procedure TDmCds.cdsEmployeeReconcileError(
  DataSet: TCustomClientDataSet; E: EReconcileError;
  UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin
  Action := HandleReconcileError(DataSet, UpdateKind, E);
end;

end.
Reconc.pas

{*******************************************************}
{                                                       }
{       Delphi Visual Component Library                 }
{       ClientDataSet Standard Reconcile Error Dialog   }
{                                                       }
{       Copyright (c) 1998 Borland International        }
{                                                       }
{*******************************************************}

{ Note: To use this dialog you should add a call to HandleReconcileError in
  the OnReconcileError event handler of TClientDataSet (see the Client dataset
  demos for an example).  Also, after adding this unit to your project you must
  go into the Project Options dialog and remove this form from the list of
  Auto-created forms or an error will occur when compiling. }

unit Reconc;

interface

uses
  SysUtils, Windows, Variants, Messages, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DB, DBClient, Provider, ExtCtrls;

const
  ActionStr: array[TReconcileAction] of string = ('Skip', 'Abort', 'Merge',
    'Correct', 'Cancel', 'Refresh');
  UpdateKindStr: array[TUpdateKind] of string = ('Modified', 'Inserted',
    'Deleted');
  SCaption = 'Update Error - %s';
  SUnchanged = '<Unchanged>';
  SBinary = '(Binary)';
  SFieldName = 'Field Name';
  SOriginal = 'Original Value';
  SConflict = 'Conflicting Value';
  SValue = ' Value';
  SNoData = '<No Records>';
  SNew = 'New';

type
  TReconcileErrorForm = class(TForm)
    UpdateType: TLabel;
    UpdateData: TStringGrid;
    ActionGroup: TRadioGroup;
    CancelBtn: TButton;
    OKBtn: TButton;
    ConflictsOnly: TCheckBox;
    IconImage: TImage;
    ErrorMsg: TMemo;
    ChangedOnly: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure UpdateDataSetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: string);
    procedure DisplayFieldValues(Sender: TObject);
    procedure UpdateDataSelectCell(Sender: TObject; Col, Row: Integer;
      var CanSelect: Boolean);
  private
    FDataSet: TDataSet;
    FError: EReconcileError;
    FUpdateKind: TUpdateKind;
    FDataFields: TList;
    FCurColIdx: Integer;
    FNewColIdx: Integer;
    FOldColIdx: Integer;
    procedure AdjustColumnWidths;
    procedure InitDataFields;
    procedure InitUpdateData(HasCurValues: Boolean);
    procedure InitReconcileActions;
    procedure SetFieldValues(DataSet: TDataSet);
  public
    constructor CreateForm(DataSet: TDataSet; UpdateKind: TUpdateKind;
      Error: EReconcileError);
  end;

function HandleReconcileError(DataSet: TDataSet;  UpdateKind: TUpdateKind;
  ReconcileError: EReconcileError): TReconcileAction;

implementation

{$R *.dfm}

type
  PFieldData = ^TFieldData;
  TFieldData = record
    Field: TField;
    NewValue: string;
    OldValue: string;
    CurValue: string;
    EditValue: string;
    Edited: Boolean;
  end;

{ Public and Private Methods }

function HandleReconcileError(DataSet: TDataSet; UpdateKind: TUpdateKind;
  ReconcileError: EReconcileError): TReconcileAction;
var
  UpdateForm: TReconcileErrorForm;
begin
  UpdateForm := TReconcileErrorForm.CreateForm(DataSet, UpdateKind, ReconcileError);
  with UpdateForm do
  try
    if ShowModal = mrOK then
    begin
      Result := TReconcileAction(ActionGroup.Items.Objects[ActionGroup.ItemIndex]);
      if Result = raCorrect then SetFieldValues(DataSet);
    end else
      Result := raAbort;
  finally
    Free;
  end;
end;

{ Routine to convert a variant value into a string.
  Handles binary fields types and "empty" (Unchanged) field values specially }

function VarToString(V: Variant; DataType: TFieldType): string;
const
  BinaryDataTypes: set of TFieldType = [ftBytes, ftVarBytes, ftBlob,
    ftGraphic..ftCursor];
begin
  try
    if VarIsClear(V) then
      Result := SUnchanged
    else if DataType in BinaryDataTypes then
      Result := SBinary
    else
      Result := VarToStr(V);
  except
    on E: Exception do
      Result := E.Message;
  end;
end;

{ TReconcileErrorForm }

constructor TReconcileErrorForm.CreateForm(DataSet: TDataSet;
  UpdateKind: TUpdateKind; Error: EReconcileError);
begin
  FDataSet := DataSet;
  FUpdateKind := UpdateKind;
  FError := Error;
  inherited Create(Application);
end;

{ Create a list of the data fields in the dataset, and store string values
  associated with NewValue, OldValue, and CurValue in string variables
  to make display switching faster }

procedure TReconcileErrorForm.InitDataFields;
var
  I: Integer;
  FD: PFieldData;
  V: Variant;
  HasCurValues: Boolean;
begin
  HasCurValues := False;
  for I := 0 to FDataSet.FieldCount - 1 do
  with FDataset.Fields[I] do
  begin
    if (FieldKind <> fkData) then Continue;
    FD := New(PFieldData);
    try
      FD.Field := FDataset.Fields[I];
      FD.Edited := False;
      if FUpdateKind <> ukDelete then
        FD.NewValue := VarToString(NewValue, DataType);
      V := CurValue;
      if not VarIsClear(V) then HasCurValues := True;
      FD.CurValue := VarToString(CurValue, DataType);
      if FUpdateKind <> ukInsert then
        FD.OldValue := VarToString(OldValue, DataType);
      FDataFields.Add(FD);
    except
      Dispose(FD);
      raise;
    end;
  end;
  InitUpdateData(HasCurValues);
end;

{ Initialize the column indexes and grid titles }

procedure TReconcileErrorForm.InitUpdateData(HasCurValues: Boolean);
var
  FColCount: Integer;
begin
  FColCount := 1;
  UpdateData.ColCount := 4;
  UpdateData.Cells[0,0] := SFieldName;
  if FUpdateKind <> ukDelete then
  begin
    FNewColIdx := FColCount;
    Inc(FColCount);
    UpdateData.Cells[FNewColIdx,0] := UpdateKindStr[FUpdateKind] + SValue;
  end else
  begin
    FOldColIdx := FColCount;
    Inc(FColCount);
    UpdateData.Cells[FOldColIdx,0] := SOriginal;
  end;
  if HasCurValues then
  begin
    FCurColIdx := FColCount;
    Inc(FColCount);
    UpdateData.Cells[FCurColIdx,0] := SConflict;
  end;
  if FUpdateKind = ukModify then
  begin
    FOldColIdx := FColCount;
    Inc(FColCount);
    UpdateData.Cells[FOldColIdx,0] := SOriginal;
  end;
  UpdateData.ColCount := FColCount;
end;

{ Update the reconcile action radio group based on the valid reconcile actions }

procedure TReconcileErrorForm.InitReconcileActions;

  procedure AddAction(Action: TReconcileAction);
  begin
    ActionGroup.Items.AddObject(ActionStr[Action], TObject(Action));
  end;

begin
  AddAction(raSkip);
  AddAction(raCancel);
  AddAction(raCorrect);
  if FCurColIdx > 0 then
  begin
    AddAction(raRefresh);
    AddAction(raMerge);
  end;
  ActionGroup.ItemIndex := 0;
end;

{ Update the grid based on the current display options }

procedure TReconcileErrorForm.DisplayFieldValues(Sender: TObject);
var
  I: Integer;
  CurRow: Integer;
  Action: TReconcileAction;
begin
  if not Visible then Exit;
  Action := TReconcileAction(ActionGroup.Items.Objects[ActionGroup.ItemIndex]);
  UpdateData.Col := 1;
  UpdateData.Row := 1;
  CurRow := 1;
  UpdateData.RowCount := 2;
  UpdateData.Cells[0, CurRow] := SNoData;
  for I := 1 to UpdateData.ColCount - 1 do
    UpdateData.Cells[I, CurRow] := '';
  for I := 0 to FDataFields.Count - 1 do
    with PFieldData(FDataFields[I])^ do
    begin
      if ConflictsOnly.Checked and (CurValue = SUnChanged) then Continue;
      if ChangedOnly.Checked and (NewValue = SUnChanged) then Continue;
      UpdateData.RowCount := CurRow + 1;
      UpdateData.Cells[0, CurRow] := Field.DisplayName;
      if FNewColIdx > 0 then
      begin
        case Action of
          raCancel, raRefresh:
            UpdateData.Cells[FNewColIdx, CurRow] := SUnChanged;
          raCorrect:
            if Edited then
              UpdateData.Cells[FNewColIdx, CurRow] := EditValue else
              UpdateData.Cells[FNewColIdx, CurRow] := NewValue;
          else
            UpdateData.Cells[FNewColIdx, CurRow] := NewValue;
        end;
        UpdateData.Objects[FNewColIdx, CurRow] := FDataFields[I];
      end;
      if FCurColIdx > 0 then
        UpdateData.Cells[FCurColIdx, CurRow] := CurValue;
      if FOldColIdx > 0 then
        if (Action in [raMerge, raRefresh]) and (CurValue <> SUnchanged) then
           UpdateData.Cells[FOldColIdx, CurRow] := CurValue else
           UpdateData.Cells[FOldColIdx, CurRow] := OldValue;
      Inc(CurRow);
    end;
  AdjustColumnWidths;
end;

{ For fields that the user has edited, copy the changes back into the
  NewValue property of the associated field }

procedure TReconcileErrorForm.SetFieldValues(DataSet: TDataSet);
var
  I: Integer;
begin
  for I := 0 to FDataFields.Count - 1 do
    with PFieldData(FDataFields[I])^ do
      if Edited then Field.NewValue := EditValue;
end;

procedure TReconcileErrorForm.AdjustColumnWidths;
var
  NewWidth, I: integer;
begin
  with UpdateData do
  begin
    NewWidth := (ClientWidth - ColWidths[0]) div (ColCount - 1);
    for I := 1 to ColCount - 1 do
      ColWidths[I] := NewWidth - 1;
  end;
end;

{ Event handlers }

procedure TReconcileErrorForm.FormCreate(Sender: TObject);
begin
  if FDataSet = nil then Exit;
  FDataFields := TList.Create;
  InitDataFields;
  Caption := Format(SCaption, [FDataSet.Name]);
  UpdateType.Caption := UpdateKindStr[FUpdateKind];
  ErrorMsg.Text := FError.Message;
  if FError.Context <> '' then
    ErrorMsg.Lines.Add(FError.Context);
  ConflictsOnly.Enabled := FCurColIdx > 0;
  ConflictsOnly.Checked := ConflictsOnly.Enabled;
  ChangedOnly.Enabled := FNewColIdx > 0;
  InitReconcileActions;
  UpdateData.DefaultRowHeight := UpdateData.Canvas.TextHeight('SWgjp') + 7; { Do not localize }
end;

procedure TReconcileErrorForm.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  if Assigned(FDataFields) then
  begin
    for I := 0 to FDataFields.Count - 1 do
      Dispose(PFieldData(FDataFields[I]));
    FDataFields.Destroy;
  end;
end;

{ Set the Edited flag in the DataField list and save the value }

procedure TReconcileErrorForm.UpdateDataSetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: string);
begin
  PFieldData(UpdateData.Objects[ACol, ARow]).EditValue := Value;
  PFieldData(UpdateData.Objects[ACol, ARow]).Edited := True;
end;

{ Enable the editing in the grid if we are on the NewValue column and the
  current reconcile action is raCorrect }

procedure TReconcileErrorForm.UpdateDataSelectCell(Sender: TObject; Col,
  Row: Integer; var CanSelect: Boolean);
begin
  if (Col = FNewColIdx) and
    (TReconcileAction(ActionGroup.Items.Objects[ActionGroup.ItemIndex]) = raCorrect) then
    UpdateData.Options := UpdateData.Options + [goEditing] else
    UpdateData.Options := UpdateData.Options - [goEditing];
end;

end.
CdsDeltaForm.dfm
object FormCds: TFormCds
  Left = 207
  Top = 126
  Width = 514
  Height = 278
  Caption = 'Client 3 Tier'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 506
    Height = 41
    Align = alTop
    TabOrder = 0
    object ButtonUpdate: TButton
      Left = 8
      Top = 8
      Width = 75
      Height = 25
      Caption = 'Update'
      TabOrder = 0
      OnClick = ButtonUpdateClick
    end
    object ButtonDelta: TButton
      Left = 88
      Top = 8
      Width = 75
      Height = 25
      Caption = 'Show Delta'
      TabOrder = 1
      OnClick = ButtonDeltaClick
    end
    object ButtonUndo: TButton
      Left = 168
      Top = 8
      Width = 75
      Height = 25
      Caption = 'Undo'
      TabOrder = 2
      OnClick = ButtonUndoClick
    end
  end
  object PageControl1: TPageControl
    Left = 0
    Top = 41
    Width = 506
    Height = 210
    ActivePage = TabSheetData
    Align = alClient
    TabIndex = 0
    TabOrder = 1
    OnChange = PageControl1Change
    object TabSheetData: TTabSheet
      Caption = 'Data'
      object DBGrid1: TDBGrid
        Left = 0
        Top = 0
        Width = 498
        Height = 182
        Align = alClient
        DataSource = DataSource1
        TabOrder = 0
        TitleFont.Charset = DEFAULT_CHARSET
        TitleFont.Color = clWindowText
        TitleFont.Height = -11
        TitleFont.Name = 'MS Sans Serif'
        TitleFont.Style = []
      end
    end
    object TabSheetDelta: TTabSheet
      Caption = 'Delta'
      ImageIndex = 1
      object DBGrid2: TDBGrid
        Left = 0
        Top = 0
        Width = 498
        Height = 182
        Align = alClient
        DataSource = DataSource2
        TabOrder = 0
        TitleFont.Charset = DEFAULT_CHARSET
        TitleFont.Color = clWindowText
        TitleFont.Height = -11
        TitleFont.Name = 'MS Sans Serif'
        TitleFont.Style = []
      end
    end
  end
  object DataSource1: TDataSource
    DataSet = DmCds.cdsEmployee
    Left = 72
    Top = 184
  end
  object DataSource2: TDataSource
    AutoEdit = False
    DataSet = DmCds.cdsDelta
    Left = 144
    Top = 184
  end
end
CdsDeltaDm.dfm
object DmCds: TDmCds
  OldCreateOrder = False
  Left = 285
  Top = 428
  Height = 182
  Width = 510
  object cdsEmployee: TClientDataSet
    Aggregates = <>
    PacketRecords = 5
    Params = <>
    ProviderName = 'EmplProvider'
    OnCalcFields = CalcStatusField
    OnReconcileError = cdsEmployeeReconcileError
    Left = 64
    Top = 88
    object cdsEmployeeStatus: TStringField
      FieldKind = fkCalculated
      FieldName = 'Status'
      Calculated = True
    end
    object cdsEmployeeDEPT_NO: TStringField
      FieldName = 'DEPT_NO'
      Required = True
      FixedChar = True
      Size = 3
    end
    object cdsEmployeeEMP_NO: TSmallintField
      FieldName = 'EMP_NO'
      Required = True
    end
    object cdsEmployeeFIRST_NAME: TStringField
      FieldName = 'FIRST_NAME'
      Required = True
      Size = 15
    end
    object cdsEmployeeLAST_NAME: TStringField
      FieldName = 'LAST_NAME'
      Required = True
    end
    object cdsEmployeeSALARY: TBCDField
      FieldName = 'SALARY'
      Required = True
      Precision = 15
      Size = 2
    end
    object cdsEmployeePHONE_EXT: TStringField
      FieldName = 'PHONE_EXT'
      Size = 4
    end
  end
  object cdsDelta: TClientDataSet
    Aggregates = <>
    Params = <>
    ReadOnly = True
    OnCalcFields = CalcStatusField
    Left = 166
    Top = 87
    object cdsDeltaStatus: TStringField
      FieldKind = fkCalculated
      FieldName = 'Status'
      Calculated = True
    end
    object cdsDeltaDEPT_NO: TStringField
      FieldName = 'DEPT_NO'
      Required = True
      FixedChar = True
      Size = 3
    end
    object cdsDeltaEMP_NO: TSmallintField
      FieldName = 'EMP_NO'
      Required = True
    end
    object cdsDeltaFIRST_NAME: TStringField
      FieldName = 'FIRST_NAME'
      Required = True
      Size = 15
    end
    object cdsDeltaLAST_NAME: TStringField
      FieldName = 'LAST_NAME'
      Required = True
    end
    object cdsDeltaSALARY: TBCDField
      FieldName = 'SALARY'
      Required = True
      Precision = 15
      Size = 2
    end
    object cdsDeltaPHONE_EXT: TStringField
      FieldName = 'PHONE_EXT'
      Size = 4
    end
  end
  object SQLConnection: TSQLConnection
    Connected = True
    ConnectionName = 'IBLocal'
    DriverName = 'Interbase'
    GetDriverFunc = 'getSQLDriverINTERBASE'
    LibraryName = 'dbexpint.dll'
    LoginPrompt = False
    Params.Strings = (
      'BlobSize=-1'
      'CommitRetain=False'

              'Database=c:\program files\interbase corp\interbase6\examples\dat' +
        'abase\employee.gdb'
      'DriverName=Interbase'
      'LocaleCode=0x0000'
      'Password=masterkey'
      'RoleName=RoleName'
      'ServerCharSet=ASCII'
      'SQLDialect=1'
      'Interbase TransIsolation=ReadCommited'
      'User_Name=sysdba'
      'WaitOnLocks=True')
    VendorLib = 'GDS32.DLL'
    Left = 32
    Top = 16
  end
  object EmplData: TSQLDataSet
    SQLConnection = SQLConnection
    CommandText =
       'select DEPT_NO, EMP_NO, FIRST_NAME, LAST_NAME, SALARY, PHONE_EXT' +
      ' from EMPLOYEE'
    Params = <>
    Left = 112
    Top = 16
  end
  object EmplProvider: TDataSetProvider
    DataSet = EmplData
    Constraints = True
    Left = 192
    Top = 16
  end
end
Reconc.dfm
object ReconcileErrorForm: TReconcileErrorForm
  Left = 289
  Top = 225
  BorderStyle = bsDialog
  Caption = 'Update Error'
  ClientHeight = 311
  ClientWidth = 527
  Color = clBtnFace
  ParentFont = True
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  OnShow = DisplayFieldValues
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 57
    Top = 13
    Width = 65
    Height = 13
    Caption = 'Update Type:'
  end
  object UpdateType: TLabel
    Left = 134
    Top = 13
    Width = 49
    Height = 13
    Caption = 'Modified'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clBlack
    Font.Height = -11
    Font.Name = 'Default'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Label3: TLabel
    Left = 57
    Top = 33
    Width = 71
    Height = 13
    Caption = 'Error Message:'
  end
  object IconImage: TImage
    Left = 12
    Top = 12
    Width = 34
    Height = 34
    Picture.Data = {
      055449636F6E0000010002002020100000000000E80200002600000020200200
      00000000300100000E0300002800000020000000400000000100040000000000
      0002000000000000000000000000000000000000000000000000800000800000
      00808000800000008000800080800000C0C0C000808080000000FF0000FF0000
      00FFFF00FF000000FF00FF00FFFF0000FFFFFF00000008888888888888888888
      8888880000008888888888888888888888888880003000000000000000000000
      0008888803BBBBBBBBBBBBBBBBBBBBBBBB7088883BBBBBBBBBBBBBBBBBBBBBBB
      BBB708883BBBBBBBBBBBBBBBBBBBBBBBBBBB08883BBBBBBBBBBBB7007BBBBBBB
      BBBB08803BBBBBBBBBBBB0000BBBBBBBBBB7088003BBBBBBBBBBB0000BBBBBBB
      BBB0880003BBBBBBBBBBB7007BBBBBBBBB708800003BBBBBBBBBBBBBBBBBBBBB
      BB088000003BBBBBBBBBBB0BBBBBBBBBB70880000003BBBBBBBBB707BBBBBBBB
      B08800000003BBBBBBBBB303BBBBBBBB7088000000003BBBBBBBB000BBBBBBBB
      0880000000003BBBBBBB70007BBBBBB708800000000003BBBBBB30003BBBBBB0
      88000000000003BBBBBB00000BBBBB70880000000000003BBBBB00000BBBBB08
      800000000000003BBBBB00000BBBB7088000000000000003BBBB00000BBBB088
      0000000000000003BBBB00000BBB708800000000000000003BBB70007BBB0880
      00000000000000003BBBBBBBBBB70880000000000000000003BBBBBBBBB08800
      000000000000000003BBBBBBBB7088000000000000000000003BBBBBBB088000
      0000000000000000003BBBBBB708800000000000000000000003BBBBB0880000
      00000000000000000003BBBB70800000000000000000000000003BB700000000
      0000000000000000000003330000000000000000F8000003F0000001C0000000
      80000000000000000000000000000001000000018000000380000003C0000007
      C0000007E000000FE000000FF000001FF000001FF800003FF800003FFC00007F
      FC00007FFE0000FFFE0000FFFF0001FFFF0001FFFF8003FFFF8003FFFFC007FF
      FFC007FFFFE00FFFFFE01FFFFFF07FFFFFF8FFFF280000002000000040000000
      0100010000000000800000000000000000000000000000000000000000000000
      FFFFFF000000000000000000000000003FFFFFC07FFFFFE07FFFFFF07FFCFFF0
      7FF87FE03FF87FE03FFCFFC01FFFFFC01FFDFF800FFDFF800FFDFF0007F8FF00
      07F8FE0003F8FE0003F07C0001F07C0001F0780000F0780000F070000078F000
      007FE000003FE000003FC000001FC000001F8000000F8000000F000000060000
      00000000FFFFFFFFFFFFFFFFC000001F8000000F000000070000000700000007
      000000078000000F8000000FC000001FC000001FE000003FE000003FF000007F
      F000007FF80000FFF80000FFFC0001FFFC0001FFFE0003FFFE0003FFFF0007FF
      FF0007FFFF800FFFFF800FFFFFC01FFFFFC01FFFFFE03FFFFFE03FFFFFF07FFF
      FFF8FFFF}
  end
  object UpdateData: TStringGrid
    Left = 9
    Top = 140
    Width = 504
    Height = 131
    ColCount = 4
    DefaultColWidth = 119
    RowCount = 2
    Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goThumbTracking]
    TabOrder = 1
    OnSelectCell = UpdateDataSelectCell
    OnSetEditText = UpdateDataSetEditText
  end
  object ActionGroup: TRadioGroup
    Left = 410
    Top = 10
    Width = 102
    Height = 113
    Caption = ' Reconcile Action '
    TabOrder = 0
    OnClick = DisplayFieldValues
  end
  object CancelBtn: TButton
    Left = 438
    Top = 281
    Width = 75
    Height = 25
    Cancel = True
    Caption = 'Cancel'
    ModalResult = 2
    TabOrder = 5
  end
  object OKBtn: TButton
    Left = 350
    Top = 281
    Width = 75
    Height = 25
    Caption = 'OK'
    Default = True
    ModalResult = 1
    TabOrder = 4
  end
  object ConflictsOnly: TCheckBox
    Left = 11
    Top = 282
    Width = 153
    Height = 17
    Caption = 'Show conflicting fields only'
    TabOrder = 2
    OnClick = DisplayFieldValues
  end
  object ErrorMsg: TMemo
    Left = 56
    Top = 52
    Width = 342
    Height = 71
    TabStop = False
    Color = clBtnFace
    ReadOnly = True
    TabOrder = 6
  end
  object ChangedOnly: TCheckBox
    Left = 185
    Top = 282
    Width = 141
    Height = 17
    Caption = 'Show changed fields only'
    TabOrder = 3
    OnClick = DisplayFieldValues
  end
end