cerrato napisał(a):

Tylko z mojego punktu widzenia, wygląda to zupełnie inaczej.

Jakby Ci się chciało poświęcić trochę czasu oraz energii i to opisać (im więcej szczegółów tym lepiej) to ja (i pewnie kilka innych osób udzielających się w tym wątku) byłbym wdzięczny, chętnie poczytam :)

Niczego nie obiecuję, brak czasu.
Mam rozbabraną i niedokończoną odpowiedź w wątku o dynamicznym generowaniu formularzy.
Ale, żeby to wyjaśnić, musiałbym napisać bardzo rozległy wstęp.
Albo nagrać film z kodowania ;-)
Tylko, ja nie mam na to czasu, a coraz bardziej skłaniam się do tego, że to sztuka dla sztuki.
Ja się narobię, żeby się "pochwalić", ale nie sądzę aby dla kogoś to było jakoś użyteczne.
A więc, po co?

Lepiej, jeśli już, ogarnąć prostsze bo skończone tematy.
Jak np, coś takiego :D

var
  lTaskState : TTaskState; //Typ wyliczeniowy reprezentujący status zadania
begin
  if not Assigned(FqGetTaskToMove) then
  begin
    //-- Utwórz zapytanie do bazy danych; TboPpSchedulerTask to klasa wydziedziczona z TFDQuery, czyli zwyczajne zapytanie FireDAC.
    FqGetTaskToMove := TboPpSchedulerTask.Create(nil, PrivPPCommand.TaskDBPersistance.Connection);
    //-- Usuń klauzulę where z zapytania
    FqGetTaskToMove.SQLParser.Where.Clear
    //-- Dodaj warunek na ID zadania i na różne od id maszyny
      .Add(FqGetTaskToMove.flIdPpTask.FieldName, coAnd, opNotEqual)
      .Add(FqGetTaskToMove.flIdDevice.FieldName)
      .BeginGroup(coAnd);
    //-- Dodaj statusy zadań do where, jako "where status in (status1, status2, itd)"
    for lTaskState in TaskOrderStates do
      FqGetTaskToMove.SQLParser.Where.Add(FqGetTaskToMove.flStatus.FieldName, Ord(lTaskState), coOr, opEqual);
    FqGetTaskToMove.SQLParser.Where.EndGroup();
    //-- Wyczyść sortowanie z zapytania - tu do niczego niepotrzebne
    FqGetTaskToMove.SQLParser.OrderBy.Clear.Add(FqGetTaskToMove.flDateStart.FieldName, soAsc);
    //-- Zatwierdź zmiany w SQL
    FqGetTaskToMove.SQLParser.CommitSQL();
    //-- Ustaw zapytanie  na szybki, jednokierunkowy odczyt danych z bazy
    FqGetTaskToMove.SetFastForward(False, False);
  end;
  Result := FqGetTaskToMove;
end;

Albo wolałbym się z kimś podzielić czymś takim (i nie tylko tym, mam tego masę całą...), pod warunkiem deklaracji wspólnego rozwoju:

  /// <summary>TDADQueryHelper zawiera metody rozszerzające funkcjonalność wszystki komponentów DAO AnyDAC'a </summary>
  TADAdaptedDataSetHelper = class helper for TADAdaptedDataSet
  strict private
  private
    function GetCurrentRec : Variant;
  protected
  public
    /// <summary>
    ///   Dodaje wiersz w sposób bezpieczny
    /// </summary>
    /// <param name="AutoPost">
    ///   Wskazuje, czy metoda ma automatycznie zapisać zmiany jeżeli DataSet jest w trybie edycji(Boolean = True)
    /// </param>
    /// <returns>
    ///   Boolean
    /// </returns>
    function AppendEx(const AutoPost : Boolean = True): Boolean; overload; virtual;
    /// <summary>Dodaje wiersz w sposób bezpieczny wypełniając go wartościami.</summary>
    /// <returns> Boolean </returns>
    /// <param name="AFields">lista pol do uzupelnienia wartościami w nowym wierszu (array of string)</param>
    /// <param name="AValues">lista wartosc do wpisanie do nowego wiersza, jeśli pusta przepisane zostaną wartości z aktywnego wiersza w DSie (array of Variant)</param>
    function AppendEx(const AFields : array of string; const AValues : array of Variant): Boolean; overload; virtual;
    /// <summary>Odpowiednik metody ApplyUpdates, z tym że automatycznie woła CommitUpdates i zapewnia poprawną, ogólną metodę obsługi wyjątków.</summary>
    /// <returns>Zwraca ilość błędów, które wystąpiły podczas zatwierdzania zmian. (Integer)</returns>
    /// <param name="AMaxErrors">Wartość określa dopuszczalną maksymalną ilość błędów podczas zatwierdzania zmian. Domyślnie nie dopuszczamy żadnego błędu. (Integer = 0) </param>
    function ApplyUpdatesEx(AMaxErrors: Integer = 0): Integer; virtual;
    function ApplyUpdatesEx2(var AMaxErrors: Integer; AAutoCommitUpdates: Boolean = True): Boolean; virtual;
    function CancelEx(const ARollbackTransaction : Boolean = False): Boolean; virtual;
    /// <summary>Metoda sprawdza czy pola w MasterDS po których łaczy się detailDS, są uzupełnionie w MasterDS </summary>
    /// <returns> TFieldsListGeneric </returns>
    /// <param name="ADSMaster"> (TADAdaptedDataSet) </param>
    /// <param name="ADSChild"> (TADAdaptedDataSet) </param>
    function CheckPrimaryKeyDS(const ADSMaster, ADSChild : TADAdaptedDataSet): TFieldsListGeneric; virtual;
    /// <summary>Sprawdza czy uzupełniono pola wymagane w bieżącym rekordzie DSa</summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="ASilent">Wskazuje, że metoda ma nie wołać dialogu z informacją o wypełnieniu pól wymaganych.(Boolean)</param>
    function CheckReqFieldsB(const ASilent : Boolean = False): Boolean; virtual;
    /// <summary>Sprawdza czy uzupełniono pola wymagane w bieżącym rekordzie DSa</summary>
    /// <returns>TFieldsListGeneric lista pól, które nie spełniają warunku wymagalności.</returns>
    /// <param name="ASilent">Wskazuje, że metoda ma nie wołać dialogu z informacją o wypełnieniu pól wymaganych.(Boolean)</param>
    function CheckReqFieldsL(const ASilent : Boolean = False): TFieldsListGeneric; virtual;
    /// <summary>
    /// Metoda klonuje bieżący rekord i nie zapisuje zmian, zostawia DataSet w stanie dsInsert.
    /// Niezależnie od wartości parametru ARewritePKFields, metoda nie przepisuje wartości pól AutoInc.
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="AIgnoreFields">Lista pól, których wartości nie mają być przepisane do nowego rekordu (array of string) </param>
    /// <param name="ARewritePKFields">Określa, czy ma przepisać wartość pól PK.(Boolean=False) </param>
    /// <param name="ATimes">Określa ile razy rekord ma zostać sklonowany.(Integer=1)</param>
    function CloneRecord(AIgnoreFields : array of string; ARewritePKFields : Boolean = False; ATimes : Integer = 1): Boolean; virtual;
    /// <summary>Zamyka DSa w sposób bezpieczny włączając DisableControls i wyłączając obsługę zdarzeń Scroll</summary>
    /// <returns> Boolean
    /// </returns>
    function CloseEx: Boolean; virtual;
    /// <summary>
    /// Otwiera/zamyka dane Query w sposób bezpieczny, a więc robi DisableControls, itd.
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="ALocateCurrentRecord">Określa czy po otwarciu ma ustawić się na tym samym rekordzie, który był bieżącym przed otwarciem (Boolean = True) </param>
    /// <param name="AForceFetchAll"> Określa czy ma wykonać FetchAll przy otwarciu(Boolean = False) </param>
    function CloseOpen(const ALocateCurrentRecord: Boolean = True; const AForceFetchAll: Boolean = False): Boolean; overload; virtual;
    /// <summary>
    /// Otwiera/zamyka dane Query w sposób bezpieczny, a więc robi DisableControls, itd.
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="AParamValues">Przekazuje wartości parametrów do zapytania</param>
    /// <param name="ALocateCurrentRecord">Określa czy po otwarciu ma ustawić się na tym samym rekordzie, który był bieżącym przed otwarciem (Boolean = True) </param>
    /// <param name="AForceFetchAll"> Określa czy ma wykonać FetchAll przy otwarciu(Boolean = False) </param>
    function CloseOpen(const AParamValues: Variant; const ALocateCurrentRecord: Boolean = True; const AForceFetchAll: Boolean = False): Boolean; overload; virtual;
    /// <summary>
    ///  Kopiuje bieżący wiersz ze źródła do bieżącego wiersza celu. Pomija pola które są NonModify, posiadają wiązania MD oraz wartości domyślne z generatora
    ///  AIgnoreDestFieldNames - lista nazw rozdziloonych średnikiem pól w DS docelowym, które mają być ignorowane podczas kopiowania danych.
    /// </summary>
    procedure CopyRow(ASourceDS: TADAdaptedDataSet; const AIgnoreDestFieldNames: string = '');
    /// <summary>Importuje (dodaje jako nowe) wszystkie wiersze ze źródła do celu. Używa CopyRow</summary>
    procedure ImportRows(ASourceDS: TADAdaptedDataSet; ADisableControls: Boolean = True; ASilent: Boolean = False; ACheckReqFields: Boolean = True; const AIgnoreDestFieldNames: string
      = '');
    /// <summary>
    ///   Usuwa wszystkie rekordy z DataSetu, ktore sa widoczne. Metoda nie zdejmuje filtrow i usuwa dane przefiltrowane.
    /// </summary>
    function DeleteAll(AAutoCommit: Boolean = False): Boolean;
    /// <summary>Metoda zapewnia bezpieczne usuwanie bieżącego rekrodu, jeżeli DS jest w trybie Insert - to anuluje bieżący wiersz, w przeciwnym wypadku usuwa go.
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="AAutoCommit">Określa, czy po usunieciu wiersz zmiany mają zostać autmatycznie zatwierdzone.
    /// Uwaga!
    /// Zatwierdzenie zmian działa dla całego DSa, a nie tylko dla bieżącego rekordu, który został usunięty.(Boolean = False)</param>
    function DeleteEx(const AAutoCommit : Boolean = False): Boolean; overload; virtual;
    /// <summary>Metoda zapewnia bezpieczne usuwanie listy rekordów, których wartości pól PK poda się w tablicy. Jeżeli DS jest w trybie Insert - to anuluje bieżący wiersz, w przeciwnym wypadku usuwa go.
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="AParamsValues">Lista wartości pól PK, które mają być odnalezione i usunięte z DataSetu</param>
    /// <param name="AAutoCommit">Określa, czy po usunięciu wiersz zmiany mają zostać automatycznie zatwierdzone. Uwaga! Zatwierdzenie zmian działa dla całego DSa, a
    /// nie tylko dla bieżącego rekordu, który został usunięty.(Boolean = False)</param>
    function DeleteEx(const AParamsValues: array of Variant; const AAutoCommit: Boolean = False): Boolean; overload; virtual;
    /// <summary>TADAdaptedDataSetHelper.EditEx  Bezpiecznie edytuje DataSet, sprawdzając czy dany DataSet można edytować, itd.</summary>
    /// <returns> Boolean </returns>
    /// <param name="AAutoAppend"> (Boolean) Domyślnie True, oznacza czy rekord ma być autmatycznie dodany w przypadku pustegoDataSetu</param>
    function EditEx(const AAutoAppend : Boolean = True) : Boolean;
    /// <summary>Zwraca zmiany wykonane w DataSet jako XML pobrany z GetChanges : TADDatSTable</summary>
    function GetChangesAsXML: string; virtual;
    /// <summary>TADAdaptedDataSetHelper.GetConnUpdate  Odnajduje Connection dla danego TADADaptedDataSet, które można użyć do aktualizacji danych </summary>
    /// <returns> TADCustomConnection </returns>
    function GetConnUpdate: TADCustomConnection; virtual;
    function GetEnumerator : TDataSetEnumerator;
    /// <summary>TADAdaptedDataSetHelper.IsChanged Sprawdza czy w danym DSie są niezapisane zmiany i jest aktywny.
    // W przypadku dADQurery sprawdza również wymagalność pod katem pustego rekordu, jeśli wymagano takigo sprawdzenia (opcja: obCheckReqFieldsIsEmpty in TDAdQuery.dFLEXConf.dFLEXBehavior)</summary>
    /// <returns> Boolean, True jeśli są niezapisane zmiany.</returns>
    function IsChanged: Boolean; virtual;
    /// <summary>Standardowa metoda IsEmpty swraca True, jeśli DS posiada dodany, a nie zapisany rekord. Jeśli AEditIsEmpty = False, to dodany rekod nie jest IsEmpty</summary>
    function IsEmptyEx(AEditIsEmpty : Boolean = True) : Boolean;
    /// <summary>Metoda przypina DataSeta jako detale do DataSource podanego w parametrze AMasterDS. Jej sposób działania polega na odszukaniu pól PK datasetu i
    /// modyfikacji klauzuli Where wg wzoru: Where DataSet.PolePK = :DataSet.PolePK Uwaga! Automatycznie wiązanie następuje tylko po polu PK DataSetu Detail!
    /// Zobacz opis parametru AMasterParamNames tej metody.</summary>
    /// <param name="AMasterDS">Określa źródło danych Mastera (TDataSource) </param>
    /// <param name="ACacheDetails"> Określa, czy ma być automatycznie ustawione keszowanie detali (Boolean = True)</param>
    /// <param name="AMasterParamNames"> Lista nazw parametrów dla pól Master, przydatne kiedy pole po którym ma nastąpić wiązanie nazywa się inaczej niże pole PK
    /// detali, np. Where IdTax = :IdTaxSale pokaże nam dane związane nie z polem o nazwie IDTaxSale, które znajduje się w MasterDS (String = '')
    /// </param>
    procedure LinkToMaster(AMasterDS: TDataSource; ACacheDetails: Boolean = True; const AMasterParamNames: String = ''); virtual;
    /// <summary>TADAdaptedDataSetHelper.OpenEx Otwiera DSa w sposób optymalny i jeżeli jest do niego przypięte Entity, to również je inicjalizuje, a następnie preparuje zapytanie</summary>
    /// <returns> Boolean </returns>
    function OpenEx: Boolean; overload; virtual;
    /// <summary>TADAdaptedDataSetHelper.OpenEx Otwiera DSa w sposób optymalny i jeżeli jest do niego przypięte Entity, to również je inicjalizuje, a następnie preparuje zapytanie</summary>
    /// <returns> Boolean </returns>
    /// <param name="AIdEntity">Przekazuje IdDbEntity którym ma byż zainicjowane Query</param>
    /// <param name="AParamValues">Przekazuje wartości parametrów do zapytania</param>
    function OpenEx(const AIdEntity: String; const AParamValues: Variant): Boolean; overload; virtual;
    /// <summary>Otwiera DSa w sposób optymalny i jeżeli jest do niego przypięte Entity, to również je inicjalizuje, a następnie preparuje zapytanie</summary>
    /// <param name="AParamValues">Tablica z wartościami dla parametrów (array of Variant)</param>
    /// <param name="ASkipMasterLinkParams>Określa czy podczas przepisywania wartości do parametrów mają zostać pominięte te, które są utworzone dla relacji Master-Detail (Boolean = True)</param>
    function OpenEx(AParamValues: array of Variant; ASkipMasterLinkParams: Boolean = True): Boolean; overload; virtual;
    /// <summary>TADAdaptedDataSetHelper.OpenEx Otwiera DSa w sposób optymalny i jeżeli jest do niego przypięte Entity, to również je inicjalizuje, a następnie
    /// preparuje zapytanie
    /// </summary>
    /// <returns> Boolean</returns>
    /// <param name="AParamValues"> Wartość parametrów jako skalar lub jako tablica, metoda sama rozpoznaje i konwertuje odpowiedni typ z Varianta(Variant) </param>
    /// <param name="ASkipMasterLinkParams>Określa czy podczas przepisywania wartości do parametrów mają zostać pominięte te, które są utworzone dla relacji Master-Detail (Boolean = True)</param>
    function OpenEx(AParamValues: Variant; const ASkipMasterLinkParams: Boolean = True): Boolean; overload; virtual;
    /// <summary>
    /// Metoda zwraca kolekcję Params dla dowolnego DataSetu AnyDAC
    /// </summary>
    /// <returns> TADParams
    /// </returns>
    function ParamsFromHelper: TADParams; virtual;
    /// <summary>Sprawdza czy podane wartości są równe wartościom parametrów DSu.</summary>
    /// <returns> Boolean </returns>
    /// <param name="AValues"> (array of Variant) </param>
    function ParamsValueIsEqual(AValues : array of Variant): Boolean; overload; virtual;
    /// <summary>Sprawdza czy podane wartości są równe wartościom parametrów DSu.</summary>
    /// <returns> Boolean </returns>
    /// <param name="AValues"> Wartość parametrów jako skalar lub jako tablica, metoda sama rozpoznaje i konwertuje odpowiedni typ z Varianta(array of Variant) </param>
    function ParamsValueIsEqual(const AValues: Variant): Boolean; overload; virtual;
    /// <summary>Pobiera listę pól, które sa PrimaryKey</summary>
    /// <returns> (string) lista nazw pól PK rozedzielona średnikami </returns>
    function PKFields: string; virtual;
    /// <summary>Zwraca ilość pól PK</summary>
    function PKFieldsCount: Integer; virtual;
    /// <summary>Pobiera listę pól, które sa PrimaryKey</summary>
    /// <returns> lista pól PK danego DataSeta (TFieldsListGeneric)</returns>
    function PKFieldsList: TFieldsListGeneric; virtual;
    /// <summary>TRue jeśli wartości dla pól PK są równe z wartościami parametrów dla pól PK</summary>
    function PKValuesInParamValuesIsEqual: Boolean; virtual;
    /// <summary>Zwraca wektor lub skalar wartości pól (lub pola) PK DataSetu jako Variant</summary>
    function PKValue: Variant; virtual;
    /// <summary>Wyszukuj wartość klucza głównego</summary>
    function PKLocate(AValue: Variant; AForceFetchAll: Boolean = False; ADisableControls: Boolean = False): Variant;
    /// <summary>Zwraca tablicę wartości pól PK DataSetu</summary>
    procedure PKValues(var AValues : array of Variant); virtual;
    /// <summary>Zapisuje dane do DataSetu w sposób bezpieczny, nie zatwierdza zmian do bazy danych w trybie CachedUpdates - zobacz PostExCommit</summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="ASilent">Określa, czy podczas sprawdzenia pól wymaganych ma używać dialogu.(Boolean = True) </param>
    function PostEx(const ASilent : Boolean = False; ACheckReqFields : Boolean = True): Boolean; virtual;
    /// <summary>
    /// Zapisuje zmiany w bezpieczny sposób i zatwierdza zmiany do bazy danych.
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="ASilent">Określa, czy podczas sprawdzenia pól wymaganych ma używać dialogu.(Boolean = True)</param>
    /// <param name="ARefresh">Określa, czy ma odświeżyć DataSet przy zapisie, działa tylko dla trybu UpdateOptions.RefreshMode = rmManual, bo w przeciwnym razi dane są odświeżane autmatycznie. Zobacz manual AnyDAC. (Boolean=False) </param>
    /// <param name="AUseTransaction">Określa, czy podsczas zapisu ma być użyta transakcja. Startuje ją automatycznie, jeżeli została wcześniej wystartowana - autmatycznie ja commituje.(Boolean=False) </param>
    function PostExtCommit(ASilent : Boolean = True; ACheckReqFields : Boolean = True; ARefresh : Boolean = False; AUseTransaction : Boolean = False) : Boolean; virtual;
    /// <summary>
    /// Odświeża DataSet w bezpieczny (ogólna obsługa wyjątków) sposób, sprawdzając czy dane można odswieżyć i wybierając odpowiednią metodę odświeżania (CloseOpen lub
    /// Refresh)
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="AOnlyCurrentRecord">Jeżeli True, to odświeża tylko bieżący rekord(Boolean = False) </param>
    /// <param name="AForceReWriteParams">Jeżeli True, to przepisuje wartości parametrów z wartości pól, których nazwa jest zgodna z parametrem.(Boolean - False)
    /// </param>
    function RefreshEx(const AOnlyCurrentRecord : Boolean = False; const AForceReWriteParams : Boolean = False): Boolean; overload; virtual;
    /// <summary>
    /// Odświeża DataSet w bezpieczny (ogólna obsługa wyjątków) sposób, sprawdzając czy dane można odswieżyć i wybierając odpowiednią metodę odświeżania (CloseOpen lub
    /// Refresh)
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="APKValues">Jeżeli True, to odświeża tylko bieżący rekord(Boolean = False) </param>
    /// <param name="AForceReWriteParams">Jeżeli True, to przepisuje wartości parametrów z wartości pól, których nazwa jest zgodna z parametrem.(Boolean - False)
    /// </param>
    function RefreshEx(const APKValues: TArray<Variant>; const APKFieldName: string): Boolean; overload; virtual;
    /// <summary>
    /// Odświeża DataSet w bezpieczny (ogólna obsługa wyjątków) sposób, sprawdzając czy dane można odswieżyć i wybierając odpowiednią metodę odświeżania (CloseOpen lub
    /// Refresh)
    /// </summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="APKValues">Jeżeli True, to odświeża tylko bieżący rekord(Boolean = False) </param>
    /// <param name="AForceReWriteParams">Jeżeli True, to przepisuje wartości parametrów z wartości pól, których nazwa jest zgodna z parametrem.(Boolean - False)
    /// </param>
    function RefreshEx(const APKValues: TArray<Variant>): Boolean; overload; virtual;
    /// <summary>Metoda tworzy relację do AMasterDS przez zmianę klauzuli WHERE i utworzenie odpowiednich parametrów. Jej sposób działania polega na odszukaniu pól PK datasetu i
    /// modyfikacji klauzuli Where wg wzoru: Where DataSet.PolePK = :DataSet.PolePK Uwaga! Automatycznie wiązanie następuje tylko po polu PK DataSetu Detail!
    /// Zobacz opis parametru AMasterParamNames tej metody.</summary>
    /// <param name="AMasterDS">Określa nadrzędny DataSet</param>
    /// <param name="AMasterParamNames"> Lista nazw parametrów dla pól Master, przydatne kiedy pole po którym ma nastąpić wiązanie nazywa się inaczej niże pole PK
    /// detali, np. Where IdTax = :IdTaxSale pokaże nam dane związane nie z polem o nazwie IDTaxSale, które znajduje się w MasterDS (String = '')
    ///  Metoda zwraca listę pól rozdzelonych śrfednikiem, które zostały użyte do utworzenia relacji.
    /// </param>
    function RelationToMaster(AMasterDS: TADAdaptedDataSet; APrepareDS: Boolean = True; const AMasterParamNames: String = ''): string; virtual;
    /// <summary>Ustawia DADQuery w tryb szybkiego pobierania danych bez buforowania (tylko kiedy UniDirectional = True), przydatne do wszelkiej maści zapytań, które pobierają dane ale nie nawigują (Prior, First, Locate, itd.) po
    /// zwróconym zbiorze danych.</summary>
    /// <param name="AFetchBlobs">Określa, czy zapytanie ma pobierać BLOBY. (Boolean=False) </param>
    /// <param name="AUniDirectional">Określa czy DS ma być ustawiony w tryb kursora tylko do przodu (szybki, małe zużycie pamięci, dane pobierane paczkami, nie nadaje się dla kontrolek dbAware); jeśli False to autmatycznie ustawiony jest jako FetchAll</param>
    /// <param name="ARowsetSize">Określa, ilość wierszy pobieranych w jednej interakcji z bazą danych (okreslone w stałej cRowsetSizeFastForward = 500) </param>
    procedure SetFastForward(AFetchBlobs: Boolean = False; AUniDirectional: Boolean = True; ARowsetSize: Integer = cRowsetSizeFastForward); virtual;
    /// <summary>
    ///   Zamienia miejscami bieżący rekord z następnym lub poprzednim w zależności od wartości parametru AMoveUp
    /// </summary>
    /// <param name="AOrderFieldName">
    ///   Określa nazwę pola, w którym jest przechowywana jest kolejność rekordów (String)
    /// </param>
    /// <param name="AMoveUp">
    ///   Określa czy ma zamienić rekord z tym, ktory jest wyżej (true) czy niżej (false) rekordu bieżącego (Boolean = True)
    /// </param>
    /// <returns>
    ///   Boolean
    /// </returns>
    function SwapRecords(const AOrderFieldName: String; AMoveUp: Boolean = True): Boolean; virtual;
    /// <summary>
    ///   Przenumerowuje rekordy dla zadanego pola [AOrderFieldName] i startuje od wartosci podanej w AStartValue
    /// </summary>
    function RenumRecords(const AOrderFieldName: String; AStartValue: Integer = 1): Boolean; virtual;
    /// <summary>Metoda przepisuje wartości parametrów z DSa podanego w parametrze AParentDS do tych pól DSa, które mają te same nazwy co parametry w ParentDS</summary>
    /// <returns> Boolean
    /// </returns>
    /// <param name="AParentDS">Określa ParentDS, czyli DS z którego należy przepisać wartości parametrów do odpowiadających pól w ChildDS (TADAdaptedDataSet=nil)
    /// </param>
    function WriteFieldsFromParentParams(AParentDS: TADAdaptedDataSet = nil; AOnlyCurrentRecord: Boolean = True): Boolean; virtual;
    /// <summary>
    ///  Bieżący rekord (wartości) przedsatiowne jak tablicowy Variant
    /// </summary>
    property CurrentRec : Variant read GetCurrentRec;
    /// <summary>
    /// Odświeża wiersz w datasecie, który w nim nie istnieje, ale wiadomo, że jest w bazie danych.
    ///  W przeciwieństwie do FirDac'owego RefreshUnknownRecord bierze pod uwagę PK.
    /// </summary>
    procedure RefreshUnknownRecordEx(const APKValue: Variant; const APKFieldName : Variant);
    /// <summary>True, jeśli wartości dla podanych nazw pól rozdzielonych średnikiem są unikalne</summary>
    function IsUniqueValues(const AFieldNames: string; ARowStates: TADDatSRowStates = [rsModified, rsUnchanged, rsInserted]): Boolean;
  end;