![]() |
TadvStringGrid -- Verschieben der Spalten
Hallo zusammen!
Ich habe folgende Problematik bei einer TadvStringGrid: Ich möchte die Spaltenreihenfolge dem Benutzer überlassen, dass heisst er soll diese nach seinem Gutdünken verschieben können. z.B: original: 1. Name 2. Vorname 3. Land 4. PLZ 5. Ort neu: 5. Ort 4. PLZ 1.Name 2. Vorname 3. Land Ich habe herausgefunden, dass dies mit der Eigenschaft goColMoving (True) eingestellt werden kann. Soweit sogut... ;-) Das Problem ist nun, wie finde ich die "OriginalReihenfolge" wieder heraus? Ich brauche dies damit für die Speicherung der Eingaben die Datenbank richtig gefüllt werden kann. Ich muss wissen, dass der Name im Original an 1. Stelle steht, usw. Irgendwo sollte eine Eigenschaft zu Designzeiten auf dem TAdvStringGrid eingestellt werden können, pro Titel. Obwohl der Name jetzt nicht mehr an 1. Stelle ist, muss ich wissen dass dieser normalerweise an Stelle 1 steht. Weiss da jemand einen Tipp? Ich wäre wirklich sehr dankbar dafür. Bis bald und allen einen schönen Tag! |
Re: TadvStringGrid -- Verschieben der Spalten
du hast doch überschriften, da kannst du doch die spalten identifizieren! oder du speicherst dir die original-reihenfolge in einem objekt.
|
Re: TadvStringGrid -- Verschieben der Spalten
hallo ibp
habe ich auch schon dran gedacht. Da aber bis zu 4 Leute am selben Projekt arbeiten, möchte ich nicht über den Titel gehen, da dieser noch in 3 Fremdsprachen übersetzt wird. Und allenfalls ein Titel von jemandem geändert werden könnte. Wenn man dann nicht daran denkt, dass dies Auswirkungen auf die Speicherung hat, gibt es wieder ein Problem... Ich denke die Entwickler von der TAdvStringGrid haben sicherlich an so einen Fall gedacht... Hat jemand noch einen Tipp? Grüsse aus dem schönen Bodenseegebiet! |
Re: TadvStringGrid -- Verschieben der Spalten
dann speichere doch die feldnamen als objekte in der titelzeile!
|
Re: TadvStringGrid -- Verschieben der Spalten
hallo ibp
danke für den Tipp, aber kannst du mir genauer sagen, was du damit meinst..? ;-( sorry so fit bin ich noch nicht in delphi... danke |
Re: TadvStringGrid -- Verschieben der Spalten
ja klar kann ich ich dir das sagen, es ist nur leichter wenn du mal ein wenig code zeigst und zwar den teil, wo du die daten ins grid schreibst und den teil wo du abspeicherst!
|
DP-Maintenance
Dieses Thema wurde von "Christian Seehase" von "Windows API / MS.NET Framework API" nach "VCL / WinForms / Controls" verschoben.
Es geht um eine VCL-Komponente |
Re: TadvStringGrid -- Verschieben der Spalten
hier der Save:
Delphi-Quellcode:
************************************************** *******************************************
function Tfrm_edecEinfuhrDeklaration.SavePositionenPPList(
RowNr: Integer): WideString; var PPList: WideString; PPDelim: string; CheckBoxState: Boolean; begin PPList := ''; Cache.PLIST := ''; Cache.PDELIM := #22; PPDelim := #22; PPList := PPList + grid_Positionen.Cells[0, RowNr] + '»'; //Position 5 // hier Status code // dann Status Text PPList := PPList + grid_Positionen.Cells[1, RowNr] + '»'; //edt_DetailStatusCode.Text 6 PPList := PPList + grid_Positionen.Cells[2, RowNr] + '»'; //edt_DetailStatusCode.Text 7 PPList := PPList + grid_Positionen.Cells[3, RowNr] + '»'; //cb_HC.Text 8 PPList := PPList + grid_Positionen.Cells[4, RowNr] + '»'; //cb_UL.Text 9 PPList := PPList + grid_Positionen.Cells[5, RowNr] + '»'; //Tarifnummer Frame 10 PPList := PPList + grid_Positionen.Cells[6, RowNr] + '»'; //cb_Schluessel.Text 11 PPList := PPList + grid_Positionen.Cells[7, RowNr] + '»'; //cb_NZEPflichtCode.Text 12 PPList := PPList + grid_Positionen.Cells[8, RowNr] + '»'; //cb_NettoVerzollung.Text 13 PPList := PPList + grid_Positionen.Cells[9, RowNr] + '»'; //nedt_RohMasse.Text 14 PPList := PPList + grid_Positionen.Cells[10, RowNr] + '»'; //nedt_ZollNettoGewicht.Text 15 PPList := PPList + grid_Positionen.Cells[11, RowNr] + '»'; //cb_WhrgStatWert.Text 16 PPList := PPList + grid_Positionen.Cells[12, RowNr] + '»'; //nedt_StatWert.Text 17 PPList := PPList + grid_Positionen.Cells[13, RowNr] + '»'; //edt_StatWertCHF.Text 18 PPList := PPList + grid_Positionen.Cells[14, RowNr] + '»'; //nedt_ZollAnsatz.Tex 19 PPList := PPList + grid_Positionen.Cells[15, RowNr] + '»'; //Reserve war vorher -->nedt_ZollAnsatzTMF.Text 20 PPList := PPList + grid_Positionen.Cells[16, RowNr] + '»'; //cb_Ac.Text 21 PPList := PPList + grid_Positionen.Cells[17, RowNr] + '»'; //cb_Praeferenz.Text 22 PPList := PPList + grid_Positionen.Cells[18, RowNr] + '»'; //ExtArtikelNummer 23 PPList := PPList + grid_Positionen.Cells[19, RowNr] + '»'; //edt_Gebc.Text 24 PPList := PPList + grid_Positionen.Cells[20, RowNr] + '»'; //cb_LagerCode.Text 25 PPList := PPList + grid_Positionen.Cells[21, RowNr] + '»'; //cb_VeranlagendeBehoerde.Text 26 PPList := PPList + grid_Positionen.Cells[22, RowNr] + '»'; //nedt_EigenMasse.Text 27 PPList := PPList + grid_Positionen.Cells[23, RowNr] + '»'; //nedt_ZusatzMenge.Text 28 PPList := PPList + grid_Positionen.Cells[24, RowNr] + '»'; //cb_WhrgMwstWert.Text 29 PPList := PPList + grid_Positionen.Cells[25, RowNr] + '»'; //nedt_MwstWert.Text 30 PPList := PPList + grid_Positionen.Cells[26, RowNr] + '»'; //nedt_MWSTWertCHF.Text 31 PPList := PPList + grid_Positionen.Cells[27, RowNr] + '»'; //cb_ZBC.Tex 32 PPList := PPList + grid_Positionen.Cells[28, RowNr] + '»'; //nedt_TaraZuschlag.Text 33 PPList := PPList + grid_Positionen.Cells[29, RowNr] + '»'; //cb_MWSTCode.Text 34 PPList := PPList + grid_Positionen.Cells[30, RowNr] + '»'; //Anzahl Packstücke 35 PPList := PPList + grid_Positionen.Cells[31, RowNr] + '»'; //edt_WarenBez1.Text 36 PPList := PPList + grid_Positionen.Cells[32, RowNr] + '»'; //edt_WarenBez2.Text 37 PPList := PPList + grid_Positionen.Cells[33, RowNr] + '»'; //cb_VerkehrsRichtungCode.Text 38 PPList := PPList + grid_Positionen.Cells[34, RowNr] + '»'; //edt_VerkehrsRichtungText.Text 39 PPList := PPList + grid_Positionen.Cells[35, RowNr] + '»'; //cb_VeredelungsTypCode.Text 40 PPList := PPList + grid_Positionen.Cells[36, RowNr] + '»'; //edt_VeredelungsTypText.Text 41 PPList := PPList + grid_Positionen.Cells[37, RowNr] + '»'; //cb_VerfahrensTypCode.Text 42 PPList := PPList + grid_Positionen.Cells[38, RowNr] + '»'; //edt_VerfahrensTypText.Text 43 PPList := PPList + grid_Positionen.Cells[39, RowNr] + '»'; //cb_AbrechnungsTypCode.Text 44 PPList := PPList + grid_Positionen.Cells[40, RowNr] + '»'; //edt_AbrechnungsTypText.Text 45 PPList := PPList + grid_Positionen.Cells[41, RowNr] + '»'; //cb_FreiPassCode.Text 46 PPList := PPList + grid_Positionen.Cells[42, RowNr] + '»'; //edt_FreiPassText.Text 47 PPList := PPList + grid_Positionen.Cells[43, RowNr] + '»'; //cb_PositionsTypCode.Text 48 PPList := PPList + grid_Positionen.Cells[44, RowNr] + '»'; //edt_PositionsTypText.Text 49 // Achtung neue Felder eingefügt!! Hier kann nicht einfach von 44-56 hochgezählt werden! // Die Neuen Felder werden am Schluss von PPList angehängt, damit Globalbeschrieb etc. noch stimmt!!! PPList := PPList + grid_Positionen.Cells[47, RowNr] + '»'; //nedt_AusfuhrWert.Text 50 PPList := PPList + grid_Positionen.Cells[50, RowNr] + '»'; //nedt_LohnKosten.Text 51 PPList := PPList + grid_Positionen.Cells[53, RowNr] + '»'; //nedt_FrachtBisGrenze.Text 52 PPList := PPList + grid_Positionen.Cells[56, RowNr] + '»'; //nedt_WertNeuMaterial.Text 53 PPList := PPList + grid_Positionen.Cells[57, RowNr] + '»'; //cb_TabakSorte.Text 54 PPList := PPList + grid_Positionen.Cells[58, RowNr] + '»'; //cb_BewPfl 55 //Checkboxen RC Code grid_Positionen.GetCheckBoxState(59, RowNr, CheckBoxState); //RC Stat.Wert 56 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(60, RowNr, CheckBoxState); //RC Warennummer 57 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(61, RowNr, CheckBoxState); //RC Eigenmasse 58 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(62, RowNr, CheckBoxState); //RC Rohmasse 59 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(63, RowNr, CheckBoxState); //RC Zusatzmenge 60 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(64, RowNr, CheckBoxState); //RC MWST Wert 61 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(65, RowNr, CheckBoxState); //RC Zollansatz 62 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(66, RowNr, CheckBoxState); //RC Tarazuschlag 63 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // grid_Positionen.GetCheckBoxState(67, RowNr, CheckBoxState); //RC MWST Code 64 if CheckBoxState = True then PPList := PPList + '1' + '»' else PPList := PPList + '0' + '»'; // PPList := PPList + grid_Positionen.Cells[45, RowNr] + '»'; //cb_WhgAusfuhrWert.Text 65 PPList := PPList + grid_Positionen.Cells[46, RowNr] + '»'; //nedt_AusfuhrWertFW.Text 66 PPList := PPList + grid_Positionen.Cells[48, RowNr] + '»'; //cb_WhgLohnkosten.Text 67 PPList := PPList + grid_Positionen.Cells[49, RowNr] + '»'; //nedt_LohnKostenFW.Text 68 PPList := PPList + grid_Positionen.Cells[51, RowNr] + '»'; //cb_WhgFrachtBisGrenze.Text 69 PPList := PPList + grid_Positionen.Cells[52, RowNr] + '»'; //nedt_FrachtBisGrenzeFW.Text 70 PPList := PPList + grid_Positionen.Cells[54, RowNr] + '»'; //cb_WhgWertNeuMaterial.Text 71 PPList := PPList + grid_Positionen.Cells[55, RowNr] + '»'; //nedt_WertNeuMaterialFW.Text 72 PPList := PPList + PPDelim; Result := PPList; end; und hier noch der Load:
Delphi-Quellcode:
[edit=Admin]Code in Delphi-Tags gesetzt. Künftig bitte selber machen, Danke. :-) Mfg, Daniel[/edit]
procedure Tfrm_edecEinfuhrDeklaration.LoadPositionenValue(
RecordString: string; ZeilenNr, i, NewPosNr: Integer); begin if RecordString <> '' then begin if NewPosNr > 0 then grid_Positionen.Cells[0, ZeilenNr] := IntToStr(NewPosNr) //Position else grid_Positionen.Cells[0, ZeilenNr] := Piece(RecordString, '»', 5); grid_Positionen.Cells[1, ZeilenNr] := Piece(RecordString, '»', 6); //Status Code Header grid_Positionen.Cells[2, ZeilenNr] := Piece(RecordString, '»', 7); //Status Code Text Header grid_Positionen.Cells[3, ZeilenNr] := Piece(RecordString, '»', 8); //Hc grid_Positionen.Cells[4, ZeilenNr] := Piece(RecordString, '»', 9); //UL grid_Positionen.Cells[5, ZeilenNr] := Piece(RecordString, '»', 10); //Tarifnr grid_Positionen.Cells[6, ZeilenNr] := Piece(RecordString, '»', 11); //Schlüssel grid_Positionen.Cells[7, ZeilenNr] := Piece(RecordString, '»', 12); //NZE Pflichtcode grid_Positionen.Cells[8, ZeilenNr] := Piece(RecordString, '»', 13); //Nettoverzollung grid_Positionen.Cells[9, ZeilenNr] := Piece(RecordString, '»', 14); //Rohmasse grid_Positionen.Cells[10, ZeilenNr] := Piece(RecordString, '»', 15); //Zollnettogewicht grid_Positionen.Cells[11, ZeilenNr] := Piece(RecordString, '»', 16); //Währung Stat Wert grid_Positionen.Cells[12, ZeilenNr] := Piece(RecordString, '»', 17); //Stat Wert grid_Positionen.Cells[13, ZeilenNr] := Piece(RecordString, '»', 18); //Stat Wert in CHF grid_Positionen.Cells[14, ZeilenNr] := Piece(RecordString, '»', 19); //Zollansatz grid_Positionen.Cells[15, ZeilenNr] := Piece(RecordString, '»', 20); //Zollansatz TMF grid_Positionen.Cells[16, ZeilenNr] := Piece(RecordString, '»', 21); //AC grid_Positionen.Cells[17, ZeilenNr] := Piece(RecordString, '»', 22); //Präferenz grid_Positionen.Cells[18, ZeilenNr] := Piece(RecordString, '»', 23); //ArtikelNummer grid_Positionen.Cells[19, ZeilenNr] := Piece(RecordString, '»', 24); //GEBC grid_Positionen.Cells[20, ZeilenNr] := Piece(RecordString, '»', 25); //Lagercode grid_Positionen.Cells[21, ZeilenNr] := Piece(RecordString, '»', 26); //Veranlagende Behörde grid_Positionen.Cells[22, ZeilenNr] := Piece(RecordString, '»', 27); //Eigenmasse grid_Positionen.Cells[23, ZeilenNr] := Piece(RecordString, '»', 28); //Zusatzmenge grid_Positionen.Cells[24, ZeilenNr] := Piece(RecordString, '»', 29); //Währung MWST Wert grid_Positionen.Cells[25, ZeilenNr] := Piece(RecordString, '»', 30); //MWST Wert grid_Positionen.Cells[26, ZeilenNr] := Piece(RecordString, '»', 31); //MWST Wert CHF grid_Positionen.Cells[27, ZeilenNr] := Piece(RecordString, '»', 32); //ZBC grid_Positionen.Cells[28, ZeilenNr] := Piece(RecordString, '»', 33); //Tarazuschlag grid_Positionen.Cells[29, ZeilenNr] := Piece(RecordString, '»', 34); //MWST Code grid_Positionen.Cells[30, ZeilenNr] := Piece(RecordString, '»', 35); //Anzahl Packstücke grid_Positionen.Cells[31, ZeilenNr] := Piece(RecordString, '»', 36); //Warenbez.1 grid_Positionen.Cells[32, ZeilenNr] := Piece(RecordString, '»', 37); //Warenbez.2 grid_Positionen.Cells[33, ZeilenNr] := Piece(RecordString, '»', 38); //Verkehrsrichtung Code grid_Positionen.Cells[34, ZeilenNr] := Piece(RecordString, '»', 39); //Verkehrsrichtung Text grid_Positionen.Cells[35, ZeilenNr] := Piece(RecordString, '»', 40); //Veredelungstyp Code grid_Positionen.Cells[36, ZeilenNr] := Piece(RecordString, '»', 41); //Veredelungstyp Text grid_Positionen.Cells[37, ZeilenNr] := Piece(RecordString, '»', 42); //Verfahrenstyp Code grid_Positionen.Cells[38, ZeilenNr] := Piece(RecordString, '»', 43); //Verfahrenstyp Text grid_Positionen.Cells[39, ZeilenNr] := Piece(RecordString, '»', 44); //Abrechnungstyp Code grid_Positionen.Cells[40, ZeilenNr] := Piece(RecordString, '»', 45); //Abrechnungstyp Text grid_Positionen.Cells[41, ZeilenNr] := Piece(RecordString, '»', 46); //Freipass Code grid_Positionen.Cells[42, ZeilenNr] := Piece(RecordString, '»', 47); //Freipass Text grid_Positionen.Cells[43, ZeilenNr] := Piece(RecordString, '»', 48); //Positionstyp Code grid_Positionen.Cells[44, ZeilenNr] := Piece(RecordString, '»', 49); //Positionstyp Text grid_Positionen.Cells[45, ZeilenNr] := Piece(RecordString, '»', 65); //cb_WhgAusfuhrWert grid_Positionen.Cells[46, ZeilenNr] := Piece(RecordString, '»', 66); //nedt_AusfuhrWertFW grid_Positionen.Cells[47, ZeilenNr] := Piece(RecordString, '»', 50); //Ausfuhrwert grid_Positionen.Cells[48, ZeilenNr] := Piece(RecordString, '»', 67); //cb_WhgLohnkosten grid_Positionen.Cells[49, ZeilenNr] := Piece(RecordString, '»', 68); //nedt_LohnKostenFW grid_Positionen.Cells[50, ZeilenNr] := Piece(RecordString, '»', 51); //Lohnkosten grid_Positionen.Cells[51, ZeilenNr] := Piece(RecordString, '»', 69); //cb_WhgFrachtBisGrenze grid_Positionen.Cells[52, ZeilenNr] := Piece(RecordString, '»', 70); //nedt_FrachtBisGrenzeFW grid_Positionen.Cells[53, ZeilenNr] := Piece(RecordString, '»', 52); //Fracht bis Grenze grid_Positionen.Cells[54, ZeilenNr] := Piece(RecordString, '»', 71); //cb_WhgWertNeuMaterial grid_Positionen.Cells[55, ZeilenNr] := Piece(RecordString, '»', 72); //nedt_WertNeuMaterialFW grid_Positionen.Cells[56, ZeilenNr] := Piece(RecordString, '»', 53); //Wert Neumaterial grid_Positionen.Cells[57, ZeilenNr] := Piece(RecordString, '»', 54); //Tabaksorte grid_Positionen.Cells[58, ZeilenNr] := Piece(RecordString, '»', 55); //BewilligungspflichtCode // Checkboxen mit Richtigcodes 9 mal... if Piece(RecordString, '»', 56) = '1' then grid_Positionen.AddCheckBox(59, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(59, ZeilenNr, False, False); //RcStatistischer Wert // if Piece(RecordString, '»', 57) = '1' then grid_Positionen.AddCheckBox(60, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(60, ZeilenNr, False, False); //RcWarennummer // if Piece(RecordString, '»', 58) = '1' then grid_Positionen.AddCheckBox(61, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(61, ZeilenNr, False, False); //RcEigenmasse // if Piece(RecordString, '»', 59) = '1' then grid_Positionen.AddCheckBox(62, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(62, ZeilenNr, False, False); //RcRohmasse // if Piece(RecordString, '»', 60) = '1' then grid_Positionen.AddCheckBox(63, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(63, ZeilenNr, False, False); //RcZusatzmenge // if Piece(RecordString, '»', 61) = '1' then grid_Positionen.AddCheckBox(64, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(64, ZeilenNr, False, False); //RcMWSTWert // if Piece(RecordString, '»', 62) = '1' then grid_Positionen.AddCheckBox(65, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(65, ZeilenNr, False, False); //RcZollansatz // if Piece(RecordString, '»', 63) = '1' then grid_Positionen.AddCheckBox(66, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(66, ZeilenNr, False, False); //RcTarazuschlag // if Piece(RecordString, '»', 64) = '1' then grid_Positionen.AddCheckBox(67, ZeilenNr, True, False) else grid_Positionen.AddCheckBox(67, ZeilenNr, False, False); //RcMWSTCode end; end; |
Re: TadvStringGrid -- Verschieben der Spalten
wow :shock: umständlich und wenig wartungsfreundlich oder? :wink:
1. bitte setz beim codeposten doch die delphitags! 2. ich würde mir überlegen, ob ihr euch nicht eine liste anlegt, in der die felder stehen!
Delphi-Quellcode:
- baeachte dabei, dass du die objekte ggf. wieder freigeben musst.
type
tint=class value:integer; end; tfelddef=record fname:string; display:string; typ:integer; // 1:string 2:integer 3:float etc end; var fldlist:array of tfelddef; anzfields:integer; ... procedure init; begin anzfields:=3; // 3 => anzahl der felder in der db hier nur als beispiel setlength(fldlist,anzfields); fldlist[0].fname:='name'; fldlist[0].display:='Name'; fldlist[0].typ:=1; fldlist[1].fname:='alter'; fldlist[1].display:='Alter'; fldlist[1].typ:=2; fldlist[1].fname:='groesse'; fldlist[1].display:='Größe'; fldlist[1].typ:=3; ...// hier die anderen end; procedure load; var zeile,spalte:integer; feldname:tint; begin query.sql.txt:='select * from tabelle'; // etc query.open; if query.eof then exit; zeile:=0; for spalte:=0 to anzfields-1 do begin feldname:=tint.Create; feldname.value:=spalte; //<- spalte zum ladezeitpunkt grid.Objects[0,Zeile]:=feldname; // der spalte(in zeile 0) das object zuweisen grid.cell[0,Zeile]:=fldlist[spalte].display; // titel end; while not query.eof do begin inc(zeile); // nächste zeile for spalte:=0 to anzfields-1 do begin case fldlist[spalte].typ of 1: grid.Cells[Spalte,Zeile]:=query.FieldByName(fldlist[spalte].fname).asString; 2: grid.Ints[Spalte,Zeile]:=query.FieldByName(fldlist[spalte].fname).asInteger; 3: grid.floats[Spalte,Zeile]:=query.FieldByName(fldlist[spalte].fname).asFloat; end; end; query.next; end; end; - das speichern über die feldnamen sollte dann keine probleme machen, da der db die reihenfolge egal ist, wenn du per feldname die werte zuweist. |
Re: TadvStringGrid -- Verschieben der Spalten
vielen Dank für Deine Hilfe.
Super Idee! ich denke damit komme ich mal klar! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz