Mittwoch, 21. Januar 2015

VBA-Code zum Drucken aller in Word installierten Schriftarten (alphabetisch)

Da will man "mal eben" eine Übersicht über alle Schriftarten, die in Office installiert sind haben und dann dauert es doch länger, weil es kein Skript gibt, das das alphabetisch macht. Hier ist jetzt eins :) Mit Alt + F11 den VBA-Editor öffnen, neues Modul einfügen und dann den Text hier nehmen.

 'Zeige alle Schriften alphabetisch  
 Sub SortDictionaryByKey()  
   'Set a reference to Microsoft Scripting Runtime by using  
   'Tools > References in the Visual Basic Editor (Alt+F11)  
   'Declare the variables  
   Dim Dict As Scripting.Dictionary  
   Dim TempDict As Scripting.Dictionary  
   Dim KeyVal As Variant  
   Dim Arr() As Variant  
   Dim Temp As Variant  
   Dim Txt As String  
   Dim i As Long  
   Dim j As Long  
   'Beispieltext  
   strText = "Der TEXT wird angezeigt pro Schrifftart"  
   'Create an instance of the Dictionary  
   Set Dict = CreateObject("Scripting.Dictionary")  
   'Set the comparison mode to perform a textual comparison  
   Dict.CompareMode = TextCompare  
   'Add keys and items to the Dictionary  
   For iFont = 1 To FontNames.Count  
     Dict.Add FontNames(iFont), iFont  
   Next  
   'Allocate storage space for the dynamic array  
   ReDim Arr(0 To Dict.Count - 1)  
   'Fill the array with the keys from the Dictionary  
   For i = 0 To Dict.Count - 1  
     Arr(i) = Dict.Keys(i)  
   Next i  
   'Sort the array using the bubble sort method  
   For i = LBound(Arr) To UBound(Arr) - 1  
     For j = i + 1 To UBound(Arr)  
       If Arr(i) > Arr(j) Then  
         Temp = Arr(j)  
         Arr(j) = Arr(i)  
         Arr(i) = Temp  
       End If  
     Next j  
   Next i  
   'Create an instance of the temporary Dictionary  
   Set TempDict = CreateObject("Scripting.Dictionary")  
   'Add the keys and items to the temporary Dictionary,  
   'using the sorted keys from the array  
   For i = LBound(Arr) To UBound(Arr)  
     KeyVal = Arr(i)  
     TempDict.Add Key:=KeyVal, Item:=Dict.Item(KeyVal)  
   Next i  
   'Set the Dict object to the TempDict object  
   Set Dict = TempDict  
   'Build a list of keys and items from the original Dictionary  
   For i = 0 To Dict.Count - 1  
     'Debug.Print Dict.Keys(i) & vbTab & Dict.Items(i)  
     iFont = Dict.Items(i)  
     strFontName = FontNames(iFont)  
     Selection.Font.Name = "Arial"  
     Selection.Font.Size = 8  
     Selection.TypeText Text:=strFontName  
     Selection.TypeText Text:=vbNewLine & vbTab & vbTab & vbTab  
     Selection.Font.Size = 12  
     Selection.Font.Name = strFontName  
     Selection.TypeText Text:=strText  
     Selection.TypeParagraph  
   Next i  
 End Sub  

Mittwoch, 10. Dezember 2014

Weiße Seite nach TYPO3 Update - dank opcode Cache

OpCache sei Dank ist meine TYPO3 Seite jetzt wesentlich schneller.  Ein Minor-Update von TYPO3 einzuspielen ist aber wesentlich hackeliger geworden. Macht man es wie gewohnt:  Sourcen runterladen und entpacken, Symlink neu setzen, alten Ordner entfernen, dann kommt nach dem nächsten Mal neu Laden nur eine leere weiße Seite.

Aus dem Zustand kommt man am besten heraus, indem man erst Mal wieder die alten Sourcen an die gleiche Stelle einspielt. Als nächsten im Backend alle Caches löschen und in einem weiteren Fenster ins InstallTool wechseln. Dort unter „Important Actions“ den Befehl „Clear PHP opcode cache“ auswählen. Jetzt noch mal den Ordner der alten Sourcen löschen (ober besser erst umbenennen - das spart dann Zeit, falls es doch noch schief geht) und noch mal alle Caches löschen.

So klappt’s bei mir in etwa. Bin jetzt schon ein paarmal in das Problem gelaufen. Das nächste Mal probiere ich meine eigene Reihenfolge ganz genau aus. Aktuell ist es nur aus dem Kopf niedergeschrieben, nachdem mal wieder alles lief :)

Dienstag, 12. August 2014

TYPO3 6.2 Form-Extension: PostProcessor in eigener Extension

Seit TYPO3 6.2 muss man die eigenen Postprocessors nicht mehr im sysext/form-Verzeichnis speichern, sondern kann die Postprozessoren in einer eigenen Extension auslagern. Dazu gibt es in sysext/form/Classes/PostProcessor/PostProcessor.php nun den Aufruf:
 if (class_exists($processorName, TRUE)) {
      $className = $processorName;
} else {
…
Alles was man tun muss, ist also einen PostProcessor erzeugen und dem Autoloading zur Verfügung stellen. Das Autoloading ist hier inder TYPO3 Anleitung beschrieben. Ich hab das ganze mit Hilfe eines Eintrages in ext_autoload.php umgesetzt.
Mein eigener Postprocessor heißt „tx_user_system_PostProcessors_MemberMail“ und wird auch genauso in der Form-Extension im Typoscropt angesprochen. Bei mir sieht das so aus:
prefix = tx_form
confirmation = 0
postProcessor {
        2 = tx_user_system_PostProcessors_MemberMail
                2 {
                               senderEmail = me@tld.com
…
In der ext_autoload.php habe ich dazu folgenden Eintrag in dem Return Array eingetragen:
 return array (…
"tx_user_system_PostProcessors_MemberMail" => t3lib_extMgm::extPath('user_system'). "Classes/PostProcessors/MemberMail.php",
…
)
In meinem Fall heißt die Extension in der ich die Datei abgelegt habe user_system.  Die Datei heißt MemberMail.php und liegt im Ordner typo3conf/ext/user_system/ Classes/PostProcessors/
In MemberMail.php heißt die Klasse „tx_user_system_PostProcessors_MemberMail“
Wichtig ist, dass diese Klasse das PostProcessorInterface implementiert. Konkret sieht das Klassenaufruf also so aus:
 
class tx_user_system_PostProcessors_MemberMail implements \TYPO3\CMS\Form\PostProcess\PostProcessorInterface
Nach den Anpassungen den Cache leeren und ab jetzt kann man den Core wieder gedankenlos updaten :)
Was ich leider nicht hinbekommen habe ist das Autoloading mit Namespaces statt ext_autoload.php hinzubekommen. Wenn jemand dazu eine Tipp hat, bin ich dankbar.
Im Forge ist die Änderung in PostPorcess.php  hier beschrieben.

Dienstag, 27. Mai 2014

Gamification in der Alumniarbeit

Auf dem ersten Hochschulbarcamp (www.hochschulbarcamp.de) stand schon meine Session zum Thema „Gamification“ auf dem Zeitplan. Gesundheitsbedingt musste ich die leider ausfallen lassen, deshalb auf diesem Weg der erste Versuch sich dem Thema zu nähern und zu erklären, was ich damit eigentlich meine.

Ist Netzwerken Glückssache?

Fast alle Alumnivereinigungen (egal ob er eigenständig oder durch die Hochschule getragen) werben mit dem Versprechen, ein großes, persönliches Netzwerk zu bieten. Aus Gesprächen und eigener Erfahrung habe ich aber den Eindruck, dass die wenigsten Verantwortlichen mit den aktuellen Teilnahmeraten bei Veranstaltungen und dem Grad der Netzwerkaktivität wirklich zufrieden sind.

Ich glaube, dass wir uns bisher zu wenige Gedanken darüber gemacht haben, dass man auch „netzwerken“ lernen muss. Für Alumnimanager ist das sicher nicht der Fall, weil man diesen Job nicht ausübt, wenn man am „netzwerken“ keinen Spaß hat. Für andere ist es aber vielleicht doch ein Kampf gegen den inneren Schweinehund, nach einem anstrengenden Arbeitstag noch an einen unbekannten Ort zu gehen, um fremde Menschen kennen zu lernen. Alles für das abstrakte Versprechen von diesem Netzwerk zu profitieren.

Jeder von uns hat zig Geschichten bei denen das Netzwerk toll funktioniert hat. Demjenigen, der sich endlich mal überwunden hat ein Treffen zu besuchen, werden diese Geschichten wenig bringen. Nach der Veranstaltung wird er sich trotzdem auf Basis seiner eigenen Erfahrung überlegen. „Lohnt sich so ein Treffen? Gehe ich da noch mal hin?“. Es hängt also viel vom Zufall oder der Person selbst ab, ob sie ein Erfolgserlebnis hatte und damit, ob sie zum nächsten Event wiederkommt, oder nicht.

An diesem Punkt „verlieren“ wir glaube ich sehr viele Mitglieder. Die zwar noch da sind, aber selten oder gar nicht zu Veranstaltungen gehen. Kurzum, wir brauchen spürbare Erfolgserlebnisse und müssen mehr Anleitungen geben, wie man zum Netzwerker wird.

Gamification bringt Spaß ins Netzwerken

Ein Mittel, mit dem man das erreichen kann, heißt Gamification. Gamification oder auf Deutsch „Gamifizieren“ ist die wissenschaftliche Auseinandersetzung mit den Fragen, was Spiele so erfolgreich macht und wie das auf die Realität/spielfremde Themen übertragen werden kann.

Insbesondere Onlinespiele ermöglichen es den Entwicklern in kürzester Zeit zu überprüfen, welche Elemente wichtig sind, um Spieler für ihr Spiel zu begeistern. Aus diesem Bereich kommen auch die meisten neueren Erkenntnisse. Da die Mehrheit der jugendlichen regelmäßig Spiele spielt, steigt entsprechend auch die Erwartung, dass sich andere Themen, wie zum Beispiel das Alumninetzwerk, ähnlich leicht erfahren lässt, wie ein Spiel. Die Zeiten in denen Handbücher bei Spielen mitgeliefert wurden sind vorbei. Die Erwartung ist, dass alles intuitiv erlernt werden kann.

Wer sich näher mit dem Thema befassen möchte, dem sei das Buch „Reality is Broken“ von Jane McGonigal  (Amazon Affiliate Link) und auch der Wikipediaartikel Gamification ans Herz gelegt. Für die Alumniarbeit gehören meiner Meinung nach die folgenden Spieleelemente zu den wichtigeren Elementen, um die wir uns kümmern müssen (bis auf den ersten, direkt aus dem Wikipedia-Artikel):
  • Steigender Schwierigkeitsgrad: Gute Spiele werden mit der Zeit schwieriger. Das erleichtert den Einstieg und sorgt gleichzeitig für Langzeitmotivation: Das erste Level von Super Mario schafft man auf Anhieb. Um das letzte zu schaffen, braucht es viel Übung.
  • Fortschrittsanzeige: Der Anwender möchte das Voranschreiten der eigenen Arbeit klar erkennen können, etwa in Form von bestimmten Attributen oder sogenannten „Badges“ oder auch einer Prozentanzeige. So entsteht Transparenz in der Erfüllung einer Teil- oder Gesamtaufgabe, ein zentrales Element der Motivation.
  • Quest: Eine Aufgabe, die der Benutzer in einer bestimmten Zeit absolvieren muss – oft ein Rätsel oder eine einfache Fleißarbeit. In vielen Fällen bauen Quests aufeinander auf, um Qualifikationen und Erfahrungen zu trainieren. Diese Aufgaben können manchmal auch mit anderen zusammen absolviert werden. Dann wird nicht nur der reine Kompetenzgewinn gestärkt, sondern auch die Teamfähigkeit.
  • Rückmeldung: Alle Aktivitäten des Anwenders sollten zu einer sichtbaren Bewertung führen, am besten unmittelbar. Durch Vermeiden negativen Feedbacks und Anstreben positiver Rückmeldung lernt der Anwender.
  • Transparenz des Resultats: Der Anwender sollte das Ergebnis einer Aktion vorher kennen. Im Falle einer gamifizierten Anwendung wären dies Erfahrungspunkte, Preise oder andere Belobigungen. So kann der Anwender bewerten und auch wertschätzen, was seine nächste Aktion ihm selber bringen wird. Dabei ist der Gedanke an ein höheres Ziel präsent (siehe „Tieferer Sinn“ unten).
  • Cascading Information:  Der Anwender sollte bei der aktuell zu lösenden Aufgabe nur die für ihn wichtige Information sehen; er soll nicht durch unverständliche Details abgelenkt und überfordert werden.
  • Gruppenarbeit: Die gemeinsame Arbeit an der Lösung bringt Anwender zusammen. So lassen sich manche Aufgaben nur durch Zusammenarbeit von mehreren Spielern (bis hin zur gesamten Community) lösen. Dies motiviert Anwender, untereinander Kontakte zu knüpfen bis hin zur Bildung eines selbstorganisierenden Systems.
  • Tieferer Sinn: Da die Anwender zielorientiert handeln, sollten die Ziele zu einer starken Motivation führen, also besonders erstrebenswert sein. Die Arbeit innerhalb der Gruppe kann bereits als sinnstiftend empfunden werden.
Mit einzelnen Elementen arbeiten jetzt schon viele Webseiten. Facebook, Xing oder LinkedIn haben bspw. eine Fortschrittsanzeige zur Profilvollständigkeit. Die Verlockung das Profil zu vervollständigen hat bestimmt bei den meisten schon dazu geführt, mehr Preis zu geben als man eigentlich wollte.

Spieleelemente im Alumnileben

Aus der oberen Liste sollte der tiefere Sinn als erstes bestimmt werden. Am besten kann er natürlich aus der Vision der Alumniorganisation abgeleitet werden. In unserem Fall wären das: das Netzwerk selbst, die Verbundenheit zur Hochschule und der fachliche Austausch (evtl. genereller zu verstehen als „lebenslanges Lernen“). Aktuell sind wir aber noch ganz am Anfang der Gamifizierung. Deshalb halte ich ein Treffen dieser strategischen Ausrichtung für verfrüht. Lieber sollten wir mit dem Thema Gamification erste Erfahrungen sammeln. Deshalb möchte ich diesen Artikel mit einem Beispiel beenden, wie die anderen Spielelemente dazu beitragen können, die Zugänglichkeit zum Netzwerk zu erhöhen.

Dazu schauen wir uns das Beispiel eines neuen Mitglieds an, das sich gerade im Verein angemeldet hat. In unserem Fall beginnt das mit dem Erhalt der Logindaten für die Homepage per Email. Schon in dieser Email können die ersten Aufgaben (Quests) stehen: Vervollständige dein Profil und schau dir auf der Weltkarte an, welche Alumni in deiner Nähe wohnen. Sobald das Profil vollständig ist, sollte eine Rückmeldung kommen. Entweder per Email oder direkt auf der Website als Pop-Up. Z. B. „Prima. Durch dein aktuelles Profil ermöglichst du es anderen Mitgliedern dich zu finden. Viel Spaß beim Netzwerken!“. Andererseits braucht es natürlich auch Hinweise, wenn das Profil nicht ganz vollständig ausgefüllt wurde: „Fast geschafft! In deinem Profil fehlt noch ein Foto. Mach es anderen leichter, dich auf Treffen zu finden, indem du ein Foto hochlädst“.

Im Fall der Weltkarte könnte ein Pop-Up darauf hinweisen, wann der nächste Event in der Gegend stattfindet oder wer der Regionalgruppenleiter ist (Cascading Information). Findet kein Event statt, könnte die Nachricht so aussehen: „Aktuell ist kein Event in deiner Nähe geplant. Aber sag doch mal „Hallo“ zu xy, der leitet die Regionalgruppe in deiner Gegend. Auf diesem Weg kannst du dich bekannt machen und gleich nach dem nächsten Event fragen ;-)“

Ein erster Quest kann der Besuch eines Events sein. Diese sollte auch wieder per Email erklärt werden. Zum einen mit dem Ziel, warum man teilnehmen sollte, aber auch mit weiteren konkreten Aufgaben: „Schau dir die Gästeliste vor dem Event an und suche andere Teilnehmer, die im gleichen Feld wie du arbeiten, oder mit denen du ein Hobby teilst. Aufgabe: Mach dich mit mindestens einer Person auf der Veranstaltung bekannt. Wenn ihr euch versteht, wieso vereinbart ihr nicht mal ein gemeinsames Mittagessen in der Stadt?“

Nach dem Event ist dann auch die entsprechende Email mit der Frage, ob es geklappt hat, wichtig. In Verbund mit einem (freiwilligen) Regionalgruppenleiter könnte gefragt werden, ob das mit dem Kennenlernen und Essensdate geklappt hat. Bzw. wobei es Probleme gab. Lief alles gut, sollte es wieder ein „Bravo“ als Feedback geben, verbunden mit weiteren, schwereren Aufgaben (z. B. mit dem Schreiben eines Artikel für’s Alumnimagazin oder die Homepage über das eigene Erlebnis auf dem Event). Gab es Probleme, ist natürlich das Feedback spannend und der Regionalgruppenleiter kann evtl. coachend eingreifen.

Die beschriebene Situation hat noch viele Wenn’s und Aber’s. Sie macht aber hoffentlich die Richtung deutlich, in die wir uns bewegen müssen. Als Gruppenarbeit könnte man bspw. einen Preis für „hervorragende Regionalgruppen“ ausloben („die beste“ würde ich vermeiden, da sich zu schnell Favoriten herauskristallisieren und die anderen dann keine Motivation mehr haben), der jährlich an alle Gruppen vergeben wird, die sich min 4. Mal getroffen haben und wo es jedes Mal ein Foto und einen kurzen Artikel über das Treffen gab. Als Belohnung kann es für die hervorragenden Gruppen dann z. B. eine Summe X für zukünftige Events geben.

So und jetzt seid erst mal ihr dran: Habe ich etwas falsch aufgefasst? Macht ihr bei euren neuen Mitgliedern/Events schon lange ganz besondere Vor- und Nachbereitung, um das Netzwerkerlebnis zu verbessern? Dann bin ich gespannt, was ihr macht, und wie es funktioniert. Ich freue mich natürlich auch auf eure Meinungen/Anregungen. 

Samstag, 22. März 2014

SEPA Teil 2: Rückblick bei der ersten Abbuchung

Den ersten Teil habe ich vor der Abbuchung des Mitgliedsbeitrags in unserem Verein geschrieben. Hier folgt der Bericht vom Einzug und den Tagen danach.

Wir hatten also von allen Mitgliedern IBAN und BIC vorliegen (wie das geht, steht im ersten Teil). Als nächstes galt es, die neuen Spielregeln einzuhalten. Bei SEPA-Abbuchungen muss man die Mitglieder jedes mal 14 Tage vor der Abbuchung über die Abbuchung informieren und hier auch die sogenannte Mandatsreferenz angeben. Wir machen das per Email. Wichtig bei dieser Email sind folgende Angaben:

  • Datum der Abbuchung (also mindestens 14 Tage in die Zukunft)
  • Betrag der Abbuchung 
  • Die Mandatsreferenz (wir nutzen hier eine Kombination aus Jahr und Mitgliedsnummer, wenn die Mitgliedsnummer fortlaufend verwendet werden, würde es reichen diese zu nutzen, was ich mittlerweile auch tun würde)
  • Gläubiger-ID (von der Bundesbank erhalten)

Wir überprüfen zusätzlich noch die Bankverbindung, indem wir die letzten Stellen der IBAN (also einen Teil der alten Kontonr.) und die BIC inkl. Banknamen mit angeben. Versendet wird dies mit einer Kombination aus Excel, Word und Outlook als Serienbrief. Sicher nicht State of the Art, aber sehr kostengünstig, weil die meisten die Programm vermutlich sowieso installiert haben.

Nachdem nun alles nötige getan ist, gilt es die Daten in das neue SEPA-Format zu bringen, damit man mit dieser Datei dann den Einzug auslösen kann. Das SEPA-Format löst das vorherige DAT-Format ab. Wir nutzen dazu den SEPAmacher. Die Software kostet in der größten Ausführung (für mehr als 50 Mitglieder) knapp 15 Euro und die Software wird regelmäßig gewartet, meiner Meinung nach ein guter Deal.

Die Software wird aus Excel befüllt, was am Anfang etwas hackelig ist, aber dank der guten Erklärungen kein Problem ist. Deshalb beschreibe ich hier nur die Felder, die bei mir zu mehr Aufwand geführt haben. In der Exceldatei müssen in der ersten Zeile bestimmte Überschriften verwendet werden, damit der Import klappt. Es wird immer das jeweils aktive Blatt geöffnet. Hat das Excel-Sheet mehrere Blätter, dann ggfs. noch mal öffnen und das richtige Blatt auswählen und dann speichern.

Bei uns ist das Feld "Identifikation" leer. Bei Mandat kommt die o. g. Mandatsreferenznummer hinein. "Erteilung" ist das Datum der Emailankündigung. Beim Feld Erstlastschrift haben wir ein fiktives Datum (1.1.2013) eingetragen, da wir alle Lastschriften als Folgelastschrift deklariert haben (Tipp unserer Sparkasse). Der SEPAmacher erzeugt dann eine XML-Datei, die man bei seiner Bank hochladen kann (wenn man für SEPA-Lastschrift freigeschaltet ist - das ist noch etwas Papierkram).

Bei uns hat es prima funktioniert. Wir hatten nach 2 Wochen bei etwa 260 Abbuchungen nur 4 Rückbuchungen, was deutlich weniger als in den Vorjahren ist. Da eine SEPA-Abbuchung vorher angekündigt wird, gab es in der Zeit der Vorankündigung von zwei Mitgliedern die Frage, ob sie auch auf die kostenlose Mitgliedschaft wechseln können. Das war ein Fortschritt, weil wir so die Chance hatten, eine Stornierung der Abbuchung durch das Mitglied zu verhindern. Wir haben das Geld hinterher zurücküberwiesen und so die Fehlbuchungsgebühren und sicher auch dem Mitglied einiges an emotionalem Ärger gespart.

Wir haben nicht von all unseren Mitgliedern ein schriftliches Mandat vorliegen, d. h. einige unserer Mitglieder könnten bis zu 13 Monate nach Einzug zurückbuchen. Da unser Beitrag freiwillig ist, gehen wir das Risiko ein, dass hier jemand zurückbucht. In der Regel passiert so etwas aber eher zeitnah und insofern hat sich da gegenüber dem Lastschriftverfahren praktisch wenig geändert. Dieser Umstand wäre aber gegenüber dem Finanzamt eine Argumentation, wieso man als Verein höhere Rücklagen benötigt (noch nicht probiert, ob das klappt).

Im ersten Teil hatte ich geschrieben, dass ich zum Thema BIC mit den letzten drei Stelle XXX melden wollte. Hier gab es bei uns keine Probleme. Allerdings waren die Konten alle in Deutschland, so dass die IBAN eigentlich alle nötigen Infos enthalten hat.

Die Beschreibung hat natürlich keinen Anspruch auf Vollständigkeit, ich hoffe sie hilft trotzdem weiter. Ich bin mir bewusst, dass wir hier einige Graubereiche nutzen, aber das ist bei bisherigen Lastschriften auch schon so gewesen, nur war man sich dessen nicht mehr bewusst, weil es über Jahre gelebte Praxis war.

Montag, 14. Oktober 2013

SEPA-Umstellung Teil 1: Vor der Abbuchung

Das Thema SEPA-Umstellung dürfte die meisten Alumni-Organisationen mit Beitragszahlern im Moment schwer beschäftigen- oder sie verdrängen es. Noch ist ein bisschen Zeit und in 2014 kann man in den ersten beiden Monaten auch noch mit BLZ und Kontonummer das Geld einziehen. Bei BiTS-Alumni ziehen wir unsere Beiträge erst Ende März ein, deshalb ist das für uns keine Option. Also habe ich mich heute mal dem Thema angenommen, und nach ca. 3 Stunden war der erste Teil erledigt. Hier ein kleiner Erfahrungsbericht.

Bevor man überhaupt über SEPA-Abbuchungen nachdenkt, muss man mit seiner Bank das SEPA-Lastschriftverfahren vereinbaren. Dafür braucht man eine SEPA-Gläubiger-ID, die man bei der Bundesbank beantragen muss. Bis dahin ist es nur etwas Papierkram, den ich hier nicht weiter beschreibe.

Als nächstes stand ich vor der Frage, wie wir mit dem Thema eigentlich umgehen wollen. Dank SEPA dürfen wir uns nicht mehr mit Kontonummer und Bankleitzahl (BLZ) befassen, sondern müssen uns mit IBAN und BIC zwei wesentlich längere Zahlen merken (oder schaffen das eben nicht). Bei bestehenden Mitgliedern ist das kein Problem. Die aktuellen Kontodaten müssen nur konvertiert werden. Man kann aus Kontonummer und BLZ die Werte einfach errechnen. Das geht mit dem kostenlosen Excel-Tool EX-IBAN von www.ex-sepa.de wunderbar. Dazu eine Anmerkung: Für den Fall, dass bei der BIC die letzten drei Stellen XXX sind, ist das kein Grund zur Panik. Viele Banken in Deutschland nutzen die Werte nicht. Die Anmerkung im EX-IBAN Tool, dass man die Werte manuell ändern muss, kann man also ignorieren – sagt zumindest unser Sparkassenberater. Erfahrungen damit habe ich noch keine gemacht (das kommt im 2. Teil).

Was aber macht man mit neuen Mitgliedern? Diesen IBAN und BIC abzuverlangen ist nicht gerade eine Einladung den (bei uns freiwilligen) Jahresbeitrag zu bezahlen. Ich habe mich deshalb dafür entschieden, dass wir beides anbieten. Mitglieder mit deutschem Konto können weiterhin Kontonummer und BLZ angeben. Im Rahmen des Rechnungslaufes wandeln wir die Werte in IBAN und BIC um und speichern diese fortan in der Datenbank. Für Mitglieder, die im Ausland leben, geht das leider nicht. Das sind bei uns aber nicht so viele, als das es den Aufwand lohnen würde, hierfür eine Programmierung vorzunehmen.

Unsere Website haben wir so erweitert, dass es bei der Überprüfung der Kontonummer/IBAN ab sofort eine Fallunterscheidung gibt: Ist der Wert eine Zahl, dann gehen wir von einer Kontonummer aus. Sind Buchstaben enthalten, dann erfolgt die Überprüfung der IBAN mittels Prüfziffer. Diese ist Teil der IBAN und man erkennt Tippfehler schon bei der Eingabe (weitere Infos auf www.sepa.de). Wir haben also keine neuen Felder, sondern speichern beide Werte im gleichen Feld.

Damit ist der aktuell machbare Teil der Arbeit schon erledigt. Ein Hinweis noch zur SEPA-Lastschrift selbst. Dort gibt es verschiedene Optionen „einmalige Abbuchung“, „erstmalige Abbuchung wiederkehrend“ und „wiederkehrende Abbuchung“ heißt es bei unserer Sparkasse. Hier hatte ich die Frage, ob wir bei der Übertragung der Abbuchungsdaten zukünftig alte und neue Mitglieder unterscheiden müssten. Die Antwort unserer Bank war, dass „wiederkehrende Abbuchung“ für alle Fälle schon okay wäre.

Den 2. Teil der Geschichte gibt es im März 2014, wenn wir die Jahresbeiträge eingezogen haben.

Fast vergessen hätte ich das Papieranmeldeformular, das muss natürlich auch angepasst werden :)

Freitag, 26. Juli 2013

Alumni Datenbanken: Sinnvoll und wenn ja, wie pflegen?

Von Zeit zu Zeit sollte man sich ja auch mal selbst hinterfragen. Angeregt durch eine Frage in der Xing Alumni Manager Gruppe habe ich mir mal meine Gedanken gemacht und auch überlegt, was überhaupt für das Vorhalten einer eigenen Datenbank spricht.

Ich halte eine Datenbank für eine sehr sinnvolle Lösung, deshalb mag dieser Artikel nicht ganz objektiv sein, ich freue mich daher über kritische Fragen und Meinungen.

Unnötig oder Essentiell?

Pro eigene Datenbank

  • Verkaufsargument gegenüber neuen Mitgliedern
  • Liefert Content für eigene Homepage und wenn er schlau aufbereitet ist, lassen sich hier weitere nutzbare Funktionen generieren (z. B. als Weltkarte oder Tag-Cloud nach Branchen/ Interessen)
  • Ist vollständig durchsuchbar durch Mitglieder (Xing, LinkedIn sind hier kostenlos nur stark eingeschränkt nutzbar)
  • Erlaubt es, schnell auch mal Listen von Mitgliedern zu erzeugen (bspw.  für die Organisation von Schwerpunktevents) – das geht mit Xing/LinkedIn nicht
  • Stärkt das Zusammengehörigkeitsgefühl („ich pflege meine Daten und leiste einen Beitrag zur Netzwerkentwicklung“) und erinnert an das Netzwerk, dessen Teil man ist
  • Macht unabhängig von externen Social Networks (deren Lebensdauer, Kosten und Data Privacy überhaupt nicht beeinflusst werden kann). 
  • Nicht alle Mitglieder sind bei Xing/LinkedIn und manche wollen dort auch nicht sein
  • Ermöglicht es, weitere Daten über die Mitglieder zu erheben, die bei Xing/LinkedIn nicht stehen /stehen können.
  • Ist langfristig das größte Asset eines Alumni Vereins (vorausgesetzt die Events des Vereins werden auch entsprechend gut besucht und es ist nicht nur eine tote Liste) . Ich würde sogar so weit gehen und behaupten, dass manche Mitglieder irritiert wären, wenn man diese Leistung nicht anbieten würde.

Contra eigene Datenbank

  • Zeit und Aufwand sie aktuell zu halten
  • Kosten für Webentwicklung
  • Datenpflege kann Mitglieder „nerven“
Ich habe mich dann noch gefragt, wie die Datenbank zur Vision des Vereins passt und bin in unserem Fall (www.bits-alumni.de) auf folgendes gekommen:
  • Datenbank ist ein Mitgliederservice
  • Ermöglicht den Austausch zwischen Mitgliedern (auf meiner Alumni Plattform, nicht woanders, das Senden von Nachrichten ist kostenlos)
Letztlich ist es eine Frage der Opportunität: Was könnte ich stattdessen in der Zeit für meine Mitglieder leisten, die ich aktuell auf Datenpflege ver(sch)wende?

These 1: Ganz ohne Datenpflege kommt niemand aus, auch nicht bei Xing. Hier sind zwar die Daten aktuell, aber im Moment kann man auch seine Gruppenmitglieder nicht wirklich gut gefiltert ansprechen. D. h. die Kosten entstehen hier bei der Selektion, die manuell erfolgen muss.

These 2: Die Kosten für die Webentwicklung entstehen zu großen Teilen trotzdem, da ich ein Mindestmaß an Pflege über die eigene Homepage z. B. für jene Mitglieder gewährleistet sein muss z. B. für die Pflege der Emailadressen.

These 3: Wenn ich meinen Mitgliedern online nicht den Eindruck vermitteln kann, dass der Verein lebt, dann kann ich sie auch nicht offline dazu bewegen zu Events zu kommen

Die Thesen 1 und 2 kann jeder leicht für sich beantworten. Bei These 3 wäre ich über eine Studie hoch erfreut. Ich glaube aber, dass es im Moment Alumninetzwerke gibt, die entweder beides gut oder beides schlecht machen.

Aus meiner Sicht ist damit die Frage klar, man braucht eine eigene Datenbank und sollte als erstes die negativen Punkte möglichst ausschalten, bevor man dann im zweiten Schritt die positiven Punkte weiter angehen kann. Dann gibt es auch keine Opportunität, da die investierte Zeit für die Datenbank sich gleich mehrfach bezahlt macht.

