# Excel Column in eine Nummer



## moritzBremen (Donnerstag um 19:29)

servus, ich habe einen fertigen code gefunden im Internet und würde ihn gerne verstehen nur leider komme ich nicht weiter. Dabei geht es darum das man eine Excel Reihennummer bekommt und diesen in eine zahl umwandeln soll nur kapier ich die rechnung nicht ganz. Man bekommt zum Beispiel parameter AA und es soll 27 kommen. Könnte mir jemand die rechnung erklären?


----------



## KonradN (Donnerstag um 19:42)

Das Geheimnis ist, dass ein char auch nur eine 16Bit Zahl ist. Daher kann man mit char Werten auch rechnen.
'A' ist also der 16Bit Code, mit dem das Zeichen A dargestellt wird. (65 bzw. 0x41 wenn man es Hexadezimal schreiben will)

Die Columns sind ja A, B, C, D, ....

Also ist 'A' -> 1
'B' -> 2
u.s.w.

Unabhängig, welcher Wert nun 'A' hat: 
'A' - 'A' ist 0. 
'B' - 'A' ist 1, ....

Das sind schon fast die gewünschten Werte - nur eben 1 zu klein. Daher noch ein +1

Jetzt fehlt nur noch dsa result *= 26

Wenn es mehr wie 26 Elemente gibt, dann geht es weiter: Nach "Z" kommt "AA".

Hier ist das Verständnis des Zahlensystems wichtig: Im Dezimalsystem hast Du bei der Zahl 123 ja:
( (1*10 + 2) * 10 ) + 3

Von Ziffer zu Ziffer wird also immer erst mit der Anzahl der Möglichkeiten multipliziert und dann die Ziffer addiert. Also ausführlich:
erst 1
dann 1*10 + 2
Dann 12 * 10 + 3

Die Anzahl der Möglichkeiten ist nun aber 26. Also haben wir bei "AB" z.B.
erst haben wir als Ergebnis 0 - noch keine Ziffer ausgewertet.
Dann gehen wir die erste Ziffer an (index 0) und rechnen erst Ergebnis * 26 -> immer noch 0. Und dann addieren wir den Wert dazu: A war 1 also 1
Dann gehen wir zur nächsten Ziffer (Index 1) und rechnen erst Ergebnis * 26 -> 1*26 = 16. Und dann addieren wir den Wert dazu: B war 2 also 26+2 = 28.

Und nun können wir prüfen:
A -> 1
B -> 2
...
Z -> 26
AA->27
AB->28 <-- Das war ja auch unser Ergebnis, also die Kontrolle zeigt, dass es richtig zu sein scheint.


----------



## moritzBremen (Gestern um 15:34)

Vielen Dank für die Antwort! Beim Gegenteil sprich man beim rückrechnen ist es dann komplett andersrum ? Zum Beispiel eine Zahl in eine hex zahl kodieren lautet dann die Funktion so: leider kapier ich dies nicht ganz haben sie da eine Ahnung? Freundliche Grüße Moritz

            while (nummer= 0) {
                nummer--;
                rest = (int) nummer % 16;
                nummer = Math.floor(nummer/ 16);
                ergebnis.add(0, hex[rest]);
            }


----------



## KonradN (Gestern um 15:58)

Also bei dem Code sind mehrere Dinge falsch:
a) die While schleife soll doch so lange laufen, wie nummer > 0 ist. Sprich: nummer == 0 wäre eine Abbruchbedingung.
b) nummer = 0 wäre auch kein Vergleich sondern eine Zuweisung.

Dann hast Du da jetzt keine Umwandllung einer Zahl in eine Excel Spaltenbezeichnung sondern statt dessen wanelt der Code (von den Fehlern mal abgesehen) eine Zahl in eine Hexadezimal-Zahl um.


----------



## moritzBremen (Gestern um 16:05)

Mein Fehler die while bedingung lautet nummer !=0. Anscheind funktioniert der code richtig ich habe leider schwierigkeiten ihn zu verstehen zum Beispeil die erste zeile in der while loop nummer--; da kann ich mir nix drunter vorstellen


----------



## moritzBremen (Gestern um 16:07)

mit > 0 funktioniert es auch


----------



## KonradN (Gestern um 16:54)

Wenn Du Dir anschaust, was in die andere Richtung gemacht wurde: Da gab es ja das +1.

Wenn Du nun in die andere Richtung alles rechnen willst, dann bedeutet es, dass man erst 1 abziehen muss.

Das ist also einfache Mathematik: Wenn a +1 = b ist und nun will man mit b eben a ausrechnen, dann stellt man es um und erhält a = b -1.

Aber noch einmal - der Code ist eben nicht die umkehr des Codes in diesem Thread! In diesem Thread wurden Excel Spaltenbezeichner in Werte gerechnet. Und dein Code rechnet mit Hexadezimal-Zahlen. Das sind zwei unterschiedliche Dinge.


----------



## moritzBremen (Gestern um 16:57)

Bedeutet das, dass die -1 sozusagen wieder wie beim entkodieren dieses eine Problem mit 0=A 1=B behebt? In diesem Fall wäre dann szg. 2=A 3=B und durch das -1 wird es korrigiert zu 1=A 2=B?


----------



## coffee drinker (Gestern um 17:06)

Es ginge auch mit der Methode `Integer.parseInt( )`, wenn kein 'Z' enthalten ist:


```
public static void main(String[] args) {
        String alphabet = "123456789";
        for (int i = 'A'; i <= 'Z' - 9; i++) {
            alphabet += (char) i;
        }
        String finalAlphabet = alphabet;
        System.out.println("finalAlphabet = " + finalAlphabet);
        String col1 = "ABC"; // Darf kein 'Z' enthalten
        System.out.println("col1 = " + col1);
        String col2 = col1.chars().mapToObj(i -> String.valueOf(finalAlphabet.charAt(i - 'A'))).collect(Collectors.joining());
        System.out.println("col2 = " + col2);
        int intVal = Integer.parseInt(col2, finalAlphabet.length());
        System.out.println("intVal = " + intVal);
    }
```


```
finalAlphabet = 123456789ABCDEFGHIJKLMNOPQ
col1 = ABC
col2 = 123
intVal = 731
```

Weiß gar nicht genau, ob Excel bis Z geht...


----------



## KonradN (Gestern um 17:23)

Sorry, aber was soll so ein Post?
a) es geht schon nicht mehr um das Problem, aus den Spaltenbezeichnngen den index zu berechnen.
b) Wenn man die Problemstellung nicht einmal verstanden hat, wie groß ist die Chance, dass da was sinnvolles heraus kommt?
c) Wenn ein Anfänger Probleme hat, einen einfachen Java Code zu verstehen: Wie sinnvoll ist es da in Deinen Augen, dem einen anderen Code ohne Dokumentation mit Strams zu geben? 
Nein - ich erwarte da keine Antwort.



coffee drinker hat gesagt.:


> Weiß gar nicht genau, ob Excel bis Z geht...


Nein, Excel geht deutlich über da Z hinaus. Nach dem "Z" würde es mit "AA" weiter gehen ... und nach dem "ZZ" mit AAA u.s.w.
Und es gibt kein



moritzBremen hat gesagt.:


> Bedeutet das, dass die -1 sozusagen wieder wie beim entkodieren dieses eine Problem mit 0=A 1=B behebt? In diesem Fall wäre dann szg. 2=A 3=B und durch das -1 wird es korrigiert zu 1=A 2=B?


Da ist erst einmal die Frage, was denn da überhaupt gemacht werden soll. Noch einmal: Das ist NICHT die Umkehrung des Codes aus #1! Das erkennst Du schon daran, dass hier mit 16 gerechnet wird und in #1 mit 26. Und was mich auch wundert: number ist keine ganze Zahl sondern eine Fließkommazahl. Das macht es auch noch etwas dubioser.


----------



## coffee drinker (Gestern um 17:34)

KonradN hat gesagt.:


> Sorry, aber was soll so ein Post?


Naja, ich wollte eine elegante alternative Möglichkeit aufzeigen. Diese musst du nicht kennen oder verstehen, und darüber brauchen wir auch nicht weiter zu diskutieren.


----------



## moritzBremen (Gestern um 17:45)

KonradN hat gesagt.:


