# Zeitleiste Grafisch darstellen Vb.net



## werner_sg (2. Juli 2021)

Hallo habe mal etwas wo ich nicht mal Ansatzweise was zu gefunden habe.

ich habe in meiner Access Tabelle jeweils einen Anfangs und einen Endzeitpunkt das ganze würde ich gerne grafisch darstellen also in einer art Linien Diagramm

Jede Zeile verfügt wie gesagt über Start und Endzeitpunkt sowie das Fahrzeug

für jedes Fahrzeug sollte eine Zeitreihe mit den Daten entstehen, ich hänge mal ein Bild drann zum besseren Verständnis.

für jeden Wink mit dem Zaunpfahl wäre ich dankbar


----------



## Spyke (6. Juli 2021)

PicureBox und Paint Ereignis abonnieren und dort mit dem Graphics Objekt aus dem EventArgs zeichnen.
Die Breite deiner PictureBox wären 100% anhand derer du die zeiteinteilung des Fahrzeugs berechnen/zeichnen könntest


----------



## werner_sg (6. Juli 2021)

Ich hatte auch eventuell überlegt eine reihe von buttons oder ähnliches anzulegen und diese dann je nach ergebnis der sql abfrage umzufärben.

ich bräuchte dann aber x Reihen die sich erst aus der Abfrage ergeben

Das ganze dann in einem Panel mit Scrollbalken

Zu deiner Variante bin ich aber auch gerade am Infos sammeln ;-)


----------



## Zvoni (6. Juli 2021)

Das mit PictureBox/Paint-Ereignis ist eigentlich der einfachere Teil.
Das schwierige wird dann eher die Mathematik dahinter sein.
Die PictureBox dürfte eine fixe Breite haben,
linker Rand = "Von"-Datum
rechter Rand = "Bis"-Datum
Falls der Zeitraum variabel ist (Falls das mit deinem Datenbank-Thread zu tun hat), musst du dann erst Tage auf Twips/Pixel/WasAuchImmer umrechnen, und dann mit diesen Einheiten weiterrechnen.

Ich hatte mal in FreePascal/Lazarus so was ähnliches gemacht, aber da gings um die Zeitleiste eines Videos, in welcher man einen Cut-In und einen Cut-Out definieren konnte.
Das grafische Zeug war einfach, aber das Umrechnen der Position(en) war ein Alptraum


----------



## werner_sg (6. Juli 2021)

Was mir am meisten Gedanken macht ist die horizontale Anordnung.

Die Daten filtern und zuordnen wird der einfachste Punkt.

Einfach eine Liste pro Fahrzeugnummer mit allen start und endpunkten, ein Fahrzeug Kann ja im Monat oder Jahr mehrere haben.

Das dann aber horizontal grafisch darstellen


----------



## Zvoni (6. Juli 2021)

Das ist ja das was ich meine.

Stell dir vor, die PictureBox is 10.000 breit (in welcher Einheit auch immer)
und der Zeitraum den du auswertest ist 100 Tage (beginnend am 01.07.2021)
Ergo entsprechen 100 PictureBox-Einheiten (PB-Einheiten) einem Tag deines Zeitraums
Bedeutet, wenn für Fahrzeug BMW320 du eine Reservierung am 03.07.2021 für einen Tag hast, wäre
die linke Position des Farbbalkens 200 PB-Einheiten, die rechte Position bei 300 PB-Einheiten
usw.


----------



## Spyke (6. Juli 2021)

Aufjedenfall keine Buttons oder anderweitige Controls zu hauf auf ein Formular packen.
Dies wird die Performance deines Fenster runterziehen und das Problem mit dem ausrechnen der Zeitlinie würde dir so und so nicht erspart bleiben.

Sie die Zeiten einfach als fixe Punkte.
z.B. deine PictureBox ist 200 Pixel breit das wären unser 100% horizontaler Zeichnugnsbereich

Auto A fährt von 08 bis 12 Uhr und wieder von 17 bis 18 Uhr.
Wenn wir von ausgehen das ein Tag nur 24 Stunden hat wären dies unsere 100% eines Tages welches wir nur in die einzelnen abschnitte aufteilen müssen.

Ganz einfach könntest du dir es hier mit TimeSpan machen wenn wir einfach die Eigenschaft Ticks zur Hilfe nehmen.

```
TimeSpan tagGesamt = new TimeSpan(23, 59, 59); //usnere 24 Stunden, die 100%

            TimeSpan fahrt1Beginn = new TimeSpan(8, 0, 0);
            TimeSpan fahrt1Ende = new TimeSpan(12, 0, 0);

            decimal tag1BeginnProzent = (fahrt1Beginn.Ticks / (decimal)tagGesamt.Ticks); //wichtig ein Wert nach decimal casten sosnt bekommen wir keine nachkommastellen
            decimal tag1EndeProzent = (fahrt1Ende.Ticks / (decimal)tagGesamt.Ticks);

            TimeSpan fahrt2Beginn = new TimeSpan(17, 0, 0);
            TimeSpan fahrt2Ende = new TimeSpan(18, 0, 0);

            decimal tag2BeginnProzent = (fahrt2Beginn.Ticks / (decimal)tagGesamt.Ticks);
            decimal tag2EndeProzent = (fahrt2Ende.Ticks / (decimal)tagGesamt.Ticks);

            int bildBreite = 200;

            //die Prozente umrechnen auf unser Bild
            Rectangle recFahrt1 = new Rectangle((int)(tag1BeginnProzent * bildBreite), 0, (int)((tag1EndeProzent * bildBreite) - (tag1BeginnProzent * bildBreite)), 10);
            Rectangle recFahrt2 = new Rectangle((int)(tag2BeginnProzent * bildBreite), 0, (int)((tag2EndeProzent * bildBreite) - (tag2BeginnProzent * bildBreite)), 10);
```


Nachtrag:
Alternativ vom DateTime die Ticks Eigenschaft verwenden wenn Zeitleiste in Verbindung auch mit Datumsangaben.
Dann sollteste aber ein Maximales Endedatum für die Zeitliste definieren, z.B. nur immer eine Woche im Voraus oder so.


----------



## werner_sg (11. Juli 2021)

Spyke hat gesagt.:


> Aufjedenfall keine Buttons oder anderweitige Controls zu hauf auf ein Formular packen.
> Dies wird die Performance deines Fenster runterziehen und das Problem mit dem ausrechnen der Zeitlinie würde dir so und so nicht erspart bleiben.


So weiter im Text   hatte erst mal alles andere vorgezogen und fertiggestellt-

habe das soweit verstanden, und mir zusätzlich noch einigen Quellen dazu durchgeschaut.

Knackpunkt:

es bestehen eventuell mehrere Reihen in der Datenbank für ein Fahrzeug

z.B. Zeile 17 Fahrzeug 1 vom 12.8.2021 bis 23.8.2021 ebenso Zeile  43 vom 31.8.2021 bis 12.09.2021 und auch noch Zeile 51 vom 15.09.2021 bis 30.09.2021

hier gillt es in diesem Fall ja auch erst mal jede Zeile oder Row zu prüfen und dann in einer Datatable oder in einem Datagrid alles zusammen in einer Zeile darzustellen

Der TimeSpan Gesamt  wäre in meinem Fall / TimeSpan MonatGesamt = new TimeSpan(31)

Den folgenden Block benötige ich sicherlich nicht oder?


```
decimal tag1BeginnProzent = (fahrt1Beginn.Ticks / (decimal)tagGesamt.Ticks); //wichtig ein Wert nach decimal casten sosnt bekommen wir keine nachkommastellen
            decimal tag1EndeProzent = (fahrt1Ende.Ticks / (decimal)tagGesamt.Ticks);
```
weil ich ja keine Kommazahlen haben werde

int bildBreite = 200; würde ich auf 620 setzen dann habe ich für jeden tag dann  20

das eingemachte


```
Rectangle recFahrt1 = new Rectangle((int)(fahrt1Beginn * bildBreite), 0, (int)((fahrt1EndeProzent * bildBreite) - (fahrt1Beginn * bildBreite)), 10);
```

hier müsste ja eigentlich ein Grundgerüst hin, welches sich per Bedarf erweitert

Prüfe ob Farzeug 1 mehrfach vorhanden ist (wenn eine vorsortierung und abbildung nebeneinander im datagrid oder Datatable nicht so einfach möglich)
wenn ja dann für jede Zeile das Bild berechnen
wenn nein nur den einzelnen Antrag anzeigen

Dann zur nächsten vorhanden Fahrzeug Nummer springen und das ganze wiederholen

Die Möglichkeit vorher zu wissen oder festzulegen wieviele Reihen man braucht gibt es nicht es werden immer X Fahrzeuge und X einträge pro Fahrzeug im Monat sein

Werde heute mal dafür zum spielen und testen eine Extra Form dafür erstellen

in das Programm werde ich an diese Stelle solange mal die Excel Datei einbinden und darstellen lassen in der das bisher per Hand gepflegt wird.

Freue mich über hilfreiche und anregende Infos und Beiträge


----------



## Zvoni (12. Juli 2021)

Würde erst mal per SQL Min- und Max-Datum pro Fahrzeug ziehen, und aus diesem Ergebnis noch einmal Min- und Max-Datum ziehen (nicht pro Fahrzeug), Es sei dann du gibst die Grenzen "manuell" an

Fahrzeug 1: 01.08.2021 bis 31.08.2021
Fahrzeug 2: 15.08.2021 bis 10.09.2021
Fahrzeug 1: 15.09.2021 bis 30.09.2021
Fahrzeug 2: 20.09.2021 bis 16.10.2021

Erste Abfrage:
Fahrzeug 1: Min=01.08.2021 - Max=30.09.2021
Fahrzeug 2: Min=15.08.2021 - Max=16.10.2021

Zweite Abfrage
Min=01.08.2021 - Max=16.10.2021

Mit der zweiten Abfrage erhälst du dann den "notwendigen" Platz den du brauchst um ihn im Bild darzustellen. Der Rest ist dann nur Skalierung.

Prinzipiell würde ich immer versuchen, so viel wie möglich direkt aus der Datenbank zu holen (im Beispiel die Gruppierung pro Fahrzeug), und so wenig wie möglich "Nachbereitung" im Frontend

