Durchschnittsberechungen aus mehreren XML-Files

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von Amelie.

    Durchschnittsberechungen aus mehreren XML-Files

    EDIT um 15:00 UHR
    Bis auf den Code in der Region "Berechnungen" habe ich mal aufgeräumt und den Code hoffentlich verbessert.


    Moin moin

    Ich schreibe weiter an meiner WetterApp. Gleich zur Info, die wird nur auf einem älteren Laptop laufen, deswegen können die Pfade so "hardcodiert" sein. Also rein privat.

    Ich erzeuge ja nun für jeden Monat eine XML-Datei. Nun sollen diese durchlaufen werden, und aus den einzelnen Knoten die Durchschnittswerte berechnet werden.
    Diese sollen dann in einem DGV angezeigt und auch wieder als XML-Datei gespeichert werden.

    Ich weiß nicht genau wie ich an die Auswertung herangehen soll. Eine Idee war es, erst für jeden Monat die ganzen Durchschnittswerte zu berechen und dann die Jahresabrechnung.
    Ich hoffe Ihr versteht was ich erreichen möchte und könnt mir bei der Umsetzung helfen.

    Einiges was ich bisher habe, funktioniert soweit.
    Probleme gibt es bei den Berechnungen und anzeigen im DGV. Ich hänge mal Bilder an um es ggf zu verdeutlichen.


    Mein bisheriger Code. Den Teil um das DGV zu formatieren habe ich weggelassen!
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class frmMain
    2. #Region "Form-laden"
    3. 'Klasse zum laden der MonatsXML etc.
    4. Private FileManager As New FileManager
    5. 'Klasse zum speichern der AbschlussXML
    6. Private SaveXMLfile As New SaveXMLfile
    7. 'Klasse für die Wetterdaten
    8. Private weatherDataList As New WeatherDataArray
    9. 'Zeilenhöhe des DGV festlegen
    10. Private Const dgvCellhight As Integer = 32
    11. Public Sub New()
    12. InitializeComponent()
    13. LoadMonthXmlFiles()
    14. 'FormatDataGridView(DGV_1, dgvCellhight)
    15. End Sub
    16. Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    17. Dim yearXmlFile As String = String.Format("Abschluss-{0}.xml", Date.Now.Year)
    18. Dim yearXmlPath As String = Path.Combine(FileManager.OutputPath, yearXmlFile)
    19. lbl_Yearfile.Text = yearXmlPath
    20. CalcAllValues()
    21. End Sub
    22. #End Region
    23. #Region "Buttons"
    24. Private Sub btn_SaveXML_Click(sender As Object, e As EventArgs) Handles btn_SaveXML.Click
    25. ' DataGridView-Daten in eine DataTable konvertieren
    26. Dim dt As DataTable = SaveXMLfile.ConvertDataGridViewToDataTable(DGV_1)
    27. ' DataTable in eine XML-Datei speichern
    28. SaveXMLfile.SaveDataTableToXmlFile(dt, FileManager.outputPath)
    29. End Sub
    30. #End Region
    31. #Region "Monats XMLs laden"
    32. Private Sub LoadMonthXmlFiles()
    33. ' Ruft die GetXmlFiles()-Methode in der XmlFileManager-Klasse auf, um die XML-Dateien zu erhalten
    34. Dim xmlFiles As List(Of String) = FileManager.GetXmlFiles()
    35. ' Füllt die Listbox mit den XML-Dateien
    36. If xmlFiles.Count > 0 Then
    37. listbox_XML_Files.DataSource = xmlFiles
    38. Else
    39. MessageBox.Show("Keine XML-Dateien gefunden.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
    40. End If
    41. End Sub
    42. #End Region
    43. #Region "Berechnungen"
    44. Private Sub CalcAllValues()
    45. Dim rainValues As New List(Of Double)
    46. For Each xmlFile In listbox_XML_Files.Items()
    47. Dim xmlDoc As New XmlDocument()
    48. xmlDoc.Load(CStr(xmlFile))
    49. Dim weatherDataNodes As XmlNodeList = xmlDoc.SelectNodes("//WeatherData")
    50. For Each weatherDataNode As XmlNode In weatherDataNodes
    51. Dim regenNode As XmlNode = weatherDataNode.SelectSingleNode("RegenTag")
    52. Dim regenValue As Double = Double.Parse(regenNode.InnerText)
    53. rainValues.Add(regenValue)
    54. Next
    55. Next
    56. 'Listbox nur zum Test
    57. listbox_regen.DataSource = rainValues
    58. listbox_regen.Refresh()
    59. ' Durchschnitt für jeden Monat berechnen
    60. For month As Integer = 1 To 12
    61. Dim currentMonth As Integer = month
    62. Dim monthRainValues = rainValues.Where(Function(r)
    63. Dim monthDate = New DateTime(dtpDatum.Value.Year, currentMonth, 1)
    64. Return monthDate.Month = currentMonth
    65. End Function)
    66. Dim averageRain = If(monthRainValues.Any(), monthRainValues.Average(), 0)
    67. 'Label nur zum Test
    68. label_averageRegen.Text = "Durchschnittlicher Regen: " & averageRain.ToString("F2") & " mm"
    69. Dim monthData As New WeatherData With {
    70. .Datum = New DateTime(dtpDatum.Value.Year, currentMonth, 1).ToString,
    71. .Regen24h = CDbl(averageRain.ToString("F2"))
    72. }
    73. weatherDataList.Add(monthData)
    74. Next
    75. ' DGV aktualisieren
    76. DGV_1.DataSource() = weatherDataList
    77. DGV_1.Refresh()
    78. End Sub
    79. #End Region
    80. End Class
    81. 'Klasse für Wetterdaten
    82. Public Class WeatherData
    83. Private _datum As Date
    84. Public Property Datum As String
    85. Get
    86. Return _datum.ToString("MM - yyyy")
    87. End Get
    88. Set(ByVal value As String)
    89. If Date.TryParse(value, _datum) Then
    90. _datum = _datum.Date
    91. Else
    92. Throw New ArgumentException("Ungültiges Datumsformat.")
    93. End If
    94. End Set
    95. End Property
    96. Public Property Regen24h As Double
    97. Public Property SchneeTag As Double
    98. Public Property SchneeNacht As Double
    99. Public Property LuftfminTag As Double
    100. Public Property LuftfmaxTag As Double
    101. Public Property LuftfminNacht As Double
    102. Public Property LuftfmaxNacht As Double
    103. Public Property TempTag As Double
    104. Public Property TempNacht As Double
    105. Public Property WindTag As Double
    106. Public Property WindNacht As Double
    107. End Class
    108. 'Klasse für Array von Wetterdaten
    109. Public Class WeatherDataArray
    110. Inherits List(Of WeatherData)
    111. End Class
    112. Public Class FileManager
    113. 'Pfade können so bleiben, da die App nur auf einem Laptop laufen wird.
    114. Private _folderPath As String = "C:\Wetterdaten"
    115. Public Property FolderPath As String
    116. Get
    117. Return _folderPath
    118. End Get
    119. Set(value As String)
    120. _folderPath = value
    121. End Set
    122. End Property
    123. Private _outputPath As String = "C:\Wetterdaten\Jahresdaten"
    124. Public Property OutputPath As String
    125. Get
    126. Return _outputPath
    127. End Get
    128. Set(value As String)
    129. _outputPath = value
    130. End Set
    131. End Property
    132. Public Sub New()
    133. CreateOutputDirectory()
    134. End Sub
    135. Public Function GetXmlFiles() As List(Of String)
    136. Return Directory.GetFiles(folderPath, "??-????.xml").Where(Function(file) Regex.IsMatch(Path.GetFileNameWithoutExtension(file), "^\d{2}-\d{4}$")).ToList()
    137. End Function
    138. Public Sub CreateOutputDirectory()
    139. If Not Directory.Exists(outputPath) Then
    140. Directory.CreateDirectory(outputPath)
    141. End If
    142. End Sub
    143. End Class
    144. Public Class SaveXMLfile
    145. 'Klasse zum speichern der AbschlussXML
    146. Public Function ConvertDataGridViewToDataTable(dgv As DataGridView) As DataTable
    147. Dim xmlDataTable As New DataTable("Abschluss")
    148. For Each column As DataGridViewColumn In dgv.Columns
    149. If column.Visible Then
    150. xmlDataTable.Columns.Add(column.HeaderText, column.ValueType)
    151. End If
    152. Next
    153. For Each row As DataGridViewRow In dgv.Rows
    154. If Not row.IsNewRow Then
    155. Dim dr As DataRow = xmlDataTable.NewRow()
    156. For Each column As DataGridViewColumn In dgv.Columns
    157. If column.Visible Then
    158. If column.Name = "Datum" AndAlso row.Cells(column.Index).Value IsNot Nothing Then
    159. Dim dateValue As Date = CType(row.Cells(column.Index).Value, Date)
    160. dr(column.HeaderText) = dateValue.ToString("MM/yyyy")
    161. Else
    162. dr(column.HeaderText) = If(row.Cells(column.Index).Value IsNot Nothing, row.Cells(column.Index).Value, DBNull.Value)
    163. End If
    164. End If
    165. Next
    166. xmlDataTable.Rows.Add(dr)
    167. End If
    168. Next
    169. Return xmlDataTable
    170. End Function
    171. Public Sub SaveDataTableToXmlFile(xmlDataTable As DataTable, outputPath As String)
    172. Dim yearXmlFile As String = String.Format("Abschluss-{0}.xml", Date.Now.Year)
    173. Dim yearXmlPath As String = Path.Combine(outputPath, yearXmlFile)
    174. xmlDataTable.TableName = "Abschluss"
    175. Try
    176. xmlDataTable.WriteXml(yearXmlPath)
    177. MessageBox.Show("XML-Datei erfolgreich gespeichert.", "Erfolgreich", MessageBoxButtons.OK, MessageBoxIcon.Information)
    178. Catch ex As Exception
    179. MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
    180. End Try
    181. End Sub
    182. End Class

    Bilder
    • jahres-1.jpg

      337,29 kB, 1.149×527, 87 mal angesehen
    • JahresXML.jpg

      373,93 kB, 417×684, 80 mal angesehen
    • MonatsXML.jpg

      410,9 kB, 417×684, 79 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Warum alles als XML speichern? Das finde ich für solche Datensammlungen unpassend. Ich würde eine richtige Datenbank empfehlen. Richtig umgesetz kannst du dann mit wenig Aufwand solche Ansichten erstellen. Dazu würde ich dir empfehlen entweder deutsche oder englische Namen für Variablen nehmen, das ist doch grauenhaft zu lesen. (Ich finde generell englisch besser, weil bei deutschen Namen sieht es immer noch "Denglisch" aus, wegen der englischen Schlüsselwörter)
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    @DTF
    Das mit den Datenbanken ist hier keine Option, weil auf dem Laptop nichts installiert werden soll. Deswegen schreibe ich die WetterApp so, das sie quasi als "portable-Version" läuft.
    Mit dem "de-en" gebe ich dir Recht, verfalle halt oft wieder ins "de" , aber ich mache das ja auch noch nicht so lange.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Hallo Amelie

    Ich würde im Dataset eine zusätzliche Tabelle anlegen. Diese würde ich mit dem Ergebnis füllen. Ich verwende immer strukturierte Datensetz, daher kann ich bei deiner Programmierung nicht direkt helfen. Evtl. könnte man mit Linq ein Agregatsabfrage erstellen. Wenn du eine Beispiel XML einstellen würde könnte ich es mal probieren.

    LG Panter

    Amelie schrieb:

    , weil auf dem Laptop nichts installiert werden soll.


    Du musst nicht unbedingt einen Datenbank Server laufen lassen. Sqlite kommt ohne aus, einfach ein Nuget-Packet dem Projekt hinzufügen fertig, bleibt also portable. Weiterer Vorteil wäre, es läuft flotter. Aber das wird bei dem Projekt nicht nennenswert sein, du sparst aber Speicher(Xml Overhead) und auch RAM ein.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    @DTF und @Panter und alle anderen ;)

    Habe gerade um 15:00 Uhr meinen Code im ersten Beitrag geändert.

    Ich würde im Dataset eine zusätzliche Tabelle anlegen. Diese würde ich mit dem Ergebnis füllen.

    Diese Idee hate ich auch aber bin dann völlig durcheinander gekommen.
    EDIT: eine MonatsXML angehangen.
    Dateien
    • 05-2023.zip

      (795 Byte, 73 mal heruntergeladen, zuletzt: )
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Ok, kurze Rückfrage @Amelie. Du verwendest wirklich NetFx und nicht NET? Ich frage weil du die XML selbst liest anstatt Dataset und Co zu nutzen. Je nach Runtime, mach ich dir mal ein kleines Beispiel heute Abend oder morgen früh.(Auf Basis von XML.

    PS.

    Woher beziehst du die Daten? Erhebst du sie selbst von Hand?
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    ​Woher beziehst du die Daten? Erhebst du sie selbst von Hand?

    Mein Opa hat so eine Wetterstation und schreibt die Werte da immer ab. Früher hat er das auf 100 Zetteln gemacht.
    Das Tool wo er die Wetterdaten eingibt und speichert läuft ja bereits. Ganz simpel.
    Ein DGV wo er die Daten eingibt und ein Button zu speichern was dann für jeden Monat einXML-File generiert.

    <a href="https://www.vb-paradise.de/index.php/Thread/136870-DataGridView-quer-ausdrucken/?postID=1180846#post1180846">DataGridView quer ausdrucken</a>
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @Amelie ich hab mir das eben angeschaut, du hattest da einen falschen Ansatz. Ich hab dir da einen "Flicken" gemacht. VB ist zu lange her bei mir, musste das in C# machen.

    PS.
    Aber dann ist die JahresAnsicht nicht drin, ich verbessere das noch.

    PPS.
    So ist dann auch der JahresSchnittberechnet, aber für die Jahresausgabe würde ich auch deinen Opa mitteilen auf wie vielen Monaten(oder Tagen) das basiert irgendwo wo du das anzeogst, weil der durchschnitt nur durch summe aller Werte / Anzahl Werte errechnet werden kann.

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Diagnostics;
    6. using System.Drawing;
    7. using System.IO;
    8. using System.Linq;
    9. using System.Text;
    10. using System.Threading.Tasks;
    11. using System.Windows.Forms;
    12. using System.Xml;
    13. using System.Xml.Serialization;
    14. namespace WDD
    15. {
    16. public partial class Form1 : Form
    17. {
    18. public Form1()
    19. {
    20. InitializeComponent();
    21. }
    22. public class WeatherDataArray : List<WeatherData> { }
    23. public class WeatherData
    24. {
    25. private DateTime _datum;
    26. public string Datum
    27. {
    28. get
    29. {
    30. return _datum.ToString("MM - yyyy");
    31. }
    32. set
    33. {
    34. if (DateTime.TryParse(value, out _datum))
    35. {
    36. _datum = _datum.Date;
    37. }
    38. else
    39. {
    40. throw new ArgumentException("Ungültiges Datumsformat.");
    41. }
    42. }
    43. }
    44. public double Regen24h { get; set; }
    45. public double SchneeTag { get; set; }
    46. public double SchneeNacht { get; set; }
    47. public double LuftfminTag { get; set; }
    48. public double LuftfmaxTag { get; set; }
    49. public double LuftfminNacht { get; set; }
    50. public double LuftfmaxNacht { get; set; }
    51. public double TempTag { get; set; }
    52. public double TempNacht { get; set; }
    53. public double WindTag { get; set; }
    54. public double WindNacht { get; set; }
    55. }
    56. private void Form1_Load(object sender, EventArgs e)
    57. {
    58. List<WeatherDataArray> list = new List<WeatherDataArray>();
    59. foreach (string filename in System.IO.Directory.GetFiles("./", "*.xml", System.IO.SearchOption.AllDirectories))
    60. {
    61. XmlSerializer serializer = new XmlSerializer(typeof(WeatherDataArray));
    62. using (FileStream fs = new FileStream(filename, FileMode.Open))
    63. {
    64. WeatherDataArray data = (WeatherDataArray)serializer.Deserialize(fs);
    65. list.Add(data);
    66. double LuftfmaxNachtDurchschnitt = data.Sum(wd => wd.LuftfmaxNacht) / data.Count;
    67. Debug.WriteLine(LuftfmaxNachtDurchschnitt);
    68. }
    69. }
    70. double LuftfmaxNachtDurchschnittJahr = list.Sum(wda => wda.Sum(wd => wd.LuftfmaxNacht / wda.Count)) / list.Count;
    71. Debug.WriteLine(LuftfmaxNachtDurchschnittJahr);
    72. }
    73. }
    74. }

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    @DTF
    Ich hab von C# noch weniger Ahnung als von VB ;(

    ​auf wie vielen Monaten(oder Tagen) das basiert

    Es wird jeder Tag / Monat aufgeschrieben und das dann in einzelnen XML-Dateien (pro Monat eine) abgelegt.
    Ich dachte nun, das man dann für jeden Monat die Durchschnitte errechent usw...

    Das habe ich jetzt noch: Macht mir nun eine XML mit den Durchschnittswerten. Aber wie weiter?????
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Calculation
    2. Private Function ReadWeatherDataFromFile(filePath As String) As List(Of WeatherData)
    3. Dim xdoc As XDocument = XDocument.Load(filePath)
    4. Dim weatherDataList As List(Of WeatherData) = (
    5. From element In xdoc.Descendants("WeatherData")
    6. Select New WeatherData With {
    7. .Datum = CStr(Date.ParseExact(element.Element("Datum").Value, "dd-MM-yyyy", Nothing)),
    8. .Regen24h = Integer.Parse(element.Element("RegenTag").Value),
    9. .SchneeTag = Integer.Parse(element.Element("SchneeTag").Value),
    10. .SchneeNacht = Integer.Parse(element.Element("SchneeNacht").Value),
    11. .LuftfminTag = Integer.Parse(element.Element("LuftfminTag").Value),
    12. .LuftfmaxTag = Integer.Parse(element.Element("LuftfmaxTag").Value),
    13. .LuftfminNacht = Integer.Parse(element.Element("LuftfminNacht").Value),
    14. .LuftfmaxNacht = Integer.Parse(element.Element("LuftfmaxNacht").Value),
    15. .TempTag = Integer.Parse(element.Element("TempTag").Value),
    16. .TempNacht = Integer.Parse(element.Element("TempNacht").Value),
    17. .WindTag = Integer.Parse(element.Element("WindTag").Value),
    18. .WindNacht = Integer.Parse(element.Element("WindNacht").Value)
    19. }
    20. ).ToList()
    21. Return weatherDataList
    22. End Function
    23. Private Function CalculateAverage(dataList As List(Of WeatherData), propertyName As String) As Double
    24. Dim propertyInfo As Reflection.PropertyInfo = GetType(WeatherData).GetProperty(propertyName)
    25. Dim propertyValues As IEnumerable(Of Double) = dataList.Select(Function(data) CType(propertyInfo.GetValue(data), Double))
    26. Dim averageValue As Double = propertyValues.Average()
    27. Return averageValue
    28. End Function
    29. Public Sub CalculateAndSaveAverages(inputFilePaths As List(Of String), outputFilePath As String)
    30. Try
    31. Dim allWeatherDataList As New List(Of WeatherData)
    32. 'Lade alle Wetterdaten aus der ersten Datei in die Liste
    33. allWeatherDataList.AddRange(ReadWeatherDataFromFile(inputFilePaths(0)))
    34. 'Erstelle den Dateinamen aus dem Monat der ersten Wetterdaten
    35. Dim firstDatum As Date = CDate(allWeatherDataList.First().Datum)
    36. Dim averageXmlFile As String = String.Format("Durchschnitt-{0:MM-yyyy}.xml", firstDatum)
    37. 'Füge den Dateinamen dem Verzeichnispfad hinzu
    38. Dim outputXML As String = Path.Combine(outputFilePath, averageXmlFile)
    39. 'Lade alle Wetterdaten in eine Liste
    40. For Each filePath As String In inputFilePaths '.Skip(1)
    41. Dim weatherDataList As List(Of WeatherData) = ReadWeatherDataFromFile(filePath)
    42. allWeatherDataList.AddRange(weatherDataList)
    43. Next
    44. 'Berechne Durchschnittswerte
    45. Dim averageRain As Double = CalculateAverage(allWeatherDataList, "Regen24h")
    46. Dim averageSchneeTag As Double = CalculateAverage(allWeatherDataList, "SchneeTag")
    47. Dim averageSchneeNacht As Double = CalculateAverage(allWeatherDataList, "SchneeNacht")
    48. Dim averageLuftfminTag As Double = CalculateAverage(allWeatherDataList, "LuftfminTag")
    49. Dim averageLuftfmaxTag As Double = CalculateAverage(allWeatherDataList, "LuftfmaxTag")
    50. Dim averageLuftfminNacht As Double = CalculateAverage(allWeatherDataList, "LuftfminNacht")
    51. Dim averageLuftfmaxNacht As Double = CalculateAverage(allWeatherDataList, "LuftfmaxNacht")
    52. Dim averageTempTag As Double = CalculateAverage(allWeatherDataList, "TempTag")
    53. Dim averageTempNacht As Double = CalculateAverage(allWeatherDataList, "TempNacht")
    54. Dim averageWindTag As Double = CalculateAverage(allWeatherDataList, "WindTag")
    55. Dim averageWindNacht As Double = CalculateAverage(allWeatherDataList, "WindNacht")
    56. 'Erstelle neue XML-Datei mit Durchschnittswerten
    57. Dim xdoc As New XDocument(
    58. New XElement("AverageWeatherData",
    59. New XElement("Regen24h", averageRain),
    60. New XElement("SchneeTag", averageSchneeTag),
    61. New XElement("SchneeNacht", averageSchneeNacht),
    62. New XElement("LuftfminTag", averageLuftfminTag),
    63. New XElement("LuftfmaxTag", averageLuftfmaxTag),
    64. New XElement("LuftfminNacht", averageLuftfminNacht),
    65. New XElement("LuftfmaxNacht", averageLuftfmaxNacht),
    66. New XElement("TempTag", averageTempTag),
    67. New XElement("TempNacht", averageTempNacht),
    68. New XElement("WindTag", averageWindTag),
    69. New XElement("WindNacht", averageWindNacht)
    70. )
    71. )
    72. 'Speichere die neue XML-Datei
    73. xdoc.Save(outputXML)
    74. MessageBox.Show("XML-Datei erfolgreich gespeichert.", "Erfolgreich", MessageBoxButtons.OK, MessageBoxIcon.Information)
    75. Catch ex As Exception
    76. MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
    77. End Try
    78. End Sub
    79. End Class

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Ich hab von C# noch weniger Ahnung als von VB


    Wirf meinen Code in diesen Konverter, der kann dir das übersetzen:
    icsharpcode.github.io/CodeConverter/

    Was ich vorhin vergessen hatte zu erwähnen, so wie ich das gemacht habe, werden ale XML dateien geparst, für eine filterung für jedes Jahr in Zeile 77 ein kleiner Edit, Where is das Stichwort, _datum in WheaterData public machen und mit dem Jahr vergleichen. Alternativ schon beim Dateinamen filtern(bei IO.Directory.GetFiles).

    PS.
    Du machst dir das zu kompliziert. Bei mir im Form_Load sinds nur ein paar Zeilen. Nimm den übersetzten ;)

    Da wo ich die Debug Ausgabe gemacht hab, machst du dann das hinzufügen der Zeilen.

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    Hallo Amelie

    Ich bin wahrscheinlich etwas weit weg von deiner Programmierung. Wie erwähnt habe ich mit dem Desinger ein Dataset erstellt und mache nun mit Linq eine gruppierte Abfrage. Diese fülle ich dann in die Ergebnis Tabelle ein. Ich habe auch das Projekt hochgeladen, ist wahrscheinlich einfacher.

    Ich persönlich würde alle Daten in eine Datei speichern, Du kannst aber auch alle Daten nacheinander in das Dataset laden und dann die Abfrage ausführen.

    Ich hoffe, du kannst etwas gebrauchen.


    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. Me.DataSet1.ReadXml("../../05-2023.xml")
    4. End Sub
    5. Private Sub BT_Speichern_Click(sender As Object, e As EventArgs) Handles BT_Speichern.Click
    6. Me.DataSet1.WriteXml("../../05-2023.xml")
    7. End Sub
    8. Private Sub BT_zusammenfassung_Click(sender As Object, e As EventArgs) Handles BT_zusammenfassung.Click
    9. Dim results =
    10. From row In DataSet1.WeatherData
    11. Let dt = CDate(row.Datum_)
    12. Let sDate = String.Format("{0:yyyy}-{0:MM}", dt)
    13. Group row By key = New With {Key .MMJJ = sDate} Into Group
    14. Select MMJJ = key.MMJJ, LuftMaxNacht = Group.Max(Function(r) r.LuftmaxNacht), LuftMinNacht = Group.Min(Function(r) r.LuftminNacht)
    15. DataSet1.Wetter_MMJJ.Clear()
    16. For Each item In results
    17. Dim row As DataSet1.Wetter_MMJJRow = DataSet1.Wetter_MMJJ.NewRow
    18. row.MMJJ = item.MMJJ
    19. row.LuftminNacht = item.LuftMinNacht
    20. row.LuftmaxNacht = item.LuftMaxNacht
    21. DataSet1.Wetter_MMJJ.Rows.Add(row)
    22. Next
    23. End Sub
    24. End Class

    Dateien
    • Wetterstation.zip

      (95,67 kB, 87 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Panter“ ()

    @Panter
    Habe hier ein Bild mit den Fehlermeldungen an gehangen.
    Liegt wohl daran, das ich auf Win7-64Bit und VS 2013 schreibe und mir deswegen wohl einiges fehlt.
    Bilder
    • fehler-1.jpg

      653,68 kB, 567×842, 64 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @Amelie Was hindert Dich daran, auf Studio 2022 umzusteigen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Noch immer mein alter PC. Habe mal mit Win10 versucht aber damit ist der grotten lahm.
    ------------------------------
    @DTF ...und alle anderen ;-)

    Ich habe dein C# Code jetzt mal etwas umgeändert.
    So berechnet das nun EINEN Wert aus den gefundenen Monats-XML-Dateien.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub AverageSnowDay()
    2. Dim list As List(Of WeatherDataArray) = New List(Of WeatherDataArray)()
    3. For Each filename As String In System.IO.Directory.GetFiles(FileManager.FolderPath, "*.xml", System.IO.SearchOption.TopDirectoryOnly)
    4. 'Zum Test werden gefundene Monats-XML angezeigt
    5. ListBox1Test.Items.Add(filename)
    6. Dim serializer As XmlSerializer = New XmlSerializer(GetType(WeatherDataArray))
    7. Using fs As FileStream = New FileStream(filename, FileMode.Open)
    8. Dim data As WeatherDataArray = CType(serializer.Deserialize(fs), WeatherDataArray)
    9. list.Add(data)
    10. Dim SchneeTagDurchschnitt As Double = data.Sum(Function(wd) wd.SchneeTag) / data.Count
    11. 'Zum Test Monatsberechnungen ausgeben
    12. lbl_averageTest2.Text = "Durchschnittlicher Schnee Monat: " & SchneeTagDurchschnitt.ToString("F2") & " cm"
    13. ListBox2Test.Items.Add(SchneeTagDurchschnitt.ToString("F2") & " cm")
    14. End Using
    15. Next
    16. Dim SchneeTagDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.SchneeTag / wda.Count)) / list.Count
    17. 'Zum Test Jahresberechnungen ausgeben
    18. lbl_averageTest1.Text = "Durchschnittlicher Schnee Jahr: " & SchneeTagDurchschnittJahr.ToString("F2") & " cm"
    19. End Sub



    Jetzt hängts in meinen Kopf.
    a) die anderen Werte aus den XMLs lesen und berechen
    b) as dann alles in ein DGV packen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Musst du wieder übersetzen. Ich habe einfach mal meinen Code ein wenig erweitert. Nur ein DatagridView aufs Form geworfen und:

    C#-Quellcode

    1. private BindingSource bindingSource = new BindingSource();
    2. private void Form1_Load(object sender, EventArgs e)
    3. {
    4. List<WeatherDataArray> list = new List<WeatherDataArray>();
    5. List<WeatherData> weatherDatas = new List<WeatherData>();
    6. foreach (string filename in System.IO.Directory.GetFiles("./", "*.xml", System.IO.SearchOption.AllDirectories))
    7. {
    8. XmlSerializer serializer = new XmlSerializer(typeof(WeatherDataArray));
    9. using (FileStream fs = new FileStream(filename, FileMode.Open))
    10. {
    11. WeatherDataArray data = (WeatherDataArray)serializer.Deserialize(fs);
    12. list.Add(data);
    13. WeatherData weatherData = new WeatherData();
    14. weatherData.Datum = data[0].Datum; // gibt ja immer den formattierten wert ist dann ja immer "MM - yyyy" und monat und jahr sind ja für alle Daten in der selben XML identisch
    15. weatherData.LuftfmaxNacht = data.Sum(wd => wd.LuftfmaxNacht) / data.Count;
    16. weatherDatas.Add(weatherData);
    17. }
    18. }
    19. double LuftfmaxNachtDurchschnittJahr = list.Sum(wda => wda.Sum(wd => wd.LuftfmaxNacht / wda.Count)) / list.Count;
    20. Debug.WriteLine(LuftfmaxNachtDurchschnittJahr);
    21. bindingSource.DataSource = weatherDatas;
    22. dataGridView1.DataSource = bindingSource;
    23. }


    Und wie durch Zauberei hat man schon die Ansicht(Siehe Anhang) für die Monate, du musst das nur noch ergänzen mit den andere Werten.
    Auf diese Weise lassen sich dann auch die Jahresansichten in einem 2. DataGridView Anschauen.
    Bilder
    • 1.jpg

      81,71 kB, 1.788×237, 61 mal angesehen
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    Hallo Amelie,
    für die tempoäre Ausgabe mache doch statt:

    Amelie schrieb:

    'Zum Test Monatsberechnungen ausgeben
    lbl_averageTest2.Text = "Durchschnittlicher Schnee Monat: " & SchneeTagDurchschnitt.ToString("F2") & " cm"


    einfach

    VB.NET-Quellcode

    1. Debug.Print("Durchschnittlicher Schnee Monat: " & SchneeTagDurchschnitt.ToString("F2") & " cm")


    Damit wird die Ausgabe in das Ausgabe-Fenster umgeleitet.
    Aus meiner Sicht ist der Vorteil, wenn man vergisst die Testausgabe zu löschen, bekommt der Anwender dies nicht mit. ggf. kommt auch kein Fehler weil ein Feld nicht mehr da ist. Es kostet nur etwas Rechenzeit.
    Natürlich sollte man diese Testausgaben später auf jeden Fall löschen.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    @DTF
    EDIT: um 14:05 Uhr !!

    Das funktioniert nun nach ersten Tests. Auch das speichern in einer neuen Jahres-XML funktioniert. Was ich nun noch ändern möchte, ist die Berechung gleich auf 2Nachkommastellen, weil in der XML-Datei etliche Nachkommastellen gespeichert werden.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub CalculateYearAverages()
    2. Dim list As List(Of WeatherDataArray) = New List(Of WeatherDataArray)()
    3. Dim weatherDatas As List(Of WeatherData) = New List(Of WeatherData)()
    4. For Each filename As String In System.IO.Directory.GetFiles(FileManager.FolderPath, "*.xml", System.IO.SearchOption.TopDirectoryOnly)
    5. 'gefundene Monats-XML anzeigen
    6. listbox_XML_Files.Items.Add(filename)
    7. Dim serializer As XmlSerializer = New XmlSerializer(GetType(WeatherDataArray))
    8. Using fs As FileStream = New FileStream(filename, FileMode.Open)
    9. Dim data As WeatherDataArray = CType(serializer.Deserialize(fs), WeatherDataArray)
    10. list.Add(data)
    11. Dim weatherData As WeatherData = New WeatherData()
    12. weatherData.Datum = data(0).Datum
    13. weatherData.SchneeTag = data.Sum(Function(wd) wd.SchneeTag) / data.Count
    14. weatherData.SchneeNacht = data.Sum(Function(wd) wd.SchneeNacht) / data.Count
    15. weatherData.LuftfminTag = data.Sum(Function(wd) wd.LuftfminTag) / data.Count
    16. weatherData.LuftfmaxTag = data.Sum(Function(wd) wd.LuftfmaxTag) / data.Count
    17. weatherData.LuftfminNacht = data.Sum(Function(wd) wd.LuftfminNacht) / data.Count
    18. weatherData.LuftfmaxNacht = data.Sum(Function(wd) wd.LuftfmaxNacht) / data.Count
    19. weatherData.TempTag = data.Sum(Function(wd) wd.TempTag) / data.Count
    20. weatherData.TempNacht = data.Sum(Function(wd) wd.TempNacht) / data.Count
    21. weatherData.WindTag = data.Sum(Function(wd) wd.WindTag) / data.Count
    22. weatherData.WindNacht = data.Sum(Function(wd) wd.WindNacht) / data.Count
    23. weatherDatas.Add(weatherData)
    24. End Using
    25. Next
    26. Dim SchneeTagDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.SchneeTag / wda.Count)) / list.Count
    27. Dim SchneeNachtDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.SchneeNacht / wda.Count)) / list.Count
    28. Dim LuftfminTagDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfminTag / wda.Count)) / list.Count
    29. Dim LuftfmaxTagDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfmaxTag / wda.Count)) / list.Count
    30. Dim LuftfminNachtDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfminNacht / wda.Count)) / list.Count
    31. Dim LuftfmaxNachtDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfmaxNacht / wda.Count)) / list.Count
    32. Dim TempTagDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.TempTag / wda.Count)) / list.Count
    33. Dim TempNachtDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.TempNacht / wda.Count)) / list.Count
    34. Dim WindTagDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.WindTag / wda.Count)) / list.Count
    35. Dim WindNachtDurchschnittJahr As Double = list.Sum(Function(wda) wda.Sum(Function(wd) wd.WindNacht / wda.Count)) / list.Count
    36. bindingSource.DataSource = weatherDatas
    37. DGV_1.DataSource = bindingSource
    38. For Each column As DataGridViewColumn In DGV_1.Columns
    39. If column.ValueType = GetType(Double) Then
    40. column.DefaultCellStyle.Format = "N2"
    41. End If
    42. Next
    43. End Sub




    @INOPIAE
    Mit dem "DebugPrint" habe ich immer so meine Probleme... ;(
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Hallo

    So bis hier hin bin ich nun fertig. Das Bild zeigt wie die DGV nun mit pseudo-Daten aus 12 XML-Files gefüllt werden.
    Das ganze kann ich nun in einer "Abschluss-2013.xml" speichern. ;)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub CalculateYearAverages()
    2. Dim list As List(Of WeatherDataArray) = New List(Of WeatherDataArray)()
    3. Dim weatherDatas As List(Of WeatherData) = New List(Of WeatherData)()
    4. For Each filename As String In System.IO.Directory.GetFiles(FileManager.FolderPath, "*.xml", System.IO.SearchOption.TopDirectoryOnly)
    5. 'gefundene Monats-XML anzeigen
    6. listbox_XML_Files.Items.Add(filename)
    7. Dim serializer As XmlSerializer = New XmlSerializer(GetType(WeatherDataArray))
    8. Using fs As FileStream = New FileStream(filename, FileMode.Open)
    9. Dim data As WeatherDataArray = CType(serializer.Deserialize(fs), WeatherDataArray)
    10. list.Add(data)
    11. Dim weatherData As WeatherData = New WeatherData()
    12. weatherData.Datum = data(0).Datum
    13. weatherData.SchneeTag = Math.Round(data.Sum(Function(wd) wd.SchneeTag) / data.Count, 2)
    14. weatherData.SchneeNacht = Math.Round(data.Sum(Function(wd) wd.SchneeNacht) / data.Count, 2)
    15. weatherData.LuftfminTag = Math.Round(data.Sum(Function(wd) wd.LuftfminTag) / data.Count, 2)
    16. weatherData.LuftfmaxTag = Math.Round(data.Sum(Function(wd) wd.LuftfmaxTag) / data.Count, 2)
    17. weatherData.LuftfminNacht = Math.Round(data.Sum(Function(wd) wd.LuftfminNacht) / data.Count, 2)
    18. weatherData.LuftfmaxNacht = Math.Round(data.Sum(Function(wd) wd.LuftfmaxNacht) / data.Count, 2)
    19. weatherData.TempTag = Math.Round(data.Sum(Function(wd) wd.TempTag) / data.Count, 2)
    20. weatherData.TempNacht = Math.Round(data.Sum(Function(wd) wd.TempNacht) / data.Count, 2)
    21. weatherData.WindTag = Math.Round(data.Sum(Function(wd) wd.WindTag) / data.Count, 2)
    22. weatherData.WindNacht = Math.Round(data.Sum(Function(wd) wd.WindNacht) / data.Count, 2)
    23. weatherDatas.Add(weatherData)
    24. End Using
    25. Next
    26. BS_DGV_1.DataSource = weatherDatas
    27. DGV_1.DataSource = BS_DGV_1
    28. BS_DGV_2.DataSource = GetType(List(Of WeatherData))
    29. Dim SchneeTagDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.SchneeTag / wda.Count)) / list.Count, 2)
    30. Dim SchneeNachtDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.SchneeNacht / wda.Count)) / list.Count, 2)
    31. Dim LuftfminTagDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfminTag / wda.Count)) / list.Count, 2)
    32. Dim LuftfmaxTagDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfmaxTag / wda.Count)) / list.Count, 2)
    33. Dim LuftfminNachtDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfminNacht / wda.Count)) / list.Count, 2)
    34. Dim LuftfmaxNachtDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.LuftfmaxNacht / wda.Count)) / list.Count, 2)
    35. Dim TempTagDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.TempTag / wda.Count)) / list.Count, 2)
    36. Dim TempNachtDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.TempNacht / wda.Count)) / list.Count, 2)
    37. Dim WindTagDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.WindTag / wda.Count)) / list.Count, 2)
    38. Dim WindNachtDurchschnittJahr As Double = Math.Round(list.Sum(Function(wda) wda.Sum(Function(wd) wd.WindNacht / wda.Count)) / list.Count, 2)
    39. Dim wetterDatenList As New List(Of WeatherData)() From {
    40. New WeatherData() With {
    41. .SchneeTag = SchneeTagDurchschnittJahr,
    42. .SchneeNacht = SchneeNachtDurchschnittJahr,
    43. .LuftfminTag = LuftfminTagDurchschnittJahr,
    44. .LuftfmaxTag = LuftfmaxTagDurchschnittJahr,
    45. .LuftfminNacht = LuftfminNachtDurchschnittJahr,
    46. .LuftfmaxNacht = LuftfmaxNachtDurchschnittJahr,
    47. .TempTag = TempTagDurchschnittJahr,
    48. .TempNacht = TempNachtDurchschnittJahr,
    49. .WindTag = WindTagDurchschnittJahr,
    50. .WindNacht = WindNachtDurchschnittJahr
    51. }
    52. }
    53. BS_DGV_2.DataSource = wetterDatenList
    54. DGV_2.DataSource = BS_DGV_2
    55. DGV_2.Columns(0).Visible = False
    56. End Sub

    Bilder
    • jahres-1.jpg

      225,8 kB, 800×393, 56 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh: