Vypočítání průměru v sloupci ListView.   zodpovězená otázka

VB.NET

Dobrý den,

chtěl bych poprosit o radu.Mám udělanej ListView,v něm 12 řádků(měsíce v roku)a 8 sloupců.

Hodnoty si v jednotlivých sloupcích umím spočítat,ale neumím vypočítat průměr.Uvádím příklad:mám hodnoty za leden,únor,březen a duben a potřeboval bych,aby mi je program vydělil čtyřma(abych dostal ten průměr).Zde zasílám kousek mého kódu :

Dim soubor As New IO.StreamReader("database1.txt") 'načtení vstupu a otevření souboru

While Not soubor.EndOfStream 'číst,dokuď nejsme na konci souboru

Dim datum As DateTime = CDate(soubor.ReadLine()) 'načíst první řádek - datum

Dim Ludek2015 As Single = CSng(soubor.ReadLine()) 'načíst druhý řádek - Luděk 2015

Dim Ivka2015 As Single = CSng(soubor.ReadLine()) 'načíst třetí řádek - Ivka 2015

Dim Ludek2016 As Single = CSng(soubor.ReadLine()) 'načíst čtvrtý řádek - Luděk 2016

Dim Ivka2016 As Single = CSng(soubor.ReadLine()) 'načíst pátý řádek - Ivka 2016

Dim Ludek2017 As Single = CSng(soubor.ReadLine()) 'načíst šestý řádek - Luděk 2017

Dim Ivka2017 As Single = CSng(soubor.ReadLine()) 'načíst sedmý řádek - Ivka 2017

Dim Ludek2018 As Single = CSng(soubor.ReadLine()) 'načíst osmý řádek - Luděk 2018

Dim Ivka2018 As Single = CSng(soubor.ReadLine()) 'načíst devátý řádek - Ivka 2018

Dim polozka As New ListViewItem() 'přidat položku do seznamu

polozka.Text = datum 'vypsat datum

polozka.SubItems.Add(Ludek2015) 'přidat druhý sloupec - Luděk 2015

polozka.SubItems.Add(Ivka2015) 'přidat třetí sloupec - Ivka 2015

polozka.SubItems.Add(Ludek2016) 'přidat čtvrtý sloupec - Luděk 2016

polozka.SubItems.Add(Ivka2016) 'přidat pátý sloupec - Ivka 2016

polozka.SubItems.Add(Ludek2017) 'přidat šestý sloupec - Luděk 2017

polozka.SubItems.Add(Ivka2017) 'přidat sedmý sloupec - Ivka 2017

polozka.SubItems.Add(Ludek2018) 'přidat osmý sloupec - Luděk 2018

polozka.SubItems.Add(Ivka2018) 'přidat devátý sloupec - Ivka 2018

ListView1.Items.Add(polozka) 'přidat položku do seznamu

End While

soubor.Close()

Dim soucet1, soucet2, soucet3, soucet4, soucet5, soucet6, soucet7, soucet8 As Single

For i As Object = 0 To ListView1.Items.Count - 1

soucet1 = soucet1 + CSng(ListView1.Items(i).SubItems(1).Text)

soucet2 = soucet2 + CSng(ListView1.Items(i).SubItems(2).Text)

soucet3 = soucet3 + CSng(ListView1.Items(i).SubItems(3).Text)

soucet4 = soucet4 + CSng(ListView1.Items(i).SubItems(4).Text)

soucet5 = soucet5 + CSng(ListView1.Items(i).SubItems(5).Text)

soucet6 = soucet6 + CSng(ListView1.Items(i).SubItems(6).Text)

soucet7 = soucet7 + CSng(ListView1.Items(i).Subitems(7).Text)

soucet8 = soucet8 + CSng(ListView1.Items(i).SubItems(8).Text)

Next

TextBox2.Text = CStr(soucet1 & (" Kč "))

TextBox4.Text = CStr(soucet2 & (" Kč "))

TextBox6.Text = CStr(soucet3 & (" Kč "))

TextBox8.Text = CStr(soucet4 & (" Kč "))

TextBox10.Text = CStr(soucet5 & (" Kč "))

TextBox12.Text = CStr(soucet6 & (" Kč "))

TextBox14.Text = CStr(soucet7 & (" Kč "))

TextBox16.Text = CStr(soucet8 & (" Kč "))

TextBox1.Text = CStr(soucet1 / 12 & (" Kč ")) " zde mi to průměr vypocítá,ale jenom pokuď

TextBox3.Text = CStr(soucet2 / 12 & (" Kč ")) mám hodnoty ve všech řádcích(měsících).

TextBox5.Text = CStr(soucet3 / 12 & (" Kč "))

TextBox7.Text = CStr(soucet4 / 12 & (" Kč "))

TextBox9.Text = CStr(soucet5 / 12 & (" Kč "))

TextBox11.Text = CStr(soucet6 / 12 & (" Kč "))

TextBox13.Text = CStr(soucet7 / 12 & (" Kč "))

TextBox15.Text = CStr(soucet8 / 12 & (" Kč "))

End Sub

Dopředu děkuji za radu.

S pozdravem Luděk.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím, je mi to povědomé... koukni sem plus pokus níže malá obměna:

http://www.dotnetportal.cz/forum/tema/35...

Dim prumer1 As Decimal = AvgColumnNumbers( ListView1, 1)
Dim prumer2 As Decimal = AvgColumnNumbers( ListView1, 2)
'...

Odkrokuj si funkci, průměr vypočítá jen z použitelných hodnot.

Např. prázdné a nepřeveditelné na číslo bude ignorovat, takže

máte-li připraveno 12 řádků pro každý měsíc, ale zatím zadané

jenom 4, neboť je duben, měl by být počet count_ být právě 4,

tudíž se bude součet dělit jen 4, v květnu 5 a pokud některé

hodnoty zůstanou přeskočeny resp. vynechány, součet bude pouze

z hodnot, kde se povede převést na číslo a dělit jejich počtem.

    Function AvgColumnNumbers(ByVal lv As ListView, ByVal columnIndex As Integer) As Decimal
        Dim sum_ As Decimal, count_ As Integer
        For i As Integer = 0 To lv.Items.Count - 1
            Dim n As Decimal
            If Decimal.TryParse(lv.Items(i).SubItems(columnIndex).Text, n) Then
                sum_ += n
                count_ += 1
            End If
        Next
        Return sum_ / count_
    End Function

...

Nalezneš zde spoustu dalších řešení, nahoře klepni hledat na webu a hledej listview.

...

Z textového souboru lze úplně stejně naplnit datatable a předat skrze source,

namátkou koukni na listview příspěvky na faru a datagridview s vařením piva :

http://www.dotnetportal.cz/forum/tema/15...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

píšu trošku později,ale přece.Moc děkuji za radu,vše funguje jak má.

S pozdravem a přáním krásného dne Luděk.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak to je moc fajn, že to pomohlo a funguje k plné spokojenosti.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

mám ještě jeden problém s tím průměrem v ListView.Jakmile vyplním první sloupec(12 řádků),pak mi v ostatních sloupcích taky dělí 12-tma.Potřeboval bych,aby byli v dalších sloupcích kolonky prázdné.Jelikož já používám NumericUpDown v Dialogu mám tam pořád nulu.Nevím,jestli jsem to napsal dost srozumitelně.

Za případnou radu dopředu děkuji.

Luděk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Chcete-li ignorovat nulové hodnoty ve výpočtu průměru, pak si přece můžete funkci upravit.

Zkuste si tam přidat podmínku pro nenulové (n<>0) nebo kladné (n>0) hodnoty, např. :

Function AvgColumnNumbers(ByVal lv As ListView, ByVal columnIndex As Integer) As Decimal
    Dim sum_ As Decimal, count_ As Integer
    For i As Integer = 0 To lv.Items.Count - 1
        Dim n As Decimal
        If Decimal.TryParse(lv.Items(i).SubItems(columnIndex).Text, n) Then
            If n <> 0 Then
                sum_ += n
                count_ += 1
            End If
        End If
    Next
    Return sum_ / count_
End Function
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

Vaše odpověď je logická,ale i po úpravě funkce to nefunguje.Vypsalo mi ti chybu " Došlo k pokusu o dělení nulou." (V řádku Return sum_ / count_)

P.S.Dík za trpělivost.

Luděk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

tak přidávám ještě pokus se zbavit chyby a vyhnout se dělení nulou :

Dim prumer_nenulovych_hodnot As Decimal = AvgColumnNumbers( ListView1, 1)

    Function AvgColumnNumbers(ByVal lv As ListView, ByVal columnIndex As Integer) As Decimal
        Dim sum_ As Decimal, count_ As Integer
        For i As Integer = 0 To lv.Items.Count - 1
            Dim n As Decimal
            If Decimal.TryParse(lv.Items(i).SubItems(columnIndex).Text, n) Then
                If n <> 0 Then
                    sum_ += n
                    count_ += 1
                End If
            End If
        Next
        If count_ > 0 Then Return sum_ / count_
    End Function