EDIT: Je länger ich mir das anschaue, desto mehr denke ich dass du sowas wie ein Pivot brauchst, und da wirds dann 3-Dimensional
Auf Anhieb wüsste ich jetzt zwei Varianten:
Abfrage auf die Fahrzeug-Haupt-Tabelle (Wo ein Fahrzeug hoffentlich UNIQUE ist) mit nem LEFT JOIN auf die Reservierungs-Tabelle inkl. COUNT
Beispiel Fahrzeug 1 und Fahrzeug 3 haben Reservierungen für den betrachteten Zeitraum, Fahrzeug 2 hat keine.
Ergebnis
Fahrzeug 1 - 4
Fahrzeug 2 - 0
Fahrzeug 3 - 2
Somit wüsstest du schon mal wieviele grafische Balken du pro Fahrzeug brauchst.
In einem zweiten Durchlauf holst du pro Fahrzeug (WHERE Fahrzeug=BMW320) die Reservierungsdaten DatumVon, DatumBis (WHERE (DatumVon BETWEEN UntereGrenze AND ObereGrenze) OR (DatumBis BETWEEN UntereGrenze AND ObereGrenze), sortiert nach EINEM der beide Daten (Ein Overlap kann ja theoretisch nicht stattfinden für ein und dasselbe Fahrzeug)

Die zweite Variante wäre ähnlich, jedoch alles schon fix und fertig per SQL holen.
Setzt jedoch voraus, dass die Datenbank (Access?) so etwas wie eine String-Aggregate-Funktion anbietet (was ich im Falle von Access bezweifel). Hier würde man sich den zweiten SQL-Durchlauf sparen können, da die Termine in einem String zurückgegeben werden, welchen man nur splitten müsste, und daraus resultierenden die Farbbalken anordnen/zeichnen.

Ich hoffe ich war verständlich


----------



## Spyke (13. Juli 2021)

Bei mir bräuchtest du die Nachkommastellen da ich dort Prozentual die Zeitleiste errechnet, wodurch dein Bild selbst eine X-beliebige Breite haben kann, die Aufteilung in der Zeitleiste erfolgt prozentual.

Da du mit Datumsangaben arbeitest und du glaube schonmal probleme mit TimeSpan hattest könnteste anstelle der TimeSpan Ticks auch einfach dein Datum als Zahl wandeln.
(Bei Datumsangaben passt TimeSpan eh auch nicht mehr)

z.B. der 10.09.2021 könntest du als Zahl 20210910 (JahrMonatTag) halten
errechnen könnte so aussehen

```
(((Year(meinDatum) * 10000) + Monath(meinDatum)) * 100) + Day(meinDatum)
```

Pseudocode mäßig könnte das ganze so aussehen

```
//minimum/kleinste Datum über alle Fahrzeuge, wandeln wir in eine Zahl
zeitleisteMin = (((Year(minimumDatum) * 10000) + Month(minimumDatum)) * 100) + Day(minimumDatum)

//maximum/höchste Datum über alle Fahrzeuge, wandeln wir in eine Zahl
zeitleisteMax = (((Year(maximumDatum) * 10000) + Month(maximumDatum)) * 100) + Day(maximumDatum)

//Minum abziehen damit wir unsere 100% zeitleiste haben (Achtung, unten wird auch Minimum immer abgezogen)
zeitleisteMaxBereich = zeitleisteMax - zeitleisteMin + 1

bildBreite = X

Liste FahrzeugeMitZeiten;
durchlaufe FahrzeugeMitZeiten (fahrzeug 1 bis N)
{
    fahrzeugNr = fahrzeug.Nummer
    fahrzeugBeginn = (((Year(fahrzeug.fahrt.beginn) * 10000) + Month(fahrzeug.fahrt.beginn)) * 100) + Day(fahrzeug.fahrt.beginn)
    fahrzeugEnde =(((Year(fahrzeug.fahrt.ende) * 10000) + Month(fahrzeug.fahrt.ende)) * 100) + Day(fahrzeug.fahrt.ende)
 
    prozentualBeginn = ((fahrzeugBeginn - zeitleisteMin) / zeitleisteMaxBereich);
    prozentualEnde = ((fahrzeugEnde - zeitleisteMin) / zeitleisteMaxBereich);
 
    Rechteck rec = neues Rechteck
    rec.Left = (prozentualBeginn * bildBreite)
    rec.Top = fahrzeugNr * 10
    rec.Width = ((prozentualEnde * bildBreite) - (prozentualBeginn * bildBreite))
    rec.Height = 10
 
    zeichnen.ZeichneRechteck(rec, Grün)
}
```


----------



## werner_sg (14. Juli 2021)

```
Private Sub PictureBox1_Paint()
    
        Dim rec As Graphics
        Dim x, y As Single
        rec = PictureBox1.CreateGraphics()
        
                Try
            Sql = "SELECT Fahrzeugnummer, Modell, Mietbegin, Mietende FROM tblreservierung"

            conn.Open()
            With dbcmd
                .CommandText = Sql
                .Connection = conn
            End With

            dbda.SelectCommand = dbcmd
            dbda.Fill(dbdt)
        -------------------------------------------------------------------
        
        'minimum/kleinste Datum über alle Fahrzeuge, wandeln wir in eine Zahl
        Dim zeitleisteMin = (((Year(Date.Now()) * 10000) + Month(Date.Now()) * 100) + Day(Date.Now()))

        'maximum/höchste Datum über alle Fahrzeuge, wandeln wir in eine Zahl
        Dim zeitleisteMax = (((Year(Date.Now()) * 10000 + 10000) + Month(Date.Now())) * 100) + Day(Date.Now())))

        'Minum abziehen damit wir unsere 100% zeitleiste haben (Achtung, unten wird auch Minimum immer abgezogen)
        Dim zeitleisteMaxBereich = zeitleisteMax - zeitleisteMin + 1

        Dim bildBreite = X

        Liste FahrzeugeMitZeiten
durchlaufe FahrzeugeMitZeiten(fahrzeug 1 bis N)
{
    Dim fahrzeugNr = "Fahrzeugnummer"
        Dim fahrzeugBeginn = (((Year("Mietbegin") * 10000) + Month("Mietbegin")) * 100) + Day("Mietbegin")
        Dim fahrzeugEnde = (((Year("Mietende") * 10000) + Month("Mietende")) * 100) + Day("Mietende")

        Dim prozentualBeginn = ((fahrzeugBeginn - zeitleisteMin) / zeitleisteMaxBereich)
        Dim prozentualEnde = ((fahrzeugEnde - zeitleisteMin) / zeitleisteMaxBereich)

        Dim rec = neues Rechteck
   Dim rec.Left = (prozentualBeginn * bildBreite)
   Dim rec.Top = fahrzeugNr * 10
    Dim rec.Width = ((prozentualEnde * bildBreite) - (prozentualBeginn * bildBreite))
    Dim rec.Height = 10

   Dim zeichnen.ZeichneRechteck(rec, Grün)
}
  
        
        -------------------------------------------------------------------
            
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            conn.Close()
        End Try

    End Sub
```

bin fleisig am suchen habe aber noch nicht so viel dazu gefunden

dein Code Beispiel lässt sich auch nicht einfach in Vb.net umwandeln daher sind da noch einige Fehler drinn

aber Mühsam ernährt sich halt das Eichhörnchen

der erste Schritt welchen ich nirgends richtig finde ist das übergeben an die PictureBox1 was ich dazu gefunden habe lässt sich im oberen Teil erkennen

im zweiten Teil mein Ansatz die Daten zur Vefügung zu stellen aus der Access Datenbank

Dann zwischen den Linien den grob angepassten Code von Dir 

Der Zeitleisten Anfang ist Date.Now*10000 und das Ende Date.Now*10000+10000 was 1 Jahr mehr ergibt

Hast du eine gute Quelle für VB.net zu dem Thema?


----------



## Spyke (14. Juli 2021)

das war Pseudocode was ich dir gab.
In die entsprechende VB Syntax mit den entsprechenden Befehlen müsstest es dann natürlich selbst umwandeln.

Da ich mit C# Programmier und nicht mit VB.Net hab ich mal kurz gegoggelt wie der Syntaktische Aufbau von Schleifen in VB.Net ist.
Für mein Schleifen Beispiel könntest es z.B. mit DO LOOP oder DO WHILE entsprechend anpassen
Visual Basic .NET: Einfache Schleifen – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher
oder hier noch was zur FOR Schleife
For...Next-Anweisung - Visual Basic
und FOREACH
For Each...Next-Anweisung - Visual Basic

Und wie man mit der PictureBox zeichnet könnteste hier mal schauen.
Control.Paint Ereignis (System.Windows.Forms)
(Sollte im Link die C# Syntax angezeigt sein, schau mal bissi über den Artikel da kannst du als Sprache dann auch VB auswählen)
Du musst nämlich das Paint Ereignis der PictureBox abonnieren und im EventArgs dann mit dem Graphics Objekt arbeiten.

Wie du an Tag, Monat und Jahr auf .Net Seite im DatetTime Objekt ran kommst sieht du hier
DateTime.Year Eigenschaft (System)
(Wieder, sollte im Link die C# Syntax angezeigt sein, schau mal bissi über den Artikel da kannst du als Sprache dann auch VB auswählen)


----------



## werner_sg (14. Juli 2021)

Spyke hat gesagt.:


> das war Pseudocode was ich dir gab.
> In die entsprechende VB Syntax mit den entsprechenden Befehlen müsstest es dann natürlich selbst umwandeln.
> 
> Da ich mit C# Programmier und nicht mit VB.Net hab ich mal kurz gegoggelt wie der Syntaktische Aufbau von Schleifen in VB.Net ist.
> ...


Ms ist ja immer sehr sparsam mit Erklärung ( Der Code zeichnet. Wieso und Warum ist ja mal egal)

Ok das mit dem Text ist logisch und kennt man von anderem ( warum aber das F oder bzw wofür steht es?)

```
' Draw a string on the PictureBox.
        g.DrawString("Zeitleiste folgt",
        fnt, Brushes.Red, New PointF(40.0F, 200.0F))
```
Das zeichnet die Linie ist ja fein egal was man ändert es bleibt bei einer Linie von links oben nach rechts unten oder es gibt gar nichts
Die Farbe ist klar wo nimmt er aber seine bezugspunkte her? im load Teil dockt er die PictureBox ja nur an


```
' Draw a line in the PictureBox.
        g.DrawLine(System.Drawing.Pens.BlueViolet, PictureBox1.Right,
        PictureBox1.Bottom, PictureBox1.Left, PictureBox1.Top)
```


----------



## werner_sg (15. Juli 2021)

Hab schon mal einen Teil erstellt

damit erhalte ich im Dim AnfangKurz und Dim EndeKurz das Datum in Form von 20210718

habs mir in der Textbox2 anzeigen lassen

Er zeigt selbstverständlich nur eine einzige Buchung an

der Versuch :
            DbReader = dbcmd.ExecuteReader
            dt.Load(DbReader)
scheitert kläglich da zur Ausführung der Reader schon geschlossen ist ????



```
Private Sub pictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)

        ' Variablen für die PictureBox.

        Dim g As Graphics = e.Graphics

        'der erste horizontale Abstand
        Dim horizontal = 50


        'Auswahl aus allen Buchungen
        conn.Open()

        Try
            dbcmd = New OleDbCommand("SELECT BuchungsNr, Kunde, Fahrzeugnummer, Modell, YEAR(Mietbegin) AS Jahr1, MONTH(Mietbegin) AS Monat1, DAY(Mietbegin) AS Tag1, YEAR(Mietende) AS Jahr2, MONTH(Mietende) AS Monat2, DAY(Mietende) AS Tag2 FROM tblreservierung ", conn)
            Dim DbReader As OleDbDataReader
            DbReader = dbcmd.ExecuteReader
            While DbReader.Read

                'Der Mietbegin als Zahl 20210518
                Dim JahrAnfang = (DbReader("Jahr1").ToString)
                Dim JahrAnfangI = Convert.ToDecimal(JahrAnfang)
                Dim MonatAnfang = (DbReader("Monat1").ToString)
                Dim MonatAnfangI = Convert.ToDecimal(MonatAnfang)
                Dim TagAnfang = (DbReader("Tag1").ToString)
                Dim TagAnfangI = Convert.ToDecimal(TagAnfang)
                Dim Anfang = ((JahrAnfangI * 10000) + (MonatAnfangI * 100) + TagAnfangI)

                'Das Mietende als Zahl 20210518
                Dim JahrEnde = (DbReader("Jahr2").ToString)
                Dim JahrEndeI = Convert.ToDecimal(JahrEnde)
                Dim MonatEnde = (DbReader("Monat2").ToString)
                Dim MonatEndeI = Convert.ToDecimal(MonatEnde)
                Dim TagEnde = (DbReader("Tag2").ToString)
                Dim TagEndeI = Convert.ToDecimal(TagEnde)
                Dim Ende = ((JahrEndeI * 10000) + (MonatEndeI * 100) + TagEndeI)

                Me.TextBox2.Text = Ende

                For Each Row As DataRow In dbdt.Rows

                    ' Zeitleisten für die PictureBox.

                    g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), Anfang, horizontal, Ende, horizontal)



                Next
                ' Text für die PictureBox.

                g.DrawString("Zeitleiste folgt",
            fnt, Brushes.Red, New PointF(40.0F, 200.0F))

            End While


            'Die Zeilenabfrage





        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            conn.Close()
        End Try








    End Sub
```


----------



## Spyke (15. Juli 2021)

wenn du das F meinst 40.0F, das F steht für float, sprich die 40.0 sollen als Datentyp float gehalten/behandelt werden

zu DrawString
Graphics.DrawString Methode (System.Drawing)

zu DrawLine
Graphics.DrawLine Methode (System.Drawing)

am besten erstell erstmal mal ein neues Projekt mit dem du mit den zeichnungselementen bissl rumspielen kannst.
Ändere dabei die Point Angaben (X,Y) und schau dir an was das Graphics Objekt noch für Methoden hat.
z.B. DrawRectangle
Graphics.DrawRectangle Methode (System.Drawing)
oder FillRectangle
Graphics.FillRectangle Methode (System.Drawing)
was ich eher zum Zeichnen einer Beginn/Ende Zeitangabe verwenden würde.


Er zeigt wahrscheinlich nur eine Buchung da ev. Anfang und Ende immer den gleichen Wert haben (müssteste mal im Debuggen Breakpoint setzen und die Werte anschauen und vorallem ob die Schleife auch öfters durchlaufen wird.


----------



## werner_sg (15. Juli 2021)

Spyke hat gesagt.:


> wenn du das F meinst 40.0F, das F steht für float, sprich die 40.0 sollen als Datentyp float gehalten/behandelt werden
> 
> zu DrawString
> Graphics.DrawString Methode (System.Drawing)
> ...


Ok dann verstehe ich jetzt auch das F in diesem Bezug konnte es nicht zuordnen.

Alles andere habe ich soweit voll verstanden er zeichnet auch was ich möchte und ihm gebe, und ich weis warum er es macht.

Was mich stört ist die Datenbank Anbindung ich hole mir ja die Daten mittels Reader

nur wenn ich mir jetzt mit : dt.Load(DbReader) die Daten für die Schleife ( For Each Row As DataRow In dt.Rows) holen möchte meckert er das der Reader bereits geschlossen ist

in dem geposteten Code ist noch eine andere datatable eingebunden, daher war das klar das dort nur eine Zeile vorhanden war und nicht mehr, hatte mich zum testen nicht gestört.


----------



## Spyke (15. Juli 2021)

Wie verwendest du genau dt.Load, verwendest du es in Verbindung mit der while Schleife (laut deinem oberen Code)?
Wenn ja ist ev. das problem das er den Reader quasi schon fertig gelesen hat


----------



## werner_sg (15. Juli 2021)

Spyke hat gesagt.:


> Wie verwendest du genau dt.Load, verwendest du es in Verbindung mit der while Schleife (laut deinem oberen Code)?
> Wenn ja ist ev. das problem das er den Reader quasi schon fertig gelesen hat


Also habe ich das load hier 

```
Try
            dbcmd = New OleDbCommand("SELECT BuchungsNr, Kunde, Fahrzeugnummer, Modell, YEAR(Mietbegin) AS Jahr1, MONTH(Mietbegin) AS Monat1, DAY(Mietbegin) AS Tag1, YEAR(Mietende) AS Jahr2, MONTH(Mietende) AS Monat2, DAY(Mietende) AS Tag2 FROM tblreservierung ", conn)
            Dim DbReader As OleDbDataReader
            DbReader = dbcmd.ExecuteReader
            Dim dt = New DataTable
            dt.Load(DbReader)

            While DbReader.Read

                'Der Mietbegin als Zahl 20210518
                Dim JahrAnfang = (DbReader("Jahr1").ToString)
```
erhalte ich die fehlermeldung: Ungültiger Versuch Read aufzurufen da der Datenleser bereits geschlossen wurde

setze ich es mit ins Wile rein

```
Dim dt = New DataTable
            dt.Load(DbReader)

            While DbReader.Read
                dt.Load(DbReader)

                'Der Mietbegin als Zahl 20210518
```

erhalte ich keine Daten für die Zeile Spalte


----------



## Spyke (15. Juli 2021)

Probiers ev. mal über den OleDbDataAdapter mit seiner Fill Methode.

Auffüllen eines 'DataSets' durch einen 'DataAdapter' - ADO.NET


----------



## werner_sg (15. Juli 2021)

Spyke hat gesagt.:


> Probiers ev. mal über den OleDbDataAdapter mit seiner Fill Methode.
> 
> Auffüllen eines 'DataSets' durch einen 'DataAdapter' - ADO.NET


Ist mir eigentlich auch lieber bleibe aber dabei die ganze Zeit hängen, hatte es ja am Anfang aber dort dann immer den fehler mit dem Format in einem der vorherigen Post und dann auf DBReader umgestiegen

Mein Problem ist hier, haben auch einige andere im Netz weil Beiträge in Forem gibt es genug, nur sind die dann meisten so schlau das sie nur irgendwann schreiben hab den Fehler gefunden und tschau, scheiß auf den nächsten der das gleiche oder ähnliches Problem hat  deswegen bin ich hier ja so zufrieden da findet man dann auch ne erklärung

Ok zum Problem


```
'richtige Konvertierung und Anzeige des Wertes in der Textbox kein Meckern von Windows
Dim JahrEnde = (DbReader("Jahr2").ToString)
Dim JahrEndeI = Convert.ToDecimal(JahrEnde)

'die Eingabe Zeichenfolge hat das falsche Format
Dim JahrEnde = (("Jahr2").ToString)
Dim JahrEndeI = Convert.ToDecimal(JahrEnde)

'klammer ich das Convert aus erhalte ich in der Textbox zum Prüfen Jahr1
Dim JahrAnfang = "Jahr1"
'Dim JahrAnfangI = Convert.ToDecimal(JahrAnfang)
```

Ich finde an jeder Straßenecke die Erklärung wie ich die Textbox an die Datenbank weitergebe aber nirgends wo ich Sie mir direkt aus der Datenbank hole (Google ist auch nicht mehr was es war, zuviel sinnloses Zeug)

Also wie bekomme ich jetzt den Tabellen Inhalt aus der Spalte Jahr1 in mein Dim JahrAnfang das ich es Anschließend wieder Convertieren kann


----------



## Spyke (16. Juli 2021)

schau dir mal die Methoden des OleDbDataReader an
OleDbDataReader Klasse (System.Data.OleDb)

wenn du in der DB schon den decimal wert hast könntest du zum Beispiel diesen direkt mittels GetDecimal anfragen, dann musst du keine Convert Sachen machen.
OleDbDataReader.GetDecimal(Int32) Methode (System.Data.OleDb)
der Parameter Ordinal ist dabei die Indexnummer deiner SELECT Spalte von der du den Wert haben willst.

könntest du jetzt selbst durchzählen in deinem SELECT (du müsstest nur prüfen unter VB.Net ob es bei 0 oder 1 beginnt, bei C# wäre es 0)
oder den Ordinal/Spaltenindex könntest du auch über GetOrdinal abfragen
OleDbDataReader.GetOrdinal(String) Methode (System.Data.OleDb)


----------



## werner_sg (16. Juli 2021)

Spyke hat gesagt.:


> schau dir mal die Methoden des OleDbDataReader an
> OleDbDataReader Klasse (System.Data.OleDb)
> 
> wenn du in der DB schon den decimal wert hast könntest du zum Beispiel diesen direkt mittels GetDecimal anfragen, dann musst du keine Convert Sachen machen.
> ...


Also wie gehabt und erfahren einen direkten weg von Tabelle scheint es dann nicht zu geben

habs jetzt so:

```
'Der Mietbegin als Zahl 20210518
                Dim JahrStart = Me.DataGridView7.CurrentRow.Cells(4).Value
                Dim JahrStartD = Convert.ToDecimal(JahrStart)
                Dim MonatStart = Me.DataGridView7.CurrentRow.Cells(5).Value
                Dim MonatStartD = Convert.ToDecimal(MonatStart)
                Dim TagStart = Me.DataGridView7.CurrentRow.Cells(6).Value
                Dim TagStartD = Convert.ToDecimal(TagStart)
                Dim StartDatum = ((JahrStartD * 10000) + (MonatStartD * 100) + TagStartD)
```

Monat, Jahr und Tag filter ich schon in der Abfrage:

```
YEAR(Mietbegin) AS JahrStart,  MONTH(Mietbegin) AS MonatStart,  DAY(Mietbegin) AS TagStart,  YEAR(Mietende) AS JahrEnde, MONTH(Mietende) AS MonatEnde, DAY(Mietende) AS TagEnde,
```
funktioniert ganz gut 

------------------------------------------------------------

hier bräuchte ich noch was an Erklärung und Unterstützung:

```
For Each Row As DataRow In dbdt.Rows
                    g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), StartDatum, horizontal, EndDatum, horizontal)
                    g.DrawString("FzgNr: " + Fahrzeug, fnt, Brushes.Black, New Point(2, horizontal))
                    horizontal += 15

                    TotalSales += Val(Row.Item("TOTAL"))
                Next
```
Eigentlich sollte er ja alle Reihen durchlaufen und Anzeigen, gut schleifen laufen tut er aber nur 9x Zeile 1 wiederholt


----------



## Spyke (17. Juli 2021)

werner_sg hat gesagt.:


> hier bräuchte ich noch was an Erklärung und Unterstützung:
> 
> ```
> For Each Row As DataRow In dbdt.Rows
> ...



du musst in deiner for each Schleife entsprechend auch die Werte für Fahrzeug, StartDatum, EndeDatum setzen/anpassen.
Aktuell haben diese in deiner Schleife immer den gleichen Wert


----------



## werner_sg (17. Juli 2021)

Spyke hat gesagt.:


> du musst in deiner for each Schleife entsprechend auch die Werte für Fahrzeug, StartDatum, EndeDatum setzen/anpassen.
> Aktuell haben diese in deiner Schleife immer den gleichen Wert


kannst Du mir dafür ein grobes Beispiel geben


----------



## werner_sg (17. Juli 2021)

Mein Codeschnipsel für die Grafik bis hierhin


```
Private Sub pictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)

        ' Variablen für die PictureBox.
        Dim g As Graphics = e.Graphics

        'der erste horizontale Abstand
        Dim horizontal = 20

        'Daten holen und Verarbeiten
        dbdt = New DataTable
        Try
            Sql = "SELECT BuchungsNr, Kunde, Fahrzeugnummer, Modell, Mietbegin, YEAR(Mietbegin) AS JahrStart,  MONTH(Mietbegin) AS MonatStart,  DAY(Mietbegin) AS TagStart,  Mietdauer, Mietende, TOTAL FROM tblreservierung  where KFZ_ABGEGEBEN='nein' ORDER BY Mietbegin ASC"

            conn.Open()
            With dbcmd
                .CommandText = Sql
                .Connection = conn
            End With

            dbda.SelectCommand = dbcmd
            dbda.Fill(dbdt)
            DataGridView7.DataSource = dbdt
            dbda.Fill(ds, "tblreservierung")           'sollte eigentlich ein Dataset mit dem Inhalt der tabelle füllen

            Dim DbReader As OleDbDataReader
            DbReader = dbcmd.ExecuteReader

            While DbReader.Read

                'Der Mietbegin
                Dim Mietbegin = Me.DataGridView7.CurrentRow.Cells(4).Value                      'Datum komplett

                'Das Jahr zur Auswahl über eine TextBox
                Dim JahrStart = Me.DataGridView7.CurrentRow.Cells(5).Value                      'Jahr
                Dim JahrStartD = Convert.ToDecimal(JahrStart)                                   'Jahr als Decimal

                'Der Mietbegin Monat und Tag als Zahl 0518
                Dim MonatStart = Me.DataGridView7.CurrentRow.Cells(6).Value                     'Monat
                Dim MonatStartD = Convert.ToDecimal(MonatStart)                                 'Monat als Decimal
                Dim TagStart = Me.DataGridView7.CurrentRow.Cells(7).Value                       'Tag
                Dim TagStartD = Convert.ToDecimal(TagStart)                                     'Tag als Decimal

                'Der Startpunkt
                Dim StartDatum = ((((MonatStartD * 100) + TagStartD) + 200))                'zusammengefasst als 0912 + 200 Abstand für die Fahrzeugnummer

                'Die Mietdauer
                Dim Mietdauer = Me.DataGridView7.CurrentRow.Cells(8).Value                      'Mietdauer in Tagen
                Dim MietdauerD = Convert.ToDecimal(Mietdauer)                                   'Mietdauer in Tagen als Decimal

                'Das Mietende
                Dim Mietende = Me.DataGridView7.CurrentRow.Cells(9).Value                      'Datum komplett


                Dim EndZeitpunkt = (StartDatum + (MietdauerD * 75))                             'zusammengefasst als 0912  * 75 um den Balken zu vergrößern

                'Fahrzeugnummer
                Dim Fahrzeug = Me.DataGridView7.CurrentRow.Cells(2).Value

                ' Me.TextBox2.Text = StartDatum
                'Me.Label15.Text = EndZeitpunkt

                Dim x As Integer

                For x = 40 To 2000 Step 50

                    g.DrawLine(New Pen(System.Drawing.Color.Black, 1), PictureBox1.Left, x, PictureBox1.Right, x)

                Next

                Dim TotalMoto = 0
                Dim TotalSales = 0

                For Each Row As DataRow In dbdt.Rows
                    g.DrawString(Mietbegin + " / " + Mietende, fnt2, Brushes.Black, New Point(StartDatum, (horizontal - 20)))
                    g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), StartDatum, horizontal, EndZeitpunkt, horizontal)
                    g.DrawString("FzgNr: " + Fahrzeug, fnt, Brushes.Black, New Point(2, (horizontal - 15)))
                    'horizontal += 15

                    TotalSales += Val(Row.Item("TOTAL"))
                Next
                Label15.Text = TotalSales

            End While



        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            conn.Close()
        End Try

    End Sub
```




besteht die Möglichkeit (denke mal ja bin auch schon am suchen) anstelle die daten über das datagrid direkt aus dem Dataset zu holen also nicht mehr : Dim Mietbegin = Me.DataGridView7.CurrentRow.Cells(4).Value

und dann hänge ich immer noch daran die gleichen fahrzeuge in eine reihe zu bekommen und für die weiteren jeweils neue Reihen.

habe eure Hinweise ja teilweise versanden, nur um so mehr man sucht um so verwirrender wird es bei den ganzen Bruchstücken die alle anders ansetzen


----------



## Spyke (19. Juli 2021)

wie man die Zeilen der DataTable durchläuft weißt du ja schon,
schau mal hier
DataRow.Item[] Eigenschaft (System.Data)
so kommst du an die Spaltenwerte einer Zeile


----------



## werner_sg (19. Juli 2021)

Spyke hat gesagt.:


> wie man die Zeilen der DataTable durchläuft weißt du ja schon,
> schau mal hier
> DataRow.Item[] Eigenschaft (System.Data)
> so kommst du an die Spaltenwerte einer Zeile


Jain So wirklich verstanden habe ich den Part nicht, teilweise weis ich was er tut aber nicht so richtig warum
daher auch das Problen mit der Kombination des Hinweis auf die Data.Row items.

Dem entnehme ich nur gerade unter anderem wie ich Werte aus dem Datagrid verarbeiten und z.B in eine Textbox schreiben kann

habe mir das schon früher angeschaut mir fehlt nur die Verbindung zu each row



ist manchmal nicht einfach mit mir


----------



## Spyke (19. Juli 2021)

so ungefähr

durchläuft die Zeilen und gibt den Wert der Spalte "MeineSpalte" aus.
Der Wert selbst wird als Object geliefert.
Deshalb, einmal Beispiel als string (ToString),
und bei den anderen beiden wird der Rückgabetyp geprüft ob dieser Integer oder DateTime ist und entsprechend drauf reagiert.

```
For Each Row As DataRow In dbdt.Rows

    Dim wert As Object = Row("MeineSpalte")

    Dim text As String = wert.ToString()
    ' irgendwas machen mit dem Text

    If TypeOf wert Is Integer Then
        Dim zahl As Integer = CInt(wert)
        ' irgendwas machen mit der Zahl
    End If


    If TypeOf wert Is DateTime Then
        Dim datum As DateTime = CType(wert, DateTime)
        ' irgendwas machen mit dem Datum
    End If

Next
```

kleiner Randtipp, solltest du mal nur C# Beispiele finden
mit Code Converter C# to VB and VB to C# – Telerik
kannst du C# Code in VB.Net konvertieren


----------



## werner_sg (19. Juli 2021)

Code Converter C# to VB and VB to C# – Telerik 
Mit dem arbeite ich immer wieder, ist sehr gut

Schau mir das heute Abend in Ruhe an danke


----------



## werner_sg (22. Juli 2021)

Spyke hat gesagt.:


> so ungefähr
> 
> durchläuft die Zeilen und gibt den Wert der Spalte "MeineSpalte" aus.
> Der Wert selbst wird als Object geliefert.
> ...


Dein Hinweis hat mir sehr geholfen an anderer Stelle einen Fehler zu beheben

aber bei der Anzeige in der PictureBox blicke ich noch nicht durch 

Hier mal den Code habe ihn soweit wie Möglich Dokumentiert    


    If String.IsNullOrEmpty(TextBox1.Text) Then

            ' Variablen für die PictureBox.
            Dim g As Graphics = e.Graphics

            'der erste horizontale Abstand
            Dim horizontal = 20

            'Daten holen und Verarbeiten
            dbdt = New DataTable
            Try
                Sql = "SELECT BuchungsNr, Kunde, Fahrzeugnummer, Modell, Mietbegin, YEAR(Mietbegin) AS JahrStart,  MONTH(Mietbegin) AS MonatStart,  DAY(Mietbegin) AS TagStart,  Mietdauer, Mietende, TOTAL FROM tblreservierung  where KFZ_ABGEGEBEN='nein' ORDER BY Mietbegin ASC"

                conn.Open()
                With dbcmd
                    .CommandText = Sql
                    .Connection = conn
                End With

                dbda.SelectCommand = dbcmd
                dbda.Fill(dbdt)
                bindingSourceVermietung1.DataSource = dbdt
                DataGridView7.DataSource = bindingSourceVermietung1
                dbda.Fill(ds, "tblreservierung")

                Dim DbReader As OleDbDataReader
                DbReader = dbcmd.ExecuteReader

                While DbReader.Read

                    'Der Mietbegin 
                    Dim Mietbegin = Me.DataGridView7.CurrentRow.Cells(4).Value                      'Datum komplett

                    'Das Jahr zur Auswahl über eine TextBox
                    Dim JahrStart = Me.DataGridView7.CurrentRow.Cells(5).Value                      'Jahr
                    Dim JahrStartD = Convert.ToDecimal(JahrStart)                                   'Jahr als Decimal

                    'Der Mietbegin Monat und Tag als Zahl 0518
                    Dim MonatStart = Me.DataGridView7.CurrentRow.Cells(6).Value                     'Monat
                    Dim MonatStartD = Convert.ToDecimal(MonatStart)                                 'Monat als Decimal
                    Dim TagStart = Me.DataGridView7.CurrentRow.Cells(7).Value                       'Tag
                    Dim TagStartD = Convert.ToDecimal(TagStart)                                     'Tag als Decimal

                    'Der Startpunkt
                    Dim StartDatum = ((((MonatStartD * 100) + TagStartD) + 200))                'zusammengefasst als 0912 + 200 Abstand für die Fahrzeugnummer

                    'Die Mietdauer
                    Dim Mietdauer = Me.DataGridView7.CurrentRow.Cells(8).Value                      'Mietdauer in Tagen 
                    Dim MietdauerD = Convert.ToDecimal(Mietdauer)                                   'Mietdauer in Tagen als Decimal

                    'Das Mietende
                    Dim Mietende = Me.DataGridView7.CurrentRow.Cells(9).Value                      'Datum komplett


                    Dim EndZeitpunkt = (StartDatum + (MietdauerD * 75))                             'zusammengefasst als 0912  * 75 um den Balken zu vergrößern

                    'Fahrzeugnummer
                    Dim Fahrzeug = Me.DataGridView7.CurrentRow.Cells(2).Value


                    Dim Zeitleiste As New List(Of String)   ' Liste für die Zeiten
                    Dim ZeitIndex = 1                       'Index für die Zeiten

                    'Zeilen Trennung
                    Dim x As Integer
                    For x = 40 To 2000 Step 50

                        g.DrawLine(New Pen(System.Drawing.Color.Black, 1), PictureBox1.Left, x, PictureBox1.Right, x)

                    Next

                    'Umsatz Anzeige
                    Dim TotalMoto = 0
                    Dim TotalSales = 0

                    ' Zeiten pro Fahrzeug

                    For Each Row As DataRow In dbdt.Rows

                        Dim Zeit As Date = CDate(Row.Item("Mietende").ToString)

                        If Date.Compare(Zeit, Today) < 0 Then
                            Zeitleiste.Add(Row.Item("Mietbegin"))


                        End If

                        ZeitIndex += 1

                        'Umsatz Anzeige
                        TotalSales += Val(Row.Item("TOTAL"))
                    Next
                    Label15.Text = TotalSales

                    ' Grafik Ausgabe in der PictureBox

                    If Not Zeitleiste.Count.Equals(0) Then

                        g.DrawString(Mietbegin + " / " + Mietende, fnt2, Brushes.Black, New Point(StartDatum, (horizontal - 20)))
                        g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), StartDatum, horizontal, EndZeitpunkt, horizontal)
                        g.DrawString("FzgNr: " + Fahrzeug, fnt, Brushes.Black, New Point(2, (horizontal - 15)))

                    End If

                End While



            Catch ex As Exception
                MsgBox(ex.Message)
            Finally
                conn.Close()
            End Try


----------



## Spyke (23. Juli 2021)

Bitte Quellcode formatiert angeben
(den entsprechenden CODE Tag)

und was genau das problem ist


----------



## werner_sg (23. Juli 2021)

Spyke hat gesagt.:


> Bitte Quellcode formatiert angeben
> (den entsprechenden CODE Tag)
> 
> und was genau das problem ist


Sorry hatte es ausversehen so reingesetzt.
Mein Problem ist das er immer noch nur die erste Zeile angezeigt hat, habe aber glaube ich meinen Fehler erkannt und werde das heute Abend mal nachbessern und dann nochmal eine Status meldung geben


----------



## werner_sg (25. Juli 2021)

Spyke hat gesagt.:


> Bitte Quellcode formatiert angeben
> (den entsprechenden CODE Tag)
> 
> und was genau das problem ist



Ok schaue bei each Row soweit durch, hatte vorher alles auérhalb von eachrow ausgeführt und auch keine Liste angelegt, nachdem ich einiges in den Block gelegt habe und eine Liste erstelle bekomme ich jetzt alle Werte richtig in extra dafür angelegten Messages angezeigt


```
Private Sub pictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)

        If String.IsNullOrEmpty(TextBox1.Text) Then                                 ' Bedingung das die Textbox1 keinen Wert bzw keine Eingabe hat

            Dim Stringliste As New List(Of String)                                  ' String Liste

            Dim Startpunkt As String = ""                                           ' Grafikpunkt Mietbegin
            Dim Endpunkt As String = ""                                             ' Grafikpunkt Mietende
            Dim Fahrzeugnummer As String = ""                                       ' Fahrzeugnummer



            Dim MietzeitIndex = 1                                                   ' Mietbegin Counter zum durchlaufen der Zeilen

            Dim horizontal = 20                                                     ' der erste horizontale Abstand für die Zeitleiste
            Dim g As Graphics = e.Graphics                                          ' Variable für die PictureBox.

            'Daten holen und Verarbeiten
            dbdt = New DataTable

            Try

                Sql = "SELECT BuchungsNr, Kunde, Fahrzeugnummer, Modell, Mietbegin, Year(Mietbegin) AS JahrStart, MONTH(Mietbegin) AS MonatStart,  DAY(Mietbegin) AS TagStart, Mietdauer, Mietende, TOTAL FROM tblreservierung  where KFZ_ABGEGEBEN='nein' ORDER BY Fahrzeugnummer, Mietbegin"

                conn.Open()
                With dbcmd
                    .CommandText = Sql
                    .Connection = conn
                End With

                dbda.SelectCommand = dbcmd
                dbda.Fill(dbdt)
                DataGridView7.DataSource = dbdt

                'Zeilen Trennung
                Dim x As Integer
                For x = 40 To 2000 Step 50

                    g.DrawLine(New Pen(System.Drawing.Color.Black, 1), PictureBox1.Left, x, PictureBox1.Right, x)

                Next

                'Umsatz Anzeige
                Dim TotalMoto = 0
                Dim TotalSales = 0

                For Each Row As DataRow In dbdt.Rows

                    Dim Mietende As Date = CDate(Row.Item("Mietende").ToString)

                    If Date.Compare(Mietende, Today) > 0 Then
                        Stringliste.Add(Row.Item("Mietbegin"))
                        Startpunkt &= vbNewLine & ((Row.Item("JahrStart") * 10000) + (Row.Item("MonatStart") * 100)) + Row.Item("TagStart")
                        Endpunkt &= vbNewLine & Row.Item("Mietdauer")
                        Fahrzeugnummer &= vbNewLine & Row.Item("Fahrzeugnummer")

                    End If
                    MietzeitIndex += 1


                    TotalSales += Val(Row.Item("TOTAL"))            'Umsatz Berchnung

                Next
                If Not Stringliste.Count.Equals(0) Then

                    MessageBox.Show(Startpunkt)
                    MessageBox.Show(Endpunkt)
                    MessageBox.Show(Fahrzeugnummer)
                    ' g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), FahrzeugnummerMessage, horizontal, FahrzeugnummerMessage, horizontal)   'Eingabezeichen haben das falsche Format

                End If

                Label15.Text = TotalSales                           'Umsatz Anzeige


            Catch ex As Exception
                MsgBox(ex.Message)
            Finally
                conn.Close()
            End Try



        End If

    End Sub
```

Habe jetzt allerdings das Problem die Werte welche ich als String habe in Decimal zu Convertieren

bei meiner jetztigen Versuchen erhalte ich die Fehlermeldung das die Eingabezeichen das falsche Format haben

habs auch schon mal hiermit versucht

```
Dim Stringliste As New List(Of String)                                  ' Mietbegin Liste

            Dim Decimalliste As List(Of Decimal) = Stringliste.ConvertAll(Function(item) Decimal.Parse(item))

            ' Dim MietzeitstartMessage As String = ""                                 ' Test Message Mietbegin
            'Dim MietdauerendeMessage As String = ""                                 ' Test Message Mietende
            ' Dim FahrzeugnummerMessage As String = ""                                ' Test Message Fahrzeugnummer

            Dim Startpunkt As Decimal = ""                                 ' Grafikpunkt Mietbegin
            Dim Endpunkt As Decimal = ""                                 ' Grafikpunkt Mietende
            Dim Fahrzeugnummer As Decimal = ""                                 ' Grafikpunkt Mietende
```
erhalte dann aber

System.InvalidCastException: "Ungültige Konvertierung von der Zeichenfolge  in Typ Decimal."


----------



## Spyke (26. Juli 2021)

Ich würde vermuten das Mietbegin vom Typ DateTime ist, du versuchst es aber nach decimal zu parsen.
Müssteste doch eigentlich wenn dann eher nach DateTime parsen.


----------



## werner_sg (26. Juli 2021)

Spyke hat gesagt.:


> Ich würde vermuten das Mietbegin vom Typ DateTime ist, du versuchst es aber nach decimal zu parsen.
> Müssteste doch eigentlich wenn dann eher nach DateTime parsen.


Ja Mietbegin und Mietende sind in der Access vom Typ DateTime muss auch sein da ich das an anderer Stelle so brauche.
In der DrawLine werden Sie ja aber als Zahl benötigt, sonst wird da gemeckert.
In der Liste sind die Werte ja als String und werden auch als String in der MessageBox so ausgegeben wie ich sie als Zahl bräuchte.
Es muss doch enen Weg geben diese als Zahl zu konvertieren


----------



## Spyke (26. Juli 2021)

ausgehend das du normal mit dem DateTime Objekt arbeitest, erstellen wir uns selbst eine eigene Zahl
(wie ich weiter vorne in einem Post mal erwähnte)


```
Dim beginnDate As DateTime = CType(Row.Item("Mietbegin"), DateTime)
    Dim beginnNum As Integer = (((beginn.Year * 10000) + beginn.Month) * 100) + beginn.Day
```

sprich in der Liste hälst du dir die original Objekte, die DateTime Objekte/Daten.

*Nachtrag:*
Oder ist der Mietbeginn in der Row schon durch SQL als Zahl quasi gewandelt?
Dann prüf mal den Inhalt deiner Liste, sind da wirklich nur Zahlen als string drin oder ev. auch ein Leer string z.B.?
Kannst dir auch mal
Decimal.TryParse Methode (System)
anschauen, da kriegst du dann nicht gleich eine Exception um die Ohren geschmissen wenn die konvertierung fehlschlägt.
Aber wie gesagt, prüf mal was in der Liste ist, ein Element scheint dann fehelrhaft zu sein.

*Nachtrag 2:*
Falls aus SQL schon die Zahl kommt dann ev. beim auslesen schon direkt nach Zahl casten und nicht den umweg über die stringliste gehen.


```
Dim wert As Decimal = CDec(Row.Item("Mietbegin"))
    decimalListe.Add(wert)
```
oder um sicher zu gehen das aus der SQL wirklich Zahlwert kommt (könnte theoretisch auch DBNull kommen, je nach SQL)

```
If TypeOf Row.Item("Mietbegin") Is Decimal Then
        Dim wert As Decimal = CDec(Row.Item("Mietbegin"))
        decimalListe.Add(wert)
    End If
```


----------



## werner_sg (28. Juli 2021)

Spyke hat gesagt.:


> ausgehend das du normal mit dem DateTime Objekt arbeitest, erstellen wir uns selbst eine eigene Zahl
> (wie ich weiter vorne in einem Post mal erwähnte)
> 
> 
> ...


Nicht ganz verstanden, also den Block schon


```
Dim Mietende As Date = CDate(Row.Item("Mietende").ToString)
```

Damit hole ich mir ja bereits das Datum als String

Und mit

```
If Date.Compare(Mietende, Today) > 0 Then
                        Stringliste.Add(Row.Item("Mietbegin"))
                        Startpunkt &= vbNewLine & ((Row.Item("JahrStart") * 10000) + (Row.Item("MonatStart") * 100)) + Row.Item("TagStart")
                        Endpunkt &= vbNewLine & Row.Item("Mietdauer")
                        Fahrzeugnummer &= vbNewLine & Row.Item("Fahrzeugnummer")

                    End If
```

prüfe ich ob das Mietende nach dem heutigen Tag liegt, da ich nur diese noch benötige, der rest ist ja erledigt. in der Mesage Box zum Testen werden dementsprechend untereinander auch nur noch Daten angezeigt welche dem entsprechen.

Endpunkt (Mietdauer) und Fahrzeugnummer liegen in der Access als Zahl vor und sollten auch dementsprechend als Zahl verarbeitet werden

Hole ich mir das Datum des Mietbegins in eine MessageBox erhalte ich das Datum mit Uhrzeit

Setze ich das Startdatum aus der SQL Abfrage Year, Month und Day zusammen mit dem jeweiligen Multiplikator erhalte ich wie geplant 20210612 für den 12.06.2021

in der Stringliste habe ich den Wert "31.07.2021 00:47:54"

Zusammengefasst was mir klar ist:

Dim Mietendeliste As New List(Of String)   erzeugt mir meine Liste mit den Endzeitpunkten (Datum) als String um im eachRow Block  bei  If Not Mietendeliste.Count.Equals(0) verarbeitet zu werden und Ansonsten keine weitere Verwendung

Dim Mietende As Date = CDate(Row.Item("Mietende").ToString) holt mir die Notwendigen Daten für die if Prüfung als String
Mietendeliste.Add(Row.Item("Mietende")) füllt die Stringliste für die If Not Prüfung sonst keine Verwendung


```
Startpunkt &= vbNewLine & ((Row.Item("JahrStart") * 10000) + (Row.Item("MonatStart") * 100)) + Row.Item("TagStart")
Endpunkt &= vbNewLine & Row.Item("Mietdauer")
Fahrzeugnummer &= vbNewLine & Row.Item("Fahrzeugnummer")
```

holt die Daten für die MessageBoxen aus der Datenbank, eigentlich überflüssig war nur zum schnelleren Überblick zum Inhalt da ich Anfangs eine Verbindung zur Stringliste gesehen habe welche ja gar nicht besteht

Ohne  vbNewLine & werden die Ergebnisse in der MessageBox als ein durchgehender String angezeigt

Die Daten Aus der SQL Abfrage kommen bei Mietbegin, Mietende, JahrStart, MonatStart und TagStart als Datum sowie Fahrzeugnummer und Mietdauer als Text

hier verstehe ich nicht welchen bezug beginn.Year haben soll, habs auch mal mit JahrStart versucht klappt aber nicht


```
Dim beginnDate As DateTime = CType(Row.Item("Mietbegin"), DateTime)
Dim beginnNum As Integer = (((beginn.Year * 10000) + beginn.Month) * 100) + beginn.Day
```

am Ende bin ich immer noch auf der Suche einer Erklärung wie ich meine Decimal Werte erhalte, CAST oder CONVERT in der SQL Abfrage bekomme ich auch nicht hin, laut MS sollte es eigentlich mit Convert zu varchar und dann weiter zu int gehen also nach dem Motto CONVERT(int, (CONVERT(var, Fahrzeugnummer))

Das Hauptproblem ist mit jedem Suchen werde ich konfuser, auf 100 Seiten finden sich unterschiedliche Infos die meisten hauen dann eine ähnliche Lösungen hin ohne Erklärung oder haben die Lösung und zeigen diese dann nicht mehr auf.


----------



## werner_sg (28. Juli 2021)

Hier nochmal mein Code für den Teil mit Kommentar für alle einzelnen Anweisungen, vieleicht hilft das meinen Denkfehler zu verstehen


```
Private Sub pictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)

        If String.IsNullOrEmpty(TextBox1.Text) Then                                 ' Bedingung das die Textbox1 keinen Wert bzw keine Eingabe hat

            Dim Mietendeliste As New List(Of String)                                ' String Liste Mietende

            Dim Startpunkt As String = ""                                           ' Grafikpunkt Mietbegin
            Dim Endpunkt As String = ""                                             ' Grafikpunkt Mietende
            Dim Fahrzeugnummer As String = ""                                       ' Fahrzeugnummer

            Dim MietzeitIndex = 1                                                   ' Counter zum durchlaufen der Zeilen

            Dim horizontal = 20                                                     ' der erste horizontale Abstand für die Zeitleiste
            Dim g As Graphics = e.Graphics                                          ' Variable für die PictureBox.

            'Daten holen und Verarbeiten
            dbdt = New DataTable

            Try
                'SQL Zugriff für alle Fahrzeuge welche noch nicht zurückgegeben sind
                Sql = "SELECT BuchungsNr, Kunde, Fahrzeugnummer, Modell, Mietbegin, Year(Mietbegin) AS JahrStart, MONTH(Mietbegin) AS MonatStart,  DAY(Mietbegin) AS TagStart, Mietdauer, Mietende, TOTAL FROM tblreservierung  where KFZ_ABGEGEBEN='nein' ORDER BY Fahrzeugnummer, Mietbegin"

                conn.Open()
                With dbcmd
                    .CommandText = Sql
                    .Connection = conn
                End With

                dbda.SelectCommand = dbcmd
                dbda.Fill(dbdt)
                DataGridView7.DataSource = dbdt

                'Zeilen Trennung Linien
                Dim x As Integer                    'definiert x als Integer Zahl
                For x = 40 To 2000 Step 50          'setzt x auf Anfang 40 und erhöht jeweils um 50 bis 2000 erreicht

                    g.DrawLine(New Pen(System.Drawing.Color.Black, 1), PictureBox1.Left, x, PictureBox1.Right, x) ' zeichnet die Linien in die PictureBox

                Next

                'Umsatz Anzeige
                Dim TotalMoto = 0
                Dim TotalSales = 0

                For Each Row As DataRow In dbdt.Rows

                    Dim Mietende As Date = CDate(Row.Item("Mietende").ToString)         'stellt das Mietende als String bereit

                    If Date.Compare(Mietende, Today) > 0 Then
                        Mietendeliste.Add(Row.Item("Mietende"))                         'fügt die Zeilen der Tabellen Spalte Mietende zur Stringliste

                        'Daten für MessageBox
                        Startpunkt &= vbNewLine & ((Row.Item("JahrStart") * 10000) + (Row.Item("MonatStart") * 100)) + Row.Item("TagStart")
                        Endpunkt &= vbNewLine & Row.Item("Mietdauer")
                        Fahrzeugnummer &= vbNewLine & Row.Item("Fahrzeugnummer")

                    End If
                    MietzeitIndex += 1          'Zähler für die reihen


                    TotalSales += Val(Row.Item("TOTAL"))            'Umsatz Berchnung

                Next
                If Not Mietendeliste.Count.Equals(0) Then           'prüft ob Daten in der Stringliste vorhanden oder nicht

                    MessageBox.Show(Startpunkt)
                    MessageBox.Show(Endpunkt)
                    MessageBox.Show(Fahrzeugnummer)
                    '     MessageBox.Show(beginnNum)

                    '  g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), Endpunkt, horizontal, Fahrzeugnummer, horizontal)   'Eingabezeichen haben das falsche Format

                End If

                Label15.Text = TotalSales                           'Umsatz Anzeige


            Catch ex As Exception
                MsgBox(ex.Message)
            Finally
                conn.Close()
            End Try



        End If

    End Sub
```


----------



## Spyke (28. Juli 2021)

sry hier hatte sich ein kleiner Fehlerteufel eingeschlichen

```
Dim beginnDate As DateTime = CType(Row.Item("Mietbegin"), DateTime)
Dim beginnNum As Integer = (((beginn.Year * 10000) + beginn.Month) * 100) + beginn.Day
```
beginn sollte beginnDate sein

```
Dim beginnDate As DateTime = CType(Row.Item("Mietbegin"), DateTime)
Dim beginnNum As Integer = (((beginnDate.Year * 10000) + beginnDate.Month) * 100) + beginnDate.Day
```


Und Problem ist das du alles mit string versuchst zu händeln, dabei bekommst du eigentlich aus der SQL auch schon die richtigen Datentypen

aber wenn wir jetzt mal von deinem StartPunkt ausgehen, den du als String hälst und der ja vom Aufbau so sein müsst 20210612
könntest du hier das decimal Parse anwenden

```
Dim startNummer As Decimal = Decimal.Parse(StartPunkt)
```
und dann mit startNummer weiter arbeiten


----------



## werner_sg (28. Juli 2021)

Spyke hat gesagt.:


> aber wenn wir jetzt mal von deinem StartPunkt ausgehen, den du als String hälst und der ja vom Aufbau so sein müsst 20210612
> könntest du hier das decimal Parse anwenden
> 
> ```
> ...


Hatte ich irgendwann auch schon mal versucht erhalte dann aber falsches Eingabeformat



> Und Problem ist das du alles mit string versuchst zu händeln, dabei bekommst du eigentlich aus der SQL auch schon die richtigen Datentypen


Weil alles und jeder einen in diese Richtung gesendet hat, dann lass uns doch nicht mit dem Parse weitermachen weil es halt mal schon so ist, sondern einfach wie den richtig verarbeiten.

Das hilft viel mehr sonst stehe ich vieleicht irgendwann mal wieder vor einem ähnlichen Problem und komm auch nicht sauber weiter weil ich mich diesmal darum geschlängelt habe.



> Dim beginnDate As DateTime = CType(Row.Item("Mietbegin"), DateTime)
> Dim beginnNum As Integer = (((beginnDate.Year * 10000) + beginnDate.Month) * 100) + beginnDate.Day


hier habe ich das Problem das ich alles im if Date.Compare Block verarbeiten muss auch das drawline

trenne ich beide oder packe das draw nicht in den gleichen Block erhalte ich eine Fehlermeldung das beginnDate nicht deklariert wurde 

mache ich es so

```
For Each Row As DataRow In dbdt.Rows

                    Dim Mietende As Date = CDate(Row.Item("Mietende").ToString)         'stellt das Mietende als String bereit
                    Dim beginnDate As DateTime = CType(Row.Item("Mietbegin"), DateTime)
                    Dim beginnNum As Decimal = (((beginnDate.Year * 10000) + beginnDate.Month) * 100) + beginnDate.Day

                    If Date.Compare(Mietende, Today) > 0 Then
                        Mietendeliste.Add(Row.Item("Mietende"))                         'fügt die Zeilen der Tabellen Spalte Mietende zur Stringliste
                        'Daten für MessageBox
                        'Startpunkt &= vbNewLine & ((Row.Item("JahrStart") * 10000) + (Row.Item("MonatStart") * 100)) + Row.Item("TagStart")
                        Endpunkt &= vbNewLine & Row.Item("Mietdauer")
                        Fahrzeugnummer &= vbNewLine & Row.Item("Fahrzeugnummer")
                        g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), 200, horizontal, 250, horizontal)   'Eingabezeichen haben das falsche Format
```
erhalte ich einen überlauf fehler


----------



## Spyke (29. Juli 2021)

hab mal versucht hier was kleines zu machen, ein bissl laut deinem Code
(ist ungetestet, und wie gesagt nur kleiner teil, musst jetzt noch bissl auf deine bedürfnisse anpassen)


```
Dim zeitleisteMaxBereich As Integer = (((DateTime.Today.Year * 10000) + 12) * 100) + 31        ' 100% für die Zeitleiste, erstmal das Jahr laut Heutetag zum 31.12

                Dim bildBreite As Integer = pictureBox1.Width    ' die Breite des Zeichnungsbereiches (unsere 100% zum zeichnen)

                For Each Row As DataRow In dbdt.Rows

                    Dim Mietbegin As DateTime = CType(Row.Item("Mietbegin"), DateTime)                    ' Mietbegin als DateTime
                    Dim MietbeginNum As Integer = (((Mietbegin.Year * 10000) + Mietbegin.Month) * 100) + Mietbegin.Day    ' Mietbegin als Zahl umgerechnet
                    Dim MietbeginProzent As Integer = CInt((MietbeginNum / CDec(zeitleisteMaxBereich)))            ' der prozentuale Anteile des Mietbegins in der Zeitleiste

                    Dim Mietende As Date = CType(Row.Item("Mietende"), DateTime)                        ' Mietende als DateTime
                    Dim MietendeNum As Integer = (((Mietende.Year * 10000) + Mietende.Month) * 100) + Mietende.Day        ' Mietende als Zahl umgerechnet
                    Dim MietendeProzent As Integer = CInt((MietendeNum / CDec(zeitleisteMaxBereich)))            ' der prozentuale Anteile des Mietendes in der Zeitleiste

                    If Date.Compare(Mietende, Today) > 0 Then
 
                        Dim leftPos1 As Integer = MietbeginProzent * bildBreite ' die X-Positionen berechnen wir anhand der Breite des zeichnugnsbereiches und dem prozentualem Anteil
                        Dim leftPos2 As Integer = MietendeProzent * bildBreite

                        g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), leftPos1, horizontal, leftPos2, horizontal)

                    End If
                    MietzeitIndex += 1          'Zähler für die reihen


                    TotalSales += Val(Row.Item("TOTAL"))            'Umsatz Berchnung

                Next

                Label15.Text = TotalSales                           'Umsatz Anzeige
```

