Excel/VB.Net Code will nicht funktionieren (details unten)

Kokujou

Lieutenant
Dabei seit
Dez. 2017
Beiträge
542
Ehrlich gesagt bin ich am Ende mit meinem Latein. Ich bin eigentlich C# gewöhnt aber ich hab langsam das Gefühl dass das nicht ein Problem der Programmiersprache ist, sondern dass Excel mich hasst >.>

Alles was ich will, ist zählen wie viele Einträge sich in einer Zeile ähneln. Ich hätte mir nie träumen lassen dass ich dafür jetzt auch noch auf Makros zurückgreifen muss und selbst damit scheint es nicht zu klappen. Also vielleicht könnt ihr mir ja sagen was in diesem code kaputt ist.

Zum Aufbau: ich habe eine Matrix erstellt Spalten, 14 Zeilen, Beschriftung ausgeschlossen, deswegen hier und da ein paar offsets. Eingetragen habe ich immer sowas wie 6/42 und Excel hat dann ne lange Zahl daraus gemacht. Ich hab schon kommas zu Punkten konvertiert, ich habe gerundet, ich habe leere Zeilen entfernt und trotzdem will er einfach icht die gleichheit von gerundeten Werten erkennen.

Code:
Sub Test()
Dim i, j As Integer
For i = 2 To 24
Dim temp(14) As Double
For j = 0 To 13
Dim value As String
Dim cell As Double
cell = Round(Cells(j + 2, i), 1)
value = Replace(CStr(cell), ",", ".")
Dim count As Integer
count = 0
For k = 0 To 13
If Round(Cells(2 + k, i), 1) = value And Len(Cells(j + 2, i)) > 0 Then
count = count + 1
End If
Next k
temp(j) = count
Cells(j + 19, i) = cell
Next j
Cells(17, i).value = WorksheetFunction.Max(temp) - 1
Next i
End Sub
 

Sun_set_1

Commander
Dabei seit
Sep. 2008
Beiträge
3.045
1. Müsste man das meiner Meinung nach über eine Array-Formel
mit Wenn-Dann, ANZAHL,WERT etc lösen können?

2. Rechnest Du bei der Vergleichsoperation den INT aus Round(Cells)) gegen den String value. Könnte die Ursache sein, weshalb er keine gleichen Werte findet.

3. Du könntest die Zeilen auch markieren, auf 2 Nachkommastellen runden. Kopieren, Rechtsklick, Werte einfügen.

4. Bedingte Formatierung anwenden. Da kannste auch gleiche/ähnliche Werte direkt farblich markieren lassen.

Viele Wege führen bei Excel nach Rom. Wenn man denn möchte ;)
 
Zuletzt bearbeitet:

Kokujou

Lieutenant
Ersteller dieses Themas
Dabei seit
Dez. 2017
Beiträge
542
Round(Cells) müsste einen Double zurückgeben, da ich ja als zweiten Wert 1 Eingegeben habe, er rundet also nicht zu int sondern zu einer Stelle nach dem Komma.

Ich will aber dass die standardwerte nicht überschrieben werden und ne zweite ähnliche Tabelle zu haben halte ich für ziemlich doof... dafür ist ja eigentlich son makro da, damit man das intern machen kann.

Das Markieren hilft mir nicht, ich brauch schon ne Zahl, weil ich das später alles grafisch darstellen will.^^

Vorschlag Nummer 1 interessiert mich aber, wie genau hast du dir das vorgestellt? Ich kann aus der Formulierung nicht ablesen, wie genau so eine Abfrage aussehen soll (ich bin neu in dem Excel VBA zeug^^)
 

Sun_set_1

Commander
Dabei seit
Sep. 2008
Beiträge
3.045
Ja aber Double ist ja prinzipiell ein Integer, mit doppelter Gleitkommagenauigkeit. Im Entwicklerleitfaden steht sinngemäß: Vergleiche immer nur mit denselben Datentypen durchzuführen. Int mit Int, Double mit Double, Object mit Object usw usf. Alles andere kann aber muss nicht funktionieren.

Hier steht mMn auch höchstwahrscheinlich die Erklärung für dein Problem:

https://docs.microsoft.com/de-de/dotnet/visual-basic/programming-guide/language-features/data-types/troubleshooting-data-types
When you work with floating-point numbers (Single Data Type and Double Data Type), remember that they are stored as binary fractions. This means they cannot hold an exact representation of any quantity that is not a binary fraction (of the form k / (2 ^ n) where k and n are integers). For example, 0.5 (= 1/2) and 0.3125 (= 5/16) can be held as precise values, whereas 0.2 (= 1/5) and 0.3 (= 3/10) can be only approximations.
Because of this imprecision, you cannot rely on exact results when you operate on floating-point values. In particular, two values that are theoretically equal might have slightly different representations.
https://www.heise.de/developer/artikel/Was-ist-1-10-im-Binaersystem-3679025.html

Zum Thema Array. Das ist komplexer und hat erstmal nichts mit VBA zu tun. Dies sind besondere Formeln in Excel, die aber auch dein Problem lösen könnten. Damit kannst Du im Prinzip alle Werte runden und miteinander innerhalb der Matrix Vergleichen.

Hier als Einstieg:

https://www.tabellenexperte.de/ab-in-die-matrix-einfuehrung-in-array-formeln/

https://www.tabellenexperte.de/besser-als-sverweis-alle-werte-finden/
 
Zuletzt bearbeitet:

Kokujou

Lieutenant
Ersteller dieses Themas
Dabei seit
Dez. 2017
Beiträge
542
Ich weiß ja nichtmal was fürn Datentyp das Resultat von Cells eigentlich ist... das scheint irgendwie alles zu sein... Ist das dann ein Object? Und seit wann haben Integer irgendeine Gleitkommagenauigkeit? XD der Trick ist doch dass es ganzzahlen sind. Darum dachte ich eigentlich auch ich vergleiche Double mit Double

Ach diese Formeln meinst du ja die kenne ich aber mir ist aktuell keine bekannt, die sowas macht... kennst du eine?

Ich hab ja zuerst mit countif angefangen aber dazu musste ich erstmal runden denn du kannst ja nicht sagen Countif "ähnlich". Du hast deine Operatoren. du könntest höchstens sagen Countif und dann ne Range festlegen so wie 0.1 > x > 0.2.

Und nur Countif geht auch nicht denn ich brauche da MAXIMUM aller Countifs. Countif zählt ja auch nur die Ähnlichkeit zu EINEM Wert. Ich brauche aber für die ganze Spalte den Wert der die meisten Ähnlichkeiten aufweist und davon dann die Anzahl und genau das macht mein Skript.

Aber wie gesagt ich kenne nicht alle Funktionen und google sagt mir nix dazu, aber wenn du eine kennst nur raus damit.

ABER!
Du hast mir doch geholfen! Denn an dem Konvertierungsmist lag es wirklich. Nicht ganz so wie du dachtest, aber nachdem ich nochmal explizit in String konvertiert hatte und die Kommata-Ersetzung rausgeschmissen habe geht's jetzt plötzlich und es kommen vernünftige werte raus. Halleluja! Für interessierte nochmal der fertige Code.

Code:
Sub Test()
For i = 2 To 24
    'Reihe mit Anzahl ähnlicher Werte
    Dim temp(14) As Double
    For j = 0 To 13
        'Zellenwert
        Dim value As String
        Dim cell As Double
        cell = Round(Cells(j + 2, i), 1)
        value = CStr(cell)
        Dim count As Integer
        count = 0
        For k = 0 To 13
            'Zusätzliche Abfrage nach leerer Zelle
            If CStr(Round(Cells(2 + k, i), 1)) = value And Len(Cells(k + 2, i)) > 0 Then
                'Erhöhen der Count
                count = count + 1
            End If
        Next k
        temp(j) = count
        Next j
    'Für jede Reihe Maximum des temp-array berechnen und ausgeben
    Cells(17, i).value = WorksheetFunction.Max(temp) - 1
Next i
End Sub
 
Zuletzt bearbeitet:

Sun_set_1

Commander
Dabei seit
Sep. 2008
Beiträge
3.045
Bzgl der benötigten Array, schau mal in dem zweiten Link zu Arrays. Ad-Hoc habe ich keine fertige Array-Formel.

Was die Datentypen betrifft. Schau mal den Heise-Link ganz unten. Bei Single sind 0,1+0,2 = 0,3000001.
Deswegen ist deine Bedingungen = nie erfüllt. Da der gerundete String Value eventuell von einem Single bzw einfachen Zahlenwert gebildet wurde. Sagen wir mal aus 0,300005 wurde nun 0,31(value). Nun vergleichst du einen Quellwert(Cells) mit doppelter Genauigkeit (Double) gerundet auf Zwei Stellen, mit value. Double wiederum ist ja ein Double und hat nun 0,3000000004 errechnet. Gerundet also 0,30. Ergo sind die Zahlenwerte nicht =.
0,31 ≠ 0,30

Versuche doch mal value nicht als String sondern als Double zu definieren. Oder beide als einfache Int bzw. Singles.


Puh, Cells ist erstmal ein Objekt, die aktuelle Zelle. Dieses Objekt kann einen Wert, String, Char oder sonstigen Wert erhalten, den Du abrufen kannst. Cells ist dabei die Variable für den Compiler für die jeweils aktuell zu durchsuchende Zelle. Cells(12,13) gibt wiederum die fixe Position einer Zelle an. (Schiffe versenken)
 

Kokujou

Lieutenant
Ersteller dieses Themas
Dabei seit
Dez. 2017
Beiträge
542
Also es klappt auf jeden Fall schonmal...Und beim Runden kommt erstmal nie 0,31 raus, denn er rundet immer so, dass die nächste Stelle gerade wird. Frag mich nicht warum, steht in der doku, ich find das komplett bekloppt. Ich bin nur froh dass der code jetzt das gewünschte ergebnis liefert:

1546175403199.png


Die letzte Reihe beschreibt genau diese mit dem Makro erstellten Werte... nur dass ich die -1 am Ende der Zellbeschreibung noch gelöscht hab also nicht wundern^^
 

Sun_set_1

Commander
Dabei seit
Sep. 2008
Beiträge
3.045
Ne das mit dem Runden hatte ich schon mathematisch falsch dargestellt. Ich wollt einfach das Prinzip verdeutlichen. Bei Double kann halt sein, dass die dritte oder vierte Nachkomma abweicht und dann kommt schlussendlich beim Runden eine minimal andere Zahl zustande.

Ich vermute wenn Du Stringent nur mit Int, Single/Double oder Strings arbeitest, geht es. Da der Compiler diese Abweichungen, entstanden durch die Binärtabellen, als solches erkennt und dann entscheidet, dass die Zahl eben doch die Gleiche ist. Vermischt Du die Datentypen jedoch, kann das vermutlich nicht mehr über den Algorithmus aufgefangen werden.

Dass die Berechnung geht, wenn Du ihn das Ergebnis nach der Operation in einen String umwandeln lässt, ist auch klar. Durch die Konvertierung in einen String wird alles egal, da hier Zahlenwerte in Chars gewandelt werden. Wichtig ist dann nur, dass die vorhergehende Operation stringent entweder auf Single oder auf Double läuft. Nur nicht beides gleichzeitig.

Also Single Wert ‘0,30’ ≠ Double INT Wert ‘0,30’

Während hingegen immer gilt:

Single Wert ‘0,30’ = Single INT Wert ‘0,30’
Double Wert
‘0,30’ = Double INT Wert ‘0,30’
Int Wert 0,30 = String Zeichen ‘0,30’



Hoffe ich konnte meine Gedanken halbwegs verständlich ausdrücken :)
Freut mich, geholfen zu haben!


Btw schau dir mal die LastRow / LastCell Funktion an. Du musst das Ende der Tabellen nicht manuell ermitteln :)

https://www.thespreadsheetguru.com/blog/2014/7/7/5-different-ways-to-find-the-last-row-or-last-column-using-vba
 
Zuletzt bearbeitet:
Top