FastReport - dostęp do komponentu kbmmemtable

FastReport - dostęp do komponentu kbmmemtable
0

Przy bardziej skomplikowanych wydrukach czasem jest problem ze zliczaniem niektórych danych, dlatego zawsze muszę używać wiele zmiennych lub tablice.
Zamiast tego próbuję z poziomy wydruku obsługiwać komponent kbmmemtable (który jest na formie w Delphi).
Ten kbmmemtable jest widoczny jako źródło danych, mogę do niego podłączyć wstęgi, ale nie wiem jak go modyfikować (dodanie kolumn, Append, Delete, Update)

Próbuję tak:

Kopiuj
var dataset : TDataSet;
begin
   dataset := TDataSet(Report.GetDataset('kbmMemTable'));
   dataset.FieldDefs.Add('Wiek',ftInteger,0,True);        <--- Acces Violation
end;

Czy to jest możliwe?

Albo
jak stworzyć wewnętrznego dataseta którego będę mogł modyfkować i który będzie widoczny jako źródło danych dla wstęgi?

edytowany 1x, ostatnio: flowCRANE
abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
1

wewnątrz kodu FR nie możesz zmieniać DS. Możesz to robić w delphi. Napisz może co chcesz osiągnąć


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

Robisz to zupełnie od tyłka strony. Dlaczego wydruk ma dodawać jakieś dane? Przy takich wydrukach najlepiej będzie jak w ramach formatki zrobisz sobie metodę np GetDataToReport() która to wypełni sobie komponent kbmMemTable danymi, a wydruk wydrukuje te dane.

0

ale na jednym oknie mam wiele różnych wydruków więc dane muszą być wypełnianie z poziomy wydruku.
Jedyne co wymyśliłem to dodanie do fastreporta kilku zewnętrznych funkcji które będą operować na tym kbmie typu dodaj pole, dodaj rekord edytuj itp

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

To w takim razie podziel te wydruki na oddzielne okna. Mieszanie kilku rzeczy nie jest najlepszym pomysłem. Już wolę nie zgadywać jak to się edytuje...

WL
  • Rejestracja:ponad 21 lat
  • Ostatnio:8 dni
  • Postów:1083
0
abrakadaber napisał(a):

wewnątrz kodu FR nie możesz zmieniać DS. Możesz to robić w delphi. Napisz może co chcesz osiągnąć

A niby dlaczego nie można?
Oczywiście, że można.
Mogę sobie równie dobrze takiego DSa w całości utworzyć w raporcie, wypełnić go danymi i zniszczyć.
A jak czegoś mi brakuje (w obszarze funkcjonalności FastScripta), to mogę sobie to dodać i zarejestrować FastScripta w raporcie.
Praktycznie wszystko jest możliwe...

0

próbowałem dynamicznie utworzyć dataseta na wydruku:

Kopiuj
var DynamicznyDataset : TDataset;
begin
   DynamicznyDataset := TDataset.Create(nil);
   DynamicznyDataset.FieldDefs.Add('ID',ftInteger, 0, True);
   DynamicznyDataset.Open;                   
end;

ale na linii DynamicznyDataset.Open mam błąd Abstract Error.
A może robię to źle?

edytowany 1x, ostatnio: flowCRANE
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

A ja się zastanawiam dlaczego chcesz tworzyć klasę bazową której duża ilość metod jest zadeklarowana jako virtual i de facto są to tylko stuby które nic nie robią. http://docwiki.embarcadero.com/Libraries/Berlin/en/Data.DB.TDataSet Co więcej trzeba było poszukać chociaż co oznacza błąd http://docwiki.embarcadero.com/Libraries/Berlin/en/System.SysUtils.EAbstractError

Do takich rzeczy jak chcesz nie wykorzystuje się TDataSet. Użyj chociaż TClientDataSet który można utworzyć, dodać definicję pól i ręcznie wypełnić danymi.

0

TClientDataSet można ręcznie wypełniać danymi jeśli zamiast Open użyje się CreateDataSet.
Tylko że w Fastreporcie (bo tego dotyczy ten temat) nie ma TClientDataSet.
Jest TfrxCustomDataset ale nie ma właściwości CreateDataSet;

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
0

napisz może co chcesz osiągnąć bo widzę, że kręcisz się w koło na jakimś własnym pomyśle


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
0