und du hast was von einem Überlauffehler und falsche Eingabeformat geschrieben.
bei sowas immer die richtige/komplette Fehlermeldugn/Exception angeben,
ansonsten kann man so erstmal nixs mit dieser Aussage anfangen.


----------



## Spyke (29. Juli 2021)

hab gerade gemerkt die prozentualle Berechnung mit zeitleisteMaxBereich, passt nicht ganz weil die Werte zu groß sind. Bewegt sich alles im 99% bereich.
mir fehlt jetzt nur die zeit da weiter zu schauen


----------



## Spyke (29. Juli 2021)

problem mit der zeitleisteMaxBereich war das ich das für das DrawLine hin hinbauen wollt.
wenn stattdessen mit DrawRectangle (oder FillRectangle) gearbeitet wird, könnte es so gehen

(Problem war die 2te X Position im DrawLine, beim Draw- oder FillRectangle kann man schön mit Breitenangabe arbeiten)


```
Dim zeitleisteBeginn As Integer = (((DateTime.Today.Year * 10000) + 01) * 100) + 01        ' Beginn der Zeitleiste, erstmal das Jahr laut Heutetag zum 01.01
                Dim zeitleisteEnde As Integer = (((DateTime.Today.Year * 10000) + 12) * 100) + 31        ' Ende Zeitleiste, erstmal das Jahr laut Heutetag zum 31.12
                ' hier eventuell dann per SQL das niedrigste und höchste Mietbeginn/Mietende ermittln anstatt hart auf den 01.01 und 31.12 zu gehen

                Dim zeitleisteMaxBereich As Integer = zeitleisteEnde - zeitleisteBeginn + 1       ' 100% für die Zeitleiste

                Dim bildBreite As Integer = pictureBox1.Width    ' die Breite des Zeichnungsbereiches (unsere 100% zum zeichnen)

                For Each Row As DataRow In dbdt.Rows

                    Dim Mietbegin As DateTime = CType(Row.Item("Mietbegin"), DateTime)                    ' Mietbegin als DateTime
                    Dim MietbeginNum As Integer = (((Mietbegin.Year * 10000) + Mietbegin.Month) * 100) + Mietbegin.Day    ' Mietbegin als Zahl umgerechnet
                    Dim MietbeginProzent As Integer = CInt(((MietbeginNum - zeitleisteBeginn) / CDec(zeitleisteMaxBereich)))            ' der prozentuale Anteile des Mietbegins in der Zeitleiste

                    Dim Mietende As Date = CType(Row.Item("Mietende"), DateTime)                        ' Mietende als DateTime
                    Dim MietendeNum As Integer = (((Mietende.Year * 10000) + Mietende.Month) * 100) + Mietende.Day        ' Mietende als Zahl umgerechnet
                    Dim MietendeProzent As Integer = CInt(((MietendeNum - zeitleisteBeginn) / CDec(zeitleisteMaxBereich)))            ' der prozentuale Anteile des Mietendes in der Zeitleiste

                    If Date.Compare(Mietende, Today) > 0 Then
 
                        Dim leftPos As Integer = MietbeginProzent * bildBreite
                        Dim widthPos As Integer = (MietendeProzent * bildBreite) - leftPos

                        g.DrawRectangle(New Pen(System.Drawing.Color.DarkRed, 10), leftPos, horizontal, widthPos, horizontal + 10)

                    End If
                    MietzeitIndex += 1          'Zähler für die reihen


                    TotalSales += Val(Row.Item("TOTAL"))            'Umsatz Berchnung

                Next

                Label15.Text = TotalSales
```

neu ist die Ermittung des zeitleisteMaxBereich, MietbeginProzent, MietendeProzent und für das zeichnen leftPos, widthPos und das DrawRectangle

*Nachtrag:*
seh grad um das DrawLine Problem zu lösen könnte man dann einfach doch so machen
(in Verbindung mit dem was ich jetzt für DrawRectangle gemacht hatte)

```
Dim leftPos1 As Integer = MietbeginProzent * bildBreite
                        Dim leftPos2 As Integer = (MietendeProzent * bildBreite)

                        g.DrawLine(New Pen(System.Drawing.Color.DarkRed, 10), leftPos1, horizontal, leftPos2, horizontal)
```


----------



## werner_sg (30. Juli 2021)

Spyke hat gesagt.:


> hab mal versucht hier was kleines zu machen, ein bissl laut deinem Code
> (ist ungetestet, und wie gesagt nur kleiner teil, musst jetzt noch bissl auf deine bedürfnisse anpassen)
> 
> 
> ...


habs gerade mal getestet, kommen zwar keine fehler meldung aber auch die PictureBox bleibt leer


> und du hast was von einem Überlauffehler und falsche Eingabeformat geschrieben.
> bei sowas immer die richtige/komplette Fehlermeldugn/Exception angeben,
> ansonsten kann man so erstmal nixs mit dieser Aussage anfangen.



Ja konnte damit auch nichts Anfangen nicht mal ein Ansatz zum Googeln, aber ist das einzige was ich zur Laufzeit als Fehler bekommen habe, Haltepunkte im Script haben auch nichts gebracht. Entweder ist es bis zum Fehler durchgelaufen oder eine zeile Vorher ist der Teil mit dem Fehler die DrawZeile noch nicht ausgeführt.
Somit wurde nur der Fehler zur Laufzeit angezeigt alles andere wurde nicht bemängelt oder mit Hinweis versehen.


----------



## Spyke (30. Juli 2021)

Immer exception komplett posten.
Und hast du meine folge post beachtet, im ersten entwurf hatte ich noch das problem mit dem zeitleisteMax


----------



## Spyke (30. Juli 2021)

Ach und seh grad, mietbeginProzent und mietendeProzent dürfen nicht integer sein, stell die mal auf decimal und nimm das CInt drum rum weg.
Bei der prozentberechnung kommen werte von 0,XX raus, wir brauchen die nachkommastellen, die gehen uns durch die ganzzahl verloren.

(Sitze grad mit handy am see weshalb ichs schlecht ausbessern kann)


----------



## werner_sg (30. Juli 2021)

Spyke hat gesagt.:


> Ach und seh grad, mietbeginProzent und mietendeProzent dürfen nicht integer sein, stell die mal auf decimal und nimm das CInt drum rum weg.
> Bei der prozentberechnung kommen werte von 0,XX raus, wir brauchen die nachkommastellen, die gehen uns durch die ganzzahl verloren.
> 
> (Sitze grad mit handy am see weshalb ichs schlecht ausbessern kann)


schau ich mir nachher mal an ist im Augenblick zu Heiß um am tag zu arbeiten ;-)


----------



## werner_sg (31. Juli 2021)

Spyke hat gesagt.:


> Immer exception komplett posten.


War diesmal sehr Wortkarg, da gabs nicht viel mehr


Spyke hat gesagt.:


> Und hast du meine folge post beachtet, im ersten entwurf hatte ich noch das problem mit dem zeitleisteMax


Ja und am Ende war ich etwas frustiert, da ich es so auch schon mehrfach hatte.
Aber die deklaration dazu immer Außerhalb des eachRow Block

So er zeigt jetzt auf jeden Fall schon mal einen Balken an, werde dann heute mal schauen das ich die Linien wieder einbaue und die Fahrzeug Nummer sowie die Zeiten


----------



## werner_sg (1. August 2021)

Spyke hat gesagt.:


> Ach und seh grad, mietbeginProzent und mietendeProzent dürfen nicht integer sein, stell die mal auf decimal und nimm das CInt drum rum weg.
> Bei der prozentberechnung kommen werte von 0,XX raus, wir brauchen die nachkommastellen, die gehen uns durch die ganzzahl verloren.
> 
> (Sitze grad mit handy am see weshalb ichs schlecht ausbessern kann)





> mietendeProzent dürfen nicht integer


genau dort fing mein Probem beim Umwandeln an, wobei mein größter Fehler daran lag das ich alles oberhalb des eachRow Block umwandeln wollte, damit ich es auch im letzten Bock der ja eigentlich gar nicht gebraucht wird und dementsprechend nicht mehr vorhanden ist nutzen konnte.

