Komponent DBGrid, wartość komórki uzależniona od ilości wystąpień pewnej wartości

0

Witajcie, natrafiłem dziś na kolejny problem, liczę na waszą pomoc.

Mianowicie chciałbym osiągnąć taki efekt (liczba2):
user image

W poniższym kodzie który napisałem, owszem działa to, ale wynik zwraca tylko do pierwszego recordu (liczba2).

 procedure TFmLista.Button11Click(Sender: TObject);
var
i,j:integer;
begin
DBGrid1.DataSource.DataSet.first;
DBGrid3.DataSource.DataSet.first;

For i:=1 to DataSource3.DataSet.RecordCount do
  if i <> 1 then DBGrid3.DataSource.DataSet.next
  else
    begin
      For j:=1 to DataSource1.DataSet.RecordCount do
        begin
          if  DBGrid1.Fields[0].Value (*numer*) = DBGrid3.Fields[0].Value  (*idnumer*)  then
            begin
              DBGrid1.DataSource.DataSet.Filtered:=False;
              DBGrid1.DataSource.DataSet.Filter:='numer = '+DBGrid1.Fields[0].AsString;
              DBGrid1.DataSource.DataSet.Filtered:=True;
              DBNavigator2.BtnClick(nbedit);
              DBGrid3.Fields[2].Value (*liczba2*) :=DBGrid3.Fields[1].Value (*liczba*)  - DataSource1.DataSet.RecordCount (*ilosc wystapien*) ;
              DBNavigator2.BtnClick(nbpost);
              DBGrid1.DataSource.DataSet.Filtered:=False;
            end;
         DBGrid1.DataSource.DataSet.next;
        end;
    end;
end;
0

To jest chore i wolne. Proponuję zrobić to za pomocą SQLa. Będzie na pewno dużo szybciej (dużo szybciej działało i dużo szybciej to ogarniesz). Zresztą takie rzeczy powinno się załatwiać za pomocą SQLa właśnie.

0

strasznie to masz rozwiązane. powinieneś po stronie bazy danych obliczać wartość wyświetlaną w polu "liczba2"

0

Bazę danych mam wykonaną w Accessie, więc teraz za bardzo nie wiem jak za to się zabrać;/

Jak coś po małej edycji zaczęło działać prawidłowo - choć wiem, że po stronie klienta nie jest to zbyt optymalne.

procedure TFmLista.Button11Click(Sender: TObject);
var
i:integer;
begin
  DBGrid3.DataSource.DataSet.first;
  For i:=1 to DataSource3.DataSet.RecordCount do
      begin
        DBGrid1.DataSource.DataSet.Filtered:=False;
        DBGrid1.DataSource.DataSet.Filter:='numer = '+DBGrid3.Fields[0].AsString;
        DBGrid1.DataSource.DataSet.Filtered:=True;
        DBNavigator2.BtnClick(nbedit);
        DBGrid3.Fields[2].Value:=DBGrid3.Fields[1].Value - DataSource1.DataSet.RecordCount;
        DBNavigator2.BtnClick(nbpost);
        DBGrid1.DataSource.DataSet.Filtered:=False;
        DBGrid3.DataSource.DataSet.next;
      end;
end; 

ogólnie w użyciu będzie tylko ten fragment, zastosowany przy dodawaniu nowego recordu dla dbgrid1:

  DBGrid1.DataSource.DataSet.Filtered:=False;
  DBGrid1.DataSource.DataSet.Filter:='numer = '+DBGrid3.Fields[0].AsString;
  DBGrid1.DataSource.DataSet.Filtered:=True;
  DBNavigator2.BtnClick(nbedit);
  DBGrid3.Fields[2].Value:=DBGrid3.Fields[1].Value - DataSource1.DataSet.RecordCount;
  DBNavigator2.BtnClick(nbpost);
  DBGrid1.DataSource.DataSet.Filtered:=False; 
1

Do baz Accessa możesz się dostać chociażby za pomocą komponentów ADO. Tam wygodnie zrobisz sobie zapytanie SQL'owe.

I taka moja mała uwaga. Nie używaj w programach DB Navigatorów. Tak się pisało 20 lat temu, a nie teraz. Jak widzę taki system to od razu mnie odrzuca. O wiele lepiej zrobić chodzenie po gridzie za pomocą strzałek jak to jest w Excelu.

2

Po pierwsze , proponował bym oderwać się od grida jako obiektu będącego dostępem do danych , grid tylko wizualizuje , o wiele prościej i szybciej działa się na datasetach .
W sytuacji gdy z jakiegoś powodu (np. ograniczeń możliwości bazy) dataset musi zawierać zarówno pola będące wprost wynikiem zapytania oraz pola będące wynikiem jakiejś funkcji (wyliczenia) na podstawie danych zaciągniętych z bazy,to do zapytania zwracającego dane z bazy dodaję pola z pustą wartością takiego typu jaka jest potrzebna .
czyli np.

select field1,field2, ... field10, '' as field11 from database

po czym po wykonaniu zapytania już po stronie aplikacji robię cos takiego :

dataset.disablecontrols;
dataset.first;
while not dataset.eof do 
begin 
   dataset.edit
   dataset.fieldbyname('field11').asstring :=  'to co ma być wyliczone';
   dataset.post;
   dataset.next;
end;
dataset.first;
dataset.enablecontrols;
0

o ile pozwolą na coś takiego to jak najbardziej , nie używam komponentu ADOTable , ale nie sądzę żeby nie miał w sumie podstawowej funkcjonalności pozwalającej na taką obróbkę danych

0

@grzegorz_so a nie lepiej by było użyć pól kalkulowanych i załatwić całośc w OnCalcFields? Wtedy to działa za każdym razem, nawet po ponownym pobraniu danych z serwera.

0

@Mr.YaHooo owszem , też stosuję takie rozwiązanie , ale tylko wtedy kiedy algorytm wyliczenia pola typu fkCalculated 'zamyka' się w obrębie bieżącego wiersza w datasecie

0
grzegorz_so napisał(a):

tylko wtedy kiedy algorytm wyliczenia pola typu fkCalculated 'zamyka' się w obrębie bieżącego wiersza w datasecie
Oczywiście. Inaczej to nie ma sensu. Widziałem rozwiązanie gdzie takie pola były liczone na podstawie innych data setów (otwieranie i szukanie za pomocą locate rekordów). Działało to bardzo wolno. W ogóle że też ktoś wpadł na takie rozwiązanie. Chociaż sam w swoim systemie używam tylko w 1 sytuacji takich pól, w każdym innym robię wyliczenia na poziomie zapytania.

0

Czy do wyświetlenia obrazka z bazy dla wybranego recordu w delphi, lepiej użyć DbImage, czy samo Image?

edit:
Już nieistotne, użyłem komponentu TImage.

1 użytkowników online, w tym zalogowanych: 0, gości: 1