Wie erhält man gute Daten von seinen Mitgliedern (ohne diese zu nerven)?

Auch auf die Gefahr hin, hier nur bekannte Umstände aufzuzählen, mache ich es dennoch verbunden mit einigen (ersten) Erfahrungen, wie erfolgreich die einzelnen Maßnahmen sind:
  1. Anbieten einer Schnittstelle für die Mitglieder um Daten von Xing oder LinkedIn zu kopieren (Beispielvideo hier https://www.youtube.com/watch?v=D4NYi1grsTw )
  2. Jährliches Gewinnspiel, an dem man teilnimmt wenn man seine Daten aktualisiert
  3. Für Neue Mitglieder Reminder im mehrwöchigen Abstand, falls das Profil noch nicht aufgefüllt wurde
  4. Für eingeloggte Mitglieder ein Hinweis mit der Bitte, das Profil zu vervollständigen, wenn bestimmte Bereiche noch gar nicht ausgefüllt wurden.
  5. Den Service die Daten ggfs. auch FÜR die Mitglieder einzutragen (wenn bspw. bei einem Mailing Rücksendungen kommen und die Mitglieder auf Nachfrage per Email die korrekten Daten angeben)
  6. Eine Standardemail bei der wir zum Abschluss gratulieren, wenn der nach unseren Informationen stattfinden müsste (in der wir aber auch Fragen, ob das der Fall ist)
  7. Wenn das Profil vollständig ist, in periodischen Abständen eingeloggte Mitglieder fragen, ob die angezeigten Daten noch aktuell sind
  8. Bei Standardmails wie z. B. Newslettern oder Einladungen in einer Infobox Mitglieder mit unvollständigen Daten bitten, diese zu aktualisieren bzw. bei vollständigen Profilen Infos anzeigen w. z. B. „Ist der Job bei Firma xy noch aktuell?“
  9. Eine Seite zum Pflegen der eigenen Daten, die auch per Smartphone gut ausfüllbar ist.
  10. Eine gezielte Kampagne bei der alle Mitglieder, zu denen innerhalb eines Jahres kein Kontakt aufgenommen werden konnte, telefonisch oder auf andere Wege kontaktiert werden-
Die ersten 6 Punkte haben wir bereits umgesetzt. Eine eindeutige Zuordnung auf die Punkte ist nur schwer möglich. So kommt es regelmäßig vor, dass Personen, die wir per Email bitten ihre Daten zu pflegen, den Datenimport aus Xing nutzen. Insgesamt haben nach einem halben Jahr 121 von 660 Mitgliedern ihre Daten aus Xing importiert, also knapp 20 %. In den Daten ist aber sichtbar, dass insbesondere die neuen Mitglieder hier eine höhere Quote haben. Da einige Maßnahmen zu dem Thema im ersten Halbjahr 2013 eingeführt wurden, ist hier also Verbesserung sichtbar. Bei den langjährigen Mitgliedern wird es vermutlich schwieriger die Zahl mittelfristig zu steigern.

Sehr gute erste Erfahrungen haben wir mit Punkt 3 gemacht. Dieses Feature ist aber noch so neu, dass die Datenbasis noch zu klein ist als das ich hier eine Prozentzahl nennen will.

Das jährliche Gewinnspiel (Punkt 2) haben wir dieses Jahr erstmalig durchgeführt in Verbindung mit der Einführung des Imports der Daten aus Xing. Hier gibt es leider keine genaue Statistik, das wird erst nächstes Jahr klappen.

Punkt 4 (Hinweis nach Login) ist leider technisch überhaupt nicht messbar, da die Erweiterung der Homepage sonst deutlich aufwändiger (teurer) gewesen wäre. Letztlich ist das aber auch eine Maßnahme, die nur mit anderen Aktionen zusammenspielt. Hierfür muss man die Mitglieder natürlich erst mal dazu bekommen sich im Alumni Portal einzuloggen.

Der Punkt 5 ist extrem aufwändig, aber genau wie Punkt 10 eigentlich Aufgabe des Alumni Managers. Schließlich geht es darum Kontakte zu pflegen.

Bei Punkt 10 sind wir erst mal froh, dass wir nur 20 Mitglieder haben (knapp 3 %), zu denen wir im letzten Jahr gar keinen Kontakt hatten (die also weder einen Newsletter geöffnet haben, noch sich auf unserer Website eingeloggt haben oder den freiwilligen Beitrag bezahlt haben).

Wie geht es weiter?

Bei uns ist der technische Fortschritt für dieses Jahr schon ausgeplant. Eine Ergänzung der Seite um ein sogenanntes Responsive Design, das dafür sorgt, dass die Website auf mobilen Endgeräten genauso gut surfbar ist, wie mit einem Laptop/PC, ist für das nächste Jahr geplant. Erst danach werden die beiden letzten Punkte interessant.

Mittwoch, 27. Februar 2013

Extracting Global Adress List Data from an Exchange Account

After searching and browsing various tools, including ContactGenie Quickport which I did not manage to prevent from crashing, I stumbled upon a nice solution how to extract the GAL via
https://www.xing.com/net/vbatreff/vba-tipps-655000/global-address-list-gal-auslesen-39374842

This allowed me to extract all global address lists from the server without having administrational access to the server. All this worked fine with an offline GAL on Office 2010.

Here's the code based on the above source. Just copy to a new VBA :



' benötigte Konstanten
Private Const olExchangeGlobalAddressList As Integer = 0
Private Const olExchangeUserAddressEntry As Integer = 0
Private Const olExchangeRemoteUserAddressEntry As Integer = 5

Public Sub readGAL()
Dim oOutlook As Object
Dim oAddressList As Object
Dim oAddressEntry As Object
Dim oExchangeUser As Object
Dim i As Integer
i = 0

' Outlook-Instanz anlegen
Set oOutlook = CreateObject("Outlook.Application")

' Alle Adress-Listen durchgehen
For Each oAddressList In oOutlook.Session.AddressLists
    ' Prüfen, ob Exchange-Liste
    If oAddressList.AddressListType = olExchangeGlobalAddressList Then
        ' Alle Adress-Einträge durchgehen
        For Each oAddressEntry In oAddressList.AddressEntries
            ' Prüfen, ob Adress-Eintrag
            If oAddressEntry.AddressEntryUserType = 1 Then
                i = i + 1
                Cells(i, 1) = oAddressEntry.Name
                For Each omyUser In oAddressEntry.Members
                    i = i + 1
                    Cells(i, 2) = omyUser.Name
                    Cells(i, 3) = omyUser.Address
                Next
            End If
        Next
    End If
Next

' Objektvariable freigeben
Set oExchangeUser = Nothing
Set oAddressEntry = Nothing
Set oAddressList = Nothing
Set oOutlook = Nothing
End Sub

Dienstag, 25. Dezember 2012

Typo3 Xing API Data Import Extension

Alumnivereine, die ein eigens Portal haben, werden es kennen. Fast kein User macht sich die Mühe ein vollständiges Profil aktuell zu halten. Wir haben das Problem jetzt damit gelöst, dass die User ihre Daten von Xing mit wenigen Klicks importieren können. Das Ganze ist als freie TYPO3 Extension verfügbar und zwar hier:
http://typo3.org/extensions/repository/view/dix_xingsync

Nachdem wir die Extension jetzt ca. 4 Wochen laufen haben, ist das Feedback äußerst positiv und die Zahl der Vollständigen Profile bei knapp 15 % von 600 Mitgliedern angekommen. Noch ein weiter weg bis zur Perfektion, die Seite sieht nach dem Login alleine durch die Mitgliederfotos aber wesentlich ansprechender aus als ständig auf die Dummy-Fotos zu schauen.

Nächste Schritte sind, das Thema immer wieder in Mailings anzusprechen (bei den Personen, die noch nicht vollständig sind,einfach in dem man noch einen Absatz mehr einfügt, wenn man gerade eh ein Mailing macht). Für neue Mitglieder ist der nächste Schritt eine Routine,die nach 2 und 4 Wochen dazu auffordert das Profil bitte zu aktualisieren.

Montag, 17. Dezember 2012

Serienemails mit Outlook 2010 und Standardkonto

Nachdem es mich unnötig Zeit gekostet hat, hier ein kurzer technischer Hinweis, wie man mit Outlook 2010 und Word 2010 Serienemails versendet, wenn man mehrere Konto hat.
Bei mir wurde immer das falsche Emailkonto als Absender verwendet - obwohl ich das gewünschte Konto vorher entsprechend als Standardkonto festgelegt hatte. Die Lösung des Problems war am Ende das Einfügen eines neuen Registry-Schlüssels, wie es hier steht:

Das 2. Problem war die Signatur, die nicht mehr verwendet wurde. In 2007 ging das noch, ab Outlook 2010 verwendet Word bei Serienmails diese nicht mehr, man muss sie also direkt in den Serienbrief aufnehmen. 

Donnerstag, 14. Juni 2012

Felder doppelt im Backend - Werte unsichtbar

Ein simples Problem hat mich gestern wieder unnötig lang beschäftigt: Im Backend wurde beim editierender FE_USER Einträge das Feld für den Nachnamen zwar angezeigt,aber es war leer. Ein Blick in den Quellcode und die Datenbank zeigten schnell, dass der Wert durchaus da ist. Im Quellcode in einem unsichtbaren Feld, aber eben nicht im sichtbaren Input Field.
Am Ende war die Lösung simpel: Ich hatte das Feld doppelt im Backend, aber auf unterschiedlichen Tabs, so dass es mir nicht aufgefallen war. Zu lösen ist das dann, indem man im TCA-Array sucht, welche Werte beim Key
$TCA['fe_users']['types']['0']['showitem'] 
vorhanden sind. Bei mir stand dort zwei Mal das Feld last_name drin. Eins entfernt und schon ging's wieder...

UPDATE: Besser spät als nie eine Richtigstellung. Die Ursache war korrekt, aber die Lösung schrecklich falsch. Ich hatte in einer Extension in der ext_tables.php das Feld last_name in addToAllTCAtypes hinzugefügt, obwohl das Feld in der Extension gar nicht selbst erstellt wurde. Dort hab ich den Wert gelöscht und schon funktionierte alles wunderbar.

Sonntag, 19. Februar 2012

Ansprechende Texte schreiben

"Toller Event, aber wieder hat keiner den Artikel gelesen." Dieser Gedanke beschleicht nicht nur mich in der Alumni Arbeit ab und an. In der Alumniarbeit tummeln sich sicher nicht nur ausgebildete Medienexperten, sondern auch viele Quereinsteiger. Einladungen und Berichte sollen natürlich trotzdem spannend sein und von den Mitgliedern gelesen werden. Durch Zufall ist mir neulich von Wolf Schneider das Buch "Deutsch für junge Profis: Wie man gut und lebendig schreibt" in die Hände gefallen. Abgesehen davon, dass es kurzweilig zu lesen ist, waren auch genug Tipps drin, die in der Alumniarbeit Anwendung finden sollten. Die besten Tipps aus meiner Sicht sind:
  • Der erste Satz muss spannend sein und Lust auf mehr machen
  • In 350 Zeichen Alles sagen
  • Nebensätze reduzieren und nur nach dem Hauptsatz 
  • Jeder 3. Satz endet mit Nebensatz zum Auflockern
  • Texte als Qualitätskontrolle laut lesen – muss sich gut anhören
  • Für Werbung/Flyer: In 2 Sekunden den Sinn erfassen können
Die Umsetzung in die Praxis ist nach eigener Erfahrung mühsam. Es hilft aber, sich solche und ähnliche Regeln zu merken bzw. beim Verfassen des nächsten Newsletters mal vor Augen zu führen und die eigenen Texte dagegen zu halten.

Donnerstag, 9. Februar 2012

Fe_Login erweitern: Username und Emailadresse zum Login verwenden


Wer kennt das nicht: Man hat eine Typo3 Seite mit Community und regelmäßig kommen Fragen per Email, weil der Username vergessen wurde? Wie schön wäre es da, wenn als Username auch die Emailadresse gehen würde. Für die Standardloginvariante fe_login wurde mein Featurerequest (http://forge.typo3.org/issues/24708) leider abgelehnt, allerdings mit dem Hinweis, wie man diese Funktionalität in einer eigenen Extension bereitstellt.

Für an diesem Feature interessiert sind, hier die Anleitung, wie man das hinbekommt.

Wichtig: Wenn man dieses Feature nutzen möchte, muss die Emailadresse einmalig (unique sein). Das kann entweder hart über die Erstellung eines Unique Index auf die fe_user Tabelle erfolgen, oder indem man im Backend und Frontend die die Werte bei Eingabe überprüft. 
Hier gibt es auch wieder 2 Varianten: Entweder sind die Emailadresse global einmalig oder nur lokal einmalig. Global bedeutet fe_users weit, lokal bedeutet, dass sie nur einmalig innerhalb einer Seite im Backend sind. Letzeres bedeutet, dass in der fe_users die Felder „pid“, „email“ und „deleted“ ZUSAMMEN  unique sein müssen.  

Ich beschreibe hier eine Variante mit Überprüfung bei Eingabe und lokaler Einmaligkeit.

Als erstes muss überprüft werden, ob es aktuell Emailadressen gibt, die doppelt vorkommen. Dabei hilft folgendes SQL:

 Select pid, email,count(1) as mycnt from fe_users where deleted = 0 group by pid,email having mycnt > 1Select pid, email,count(1) as mycnt from fe_users where deleted = 0 group by pid,email having mycnt > 1  

Diese Fälle müssen gelöst werden, bevor man die Loginvariante freischaltet.

Als nächstes brauchen wir für’s Backend die Möglichkeit sicherzustellen, dass die Emailadresse einmalig ist. Dazu müssen wir eine neue Extension erstellen oder in einer bestehenden Extension eine neue Evaluationsklasse hinzufügen. Letzteres geht in drei Schritten:
1. ext_tables.php erweitern, so dass das fe_users Feld „email“ evaluiert wird:
 $TCA['fe_users']['columns']['email']['config']['eval'] = 'trim, lower, tx_felogin_emaillogin_uniqueemail, required';  
Trim, lower und required sind bereits existente Evaluationsmethoden “felogin_emaillogin_uniqueemail”.


2. Die Methode felogin_emaillogin_uniqueemail “anmelden” in ext_localconf.php
 $TYPO3_CONF_VARS['SC_OPTIONS']['tce']['formevals']['tx_felogin_emaillogin_uniqueemail'] = 'EXT:felogin_emaillogin/Resources/Private/Classes/class.felogin_emaillogin_uniqueemaileval.php';  


3. Das php Script an den eben definierten Ort kopieren (alle Files weiter unten im  .t3x file zum Runterladen)

An dieser Stelle kann man schon mal testen, ob man im Backend 2 Nutzern die gleiche Emailadresse geben kann.

Jetzt kommt das Frontend dran. Auch hier muss in der ext_localconf.php eine Anpassung erfolgen. Es wird ein neuer Authorisierungsservice hinzugefügt:

 t3lib_extMgm::addService(  
      'felogin_emaillogin',  
      'auth',  
      'tx_felogin_emaillogin_authservice',  
      array(  
           'title' => 'FE-Authentification via eMail',  
           'description' => 'looks up given username in email field (to allow using both email and username) ',  
           'subtype' => 'getUserFE',  
           'available' => TRUE,  
           'priority' => 70, // must be higher than tx_sv_auth (50) and rsaauth (60) but lower than OpenID (75) if you want to use OpenID too  
           'quality' => 70,  
           'os' => '',  
           'exec' => '',  
           'classFile' => 'EXT:felogin_emaillogin/Resources/Private/Classes/class.felogin_emaillogin_authservice.php',  
           'className' => 'tx_felogin_emaillogin_authservice',  
      )  
 );  

Im nächsten Schritt muss die Klasse an den entsprechenden Ort kopiert werden (auch wieder im .t3x File)

Jetzt klappt das Login schon mit der Emailadresse. Allerdings sollte noch die Registrierung so angepasst werden, dass auch hier jede Emailadresse nur einmal vergeben werden kann. Dazu nutze ich die Erweiterung sr_feuser_register. Hier kann man mittels Typoscript die Anpassungen vornehmen:
 plugin.tx_srfeuserregister_pi1.edit.evalValues.email = email,uniqueLocal  
 plugin.tx_srfeuserregister_pi1.create.evalValues.email = email,uniqueLocal  

Jetzt fehlt noch das Loginformular selbst. Dort habe ich Quick and Dirty einfach die deutsche Übersetzung wie folgt angepasst.
 plugin.tx_felogin_pi1._LOCAL_LANG.de.username=Userame/Email

Alle Dateien findet ihr in folgender Extension zum herunterladen, für die ich keine Garantie übernehme, die aber funktioniert :-)

Mittwoch, 25. Januar 2012

Form: Einfaches Nachrichtensystem für Mitglieder mit Spamschutz

Das Problem: Es gibt eine Community und Personen sollen sich untereinander erreichen können, trotzdem sollen Emailadressen nicht im System angezeigt werden. Außerdem wollte ich kein weiteres großes Plugin und die Nachricht sollte direkt an die Emailadresse des anderen Nutzers gehen und den anderen Nutzer nicht dazu zwingen sich erst einloggen zu müssen.

Die Lösung: Eine Erweiterung der Form-Extension um 2 Postprocessoren: Der eine schickt Emails im Namen des eingeloggten Users an einen anderen User und sendet gleichzeitig eine Bestätigungsnachricht an den Sender (ohne aber die Emailadresse des Originalempfängers preis zu geben). Der 2. Postprocessor verhindert, dass ein User mehr als 1 Nachricht alle 60 Sekunden verschickt und baut gleich noch eine Statistik auf.

Im Typoscript sieht das Formular so aus: 
 prefix = tx_form  
 confirmation = 0  
 postProcessor {  
     1 = minimumdelaychecker  
     1 {  
        delay=60  
        errorPageID = 226  
     }  
      2 = memberMail  
      2 {  
           recipientEmailField = EmpfaengerID  
           senderEmail = sender@domain
           senderName = Absendername 
           subject = Direktnachricht von Domain Mitglied:   
           replyToField = absenderemail  
         messages {  
                success = Deine Nachricht wurde erfolgreich an das Mitglied gesendet. Du erhälst von der Email eine Kopie  
           }  
      }  
 }  
 10 = FIELDSET  
 10 {  
      legend {  
           value = Private Nachricht an ein anderes Mitglied senden  
      }  
      20 = TEXTLINE  
      20 {  
           name = absenderemail  
           readonly = readonly  
           value = {TSFE:fe_user|user|email}  
           label.value = Deine Emailadresse  
      }  
      30 = TEXTLINE  
      30 {  
           name = name  
           readonly = readonly  
           value = {TSFE:fe_user|user|first_name} {TSFE:fe_user|user|last_name}  
           label.value = Dein Name  
      }  
 32 = TEXTLINE  
 32 {  
   name = Empfänger  
 readonly=readonly  
 value = {gp:receiverName}  
 label.value = Empfänger  
 }  
      40 = TEXTAREA  
      40 {  
           cols = 50  
           rows = 10  
           name = Nachricht  
           label.value = Nachricht  
      }  
 41 = HIDDEN  
 41 {  
   name = EmpfaengerID  
  value = {gp:receiverID}  
 }  
      50 = SUBMIT  
      50 {  
           name = Submit  
           value = Abschicken  
      }  
 }  

Das Formular selbst ist sehr einfach gehalten. Wie man Variablen im Formular auswertet, habe ich in diesem Blogbeitrag erklärt.

Der "Minimumdelaychecker" ist ein Postprocessor, der eine kleine Statistik erstellt, wer wie viele Nachrichten verschickt hat und wann die letzte Nachricht geschickt wurde. Dazu werden in der fe_users-Tabelle die 2 Felder user_system_number_of_messages und user_system_last_message_timestamp erwartet. Diese Felder können natürlich auch umbenannt werden, dann muss aber auch der Postprocessor angepasst werden. Diesen Postprocessor gibt es hier zum runterladen. Wenn jemand innerhalb der im Typoscript definierten Zeit (Variable "delay") 2 Nachrichten schickt, wird er auf die Seite mit der in der ebenfalls in Typoscript (errorPageID) definierten Seite umgeleitet.

Der 2. Postprocessor ersetzt den Standard Mail Postprocessor. Runterladen könnt ihr ihn hier. Dieser Postprocessor setzt zum einen als Absender nicht die Emailadresse, die vorher im Formular angezeigt wurde, sondern diejenige, die für den eingeloggten User hinterlegt ist. So wird verhindert, dass jemand  die Daten im Form vor dem senden editiert. Das geht in HTML auch dann, wenn der die Felder - wie im Beispiel - gesperrt sind.

Was noch fehlt? Der Aufruf der des Formulars. Hier habe ich es mir einfach gemacht:. Aus einer anderen Extension heraus rufe ich die Seite, die das Formular enthält auf und übergebe per URL die ID (und den Namen des Empfängers):
?receiverID=272&receiverName=Dein%20Name

Ich hoffe, die Beschreibung ist ausführlich genug. Wenn nicht, fragt ruhig :)

Dienstag, 27. Dezember 2011

Form: Postprocessor um Kopie an Sender zu senden

Die Postprocessoren haben es mir gerade angetan. Liegt wohl daran, dass sie so schnell und schmutzig gehen ;)
In diesem Postprocessor geht es darum, wie man dem Absender auch eine Kopie zuschickt. In allen Fällen sollte man daran denken, dass so ein Formular auch als Mailschleuder genutzt werden könnte. Richtigen Schutz bietet da wohl nur ein Captcha, für eingeloggte User schreibe ich später meine Lösung dazu.
Dieser Postprocessor nimmt den Mail-Postprocessor und erweitert ihn sehr direkt. Dafür als erstes mal die Datei Mail.php kopieren und die Kopie in Mailtosendertoo.php umbenennen. Nun den Namen der Klasse in tx_form_System_Postprocessor_Mailtosendertoo ändern, bevor wir mit dem Anpassen der Funktion anfangen können.
In die Funktion process() kommt hinter den Aufruf
$this->send(); 
Noch eine neue Zeile, um die Funktion aufzurufen, in der die Kopie gesendet wird :
$this->sendCopyToSender();
Die neue Funktion sieht dann so aus:
 /**
 * Changes the To, Reply-To, Subject and sends message to the sender of this message
 * Function makes use of the same mailMessage object, thus should be used only after the original message is send* @return void
 */
protected function sendCopyToSender() {
 $this->mailMessage->setSubject("Die folgende Nachricht wurde eben in Deinem Namen via BiTS-Alumni.de verschickt");
 $this->mailMessage->setReplyTo($this->mailMessage->getSender());
 $this->mailMessage->setTo($this->typoScript['senderEmail']);
 }
 $this->send();
}
 Die Funktion tauscht entsprechend Subject, Empfänger, und ReplyTo der Email. Danach wird die Email gesendet.

Im Typoscript anstatt
 1 = Mail  
 1 {  
 …  
 }  
Jetzt:
 1 = Mailtosendertoo  
 1 {  
 …  
 }  
Der Rest bleibt gleich. Fertig!

Donnerstag, 22. Dezember 2011

Typoscript Variablen in der Form Extension auslesen

In Forum auf Typo3.net war es schon beschrieben, aber ich will hier noch mal kurz darauf eingehen, wie man die Stelle findet und warum die Lösung nicht immer zu nutzen ist.

Mit verschiedenen Extensions in Typo3 4.5 war es problemlos möglich Variablen mit Hilfe von Typoscript vorzubelegen:
{TSFE:fe_user|user|email}
Und ähnliche Werte konnte man öfter finden.
In der neuen Form ist das nicht mehr möglich. Laut diesem Issue (http://forge.typo3.org/issues/25931) im Forge liegt das an dem Securitykonzept der Extension. Die Idee der neuen Form ist offensichtlich, dass man auch Redakteuren erlaubt Forms zu erstellen. Diese wären dann in der Lage mittels Variablen eigenen Code einzuschleusen, vermute ich. Ich bin jetzt zu bequem diese Lücke gedanklich voll durchzudenken.

Für alle, bei denen es keine Redakteure gibt, hier die Quick & Dirty Lösung, mittels der man Variablen „erlauben“ kann. Alles was es braucht ist in sysext/form/Classes/ Domain/Factory/Typoscript.php in der Funktion reconstituteElement als erste Zeile folgendes:
 $arguments['value']= $this->getLocalConentObject()->insertData($arguments['value']);  

So kann dann mittels Typoscript zum Beispiel auf Werte des TSFE oder auch auf Werte, die per URL übergeben wurden, zugreifen.

 10 = Fieldset  
 10 {  
 10 = hidden  
 10.value = {TSFE:fe_user|user|email}  
 20 = hidden  
 20.value = {gp:receiverID}  
 }  


Die erste Zeile gibt die Emailadresse des eingeloggten Users zurück. Die zweite Zeile sucht in der URL nach dem Parameter receiverID und gibt deren Wert zurück. Also bspw. den Wert 23, wenn die URL so aussieht:  index.html?receiverID=23

Die Übergabe über die URL ist natürlich nicht frei von Risiken, weil jeder Nutzer hier natürlich die Werte ändern könnte. Deshalb sollte man sich genau überlegen, wann man mittels gp:… auf URL Übergaben vertraut.

Meine zugegebenermaßen sehr einfachen Tests ergaben, dass hier keine Risiken existieren. Weil jeglicher Code ja vorher bereits in HTML Sonderzeichen umgewandelt wird. Trotzdem sollte man diese Variante nur sparsam einsetzen. Wozu ich es  nutze, schreibe ich im nächsten Artikel.

Hintergrund
Wie aber findet man die Stelle in der Extension an der die Anpassung vorgenommen werden muss? In extBase Extensions kann man dazu eigentlich  in der ext_localconf.php anfangen und sich dann via Controller-Classes weiter hangeln. Für die Form Extension gilt das leider nicht ganz, weil der Einstieg etwas komplizierter ist, da die Form Extension das Standardform-Element und dessen Funktionen teilweise überschreibt.  Ein Blick in den Controller schadet aber auch nicht. Im Ordner form/Classes/Controller/ gibt es 2 Dateien: Form.php und Wizard.php. Form.php  klingt vielversprechend (wir wollen ja nicht den Backend Wizard bearbeiten).

In dieser Datei gibt es die Funktion cObjGetSingleExt, diese wird laut Kommentar 2 mal aufgerufen und trägt diesen Namen, weil der Typo3 Core das verlangt.
Am Ende ruft sie die Funktion execute() auf, die wiederrum die Funktion renderForm aufruft, wenn noch kein PostEvent stattgefunden hat (das wird in showForm() überprüft).
RenderForm ruft jetzt die Funktion buildModelFromTyposcript() des Objekts $this->typoscriptFactory auf. Klingt schon sehr nach dem, was wir wollen. Das Objekt $this->typoscriptFactory wird noch immer in Form.php erstellt und zwar mit der Zeile:

 t3lib_div::makeInstance('tx_form_Domain_Factory_Typoscript');  

Also suchen wir jetzt in Classes/Domain/Factory/Typoscript.php nach der Funktion “buildModelFromTyposcript“.
In dieser Funktion scheint die Methode createElement vielversprechend, zumal sie auch die Variable $typoscript enthält, in der die Werte, die wir im Formwizard eingegeben haben, enthalten sind. Das findet man heraus, indem man sich mittels der Extension debugster oder der php Funktion print_r() die Werte der Variable ausgeben lässt. In dem $typoscript Array sind wir daran interessiert, dass die Werte in 'value' umgeformt werden. An der Stelle ist die Extension etwas komplexer, weil reconstituteElement mehrfach rekursiv durchlaufen wird. Da die Funktion insertData() aber den Eingabewert unverändert zurück gibt, wenn es keine Variable {TSFE....} ist, kann einfach am Anfang der Funktion die besagte Zeile:
$arguments['value']= $this->getLocalConentObject()->insertData($arguments['value']);
Stehen.

Eine gute Beschreibung für extBase und Fluid habe ich jetzt auch noch bei Mittwald gefunden: http://www.mittwald.de/fileadmin/pdf/extbase_fluid.pdf
Ist zwar etwas älter, aber immer noch aktuell.

Mittwoch, 7. Dezember 2011

Freakonomics über Fundraising

Ein kurzer Abriss darüber, was Spender motiviert und wie man die Spendenbereitschaft erhöht gibt es aktuell bei Freakonomics, einem populärem Wissenschaftsblog & -podcast. Wie es sich für Alumniarbeit in Deutschland gehört ist das ein toller erster Beitrag zu dem Thema in diesem Blog. Das Transscript und den Podcast gibt es hier zum Download.

Mein Highlight daran ist, dass sich die Spendenbereitschaft dadurch erhöht, dass man ein Feld anbietet für permanentes Opt-Out. Das Feld selbst wird aber kaum angekreuzt. Ob das in Deutschland auch so wäre?

Typo3 4.6 und die neue Form Extension - ein erster eigener Postprocessor

Die neue Form Extension in Typo3 hat mich in der letzten Zeit viel beschäftigt und wird es wohl auch eine Weile tun. Hier werde ich in den nächster Zeit meine Erkenntnisse abwerfen in der Hoffnung, dass sie anderen weiterhelfen und ich durch Kommentare lerne. Genau so, wie ich dank Google-Suche und ähnlicher Seiten bis hierhin gekommen bin.

Das Ziel: Einen Postprocessor zu entwerfen, der mit Extbase konform geht und nicht im Sysfolder rumliegt.

Der aktuelle Status: Ein erster Postprocessor, der in der Lage ist den Typoscript Code auszuwerten, aber leider noch einer Datei in den sysext Ordner typo3\sysext\form\Classes\System\Postprocessor\ schreiben will. Die Datei findet Ihr unten. Sie heißt Forward.php und wird über folgenden Code als Postprocessor eingebunden:

 postProcessor {  
   1 = mail  
   1 {  
     recipientEmail = xxx@xxx.de  
     senderEmailField = xxx@xxx.de  
   }  
   2 = forward  
   2.forwardID = 218  
 }  
Durch die Eintragung der zwei Zeilen wird in "sysext\form\Classes\System\Postprocessor\Postprocessor.php" versucht eine Klasse zu erzeugen, die auf den Namen tx_form_System_Postprocessor_Forward hört und im entsprechenden Ordner liegt. Nach meinem aktuellen Kenntnisstand muss diese Datei im gleichen Ordner liegen. Entweder ich liege falsch, oder es braucht einen Changerequest, weil das ja nicht wirklich sauber ist. (UPDATE: Dass der Postprocessor in einem anderen Ordner liegt, wird wohl erst ab Typo3 4.7 möglich sein. Hier der Bug-Eintrag in Forge). Der Parameter forwardID gibt einfach eine Typo3 Page ID an auf die Seite, auf die nach versandt der Nachricht geforwarded wird. Das geschieht in der angehängten Datei im wesentlichen mit folgenden Zeilen:

 $cObj=t3lib_div::makeInstance('tslib_cObj');  
 header("Location: " . $GLOBALS['TSFE']->tmpl->setup['config.']['baseURL'] . $cObj->typoLink_URL(array('parameter' => $this->typoScript['forwardID'])), true, 303);  

Die zweite Zeile schickt also einen neuen Header, was mir gar nicht sauber vorkommt, aber immerhin funktioniert...

Die Datei Forward.php runterladen.

Wer mit Extbase noch nicht so vertraut ist, sollte sich unbedingt folgendes Buch zulegen: Typo3 Extensions mit Extbase & Fluid. Das hat mir auch sehr geholfen die Struktur von neuen Extbase Extensions zu verstehen.
UPDATE 12.08.2014: Wie man das Ganze jetzt in TYPO3 6.2 so umsetzt, dass man den PostProcessor in einer eigenen Extension unterbringt, habe ich hier beschrieben.