Habs jetzt Dank deiner Hilfe Verstanden und soweit das jetzt schon mal alle Termine auf einer Linie angezeigt werden.
Auf dem Bild überlagern sich am Anfang Fahrzeug Nr. 1 vom 31.7 bis zum 20.8 und Fahrzeug Nr. 3 vom 31.7 bis 22.8, da das Fahrzeug Nr. 3 am 22.8 wieder startet wirkt es wie ein Balken.

Stellt sich also noch die Frage wie ich das jetzt nach Fahrzeugen auf unterschiedliche Linien bekomme, dann ist es perfekt.


----------



## Spyke (2. August 2021)

Du musst dafür die Y-Position beim DrawLine entsprechend anpassen (deine Variable horizontal)
(hatte ich in meinen Beispielen jetzt nicht gemacht)

z.B. wie du es glaube schon an einer stelle hattest
in der for each Schleife
horizontal = horizontal + 10

ev. alternativ je fahrzeug könntest du probieren wenn du die fahrzeugnummer zur Berechnung der Y-Position nimmst
horizontal = fahrzeugNummer * 10


----------



## werner_sg (2. August 2021)

Spyke hat gesagt.:


> Du musst dafür die Y-Position beim DrawLine entsprechend anpassen (deine Variable horizontal)
> (hatte ich in meinen Beispielen jetzt nicht gemacht)
> 
> z.B. wie du es glaube schon an einer stelle hattest
> ...




```
Dim horizontal = Row.Item("Fahrzeugnummer")                                                  
Dim FzgNr As Integer = (horizontal * 30)
```
brav im for each Block und nicht wieder meilenweit vorher und es läuft ideal




jetzt noch ein wenig Feinschliff und Fertig

Muchas Gracias


----------



## werner_sg (2. August 2021)

> hier eventuell dann per SQL das niedrigste und höchste Mietbeginn/Mietende ermittln anstatt hart auf den 01.01 und 31.12 zu gehen



kennst Du oder gibt es eine Alternative zur SQL Abfrage:  Min(Mietbegin) AS BoxAnfang, ?
hiermit erhalte ich die Meldung das BuchungsNr nicht als Teil der Agregatfunktion eingeschlossen ist. scheint also von Access nicht akzeptiert zu werden obwohl es fast immer als Lösung angegeben wird.


----------



## Spyke (3. August 2021)

dir fehlt ein GROUP BY in der SQL
Du gibts in deiner SQL noch weitere Felder/Spalten mit aus die, ich sag mal, in keiner Aggregatfunktion laufen.
Diese Felder musst du für die SQL mittels GROUP BY gruppieren.
In deinem Fall wäre es ev. so

```
SELECT buchungsNr, MIN(mietbeginn) AS BoxAnfang, ...
FROM ...
WHERE ...
GROUP BY buchungsNr
```

Für nähere Angaben brauch man aber die SQL.
(Bei solchen Fragen am besten immer gleich die SQL mit angeben)

Die buchugnsnummer sollte aber in diesem Fall nicht mit ausgegeben werden.
Wir wollen ja die Datümer über alle Buchungen, und nicht je Buchung.

Für nähere SQL Fragen aber ev. am besten einen Thread hier auf tutorials im SQL bereich (relationale Datenbanksysteme) posten.
Da gibts dann auch noch weitere Leute die sich mit auskennen.


----------



## werner_sg (3. August 2021)

Spyke hat gesagt.:


> dir fehlt ein GROUP BY in der SQL
> Du gibts in deiner SQL noch weitere Felder/Spalten mit aus die, ich sag mal, in keiner Aggregatfunktion laufen.
> Diese Felder musst du für die SQL mittels GROUP BY gruppieren.
> In deinem Fall wäre es ev. so
> ...


OK werde mich da mal durchwühlen, mit Group by hatte ich mich noch nicht beschäftigt


Spyke hat gesagt.:


> Für nähere Angaben brauch man aber die SQL.
> (Bei solchen Fragen am besten immer gleich die SQL mit angeben)


Bin davon ausgegangen das es nicht an der SQl liegt sondern das es von Access nicht unterstützt wird


Spyke hat gesagt.:


> Die buchugnsnummer sollte aber in diesem Fall nicht mit ausgegeben werden.
> Wir wollen ja die Datümer über alle Buchungen, und nicht je Buchung.


Buchungsnummer brauche ich in der Abfrage da ich Sie in der Zeitleiste verarbeite.
Über demr Linie habe ich zum Startpunkt das Anfangsdatum stehen und am Endpunkt das Enddatum, auf der Zeitleiste welche ich Hellblau gefärbt habe und höher gemacht habe, findet sich jetzt die Fahrzeugnummer und darunter die Buchungsnummer.
Somit sind alle wichtigen Daten zur Übersicht gut ersichtlich.


Spyke hat gesagt.:


> Für nähere SQL Fragen aber ev. am besten einen Thread hier auf tutorials im SQL bereich (relationale Datenbanksysteme) posten.
> Da gibts dann auch noch weitere Leute die sich mit auskennen.


Ja Yaslaw ist zum Beispiel sehr fit in SQL, schau erst mal so durch und im Notfall mache ich das noch

Danke für den Hinweis auf die Group Funktion


----------



## Spyke (3. August 2021)

Für die Ermittlung von MIN, MAX einfach eine neue/extra SQL für Aufrufen.
Das alles in eine zu packen, das es irgendwie funktioniert, bringt nixs.

Und bei größeren Datensätzen könnte sowas theoretisch auch die performance der SQL Abfrage runterziehen.

Außerdem wäre es so leichter wartbar, wenn du dies trennst.

Kurz gesagt, mach eine extra SQL, welche sich nur um die Ermittlung von MIN und MAX Datum kümmert (diese SQL zu beginn aufrufen um entsprechend damit zeitleisteBeginn und zeitleisteEnde setzen zu können)


----------



## werner_sg (4. August 2021)

Spyke hat gesagt.:


> Für die Ermittlung von MIN, MAX einfach eine neue/extra SQL für Aufrufen.
> Das alles in eine zu packen, das es irgendwie funktioniert, bringt nixs.
> 
> Und bei größeren Datensätzen könnte sowas theoretisch auch die performance der SQL Abfrage runterziehen.
> ...


bin wieder Da  

Yaslaw hat mir bei der SQL sehr geholfen und mir das dann mit dem Alias in der SQL erklärt kannte ich noch nicht, so wurde es dann doch eine Abfrage


```
Sql = "
select
    r.BuchungsNr,
    r.Fahrzeugnummer,
    r.Mietbegin,
    r.Mietdauer,
    r.Mietende,
    ragg.min_begin,
    ragg.max_ende
from
    tblreservierung r,
    (
        select
            min(Mietbegin) as min_begin,
            max(Mietende) as max_ende
        from tblreservierung
        where KFZ_ABGEGEBEN='nein'
    ) ragg
where r.KFZ_ABGEGEBEN='nein'
ORDER BY r.Fahrzeugnummer, r.Mietbegin

 "
```

Mit der Konvertierung habe ich ja soweit verstanden


```
Dim MinDatum As DateTime = CType(Row.Item("min_begin"), DateTime)                                      ' ZeitleisteStart als DateTime
                    Dim ZeitleisteStart As Integer = (((MinDatum.Year * 100) + MinDatum.Month) * 100) + MinDatum.Day       ' ZeitleisteStart als Zahl umgerechnet

                    Dim MaxDatum As DateTime = CType(Row.Item("min_begin"), DateTime)                                      ' ZeitleisteStop als DateTime
                    Dim ZeitleisteStop As Integer = (((MaxDatum.Year * 100) + MaxDatum.Month) * 100) + MaxDatum.Day        ' ZeitleisteStop als Zahl umgerechnet
```

zeigt auch brav das Datum wie folgt an: 20210731, am Anfang war es 2021000731, lag an dem Year * 10000 habe das überall auf 100 reduziert (Ergebnis ist optisch das gleiche wie vorher)

Funktioniert aber nur im eachRow Block, verständlich holt sich die Daten ja per Row.Item, kann dadurch aber nicht oberhalb des Blocks mit

```
Dim zeitleisteMaxBereich As Integer = (zeitleisteEnde - zeitleisteBeginn + 1)        ' 100% für die Zeitleiste
```
darauf zugreifen

wie kann ich das lösen?

und mal ne andere Frage, kannst Du mir ein gutes Buch zu dem allem empfehlen.
Da ich mitlerweile in Spanien bin kann ich schlecht in die nächste Buchhandlung und schauen was es da gibt, auf deutsch haben die nichts da, muss also online bestellen und kann da kaum vorher reinschauen


----------



## Spyke (5. August 2021)

Sry, was es da aktuell ev. für Bücher gibt die empfehlenswert wären weiß ich nicht.

zum zeitleisten problem
pack dann einfach zeitleisteBeginn, zeitleisteEnde und zeitleisteMaxBereich runter in das for each.
Im for each dann so das es mit als erstes verarbeitet wird.

Und kleiner Tipp noch es könnte ja sein das durch die SQL dein MinDatum zum Beispiel der 07.10.2021 ist.
Einfach weil da die erste gültige Buchung ist.
Bei sowas wäre zu überlegen ob du nicht prüfst:

```
Dim MinDatum As DateTime = CType(Row.Item("min_begin"), DateTime)                                      ' ZeitleisteStart als DateTime
                    
                    Dim checkMinDatum As DateTime = New DateTime(MinDatum.Year, 1, 1)                                      ' Hilfsvariable für den 01.01 des Jahres
                    If MinDatum > checkMinDatum Then MinDatum = checkMinDatum                                              ' Wenn MinDatum höher als der 01.01 dann MinDatum auf den 01.01 setzen, damit anhand 01.01 die Zeitleiste aufgebaut wird
    
                    Dim ZeitleisteStart As Integer = (((MinDatum.Year * 100) + MinDatum.Month) * 100) + MinDatum.Day       ' ZeitleisteStart als Zahl umgerechnet
```
So sollte deine Zeitleiste in den meisten Fällen die Abstände immer richtig zeichen (ansonsten wird ev. alles zu sehr zusammengestaucht gezeichnet)

so änhlich dann ev. für MaxDatum prüfen, nur das da zum 31.12 hin geprüft wird und auf den 31.12 gesetzt wird wenn MaxDatum kleiner ist


----------



## werner_sg (5. August 2021)

Spyke hat gesagt.:


> Sry, was es da aktuell ev. für Bücher gibt die empfehlenswert wären weiß ich nicht.
> 
> zum zeitleisten problem
> pack dann einfach zeitleisteBeginn, zeitleisteEnde und zeitleisteMaxBereich runter in das for each.
> ...


??????

keine Ahnung warum aber sobald ich den Inhalt aus dem MinDatum nutze ist die Anzeige gleich Null, soll aber jetzt nicht weiter stören lass es erst mal pro Jahr eventuell setze ich noch ne if Abfrage rein um das Jahr zu wechseln.
Also: ((Mietbegin.Year+1) * 100)


----------