Przecież napisałem że z poziomu FastReporta chcę utworzyć komponent, dodawać do niego kolumny a później INSERT i UPDATE.
zaproponowałem dostęp do komponentu KBMMemTable który jest na formie lub dynamiczne utworzenie TDataset wewnątrz wydruku.

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
0

nie - napisałeś co się tobie wydaje, że musisz zrobić - ja pytam o cel takiej operacji.


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
0

Cel?
np zliczanie ilości wystąpień każdej pozycji z faktury (czyli z DetailData)
Na każdym OnBeforPrint wstęgi DetalData sprawdzam czy w datasecie jest już taka pozycja - jak jest to zwiększam ilość jak nie to dodaję nowy rekord.
Chyba że ktoś zaproponuje prostsze rozwiązanie?

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
0

co???? Czy przypadkiem jedna pozycja na fakturze nie może wystąpić tylko raz? Może pokaż przykładowy wydruk i wytłumacz jak idiocie (najlepiej z rysunkami :P) co chcesz policzyć . BTW takie rzeczy to się załatwia zapytaniem i/lub sumowaniem/grupowaniem.


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
0

ale jak drukujesz listę wszystkich faktur (100 stron), każda faktura ma jakieś swoje pozycje.
Niech ktoś spróbuje zrobić zliczenie ile razy wystąpiły poszczególne towary na całym wydruku (czyli na wszystkich fakturach).

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
0

no to chyba prościej i szybciej będzie to policzyć po stronie SQLa - SELECT towar, count(towar) ile FROM pozycje_faktur WHERE warunek_na_faktury_ktore_drukujesz


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
0

oczywiście że tak prościej, ale:

  1. nie wiem które faktury drukuje klient (musiałbym najpierw przelecieć po całym datasecie żeby zebrać id faktur)
  2. na samym wydruku są opcje które dodatkowo ukrywają niektóre wiersze (np towary których ilość na danej fakturze jest mniejsza niż 10)

Zrobiłem najpierw zliczanie wszystkich id faktur do zmiennej string.
potem podstawiłem tę listę do zapytania

Kopiuj
 ... 
WHERE id_faktura in ( '  + lista_id + ') 

Dla małych ilości działa dobrze.
Ale jak drukuję faktury za dłuższy okres to dostałem błąd: Too many values (more than 1500) in member list.

Okazuje się że FIREBIRD, bo na tym działa baza, może mieć tylko 1500 parametrów w warunku IN.

edytowany 1x, ostatnio: flowCRANE
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

Nie chcesz chyba powiedzieć, że user sobie wybiera z jakiejś listy 1500 faktur na zestawienie? Jeśli tak to radzę Ci zmień to, bo to brzmi jak wytwór pijanego programisty. Jeśli masz inaczej to przecież możesz zawrzeć dokładnie takie same warunki jak wybierając automatem faktury. Daty, wartości, czy nawet ilość mniejsza niż 10.

edytowany 1x, ostatnio: flowCRANE
0

chodzi i o to, że użytkownik ma różne kryteria w selekcji po którym może wyszukać faktury (po datach, po kwotach, po nazwisku, po statusach: opłacone, nieopłacone, anulowane itp i jeszcze inne warunki).
I teraz mam te same wszystkie warunki przenosić na wydruk uwzględniając dodatkowo opcje które są w oknie dialogowym na wydruku?

WL
  • Rejestracja:ponad 21 lat
  • Ostatnio:8 dni
  • Postów:1083
1
Pele2 napisał(a):

I teraz mam te same wszystkie warunki przenosić na wydruk uwzględniając dodatkowo opcje które są w oknie dialogowym na wydruku?

Skoro już masz te dane, to możesz po prostu przekazać referencję do Fastreporta na DataSet zawierający dane wybrane przez użytkownika i wydrukować.
Po prostu.
Naprawdę nie widzę, gdzie jest problem...
Nie trzeba przenosić tych danych przez jakikolwiek MemTable - bo i po co?

MY
Chyba chodzi o to, że kolega nie wie jak to zrobić. Akurat nie mam pod ręką FastReporta, więc nie podam dokładnych wskazówek. Ale przecież nie jest to jakieś skomplikowane z tego co kojarzę.
0

Przecież mam dostęp do dataseta z nagłówkami dokumentów (MasterData jest z nim połączona).
Ale jak pisałem wcześniej jest problem jeśli dataset zawiera więcej niż 1500 rekordów.