Pokus se zbavit chyby, vyhnout se dělení nulou,

obměna užitím listu a volitelně vymechat nuly :

Dim prumer_jinak As Decimal = AverageColumnNumbers(lv, 2, True)

    Function AverageColumnNumbers(ByVal lv As ListView, ByVal columnIndex As Integer, Optional ByVal ExcludeZeros As Boolean = False) As Decimal
        Dim al As New List(Of Decimal)
        For i As Integer = 0 To lv.Items.Count - 1
            Dim n As Decimal
            If Decimal.TryParse(lv.Items(i).SubItems(columnIndex).Text, n) Then
                If Not (ExcludeZeros AndAlso n = 0) Then
                    al.Add(n)
                End If
            End If
        Next
        If al.Count > 0 Then Return al.Average()
    End Function

Pořádně otestujte, zda-li vrací správné výsledky a nedojde-li znovu k nějakým nepředpokládaným stavům. Snad už to projde... ;)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Také můžete použít LINQ, třeba se příklad bude líbit :

    Function ColumnAverageWhereNumbers(ByVal lv As ListView, ByVal columnIndex As Integer, Optional ByVal ExcludeZeros As Boolean = False) As Decimal
        Dim ld As List(Of Decimal)
        If ExcludeZeros Then
            ld = (From lvi As ListViewItem In lv.Items
                Where IsNumeric(lvi.SubItems(columnIndex).Text) AndAlso Decimal.Parse(lvi.SubItems(columnIndex).Text) <> 0
                Select Decimal.Parse(lvi.SubItems(columnIndex).Text)).ToList
        Else
            ld = (From lvi As ListViewItem In lv.Items
                Where IsNumeric(lvi.SubItems(columnIndex).Text)
                Select Decimal.Parse(lvi.SubItems(columnIndex).Text)).ToList
        End If
        If ld.Count > 0 Then Return ld.Average
    End Function

Obdobně jako nyní pro Average lze použít třeba taky pro výpočet Sum ,Min Max ...

Podmínka může být složitější, např. v prvním sloupci řádky, kde je Luděk a z druhého sloupce vrátit Max, záleží na vaší potřebě a fantazii. Mohlo by to být k užitku...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

moc děkuji za odpověď.Skoušel jsem první i druhou možnost,obě vypadají nadějně.Jenom,pokuď spustím debug a dám odebrat položku(žádná ale není označena,tak mně to vyhodí s poznámkou : InvalidArgument = Hodnota 0 není platnou hodnotou pro argument index.

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

If ListView1.Items.Count = 0 Then Exit Sub 'pokud není vybrána žádná položka,nic nemazat

ListView1.Items.Remove(ListView1.SelectedItems(0)) - chybové hlásení mně odkáže na tenhle řádek.

Ale to počítání průměru funguje perfektně.Jěště jednou moc dík.

S pozdravem a hezký večer

Luděk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pro odebrání listitem z listview by mohlo pomoct :

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

'pokud nejsou v listview žádné položky neni vlastne co mazat
If ListView1.Items.Count = 0 Then Exit Sub 

'pokud není vybraná žádná položka, neni mozne ji odebrat
If Not ListView1.SelectedItems(0) Is Nothing Then 
    ListView1.Items.Remove(ListView1.SelectedItems(0))
End If

End Sub
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

skoušel jsem Vaši poslední radu,ale nějak mi to nešlo.Pak mě napadlo použít Try ... Catch a ono to funguje.

Try

ListView1.Items.Remove(ListView1.SelectedItems(0)) 'pokud není vybrána žádná položka,nic nemazat

Catch

MsgBox("Nebyla vybrána žádná položka !")

End Try

Moc děkuji za pomoc.Teď mám v pláně vytvořit si k ListView graf.Snáď se mi to podaří.Dám vědět.

S pozdravem Luděk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

mám ještě jeden malý problém.Pokouším se sčítat hodnoty ne ve sloupcích,ale v jednotlivých řádcích.Ale bohužel nějak na to nemůžu přijít.Mohl by mi někdo poradit ?

Dopředu pěkně děkuji.S pozdravem Luděk.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback