Gemeine Entwickler…
November 23rd, 2008gibt es wohl auf entwicklerGemein.de.
Liebe Leute, man muss nicht jede Mode mitmachen.
(Über die Qualität dieser site will ich hier ausdrücklich keine Aussage machen).
Viele Grüße,
Andreas
gibt es wohl auf entwicklerGemein.de.
Liebe Leute, man muss nicht jede Mode mitmachen.
(Über die Qualität dieser site will ich hier ausdrücklich keine Aussage machen).
Viele Grüße,
Andreas
zumindest wenn man den tags auf stackoverflow.com glaubt.
Erstaunt hat mich auch die Popularität von Python im Vergleich zu Perl.
Viele Grüße,
Andreas
Hallo,
im letzten Teil dieser Serie habe ich beschrieben wie man bestimmte Fragmente eines Dokumentes anhand der Formatvorlage (engl. “style”) findet. Eine genaue Beschreibung der Überprüfung der damit gefunden OCL-Fragmente ist im Rahmen von postings über Microsoft Office Programmierung weniger interessant.
Relevanter wird es wieder bei der Frage nach der Darstellung der Ergebnisse.
Hierfür gibt es in den von mir verwendeten OCL libraries bereits ein UserControl “ErrorList”, das im Rahmen des Office-AddIns wiederverwendet werden soll. Dieses control stellt Fehler tabellarisch dar und signalisiert einen Doppelklick auf einen Fehlereintrag mit einem event:
Um ein solches control mit einem Dokument zu assoziieren bietet sich eine CustomTaskPane an.
Eine solche CustomTaskPane ist ein container für ein UserControl der gleichzeitig zu dem Dokument angezeigt wird:
Die CustomTaskPane kann vom Anwender per drag and drop an jeder Seite des Dokumentes gedockt werden. Bei Bedarf kann man davon auch per event benachrichtigt werden um z.B. das Layout im gehosteten UserControl anzupassen.
Unser AddIn gibt dem Benutzer die Möglichkeit die CustomTaskPane mit den Ergebnisse des OCL checks unsichtbar oder sichtbar zu machen (mit der “Display check results” checkbox im “OCL” tab des ribbons – siehe obiges Bild).
Dadurch wird das handling nicht völlig trivial, weshalb ich im folgenden einen möglichen Ansatz für den Umgang mit der CustomTaskPane vorschlagen will. Eine Überlegung besteht darin, dass die Steuerung der Sichtbarkeit nicht in den Eventhandlern des ribbons erfolgen sollte, sondern in der Klasse “ThisAddIn” die die Steuerung des AddIns zentral implementieren sollte.
Um dies zu erreichen, wurde für die generierte Ribbon-Klasse ein neuer event “OnDisplayResultTaskPane” eingeführt. Falls nun die checkbox “Display check result” geclickt wird, erzeugt das ribbon lediglich einen entsprechenden event. Die ThisAddIn-Klasse meldet sich für diesen event an und reagiert dann entsprechend indem sie die CustomTaskPane sichtbar oder unsichtbar macht.
private void ThisAddIn_Startup(object sender, System.EventArgs e) { .... ribbonTabOcl.Instance.OnDisplayResultTaskPane += this.OnDisplayResultTaskPane; .... }
Das Erzeugen der CustomTaskPane ist so implementiert:
private ErrorList CreateCustomTaskPane() { if (this.CustomTaskPanes.Contains(m_checkResultsTaskPane)) { this.CustomTaskPanes.Remove(m_checkResultsTaskPane); } ErrorList el = new ErrorList(); el.OnErrorSelected += this.OnErrorSelected; m_checkResultsTaskPane = this.CustomTaskPanes.Add(el, "OCL check results"); m_checkResultsTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionBottom; m_checkResultsTaskPane.VisibleChanged += new EventHandler(m_checkResultsTaskPane_VisibleChanged); return (el); }
In Zeile 11 wird das CustomTaskPane-Objekt erzeugt. Im Konstruktor wird dabei das UserControl übergeben, das in der CustomTaskPane dargestellt werden soll. Es empfiehlt sich, das UserControl an den Aufrufer zurückzugeben, damit dieser dort Eventhandler registrieren kann und properties des UserControls setzen oder lesen kann.
Ich habe die Beobachtung gemacht, dass das managed CustomTaskPane-Objekt gelegentlich aufgrund der Benutzerinteraktionen sein natives Objekt “verliert” ohne das man dies durch einen event gemeldet bekommt. In einem solchen Fall gäbe es eine Exception beim Zugriff auf das CustomTaskPane-Objekt. Deshalb wird die Methode CreateCustomTaskPane() nach jedem click auf den “Check all expressions” button aufgerufen, obwohl dies streng genommen nicht nötig wäre.
Ein Schliessen der CustomTaskPane durch klicken auf ihren close button zerstört das Objekt nicht. In einem solchen Fall wird ein VisibleChanged event generiert den man benutzen kann um das GUI synchron zu halten (in unserem Fall die “Display check results” checkbox zu deselektieren).
Insgesamt bieten die CustomTaskPanes eine elegante Möglichkeit, beliebige controls mit einem Word-Dokument zu assoziieren.
Viele Grüße,
Andreas
Technorati Tags: Office 2007, Word 2007, AddIn, CustomTaskPane
Hallo,
ein nicht namentlich bekannter Softwareentwickler (vielleicht Kishore Kumar?) hat einige lesenwerte Artikel zum Thema UML auf seinem blog veröffentlicht. Die Artikel sind nicht nur sehr liebevoll geschrieben, mit vielen Bildern und Zitaten, sondern scheinen mir auch sehr profund und nachvollziehbar.
Einige seiner Aussagen lauten:
In diesem Artikel spricht er einen Effekt an, den ich selbst sehr gut bestätigen kann. Unabhängig von dem dauerhaften Wert der Modelle schafft allein der Akt des Modellierens ein besseres Verständnis des Systems. Man denkt eigentlich automatische tiefer und weiter als wenn man zu früh mit dem Kodieren anfängt.
Viele Grüße,
Andreas
Technorati Tags: UML, Modellierung
Hallo,
bei einer ClickOnce-Installation einer Microsoft .NET Software kann bei der Erstellung des setup-Programmes in Visual Studio eine Option gewählt werden, die bewirkt dass vorausgesetzte Software (”redistributable prerequisites” – wie etwas das .NET framework selbst) automatisch als Teil der Installation geladen und installiert werden.
Dabei kann angegeben werden, ob die Komponenten von der Website des Hersteller oder von einer anderen Quelle geladen werden sollen.
Im ersteren Fall kann folgendes Fehlerszenario entstehen:
Der Entwickler hat eines der vorausgesetzten Softwarepakete (z.B. das deutsche language pack vstor_lp_de_30.exe für die VSTO 3.0 runtime) lokal installiert. Beim Erstellen des setup-Programmes wird dieses Paket nicht integriert, wohl aber Information über die verwendete Version.
Nun wird die Installation auf einem beliebigen anderen Rechner gestartet. Der installer sieht dass auf der Website des Komponentenherstellers (also Microsoft für obiges Beispiel) eine andere Version der Komponente verfügbar ist. Genau dann wird diese Fehlermeldung generiert:
Error: Die Datei “C:\DOKUME~1\awa\LOKALE~1\Temp\VSD6.tmp\VSTOR30\vstor_lp_de_30.exe” wurde seit ihrer ersten Veröffentlichung geändert.
Die lokal auf dem Entwicklungsrechner mit Visual Studio 2008 SP1 installierte Version war vom 27.12.2007 während die Version auf der Microsoft Website vom 12.08.2008 war.
Dieses Verhalten ist ziemlich problematisch, kann doch ein update auf der Website des Komponentenherstellers grundsätzlich zu einem beliebigen Zeitpunkt erfolgen. Danach müssten alle ClickOnce-setups, die die aktualisierte Komponente benötigen, aktualisiert werden.
Es wäre sinnvoll, zumindest kleinere Abhängigkeiten direkt in das setup zu integrieren. Leider kann das Verhalten nicht für einzelne Abhängigkeiten individuell eingestellt werden, so dass in diesem Fall auch die .NET runtime in das setup integriert werden müsste, was nicht wirklich attraktiv ist.
Falls prerequisites ausgeschlossen werden bricht die Installation ohne konkrete Fehlermeldung ab, wenn die prerquisites nicht vorhanden sind bzw. nicht in der richtigen Version vorhanden sind.
Insgesamt würde ich empfehlen ausser den .NET runtimes alle erforderlichen prerequistes dem setup mit der Option “Erforderliche Komponenten vom demselben Speicherort wie die Anwendung herunterladen” hinzuzufügen. Die Installationsanleitung muss dann einen deutlichen Hinweis auf die erforderliche .NET runtime bzw. weitere nicht eingeschlossene prerequistes beinhalten.
Vielen Dank an Joe Wirtley für den Hinweis auf die root cause.
Viele Grüße,
Andreas
Hallo,
wie erwartet war dieser Teil einfach zu lösen, da es im Internet genügend Beispiele gibt, wie man mit dem Word-Objektmodell arbeitet. Die OCL-Fragmente werden anhand ihrer Vorlage identifiziert. Die Vorlage muss “OCL” heißen, kann ansonsten aber beliebig gestaltet werden. Die Verwendung eines fonst mit fester Zeichenbreite (”fixed width”) empfiehlt sich.
Ein wenig mehr Zeit als nötig habe ich benötigt, weil mir anfangs nicht klar war, dass der englische Begriff für “Formatvorlage” “Style” ist und nicht “Format”.
Bei der Umsetzung merkt man, dass die Kompatibilität zu Visual Basic for Applications (VBA) kein Designziel für C# war. Ein komfortabler Umgang mit den Office-Objektmodellen setzt einige features voraus, die Visual Basic.NET hat, C# aber nicht (z.B. default parameter). Deshalb sollte man grössere Anbindungen von Office-Objektmodellen in eigenen Visual Basic.NET assemblies erstellen. Für unser kleines Word-AddIn spielt das aber keine Rolle, da wir nur minimal auf die Word-Objekte zugreifen.
Um die OCL-Fragement zu finden, wird das Word “Find”-Objekt benutzt:
IList<TextFragment> FindFragmentsByStyle(Word.Document doc, Object styleName) { List<TextFragment> result = new List<TextFragment>(); Object start = 0; Object end = doc.Characters.Count; Word.Range range = doc.Range(ref start, ref end); Word.Find find = range.Find; Object style = null; try { style = doc.Styles.get_Item(ref styleName); } catch (Exception) { /* * Style not found. */ return (result); } find.set_Style(ref style); ExecuteFind(find); while (find.Found) { string text = range.Text; int linenum = GetRelativeLineNum(doc, range); int pagenum = (int)range.get_Information(Microsoft.Office.Interop.Word.WdInformation.wdActiveEndPageNumber); result.Add(new TextFragment(text, linenum, pagenum)); ExecuteFind(find); } return (result); }
Die Methode ExecuteFind() enthält einige low level Details beim Suchen nach dem nächsten Treffer:
private bool ExecuteFind(Word.Find find, Object wrapFind, Object forwardFind) { // Simple wrapper around Find.Execute: Object forward = forwardFind; Object wrap = wrapFind; return find.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref forward, ref wrap, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); }
Als Ergebnis gibt die Methode FindFragmentsByStyle() eine Liste von Objekten der (selbst erstellen) Klasse TextFragment zurück. Diese Klasse speichert den eigentlichen Text und Informationen zur Position des Textes im Dokument (Seiten- und Zeilennummer).
Viele Grüße,
Andreas
Technorati Tags: Word.Find, Office Programmierung, .NET
Hallo,
wer wie ich seinen Berufseinstieg in der Softwareentwicklung noch ohne Internet + Google gemacht hat, ist vielleicht immer noch dankbar wenn er nach 15 Minuten “googeln” eine Antwort auf ein Problem gefunden hat, das ihn früher vielleicht Tage gekostet hätte. Die meisten relevanten Treffer finden sich in Foren oder speziellen “Experten-sites” wie etwa Experts Exchange.
Nun tritt einen neue website an, um das teilen von Wissen zur Softwareentwicklung noch effizienter zu machen: stackoverflow.com.
Hinter der Seite steht unter anderem Joel Spolky, einer der einflussreichsten Köpfe in der IT-Szene. Auf seiner Website erklärt er, warum stackoverflow.com die beste derartige Resource sein soll.
In der Tat hat die site einige Alleinstellungsmerkmale, die sie zu einem Erfolg machen könnten:
Das Konzept scheint aufzugehen wie man etwa an enthusiastischen Diskussionen in Foren und an der bereits nach kurzer Zeit sehr hohen Zahl von Fragen sieht.
Es lohnt sich auf jeden Fall mal einen Blick auf stackoverflow.com zu werfen. In den FAQs kann man sich am schnellsten einen Überblick verschaffen.
Viele Grüße,
Andreas
Hallo,
auf spiegel.de wurde ein interessanter Artikel veröffentlicht, in dem einige indische Traditionen und ihre Auswirkungen auf die Leistungsfähigkeit von Mitarbeitern in der IT-Branche beschrieben sind.
Während mir die durch strenges Hierarchiedenken verursachten Probleme beim Outsourcing von IT-Projekten bekannt sind, waren die potentiellen Mängel in der Motivation für mich neu.
Erstere lassen sich durch entsprechendes Training wohl in den Griff bekommen, aber was soll man gegen fehlendes Interesse an der Sache machen?
Viele Grüsse,
Andreas
Technorati Tags: outsourcing, Indien
Hallo,
Microsofts Silverlight stellt eine Plattform dar, mit der man “Rich Internet Applications” (RIAs) mit Schwerpunkt auf grafische Darstellung erstellen kann.
Wer sich für Silverlight interessiert findet unter http://foidoschess.tv/ eine nette Demonstration der Möglichkeiten von Silverlight. Dummerweise ist eine Registrierung erforderlich, ich habe hierfür eine Email-Adresse @mailinator.com verwendet.
Ausserdem muss man noch die Silverlight Runtime installieren, was aber schnell und unkompliziert geht.
Da ich öfter das Internet nutze um Schachpartien live zu verfolgen (z.B. soweit möglich bei dem im Oktober anstehenden Weltmeisterschaftskampf) kann ich den Mehrwert der Foidos-Plattform durchaus erkennen.
Viele Grüße,
Andreas
Technorati Tags: Microsoft, Silverlight
Hallo,
in diesem posting beschreibe ich, wie man dem Word Ribbon eine eigene RibbonGroup hinzufügt, mit dem man die AddIn-spezifische Funktionalität aufrufen kann.
Dazu muss man dem Projekt ein neues Objekt vom Typ “Multifunktionsleiste (Visueller Designer)” hinzufügen:
Der visuelle Designer hat gewisse funktionale Einschränkungen gegenüber der Erstellung einer XML-Datei zur Ribbon-Erweiterung aber für unsere Zwecke ist er völlig ausreichend und wir nutzen gerne den erheblichen Produktivitätsvorteil.
Der Designer zeigt uns nun das neue RibbonTab an. Wir setzen noch sein label ( “OCL” – der Anhang “(Integriert)” wird von Visual Studio hinzugefügt und ist nur im design mode sichtbar) und das label der automatisch erstellten RibbonGroup (”Check”):
Projekt erstellen, Starten, und tatsächlich, unser RibbonTab wird angezeigt:
Jetzt wollen wir die buttons zum Laden einer XMI-Datei und zum anstoßen der Prüfung aller im Dokument enthaltenen OCL-Ausdrücke hinzufügen. VSTO stellt in der Toolbox den eigenen Abschnitt “Steuerelemente für Office-Multifunktionsleiste” bereit, aus dem wir uns bedienen können.
Wie gewohnt lassen sich die buttons mittels drag and drop dem ribbon hinzufügen, konfigurieren und mit einem Handler für das ‘Click’-Ereignis versehen.
An diesem Punkt stellt sich die erste Design-Frage. Die Eventhandler in der von Visual Studio erzeugten OfficeRibbon-Klasse werden zwar gerufen, aber die dabei implizit erzeugte Instanz hat keine Verbindung zu der ebenfalls impliziten Instanz der eigentlichen AddIn-Klasse “ThisAddin”. Es stellt sich also die Frage, wer die diversen events und Informationen orchestriert und wie events und Informationen zwischen den verschiedenen Instanzen ausgetauscht werden.
Hier gibt es sicherlich verschiedenste Wege, hier der den ich gewählt habe:
Damit sieht die Initialisierungsroutine des AddIns so aus:
private void ThisAddIn_Startup(object sender, System.EventArgs e) { Application.DocumentOpen += new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentOpenEventHandler(application_DocumentOpen); ribbonTabOcl.Instance.OnLoadXmi += this.OnLoadXmi; ribbonTabOcl.Instance.OnCheckAllExpressions += this.OnCheckAllExpressions; ribbonTabOcl.Instance.OnDisplayResultTaskPane += this.OnDisplayResultTaskPane; ConfigureLog4Net(); }
Viele Grüße,
Andreas
Technorati Tags: Visual Studio, Ribbon, Events