title: "Class TBCDField not found" - Error in Delphi
body: <p>I am using Delphi Seattle.</p>
  
  <p>I have below constructor, and while executing first statement I am getting an error "Class TBCDField not found".</p>
  
  <pre><code>constructor TFrmMyForm.Create(AOwner:Tcomponent; AParam1:Real; var AParam2:Real);
  begin
    inherited Create(AOwner);  //This statement is giving an error
  
    FValue1 := AParam1;
    FValue2 := AParam2;
  end;    
  </code></pre>
  
  <p>I googled but didn't get relevant information and also tried to put below statement in try..except block but didn't get other exception message where I could see what is causing the issue.</p>
  
  <pre><code>inherited Create(AOwner);
  </code></pre>
  
  <p>TFrmMyForm is derived from TForm class.</p>
  
  <p>Class TBCDField is as below:</p>
  
  <pre><code>TBCDField = class(TNumericField)
    private
      FCurrency: Boolean;
      FCheckRange: Boolean;
      FMinValue: Currency;
      FMaxValue: Currency;
      FPrecision: Integer;
      procedure SetCurrency(Value: Boolean);
      procedure SetMaxValue(Value: Currency);
      procedure SetMinValue(Value: Currency);
      procedure SetPrecision(Value: Integer);
      procedure UpdateCheckRange;
    protected
      class procedure CheckTypeSize(Value: Integer); override;
      procedure CopyData(Source, Dest: TValueBuffer); overload; override;
  {$IFNDEF NEXTGEN}
      procedure CopyData(Source, Dest: Pointer); overload; override; deprecated 'Use overloaded method instead';
  {$ENDIF !NEXTGEN}
      function GetAsBCD: TBcd; override;
      function GetAsCurrency: Currency; override;
      function GetAsSingle: Single; override;
      function GetAsFloat: Double; override;
      function GetAsInteger: Longint; override;
      function GetAsLargeInt: Largeint; override;
      function GetAsLongWord: LongWord; override;
      function GetAsString: string; override;
      function GetAsVariant: Variant; override;
      function GetDataSize: Integer; override;
      function GetDefaultWidth: Integer; override;
      procedure GetText(var Text: string; DisplayText: Boolean); override;
      function GetValue(var Value: Currency): Boolean;
      procedure SetAsBCD(const Value: TBcd); override;
      procedure SetAsCurrency(Value: Currency); override;
      procedure SetAsSingle(Value: Single); override;
      procedure SetAsFloat(Value: Double); override;
      procedure SetAsInteger(Value: Longint); override;
      procedure SetAsLargeInt(Value: Largeint); override;
      procedure SetAsLongWord(Value: LongWord); override;
      procedure SetAsString(const Value: string); override;
      procedure SetVarValue(const Value: Variant); override;
    public
      constructor Create(AOwner: TComponent); override;
      procedure SetFieldProps(FieldDef: TFieldDef); override;
      procedure SetFieldDefProps(FieldDef: TFieldDef); override;
      property Value: Currency read GetAsCurrency write SetAsCurrency;
    published
      { Lowercase to avoid name clash with C++ Currency type }
      [Default(False)]
      property currency: Boolean read FCurrency write SetCurrency default False;
      property MaxValue: Currency read FMaxValue write SetMaxValue;
      property MinValue: Currency read FMinValue write SetMinValue;
      [Default(0)]
      property Precision: Integer read FPrecision write SetPrecision default 0;
      [Default(4)]
      property Size default 4;
    end;
  </code></pre>
  
  <hr>
  
  <h2>Definition Section</h2>
  
  <pre><code>{ TBCDField }
  
  constructor TBCDField.Create(AOwner: TComponent);
  begin
    inherited Create(AOwner);
    SetDataType(ftBCD);
    Size := 4;
    ValidChars := [FormatSettings.DecimalSeparator, '+', '-', '0'..'9'];
  end;
  
  procedure TBCDField.SetFieldProps(FieldDef: TFieldDef);
  begin
    inherited SetFieldProps(FieldDef);
    Precision := FieldDef.Precision;
  end;
  
  procedure TBCDField.SetFieldDefProps(FieldDef: TFieldDef);
  begin
    inherited SetFieldDefProps(FieldDef);
    FieldDef.Precision := Precision;
  end;
  
  class procedure TBCDField.CheckTypeSize(Value: Integer);
  begin
    { For BCD fields, the scale is stored in the size property.
      We allow values up to 32 here even though the currency data type
      only supports up to 4 digits of scale.  The developer can check
      for sizes &gt; 4 to determine if the value from the server may have
      been rounded }
    if Value &gt; 32 then DatabaseError(SInvalidFieldSize);
  end;
  
  function TBCDField.GetAsBCD: TBcd;
  var
    C: System.Currency;
  begin
    if GetValue(C) then CurrToBcd(C, Result) else Result := NullBcd;
  end;
  
  function TBCDField.GetAsCurrency: Currency;
  begin
    if not GetValue(Result) then Result := 0;
  end;
  
  function TBCDField.GetAsFloat: Double;
  begin
    Result := GetAsCurrency;
  end;
  
  function TBCDField.GetAsInteger: Longint;
  begin
    Result := Longint(Round(GetAsCurrency));
  end;
  
  function TBCDField.GetAsLargeint: Largeint;
  begin
    Result := Largeint(Round(GetAsCurrency));
  end;
  
  function TBCDField.GetAsLongWord: LongWord;
  begin
    Result := LongWord(Round(GetAsCurrency));
  end;
  
  function TBCDField.GetAsSingle: Single;
  begin
    Result := GetAsCurrency;
  end;
  
  function TBCDField.GetAsString: string;
  var
    C: System.Currency;
  begin
    if GetValue(C) then Result := CurrToStr(C) else Result := '';
  end;
  
  function TBCDField.GetAsVariant: Variant;
  var
    C: System.Currency;
  begin
    if GetValue(C) then Result := C else Result := Null;
  end;
  
  function TBCDField.GetDataSize: Integer;
  begin
    // SizeOf(TBcd) is used here instead of SizeOf(Currency) because some
    // datasets store the currency data in TBcd format in the record buffer.
    // For these classes (TBDEDataset &amp; TClientDataset) a call to
    // TField.GetData(Buffer, True) will return a TBcd.
    Result := SizeOf(TBcd);
  end;
  
  function TBCDField.GetDefaultWidth: Integer;
  begin
    if FPrecision &gt; 0 then
      Result := FPrecision + 1 else
      Result := inherited GetDefaultWidth;
  end;
  
  procedure TBCDField.GetText(var Text: string; DisplayText: Boolean);
  var
    C: System.Currency;
    Format: TFloatFormat;
    Digits: Integer;
    FmtStr: string;
  begin
    try
      if GetValue(C) then
      begin
        if DisplayText or (EditFormat = '') then
          FmtStr := DisplayFormat
        else
          FmtStr := EditFormat;
        if FmtStr = '' then
        begin
          if FCurrency then
          begin
            if DisplayText then Format := ffCurrency else Format := ffFixed;
            Digits := FormatSettings.CurrencyDecimals;
          end
          else
          begin
            Format := ffGeneral;
            Digits := 0;
          end;
          Text := CurrToStrF(C, Format, Digits);
        end
        else
          Text := FormatCurr(FmtStr, C);
      end
      else
        Text := '';
    except
      on E: Exception do
        Text := SBCDOverflow;
    end;
  end;
  
  function TBCDField.GetValue(var Value: Currency): Boolean;
  begin
    Result := GetData(FIOBuffer, False);
    if Result then
      Value := TDBBitConverter.UnsafeInto&lt;System.Currency&gt;(FIOBuffer);
  end;
  
  procedure TBCDField.SetAsBCD(const Value: TBcd);
  var
    C: System.Currency;
  begin
    BcdToCurr(Value, C);
    SetAsCurrency(C);
  end;
  
  procedure TBCDField.SetAsCurrency(Value: Currency);
  begin
    if FCheckRange and ((Value &lt; FMinValue) or (Value &gt; FMaxValue)) then
      RangeError(Value, FMinValue, FMaxValue);
    if FIOBuffer &lt;&gt; nil then
      TDBBitConverter.UnsafeFrom&lt;System.Currency&gt;(Value, FIOBuffer);
    SetData(FIOBuffer, False);
  end;
  
  procedure TBCDField.SetAsFloat(Value: Double);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TBCDField.SetAsInteger(Value: Longint);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TBCDField.SetAsLargeint(Value: Largeint);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TBCDField.SetAsLongWord(Value: LongWord);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TBCDField.SetAsSingle(Value: Single);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TBCDField.SetAsString(const Value: string);
  var
    C: System.Currency;
  begin
    if Value = '' then Clear else
    begin
      if not TextToFloat(PChar(Value), C, fvCurrency) then
        InvalidFloatValue(Value);
      SetAsCurrency(C);
    end;
  end;
  
  procedure TBCDField.SetCurrency(Value: Boolean);
  begin
    if FCurrency &lt;&gt; Value then
    begin
      FCurrency := Value;
      PropertyChanged(False);
    end;
  end;
  
  procedure TBCDField.SetMaxValue(Value: Currency);
  begin
    FMaxValue := Value;
    UpdateCheckRange;
  end;
  
  procedure TBCDField.SetMinValue(Value: Currency);
  begin
    FMinValue := Value;
    UpdateCheckRange;
  end;
  
  procedure TBCDField.SetPrecision(Value: Integer);
  begin
    if (DataSet &lt;&gt; nil) then
      DataSet.CheckInactive;
    if Value &lt; 0 then Value := 0;
    if Value &gt; 32 then Value := 32;
    if FPrecision &lt;&gt; Value then
    begin
      FPrecision := Value;
      PropertyChanged(False);
    end;
  end;
  
  procedure TBCDField.SetVarValue(const Value: Variant);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TBCDField.UpdateCheckRange;
  begin
    FCheckRange := (FMinValue &lt;&gt; 0) or (FMaxValue &lt;&gt; 0);
  end;
  
  procedure TBCDField.CopyData(Source, Dest: TValueBuffer);
  begin
    Move(Source[0], Dest[0], SizeOf(System.Currency));
  end;
  
  {$IFNDEF NEXTGEN}
  procedure TBCDField.CopyData(Source, Dest: Pointer);
  begin
    System.Currency(Dest^) := System.Currency(Source^);
  end;
  {$ENDIF !NEXTGEN}
  
  { TFMTBCDField }
  
  constructor TFMTBCDField.Create(AOwner: TComponent);
  begin
    inherited Create(AOwner);
    SetDataType(ftFMTBCD);
    Size := 8;
    ValidChars := [FormatSettings.DecimalSeparator, '+', '-', '0'..'9'];
    FMinValue := '';
    FMaxValue := '';
  end;
  
  procedure TFMTBCDField.SetFieldProps(FieldDef: TFieldDef);
  begin
    inherited SetFieldProps(FieldDef);
    Precision := FieldDef.Precision;
  end;
  
  procedure TFMTBCDField.SetFieldDefProps(FieldDef: TFieldDef);
  begin
    inherited SetFieldDefProps(FieldDef);
    FieldDef.Precision := Precision;
  end;
  
  class procedure TFMTBCDField.CheckTypeSize(Value: Integer);
  begin
    { For BCD fields, the scale is stored in the size property.
      We allow values up to 32 here even though the currency data type
      only supports up to 4 digits of scale.  The developer can check
      for sizes &gt; 4 to determine if the value from the server may have
      been rounded }
    if Value &gt; MAXFMTBcdFractionSize then DatabaseError(SInvalidFieldSize);
  end;
  
  function TFMTBCDField.GetAsBCD: TBcd;
  begin
    if not GetValue(Result) then Result := NullBcd;
  end;
  
  function TFMTBCDField.GetAsCurrency: Currency;
  begin
    Result := GetAsFloat;
  end;
  
  function TFMTBCDField.GetAsFloat: Double;
  var
    bcd: TBcd;
  begin
    if GetValue(bcd) then Result := BcdToDouble(bcd) else Result := 0;
  end;
  
  function TFMTBCDField.GetAsInteger: Longint;
  begin
    Result := Longint(Round(GetAsFloat));
  end;
  
  function TFMTBCDField.GetAsLargeInt: Largeint;
  begin
    Result := Largeint(Round(GetAsFloat));
  end;
  
  function TFMTBCDField.GetAsLongWord: LongWord;
  begin
    Result := LongWord(Round(GetAsFloat));
  end;
  
  function TFMTBCDField.GetAsSingle: Single;
  var
    bcd: TBcd;
  begin
    if GetValue(bcd) then Result := BcdToDouble(bcd) else Result := 0;
  end;
  
  function TFMTBCDField.GetAsString: string;
  var
    bcd: TBcd;
  begin
    if GetValue(bcd) then Result := BcdToStr(bcd) else Result := '';
  end;
  
  function TFMTBCDField.GetAsVariant: Variant;
  var
    Bcd: TBcd;
  begin
    if GetValue(Bcd) then Result := VarFMTBcdCreate(Bcd) else Result := Null;
  end;
  
  function TFMTBCDField.GetDataSize: Integer;
  begin
    Result := SizeOf(TBcd);
  end;
  
  function TFMTBCDField.GetDefaultWidth: Integer;
  begin
    if FPrecision &gt; 0 then
      Result := FPrecision + 1 else
      Result := inherited GetDefaultWidth;
  end;
  
  procedure TFMTBCDField.GetText(var Text: string; DisplayText: Boolean);
  var
    bcd: TBcd;
    Format: TFloatFormat;
    Digits: Integer;
    FmtStr: string;
  begin
    try
      if GetValue(bcd) then
      begin
        if DisplayText or (EditFormat = '') then
          FmtStr := DisplayFormat
        else
          FmtStr := EditFormat;
        if FmtStr = '' then
        begin
          if FCurrency then
          begin
            if DisplayText then Format := ffCurrency else Format := ffFixed;
            Digits := FormatSettings.CurrencyDecimals;
          end
          else begin
            Format := ffGeneral;
            Digits := 0;
          end;
          Text := BcdToStrF(bcd, Format, FPrecision, Digits);
        end
        else
          Text := FormatBcd(FmtStr, bcd);
      end
      else
        Text := '';
    except
      on E: Exception do
        Text := SBCDOverflow;
    end;
  end;
  
  function TFMTBCDField.GetValue(var Value: TBcd): Boolean;
  var
    iLen: Integer;
  begin
    Result := GetData(FIOBuffer, True);
    if Result then begin
      Value := TDBBitConverter.UnsafeInto&lt;TBcd&gt;(FIOBuffer);
      iLen := (Value.Precision + 1) div 2;
      if iLen &lt; SizeOf(Value.Fraction) then
        FillChar(Value.Fraction[iLen], SizeOf(Value.Fraction) - iLen, 0);
    end;
  end;
  
  procedure TFMTBCDField.BcdRangeError(Value: Variant; Max, Min: string);
  begin
    DataBaseErrorFmt(sBcdFieldRangeError, [Value, Self.FieldName, Max, Min]);
  end;
  
  procedure TFMTBCDField.SetAsBCD(const Value: TBcd);
  
    procedure DoCheckRange;
    var
      V, VMax, VMin: Variant;
    begin
      VMax := VarFMTBcdCreate(FMaxValue, Self.Precision, Self.Size);
      VMin := VarFMTBcdCreate(FMinValue, Self.Precision, Self.Size);
      V := VarFMTBcdCreate(Value);
      if (V &lt; VMin) or (V &gt; VMax) then
        BcdRangeError(V, VMin, VMax);
    end;
  
  begin
    if FCheckRange then
      DoCheckRange;
    if FIOBuffer &lt;&gt; nil then
      TDBBitConverter.UnsafeFrom&lt;TBcd&gt;(Value, FIOBuffer);
    SetData(FIOBuffer, True);
  end;
  
  procedure TFMTBCDField.SetAsCurrency(Value: Currency);
  var
    LValue: TBcd;
  begin
    CurrToBcd(Value, LValue, MaxBcdPrecision, MaxBcdScale);
    SetAsBCD(LValue);
  end;
  
  procedure TFMTBCDField.SetAsFloat(Value: Double);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TFMTBCDField.SetAsInteger(Value: Longint);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TFMTBCDField.SetAsLargeInt(Value: Largeint);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TFMTBCDField.SetAsLongWord(Value: LongWord);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TFMTBCDField.SetAsSingle(Value: Single);
  begin
    SetAsCurrency(Value);
  end;
  
  procedure TFMTBCDField.SetAsString(const Value: string);
  var
    Bcd: TBcd;
  begin
    if Value = '' then Clear else
    begin
      Bcd := StrToBcd(Value);
      SetAsBCD(Bcd);
    end;
  end;
  
  procedure TFMTBCDField.SetCurrency(Value: Boolean);
  begin
    if FCurrency &lt;&gt; Value then
    begin
      FCurrency := Value;
      PropertyChanged(False);
    end;
  end;
  
  procedure TFMTBCDField.SetMaxValue(Value: string);
  begin
    FMaxValue := Value;
    UpdateCheckRange;
  end;
  
  procedure TFMTBCDField.SetMinValue(Value: string);
  begin
    FMinValue := Value;
    UpdateCheckRange;
  end;
  
  procedure TFMTBCDField.SetPrecision(Value: Integer);
  begin
    if (DataSet &lt;&gt; nil) then
      DataSet.CheckInactive;
    if Value &lt; 0 then Value := 0;
    if Value &gt; MaxFMTBcdFractionSize then Value := MaxFMTBcdFractionSize;
    if FPrecision &lt;&gt; Value then
    begin
      FPrecision := Value;
      PropertyChanged(False);
    end;
  end;
  
  procedure TFMTBCDField.SetVarValue(const Value: Variant);
  begin
    SetAsBCD(VarToBcd(Value));
  end;
  
  procedure TFMTBCDField.UpdateCheckRange;
  begin
    FCheckRange := (FMinValue &lt;&gt; '') or (FMaxValue &lt;&gt; '');
  end;
  </code></pre>