Odczytanie z ListView SubItemu oraz wyszukanie we wszystkich SubItemach największej liczby

0

Witam.
Mam problem z tym, aby po naciśnięciu buttonu "Dodaj" dodać wiersz, który w pierwszej kolumnie miałby liczbę większą o jeden od liczby z poprzedniego wiersza w listview. Mogę usuwać na liście jakieś wiersze, dlatego w pierwszej kolumnie nie muszę mieć dokładnie od 1 do iluś tam (np. mam 10 wierszów numerownaych od 1 do 5 i od 7 do 11).

Na początku tak miałam:

for i := 0 to listanazwisk.items.count-1 do

Jednak to odpada, ponieważ po dodaniu nowego wiersza pierwsza kolumna od nowa odlicza (uzupełnia luki między numerami, np. 7 staje się 6 itd nie ignerując w pozostałe kolumny), a nie chcę, by wiersze zmieniały swoje numery.

Próbowałam tak:

var
 i, liczba: integer;
 last : string;

begin
    item := listanazwisk.Items.Add;
    liczba := listanazwisk.items.count;

  last := listanazwisk.Items[liczba].Caption ;

    item.caption := last+1;
    item.SubItems.Add(nazwisko);
    item.SubItems.Add(imie);

Jednak to nie działa.