WL
  • Rejestracja:ponad 21 lat
  • Ostatnio:8 dni
  • Postów:1083
0
Pele2 napisał(a):

Przecież mam dostęp do dataseta z nagłówkami dokumentów (MasterData jest z nim połączona).

To go użyj.

Pele2 napisał(a):

Ale jak pisałem wcześniej jest problem jeśli dataset zawiera więcej niż 1500 rekordów.

Niezupełnie; wcześniej pisałeś o limicie dla klauzuli WHERE i operatora IN z limitem 1500 elementów.
A to mnie zupełnie nie obchodzi, ponieważ nie o tym piszę.
Powtarzam; skoro masz przefiltrowane dane w datasecie, które sobie user wyklikał, to nie zbieraj IDków z tego Dsa i nie przekazuj go do zapytania przez IN, tylko po prostu użyj tego DSa w raporcie.
Doczytaj sobie jak dodać dynamicznie DataSet do raportu - to banalne, dwie linie kodu...

0
wloochacz napisał(a):

skoro masz przefiltrowane dane w datasecie, które sobie user wyklikał, to nie zbieraj IDków z tego Dsa i nie przekazuj go do zapytania przez IN, tylko po prostu użyj tego DSa w raporcie.

Ale jeśli dane nie są posortowane (a nie są) to automatyczne podsumowanie na wstęgach nie wyjdzie tak jak bym chciał.
Żeby zliczyć ilość wystąpienia każdego towaru, rekordy w datasecie muszą być posortowane.
Poza tym, skoro towary są na DetailData, to znaczy że ten dataset jest wielokrotnie zamykany i otwierany, więc muszę zbierać ilości do wewnętrznych zmiennych.
Sam Fastreport tego nie potrafi zliczyć.

PD
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 11 godzin
0

to utwórz w bazie tabelę, do której będziesz przed wywołaniem raportu zapisywał id dokumentów wybranych do raportu oraz jakąś nazwę/id sesji/użytkownika, aby pobierać na raporcie tylko dokumenty wybrane przez danego użytkownika, a następnie wykorzystuj tą tabelę w zapytaniach, np. poprzez join. w ten sposób będziesz mógł na końcu robić podsumowania.


pozdrawiam
paweld
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

@Paweł Dmitruk kolega używa Firebirda. W tym celu fajnie można wykorzystać mechanizm Global Temporary Tables (GTT) wtedy nie trzeba zapisywać nazwy czy tam ID usera. Tylko załadować tam dane i korzystać jak z normalnej tabeli wykonując na nich kolejne zapytania.

PD
Bardziej chodziło mi o to aby wykorzystać do tego bazę danych, a czy będą to zwykłe tabele, czy też tymczasowe, to już nie ma aż takiego znaczenia.
MY
@Paweł Dmitruk ja to wiem. Jednak chciałem zaznaczyć, że według mnie lepiej użyć tabeli tymczasowej.
0

wszyscy mnie tutaj przekonują żeby nie robić tak jak chciałem.
Ale w końcu zrobiłem dostęp do KBM z poziomu fastreporta.
Położony jest na DataModule, więc jest widoczny w każdym oknie, a następnie z poziomu wydruku dodaję do niego pola i obsługę dodawania, usuwania i edycji rekordów.
I bardzo mi to ułatwiło wiele skomplikowanych podsumowań na wydrukach.

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

Generalnie jest ok, chociaż nie do końca. Bo używasz zmiennych globalnych. Wydaje się, że takie projektowanie programów jest ok, ale wcześniej czy później zemści się.

0

Okno wydruku jest modalne, więc nie da się zrobić dwóch wydruków jednocześnie, więc nie powinno być problemów.
Już kilka razy wykorzystałem ten komponent i wszystkie wydruki działają pięknie.

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 dni
  • Postów:1083
0

Ale tu nie chodzi o modalność/niemodalność. Wprowadzanie zmiennych globalnych tylko dlatego, że wygodnie jest ich używać podczas design-time jest złe. Ja wiem, cała biblioteka VCL polega na tych zmiennych i to moim zdaniem jest jej poważny minus. Popatrz, że wszędzie (nawet na tym forum) odradza się używanie zmiennych globalnych. Wprowadzają one (czasem) niejawne zależności oraz przy bardziej skomplikowanych systemach mogą prowadzić do trudnych do wyłowienia błędów.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.