Powershell - aus csv Spaltensumme einlesen und in Variable bzw. neue csv schreiben
Hallo an alle,
ich hab mit folgendem Code versucht anhand einer Beispieldatei die Spaltensumme zu ermitteln:
Was mache ich falsch? Ich möchte die Summe der Spalte1 und Spalte2 in eine Variable schreiben bzw. in das C:\Temp\Data2018_Summe.csv schreiben.
Kann mir bitte jemand helfen?
Vielen Dank
ich hab mit folgendem Code versucht anhand einer Beispieldatei die Spaltensumme zu ermitteln:
$csv= import-csv C:\Temp\Data2018.csv
$betrag1 = $csv.Betrag1 | measure-object -sum
$object = -Name NumCpu -Value $Betrag1.sum
[System.Windows.Forms.MessageBox]::Show($betrag1,"Kontrollsummen",0)
Was mache ich falsch? Ich möchte die Summe der Spalte1 und Spalte2 in eine Variable schreiben bzw. in das C:\Temp\Data2018_Summe.csv schreiben.
Kann mir bitte jemand helfen?
Vielen Dank
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 416467
Url: https://administrator.de/contentid/416467
Ausgedruckt am: 24.11.2024 um 01:11 Uhr
20 Kommentare
Neuester Kommentar
Was mache ich falsch?
"Strings" kannst du nicht summieren . Du musst sie erst zu echten Zahlen umwandeln![Int]
[Decimal]
[Double]
&Co. sind deine Freunde
$betrag1 = import-csv 'C:\Temp\Data2018.csv' -delim ";" | %{[decimal]::Parse($_.betrag1,[cultureinfo]::GetCultureInfo('de'))} | measure -Sum | select -ExpandProperty Sum
Moin,
Hier fehlt der delimiter.
Das ist soweit ok. Wenn das Trennzeichen bekannt ist, dann wird das das richtige Ergebnis auswerfen.
Was soll das werden?
Hier fehlt das .sum hinter $betrag1. So steht das im Popup "Microsoft.Powershell..."
hth
Erik
<edit>P. S.: Warum schreibst Du nicht einfach =summe(b2:b4) in Deine Exceltabelle? </edit>
Hier fehlt der delimiter.
$betrag1 = $csv.Betrag1 | measure-object -sum
Das ist soweit ok. Wenn das Trennzeichen bekannt ist, dann wird das das richtige Ergebnis auswerfen.
$object = -Name NumCpu -Value $Betrag1.sum
Was soll das werden?
[System.Windows.Forms.MessageBox]::Show($betrag1,"Kontrollsummen",0)
Hier fehlt das .sum hinter $betrag1. So steht das im Popup "Microsoft.Powershell..."
hth
Erik
<edit>P. S.: Warum schreibst Du nicht einfach =summe(b2:b4) in Deine Exceltabelle? </edit>
Richtig von oben kopieren sollte man schon können.
Ich bin kompletter PS Anfänger
Dann mach halt erst mal einen Kurs und pfusch dich hier nicht so durch, das bringt dir nämlich gar nüscht.
Moin,
Klar. $betrag1 ist ja auch leer.
so funktioniert es:
Liebe Grüße
Erik
Zitat von @Manrique:
import-csv 'C:\Temp\Data2018.csv' -delim ";" | %{[decimal]::Parse($_.BETRAG1,[cultureinfo]::GetCultureInfo('de'))} |measure -Sum | select -Expand Sum
>
> $betrag1 = $csv.Betrag1 | measure-object -sum
Klar. $betrag1 ist ja auch leer.
so funktioniert es:
$csv= import-csv C:\Temp\Data2018.csv -delimiter ";"
$betrag1 = $csv.Betrag1 | measure-object -sum
[System.Windows.Forms.MessageBox]::Show($betrag1.sum,"Kontrollsummen",0)
Liebe Grüße
Erik
Zitat von @Manrique:
danke. Jetzt ist nur noch das "String-Thema", weil bei Summierung von Betrag 2 ist das Ergebnis 665 statt 86,3.
Kann mir bitte hier noch jemand helfen?
Sag mal bist du blind? Lese meinen ersten Beitrag nochmal da steht's schon in Codeform!danke. Jetzt ist nur noch das "String-Thema", weil bei Summierung von Betrag 2 ist das Ergebnis 665 statt 86,3.
Kann mir bitte hier noch jemand helfen?
@erikro wandelt es nicht um das ist der Grund, in meinem ersten Beitrag steht es korrekt inkl. Umwandlung der Strings in Decimal.
Hier nochmal für Blinde:
$betrag1 = import-csv 'C:\Temp\Data2018.csv' -delim ";" | %{[decimal]::Parse($_.betrag1,[cultureinfo]::GetCultureInfo('de'))} | measure -Sum | select -ExpandProperty Sum
$betrag1
Dann hast du leere Felder in der CSV , die Felder musst du vorher ausfiltern.
$betrag1 = import-csv 'C:\Temp\Data2018.csv' -delim ";" | ?{$_.betrag1 -match "\d"} | %{[decimal]::Parse($_.betrag1,[cultureinfo]::GetCultureInfo('de'))} | measure -Sum | select -ExpandProperty Sum
Moin,
Kannst Du Dich vielleicht mal im Ton mäsigen, zumal dann, wenn das, was Du erklärst nicht korrekt ist.
Das Problem ist nicht, dass die Zahlen nicht als Zahlen erkannt werden. Sonst würde die PS ja gar nicht rechnen und eine Fehlermeldung auswerfen. Das Problem ist, dass die Übergabe 12,23 nicht als zwölfkommazweidrei interpretiert wird, sondern als Array aus zwei Zahlen mit den Werten 12 und 23. Damit kommt bei der Summierung von scheinbar zwei Werten die Summe von vier Werten heraus. Also wenn ich die Zahlen 12,23 und 13,34 summiere, ist das Ergebnis nach dieser Logik korrekterweise 12 + 23 + 13 + 34 = 82. Die einfache Lösung des Problems ist, die Kommata vor der Berechnung durch Punkte zu ersetzen. Dann stimmt auch das Ergebnis. Das ist die wesentlich bessere Lösung, da ich dann nämlich nicht bei jedem Betrag das csv einzeln einlesen muss.
Liebe Grüße
Erik
Zitat von @138810:
@erikro wandelt es nicht um das ist der Grund, in meinem ersten Beitrag steht es korrekt inkl. Umwandlung der Strings in Decimal.
Hier nochmal für Blinde:
Zitat von @Manrique:
danke. Jetzt ist nur noch das "String-Thema", weil bei Summierung von Betrag 2 ist das Ergebnis 665 statt 86,3.
Kann mir bitte hier noch jemand helfen?
Sag mal bist du blind? Lese meinen ersten Beitrag nochmal da steht's schon in Codeform!danke. Jetzt ist nur noch das "String-Thema", weil bei Summierung von Betrag 2 ist das Ergebnis 665 statt 86,3.
Kann mir bitte hier noch jemand helfen?
@erikro wandelt es nicht um das ist der Grund, in meinem ersten Beitrag steht es korrekt inkl. Umwandlung der Strings in Decimal.
Hier nochmal für Blinde:
> $betrag1 = import-csv 'C:\Temp\Data2018.csv' -delim ";" | %{[decimal]::Parse($_.betrag1,[cultureinfo]::GetCultureInfo('de'))} | measure -Sum | select -ExpandProperty Sum
> $betrag1
>
Kannst Du Dich vielleicht mal im Ton mäsigen, zumal dann, wenn das, was Du erklärst nicht korrekt ist.
Das Problem ist nicht, dass die Zahlen nicht als Zahlen erkannt werden. Sonst würde die PS ja gar nicht rechnen und eine Fehlermeldung auswerfen. Das Problem ist, dass die Übergabe 12,23 nicht als zwölfkommazweidrei interpretiert wird, sondern als Array aus zwei Zahlen mit den Werten 12 und 23. Damit kommt bei der Summierung von scheinbar zwei Werten die Summe von vier Werten heraus. Also wenn ich die Zahlen 12,23 und 13,34 summiere, ist das Ergebnis nach dieser Logik korrekterweise 12 + 23 + 13 + 34 = 82. Die einfache Lösung des Problems ist, die Kommata vor der Berechnung durch Punkte zu ersetzen. Dann stimmt auch das Ergebnis. Das ist die wesentlich bessere Lösung, da ich dann nämlich nicht bei jedem Betrag das csv einzeln einlesen muss.
$csv= import-csv betrag.csv -delimiter ";"
$betrag1 = $csv.Betrag1.replace(",",".") | measure-object -sum
$betrag2 = $csv.Betrag2.replace(",",".") | measure-object -sum
Liebe Grüße
Erik
Das ist die wesentlich bessere Lösung, da ich dann nämlich nicht bei jedem Betrag das csv einzeln einlesen muss.
Nö, so werden dann nämlich auch falsch formatierte Zahlen falsch interpretiert und es kommt das falsche Ergebnis heraus, deswegen besser gleich einzeln mit der passenden Culture einlesen und validieren oder TryParse nutzen dann stimmt das Ergebnis auch.
Man fragt sich wie der TO so ein Script hinbekommt wo es doch an den Grundlagen schon scheitert, wahrscheinlich wieder irgendwo her kopiert und ohne Quellenangabe hier reingepastet ...
Mit der Installation des ImportExcel Moduls von Doug Finke
https://github.com/dfinke/ImportExcel
https://www.powershellgallery.com/packages/ImportExcel/5.4.4
Kannst du mit diesem Skript (auch ohne installiertes Excel) direkt Excel Dateien lesen/schreiben ohne Umweg über .csv Datein.
Bekommst du diese Ausgabe:
Und direkt auch als .xlsx Datei
Die MessageBox geht zwar, sieht aber durch den Standard Font (variable width) blöd aus.
https://github.com/dfinke/ImportExcel
https://www.powershellgallery.com/packages/ImportExcel/5.4.4
Kannst du mit diesem Skript (auch ohne installiertes Excel) direkt Excel Dateien lesen/schreiben ohne Umweg über .csv Datein.
$Data2018 = Import-Excel .\Data2108.xlsx
$KontrollSummen = [PSCustomObject]@{
Name = 'Summe Data2018'
Betrag1 = ($Data2018|Measure-Object Betrag1 -Sum).Sum
Betrag2 = ($Data2018|Measure-Object Betrag2 -Sum).Sum
}
$KontrollSummen
$KontrollSummen | Export-Excel .\Data2018_Summe.xlsx -AutoSize
[System.Windows.Forms.MessageBox]::Show(($KontrollSummen|Out-String),,"Kontrollsummen",0)
Bekommst du diese Ausgabe:
> $KontrollSummen
Name Betrag1 Betrag2
---- ------- -------
Summe Data2018 36 86,3
Und direkt auch als .xlsx Datei
Die MessageBox geht zwar, sieht aber durch den Standard Font (variable width) blöd aus.
Moin,
Wieder falsch. Stehen da keine Zahlen drin, dann gibt es wie bei Deiner Lösung eine Fehlermeldung um die Ohren.
Janee, is klar. Macht ja auch kaum ein Unterschied, wenn ich aus 2.000.000 Datensätzen je zehn Werte auslese, ob ich dann das csv einmal oder zehnmal komplett auslesen muss. Wir haben ja heute schnelle Prozessoren und einen Haufen Speicher. Und die PS ist ja bekannt dafür, dass sie rasend schnell arbeitet.
Wenn ich schon validiere, dann will ich aber auch wissen, welcher DS meiner 2 Mio. denn das Berechnen verhindert. Dann vielleicht so:
Zitat von @138810:
Das ist die wesentlich bessere Lösung, da ich dann nämlich nicht bei jedem Betrag das csv einzeln einlesen muss.
Nö, so werden dann nämlich auch falsch formatierte Zahlen falsch interpretiert und es kommt das falsche Ergebnis heraus,Wieder falsch. Stehen da keine Zahlen drin, dann gibt es wie bei Deiner Lösung eine Fehlermeldung um die Ohren.
deswegen besser gleich einzeln mit der passenden Culture einlesen
Janee, is klar. Macht ja auch kaum ein Unterschied, wenn ich aus 2.000.000 Datensätzen je zehn Werte auslese, ob ich dann das csv einmal oder zehnmal komplett auslesen muss. Wir haben ja heute schnelle Prozessoren und einen Haufen Speicher. Und die PS ist ja bekannt dafür, dass sie rasend schnell arbeitet.
und validieren oder TryParse nutzen dann stimmt das Ergebnis auch.
Wenn ich schon validiere, dann will ich aber auch wissen, welcher DS meiner 2 Mio. denn das Berechnen verhindert. Dann vielleicht so:
# Referenzvariable für TryParse
[decimal]$test = $null
# Variablen leeren, damit keine falschen Ergebnisse angezeigt werden
$betrag1 = ""
$betrag2 = ""
# Zählvariable für den aktuellen Datensatz
$i = 1
# Semaphor für die Berechnung
$sem = $true
# Daten importieren
$csv= import-csv betrag.csv -delimiter ";"
# Prüfung, ob Zahlen korrekt
foreach($dataset in $csv) {
if(!([decimal]::TryParse($dataset.betrag1 , [ref]$test) -and [decimal]::TryParse($dataset.Betrag2 , [ref]$test))) {
$sem = $false
write-output "Datensatz $i enthält falsche Zahlen!"
}
$i++
}
if($sem) {
# Umwandlung des Kommas in Punkt und Summenbildung
$betrag1 = $csv.Betrag1.replace(",",".") | Measure-Object -sum
$betrag2 = $csv.Betrag2.replace(",",".") | Measure-Object -Sum
}
# Ausgabe auf dem Bildschirm
write-output "Betrag 1:" $betrag1.sum
write-output "Betrag 2:" $betrag2.sum
Wieder falsch. Stehen da keine Zahlen drin, dann gibt es wie bei Deiner Lösung eine Fehlermeldung um die Ohren.
Du willst nicht verstehen und verdrehst einem das Wort ... schon klar.[decimal]::TryParse(
Und auf einmal nutzt er es auch wie vorgeschlagen . Ja nee is klar.Glaub der TO kommt da eh nicht mit, wenn er es noch nicht mal selbst einbauen kann. Vermutlich also Zwecklos.
Zitat von @138810:
Wieder falsch. Stehen da keine Zahlen drin, dann gibt es wie bei Deiner Lösung eine Fehlermeldung um die Ohren.
Du willst nicht verstehen und verdrehst einem das Wort ... schon klar.Nein, Du verstehst nicht, dass das Einlesen der csv jeweils für einen Wert nicht performant ist. Ein csv lese ich genau einmal in einem Skript ein und nicht für jede Spalte neu. Und wo verdrehe ich Deine Worte? Wie anders soll ich das
Nö, so werden dann nämlich auch falsch formatierte Zahlen falsch interpretiert und es kommt das falsche Ergebnis heraus,
verstehen als so, dass bei z. B. 1,,2 oder bei 1text2 ein Ergebnis heraus kommen soll? Das ist schlicht und ergreifend falsch. Wenn ich bei meiner Lösung irgend etwas anderes als eine Zahl im deutschen oder englischen Format reinschreibe, dann gibt es eine Fehlermeldung, die besagt, dass da keine Zahl steht.
[decimal]::TryParse(
Und auf einmal nutzt er es auch wie vorgeschlagen . Ja nee is klar.Und wieder falsch. Du schlägst vor, die Werte spaltenweise einzeln einzulesen, die Spalte zu validieren und dann zu rechnen oder eben auch nicht. Ich schlage vor, dass, wenn denn nicht schon vorher in Excel oder wo auch immer validiert wurde, die Tabelle am Stück einzulesen, die einzelnen Werte jedes Datensatzes zu validieren, dann entweder zu rechnen oder auszugeben welche Werte genau denn nicht validiert werden konnten. Ich mache also etwas vollkommen anderes als Du.