> Sorry, aber was soll so ein Post?
> a) es geht schon nicht mehr um das Problem, aus den Spaltenbezeichnngen den index zu berechnen.
> b) Wenn man die Problemstellung nicht einmal verstanden hat, wie groß ist die Chance, dass da was sinnvolles heraus kommt?
> c) Wenn ein Anfänger Probleme hat, einen einfachen Java Code zu verstehen: Wie sinnvoll ist es da in Deinen Augen, dem einen anderen Code ohne Dokumentation mit Strams zu geben?
> ...


Danke für Ihre Antworten! Mir ist bewusst das es sich gerade nicht um die Basis 26 handelt. Die 26 hab ich mittlerweile dank Ihrer Erklärung und üben verstanden! Ich wollte das kodieren nochmal verstehen bei der basis 16 handelt es sich ja um hex zahlen sprich man verwandelt zahlen in hex spaltennummern. Tut mir leid hätte ich ein bisschen genauer beschreiben sollen. Bei der hex kodierung wunder ich mich warum man -1 macht. Mir ist bewusst das es einfach eine Umkehrung vom Dekodieren aber so ganz Klick hat es leider noch nicht gemacht. Was das % und / ist mir klar. % macht man um den Rest rauszukriegen dieser Rest ist dann auch die gewünschte zahl im gewünschten zahlensystem sprich hier bei uns hexa anschließend kommt die / um die nächste Ziffer zu betrachen so ähnlich wie beim dekodieren mit dem * nur halt andersrum (ich hoffe diese erklärung ist richtig ) und dieses -1 würde ich mit dem aktuellen wissensstand so erklären wie beim dekodieren nur anders rum statt + machen wir - dass das mit den buchstaben wieder passt


----------



## KonradN (Gestern um 20:27)

Das Problem mit dem -1 bzw -- Operator ist bei den Excel Spalten, weil wir ein System haben, das ab 1 losgeht.

A ist 1.
Z ist 26.

Also wenn man da eine Zahl hat, dann müssen wir von der Zahl erst 1 abziehen und dann %26 rechnen.
1 - 1 = 0. => 'A' + 0 = 'A'
26 - 1 = 25. => 'A' + 25 = 'Z'

AA soll 27 sein. Also rückwärts gerechnet:
27 -1 = 26. Dann 26 % 26 = 0  ==> 'A' + 0 = 'A'
Weiter zu betrachten: 26 / 26 = 1. 
Bei der 1 dann wieder:
1 - 1 = 0. ==> 'A' + 0 = 'A' ==> "AA" kommt da raus.

Dieses -1 wird aber nur notwendig, weil wir sozusagen ein Zahlensystem haben, das keine "0" kennt.

Daher ist das bei dem Hexadezimalen Zahlen nicht mehr so. Da haben wir eine 0:

0 -> 0
1 -> 1
...
9 -> 9
10 -> A
11 -> B
15 -> F
16 -> 10
...

Dadurch braucht man keine -1 mehr. Wenn ich also die 54 Dezimal in Hexadezimal haben will, dann rechne ich kein -1 sondern rechne das Module direkt mit der ursprünglichen Zahl:
54 % 16 = 6
Weiter zu betrachten: 54 / 16 = 3

die 54 ist somit 0x36

Und der Unterschied ist hier, dass wir eine 0 haben!


----------



## moritzBremen (Gestern um 22:11)

Vielen Dank! Tatsächlich braucht man bei hex auch -1 da sonst das ergebnis falsch ist :/


----------



## KonradN (Gestern um 22:38)

moritzBremen hat gesagt.:


> Vielen Dank! Tatsächlich braucht man bei hex auch -1 da sonst das ergebnis falsch ist :/


Das ist jetzt für mich gerade nicht nachvollziehbar. Kannst Du da mal den ganzen Code zeigen, also inclusive dem Array hex und dem Code, wie er gerade bei Dir funktioniert?

Die eigentliche Umwandlung von reinen Zahlen wäre rein mit % und / zu machen - ohne eine 1 abzuziehen. Daher ist das gerade irritierend.


----------



## KonradN (Gestern um 23:39)

Also nur um meine Irritation zu erklären: Ich habe mir einmal angeschaut, was man da so an Ergebnissen bekommt. Dazu habe ich Deinen Code einfach einmal genommen und minimal imgeschrieben:


```
public String translateToHex(int number) {
        String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
        int rest;
        String ergebnis = "";
        while (number > 0) {
            number--;
            rest = number % 16;
            number = number/ 16;
            ergebnis = hex[rest] + ergebnis;
        }
        return ergebnis;
    }
```

Das habe ich dann einfach einmal getestet (Die Zahlen habe ich in der Hexadezimalen Schreibweise angegeben - das macht es besser lesbar!):

```
@ParameterizedTest
    @CsvSource({
            "0x01, 1",
            "0x0f, F",
            "0x10, 10",
            "0x20, 20",
    })
    public void testTranslateToHex(int number, String result) {
        assertEquals(result, translateToHex(number));
    }
```

Und das kommt so nicht hin. Schauen wir es uns einfach einmal an:

bei 0x01 (1) kam 0
bei 0x0f (15) kam E
bei 0x10 (16) kam F 
bei 0x20 (32) kam 0F 

Man erkennt an diesen Tests, dass es ein Schema gibt: Die Ziffer ist immer eins zu klein. Also kann man dann ja die hex Tabelle um eins verschieben, also statt mit der 0 fangen wir mit der 1 an. Um den Effekt zu sehen nehme ich die "0", einfach einmal ganz raus und starte den Test erneut.

Die ersten Tests laufen nun durch. Aber die 0x10 und 0x20 kriegen jetzt eine Index out of bounds Exception.

Generell funktioniert es - es darf nur keine 0 vorkommen, denn die haben wir ja raus geworfen.

Also wenn wir die Tests erweitern:

```
@ParameterizedTest
    @CsvSource({
            "0x01, 1",
            "0x0f, F",
            "0x11, 11",
            "0x1F, 1F",
            "0x7F, 7F",
            "0x10, 10",
            "0x20, 20",
            "0x201, 201"
    })
    public void testTranslateToHex(int number, String result) {
        assertEquals(result, translateToHex(number));
    }
```

Alle Tests ohne eine 0 in der Zahl laufen durch (führende 0er zählen natürlich nicht wie bei 0x01). Also 1, F, 11, 1F, 7F funktionieren, aber 10, 20, 201 - die Tests funktionieren nicht wegen der fehlenden Stelle. Und das Problem ist: Da gibt es nichts, das man eintragen könnte. Da könnte man zwar eine 0 setzen, aber der Wert wäre falsch, denn dann wäre aus 0x10 eben ein "0" geworden.

Daher fürchte ich, dass der Algorithmus von Dir nicht funktioniert und Du vermutlich nur Zahlen getestet hast, die in der Hexadezimalen Form keine 0 enthalten haben!


----------



## coffee drinker (Heute um 00:38)

Mir ist doch noch eine Möglichkeit eingefallen, wie es mit der gegebenen parseInt( ) Methode und einer Ergänzung funktionieren würde:


```
public static int convertColumnIndexOneBasedToIntWithParseIntMethod(String col) {

        System.out.println("col = " + col);

        String alphabet = "0123456789ABCDEFGHIJKLMNOP";
        StringBuilder col2 = new StringBuilder();
        for (char c : col.toCharArray()) {
            col2.append(alphabet.charAt(c - 'A'));
        }
        int val = Integer.parseInt(col2.toString(), alphabet.length());
        int add = 1;
        for (int i = 0; i < col.length(); i++) {
            val += add;
            add *= alphabet.length();
        }

        System.out.println("val = " + val);

        return val;
    }

    public static void main(String[] args) {
        convertColumnIndexOneBasedToIntWithParseIntMethod("A");
        convertColumnIndexOneBasedToIntWithParseIntMethod("AA");
        convertColumnIndexOneBasedToIntWithParseIntMethod("AB");
        convertColumnIndexOneBasedToIntWithParseIntMethod("BA");
        convertColumnIndexOneBasedToIntWithParseIntMethod("Z");
        convertColumnIndexOneBasedToIntWithParseIntMethod("ZZ");
    }
```


```
col = A
val = 1
col = AA
val = 27
col = AB
val = 28
col = BA
val = 53
col = Z
val = 26
col = ZZ
val = 702
```

Man muss also noch für jede Stelle 1,26,676,17576,usw. addieren. Aus meiner Sicht, wäre das ok.


----------