Co robię źle? Jak mogę inaczej zrobić tak, aby item caption był zależny od ostatniego wiersza (zatem wiadomo wtedy, że jest w items[listanazwisk.items.count] czy jakoś tak. Chciałabym właśnie ten subitem z ostatniego wiersza z pierwszej kolumny odczytać (zatem to komórka w "items.count"-tym wierszu) 1 dodać 1 dla kolejnego wiersza.

Jak to zrobić?
Dziękuję.

0

Za późna pora albo po prostu to co napisane jest powyżej to jakiś bełkot. Napisz normalnie przykłady: co jest w Itemach/SubItemach. I co ma być. Bo jakim cudem chcesz do string dodać +1, jakby to był integer? Jedno wielkie WTF! Musisz po prostu poczytać podstawy zanim się weźmiesz za programowanie czegokolwiek. Taki kod jak poniżej działa bez problemu:

var
  I : integer;
  LI : TListItem;
begin
  I := ListView1.Items.Count;
  LI := ListView1.Items.Add;
  LI.Caption := IntToStr(I + 1);
end;

Natomiast jeżeli chcesz operować na czymś, co znajduje się w danym Itemie, ale w kolumnie o Indeksie wyższym od zera. To należy się odwoływać raczej w taki sposób:
Items.Item[IndekxItema].SubItems[IndeksSubItema]

A wątek przenoszę do Newbie, bo z tego co widzę dotyczy on podstaw programowania w Delphi. I to banalnych. Póki dział Newbie istnieje w takiej formie jak istnieje, tam należy pisać z takimi, powielanymi mnóstwo razy, banalnymi do ogarnięcia i prostymi do znalezienia w Google rzeczami! A nie tutaj!!!

P.S.: i jeszcze raz dostrzegę takie tagowanie "wzięte z czterech liter". Czyli powielanie słów z tematu, jakieś powielanie delphi jako delphi7. Będę nieugięty. Ponieważ nie raz prosiliśmy o tagowanie z głową, wstawianie kodu w konkretne znaczniki i inne. Nie chcecie się dostosowywać, mając nasze prośby w poważaniu. Trudno. Taki wątek poleci do Kosza i tyle.

0

Dziękuję za próbę pomocy. Wiem, że ten kod działa, ale właśnie nie to miałam na myśli. Rzeczywiście zaczynam od podstaw i na początku miałam malutką aplikację, gdzie tylko dodawałam po nazwisku za pomocą buttona "Dodaj" z jednego edita do listview. Jednak powoli ulepszałam tę aplikację, bawiąc się, dodając kolejne edity i kolumny w listview, później także zrobiłam możliwość zapisania listy i wczytania jej. Mam też możliwość usunięcia zaznaczonego wiersza.

Załóżmy, że dodałam 12 osób, zatem było 12 wierszy, zapisałam ją, następnego dnia wczytałam tę listę, usunęłam z niej osoby o numerach 6 i 10, później zapisałam i taką listę wczytałam przy następnym uruchomieniu aplikacji.

Załóżmy, że tak to na razie wygląda, bo mam 10 osób:

1 / Kowalska / Anna
2 / Kowal / Julia
3 / Nowak / Maria
4 / Nowakowski / Jan
5 / Kowalski / Karol
7 / Pawłowski / Paweł
8 / Nowak / Anna
9 / Nowakowska / Kachna
11 / Nowakówna / Ewa
12 / Kowalczyk / Mariusz

Jak widać, już nie ma wierszy o numerach 6 i 10, ale nadal chcę, aby każda z tych osób zawsze miała ten sam numer przy swoim imieniu, więc mi nie przeszkadzają te brakujące wiersze, niech tak sobie zostaną na razie. Jednak chcę, aby teraz po dodaniu nowego nazwiska w pierwszej kolumnie był numer o jeden większy od ostatniego. Aby to zrobić, chcę, aby program odczytał, co się znajduje w ostatniej komórce w pierwszej kolumnie i dodał do niego 1.

Gdybym tak zrobiła, jak to wskazałeś (a tak już próbowałam wcześniej), to wtedy numerem wiersza nowej 11-stej osoby nie byłby 13, ponieważ program wyliczył, że miałam 10 wierszy. W przyszłości mogę mieć 50 osób, a ostatnim numerem byłby 70, ponieważ usunęłam ze srodka listy 20 osob.

Aby sprawdzić, czy to działa, podstawiając w indeks itema jakąś znaną już cyfrę.

item := listanazwisk.Items.Add;
i := listanazwisk.Items.Count;
j := listanazwisk.Items.Item[2].Caption;
item.Caption := j;

Tutaj rzeczywiście po dodaniu nowego nazwiska jego numerem będzie ten sam co w wierszu o indeksie 2 (wiem, że program liczy od 0).

Jak ładnie zapisać, aby zamiast tej 2 mieć to "i" i dodać do całosci 1, aby nowe nazwisko miało id większy o jeden od ostatniego nazwiska? Różnie próbowałam i program zgłaszał błąd lub numer w ogóle nie był pokazywany.
Dziękuje.

2

Chyba może być tak:

var
  item: TListItem;
  count: Integer;
  index: Integer;
begin
  index:= 1; //domyslnie numeracja zaczyna sie od 1
  count:= ListView1.Items.Count;
  if count > 0 then
    index:= StrToInt(ListView1.Items[count - 1].Caption) + 1;
  item:= ListView1.Items.Add;
  item.Caption:= IntToStr(index);
  item.SubItems.Add('blabla');
  item.SubItems.Add('blabla');
end;
2

Może w takim razie zastanów się nad:

var index:Integer;
begin
  index:=ListView1.Tag+1; //domyslnie numeracja zaczyna sie od 1
  with ListView1.Items.Add do
  begin
    Caption:=IntToStr(index);
    SubItems.Add('blabla');
    SubItems.Add('blabla');
  end
  ListView1.Tag:=index;
end;
0

Zamiast zakładać kolejny wątek uznałam, że lepiej w swoim wątku zadam kolejne podobne pytanie. Otóż teraz dodałam możliwość posortowania wg dowolnej kolumny po kliknięciu w nagłówek kolumny w ListView. Jak pewnie sami się domyślacie - po posortowaniu według imienia pomieszałam kolejność wierszy.

Załóżmy, że po posortowaniu mam tak:

1 / Kowalska / Anna
8 / Nowak / Anna
11 / Nowakówna / Ewa
4 / Nowakowski / Jan
2 / Kowal / Julia
9 / Nowakowska / Kachna
5 / Kowalski / Karol
3 / Nowak / Maria
12 / Kowalczyk / Mariusz
7 / Pawłowski / Paweł

Zatem teraz muszę zrobić to tak, aby po dodaniu nowego wiersza on miał numer o jeden większy od największej liczby w pierwszej kolumnie. Dotąd nie miałam sortowania, ale teraz już mam i ono niezbyt ładnie sortuje akurat liczby (bo np. 1,10,11,2,3,..), zatem odpada automatyczne sortowanie wg pierwszej kolumny (po naciśnięciu "Dodaj nazwisko") i dopiero potem dopisanie tego nazwiska.

Niestety jednak nie wiem jak za to się zabrać, rozumiem, że potrzeba tu zrobić pętli, żeby program znalazł największą liczbę w pierwszej kolumnie. By to ułatwić, może zacząć od liczby wierszy (nie będzie to możliwe, aby numer nowego wiersza był mniejszy niż suma wierszy). Zaczęłam od przeszukiwania google, by się dowiedzieć o pętlach.

Ostatecznie spróbowałam zakodować to tak, by nie wywalał żadnego erroru:

var
  i,max, count, index: integer;
  item: TListItem;

begin
  index:= 1; 
  item:= ListView1.Items.Add;
  max:= ListView1.Items.Count;
  
for i:=0 to ListView1.Items.Count-1 do
  begin
    if StrToInt(ListView1.Items[i].Caption) < max then
      begin
      end
    else
      begin
       index:=StrToInt(ListView1.Items[i].Caption) + 1;
       break;
      end;
    end;

  item.Caption:= IntToStr(index); //dodawanie wiersza
  item.SubItems.Add('blabla');
  item.SubItems.Add('blabla');
end;

Efekt pozornie jest taki jakiego oczekiwałam, po pomieszaniu wierszy (np. posortowani uwg nazwisk) to rzeczywiście po dodaniu nowego nazwiska jego numer jest większy od ejdne od najwiekszej liczby w tej samej kolumnie, ale jeśli usunę jakiś dowolne wiersze to wtedy i dodam znów jakieś nazwiska to wtedy numer się powtarza lub jest mniejszy od większego. Zatem mój kod w ogóle nie jest prawidłowy. Jak poprawnie trzeba napisać kod z pętlą lub warunkiem? Dziękuję.

0

A co ma w ogóle robić ta pętla? :

for i:=0 to ListView1.Items.Count-1 do
  begin
    if StrToInt(ListView1.Items[i].Caption) < max then
      begin
      end
    else
      begin
       index:=StrToInt(ListView1.Items[i].Caption) + 1;
       break;
      end;
    end;

Po pierwsze to niepotrzebnie dwa razy dokonujesz konwersji funkcją StrToInt, po drugie - niepotrzebnie zostawiasz pusty blok w warunku, zamiast po prostu zmienić operator do porównania:

var
  intMax, intCaption: Integer;

{...}

intMax := -1;

for I := 0 to ListView1.Items.Count - 1 do
begin
  intCaption := StrToInt(ListView1.Items[I].Caption);

  if intCaption >= intMax then
    intMax := intCaption + 1;
end;

Nie wiem natomiast po co to, skoro po usunięciu itema z numerem nienajwiększym zrobi się dziura w indeksach, bo zawsze wyszukujesz wartość maksymalną, a nie pierwszą wolną (chyba że to nie przeszkadza);

W każdym razie kolejny wolny indeks lepiej by było trzymać w jakimś polu czy we właściwości Tag komponentu (lub gdziekolwiek indziej), niż w kółko go wyszukiwać.

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