MS-Office 2010 Programmierung - created by Daniel Deckensattl in
Transcription
MS-Office 2010 Programmierung - created by Daniel Deckensattl in
W14Makroprogrammierung.dotm VBA-Bibliothek und Schulung MS-Office 2010 Word-VBA-Programmierung Deckensattl Daniel [08.01.2015] MS-Office 2010 Programmierung Office-Applikationen von Microsoft lassen sich mit Visual Basic for Application, kurz VBA, gelungen automatisieren. In diesem Dokument wird genauer beschrieben, wie Makros anzulegen und wo die Grenzen sind. Anhand von mehreren VBA-Projekten wird illustriert, wie man effizient in Visual Basic programmiert und welche Werkzeuge dazu verwendet werden. Wer einmal in Winword und Excel Makros erstellt hat und ein Flair für die VBA-Programmierung entwickelt hat, kann dies dann auch sehr schnell zB. in Outlook, CorelDraw und anderen VBA-unterstützten Programmen einsetzen und die tollsten Dinge realisieren. Erste Schritte mit VBA Um den Einstieg zu erleichtern, beginnen wir mit einer Makro-Aufzeichnung um zB. einen Titel automatisch zu formatieren. Hierzu wird in Word im Menüregister [Ansicht] der Menüpunkt [Makros] aktiviert, wo wir ein Untermenüpunkt [Makro aufzeichnen] starten. Es erscheint ein Aufzeichnungsdialog der beschreibt, welcher Makroname das System verwendet, unter welchem der VBA-Code abgelegt wird. Hier geben wir einen kurzen Beschreibungstext hinzu, der erklärt, was der Makro zu leisten vermag. Nun wird der Schreibcursor in diese Titelzeile gesetzt, dann drücken wir die HOME-Taste (Cursor fährt dann zum Beginn der Zeile). Weiter halten wir die Umschalttaste gedrückt und aktivieren die END-Taste (gesamte Zeile wird nun selektiert). Jetzt wechseln wir in Word zu Menüregister [Start] und fetten diesen markierten Text ein und vergeben die Schriftgrösse 11. Als letzten Schritt drücken wir die Pfeiltaste rechts sodass die Markierung wieder aufgelöst wird. Das war es schon, nun kann die Makroaufzeichnung beendet werden, was wieder ein Registerwechsel zur [Ansicht] bedeutet, wo wir unter Makros die Aufzeichnung beenden können. Im Hintergrund hat nun Word folgenden VBA-Code generiert (siehe Kasten rechts): Von nun an können Sie Titelzeilen per Makroaufruf einfetten und vergrössern. Bevor wir jedoch auf den VBA-Code näher eingehen, möchte ich an diesem Beispiel noch aufzeigen, wie wir diesen Makro in unser Wordmenü aufnehmen, sodass wir diesen per Mausklick auf eine gewünschte Makroschaltfläche starten können. Sub Makro1() ' ' Makro1 Makro ' Fettet eine Zeile ein und stattet diese mit der Schriftgrösse 11 aus. ' Selection.HomeKey Unit:=wdLine Selection.EndKey Unit:=wdLine, Extend:=wdExtEnd Selection.Font.Bold = wdToggle Selection.Font.Size = 11 Selection.MoveRight Unit:=wdCharacter, Count:=1 End Sub D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 1 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] In sechs Schritten binden wir unser erstelltes Makro in unsere Menüliste ein. Mit einem Rechtsklick auf das Menüband erscheint das Kontextmenü [Menüband anpassen] welches den Optionen-Dialog von Word aktiviert. Beim ersten Einfügen einer neuen Makroschaltfläche muss eine neue Menügruppe erstellt werden (Schritt 2), was wir hier im Menü [Ansicht] vornehmen. Im Schritt drei benennen wir die neuerstellte Gruppe um, zB. in Tools. Jetzt wählen wir im Listenfenster Befehle auswählen (Schritt 5) den Listenpunkt Makros aus und sogleich wird unser Makro unterhalb dargestellt. Diesen nun selektieren und über die HinzufügenSchaltfläche der neuen Gruppe Tools zuschieben (Schritt 6). Das hinzugefügte Makro kann nun umbenennt werden, hier im Beispiel mit „Titel einfetten“ und mit einem aussagekräftigem Bildchen versehen werden. Als Ergebnis erhalten wir eine neue Schaltfläche in unserem Menüband über welches unser Makro jederzeit gestartet werden kann. VBA-Editor aktivieren Am schnellsten geht die Aktivierung der Makro-Programmierumgebung (IDE) über die Tastenkombination Alt/F11. Sie könne jedoch auch über das Makromenü den Makro anzeigen lassen. Ûber die Schaltfläche Bearbeiten gelangen Sie auch in die VBAEntwicklerumgebung, die wir an dieser Stelle etwas genauer unter die Lupe nehmen wollen D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 2 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Die VBA-Entwicklerumgebung, kurz IDE genannt, hat standartmässig drei Unterfenster, über welche Makros strukturiert sind. Im Projektfenster sehen wir das Makromodul NewMacros, welches beim Erstellen von Makros eingerichtet wird und unsere Makros aufnimmt. Unterhalb dieses Projektfensters wird das Eigenschaftsfenster angezeigt, wo wir den Namen zB. umbenennen können. Im rechten Hauptfenster befindet sich der Makrocode, den wir aufgezeichnet haben und natürlich auch jederzeit erweitern können. Über den Punktoperator wird ein Submenü angezeigt, welches alle verfügbaren VBA-Befehle eines Objektes (hier im Bild das Selection-Objekt) zur Auswahl anzeigt. Man muss nicht alle Befehle auswendig lernen, sondern diese können aus dieser Liste ausgewählt werden, was die Arbeit mit Visual Basic enorm erleichtert. Wer mehr Informationen über ein VBA-Objekt benötigt, der kann in der IDE-Umgebung über das Menü [Ansicht/Objektkatalog] den Objektkatalog anzeigen lassen, wo jeder Befehl mit Parameter aufgeführt ist. Mit der F1-Taste wird die Wordhilfe aufgerufen, welche dann diverse Beispiele bereit hält, wie ein selektierter Befehl (hier zB. MoveRight) in Makro eingesetzt werden kann. Innerhalb der Wordhilfe kann weiter gesucht werden, was über die Suchen-Schaltfläche vonstatten geht. Wer noch nicht so mit VBA vertraut ist soll sich etwas Zeit nehmen die Beispiele zu studieren oder sogar einfach zu kopieren und ausprobieren. Einstiegsmakros Z o o m mo d u s an p a s se n Per Knopfdruck zur gewünschten Zoomansicht D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 3 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] wechseln ist hier das Motto. Wer viel mit Word arbeitet stellt die Ansicht gerne in die gewünschte Grösse ein. Hier das Beispielmakro dazu. '/-----------------------------------------------------------------------------------------------------------'/ Diese Beispiel-Makroprozedur wechselt die Fensteransichtsgrösse auf einen gewünschten Wert. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub AutoZoom() Dim intZoomWert As Integer intZoomWert = 180 ActiveWindow.ActivePane.View.Zoom.Percentage = intZoomWert Application.StatusBar = "Aktuelles Fenster wurde auf " & Format(intZoomWert, "0") & "% Ansichtsgrösse eingestellt" End Sub In der unteren Dokumentfenster-Leiste wird die Umstellung angezeigt. Su ch en / E r s et z e n - M akro Nehmen wir an Sie haben ein längeres Dokument in welchem Sie zB. den Firmennamen MUSTER in MUSTER AG umtauschen möchten und wollen dies einem Makro überlassen. Folgende Befehle werden vom Makrogenerator aufgezeichnet was sich aber auch kürzen lässt wie dieses Beispiel zeigt. Im Beispieltext sollen 3 Wert getauscht werden, der Firmenname MUSTER, die Telefonnummer und die Ansprechsperson. Die Firma MUSTER stellt hochwertige Geräte her die für den Umbau von Küchen spezialisiert sind. Die Mitarbeiter der Firma MUSTER sind sehr kompetent und erfüllen Ihre Wünsche im Handumdrehen. Unter der Telefonnummer 041 555 26 30 können Kunden jederzeit anrufen. Herr Meier nimmt sich Ihrem Anliegen an und kümmert sich um eine prompte Erledigung. Der aufgezeichnete Makro Makro2 produziert eine Menge VBA-Code was sich mit Hilfe einer neuen Funktion SuchenTausch(..) stark reduzieren lässt. Diese Prozedur kann nun in anderen VBA-Projekten eingesetzt werden, wo wir Suchbegriffe in einem ganzen Dokument tauschen möchten. Dieses Beispiel verdeutlicht, das wir viele Schritte in Word aufzeichnen können, um den produzierten Code dann in eigenen Makros einsetzen zu können. Sub Makro2() ' ' Makro2 Makro ' ' Selection.Find.ClearFormatting Selection.Find.Replacement.ClearFormatting With Selection.Find .Text = "MUSTER" .Replacement.Text = "MUSTER AG" .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute replace:=wdReplaceAll With Selection.Find .Text = "041 555 26 30" .Replacement.Text = "052 222 16 88" .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute replace:=wdReplaceAll With Selection.Find .Text = "Meier" .Replacement.Text = "Koller" .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute replace:=wdReplaceAll End Sub Sub WörterErstzen() SuchenTausch "MUSTER", "MUSTER AG" SuchenTausch "041 555 26 30", "052 222 16 88" SuchenTausch "Meier", "Koller" End Sub '-- Suchfunktion die des öfteren in Gebrauch ist Private Function Suchen(ByVal Suchbegriff As String, _ Optional ByVal Ersetzen As String = "", _ Optional ByVal bolNachUntenSuchen As Boolean = True, _ Optional ByVal bolWeitersuchen As Boolean = True) As Boolean Selection.Find.ClearFormatting With Selection.Find .Text = Suchbegriff .Replacement.Text = Ersetzen .Forward = bolNachUntenSuchen If bolWeitersuchen = True Then .Wrap = wdFindContinue Else .Wrap = wdFindStop End If .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Suchen = Selection.Find.Execute End Function Beim nächsten Beispiel wird dies noch deutlicher, wieviel Code wir einsparen können, wenn ein aufgezeichneter Makro entschlankt wird. M akro s en t s ch l an k en Um folgende leere zweizeilige Tabelle per Makro zu erzeugen, wird folgender VBA-Code produziert, was wir aber mit drei Makrocodezeilen realisieren können: D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 4 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Sub Makro8() ' ' Makro8 Makro ' ' ActiveDocument.Tables.Add Range:=Selection.Range, _ NumRows:=4, NumColumns:= 4, _ DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _ wdAutoFitFixed With Selection.Tables(1) If .Style <> "Tabellenraster" Then .Style = "Tabellenraster" End If .ApplyStyleHeadingRows = True .ApplyStyleLastRow = False .ApplyStyleFirstColumn = True .ApplyStyleLastColumn = False .ApplyStyleRowBands = True .ApplyStyleColumnBands = False End With End Sub Deckensattl Daniel [08.01.2015] Sub NeueTabelle() Dim myTable As Table Set myTable = ActiveDocument.Tables.Add(Range:=Selection.Range, _ NumRows:=2, NumColumns:=4) myTable.Style = "Tabellenraster" End Sub Das Makro Aufzeichnungstool zeichnet deutlich mehr VBACode auf als nötig ist, um denselben Effekt zu erreichen. Das mit Set myTable erstellte Objekt kann mit dem Punktoperator weiter gesteuert werden um zB. die Gesamtbreite der Tabelle zu beeinflussen, mit: myTable.PreferredWidth = 200 ' (Pixel) Dat u m st a b e ll e e in f ü g en l as s en Beim nächsten Makro wird illustriert, wie wir das gelernte in Praxisbeispiele umsetzen können folgende Tabelle soll automatisch erzeugt werden mithilfe eines Auswahldialoges. Der Monatskalender-Dialog soll so aussehen: Dezember 2014 Mo Di Mi 01 02 03 08 09 10 15 16 17 22 23 24 29 30 31 Do 04 11 18 25 Fr 05 12 19 26 Sa 06 13 20 27 So 07 14 21 28 Um eine neue leeren Dialogform zu erstellen, klicken Sie im Projekt-Explorer der IDE mit einem Rechtsklick auf den Ordner Module und fügen dann eine leere UserForm ein. Im Menü Ansicht gibt es einen Untermenüpunkt Werkzeugsammlung, dieser wird aufgerufen um die nötigen Labels, ComboBoxen und Schaltflächen auf die noch leere UserForm zu ziehen. Unterhalb des Projektexplorers befindet sich das Eigenschaftsfenster über welches jedem neu eingefügten Control ein aussagekräftiger Name (wie oben angedeutet) vergeben wird, so auch der Form selber (frmMonatskalender). D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 5 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Nachdem Sie die Beschriftung (Einmalklick auf die neuen Buttonelemente) OK und Abbrechen eingegeben haben, doppelklicken Sie auf eine der neuen Schaltflächen (zB. OK) und landen dann im VBA-Formmodul wo wir folgenden Code eingeben: '/-----------------------------------------------------------------------------------------------------------'/ Autor: disi@gmx.ch Erstellt: 03.12.2014 Update: 03.12.2014 Ver.: 1.00 ¦ '/ ¦ '/ Zweck: Erstellt eine kleine Datumstabelle von einem per Dialog ausgewähltem Datum ¦ '/-----------------------------------------------------------------------------------------------------------Dim vntMonthArray As Variant Private Sub UserForm_Initialize() Dim intI As Integer vntMonthArray = Array("Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember") For intI = 1 To 12 cmbMonat.AddItem vntMonthArray(intI - 1) Next cmbMonat.ListIndex = Month(Now) - 1 For intI = 1900 To 2100 cmbJahr.AddItem Format(intI, "####") Next cmbJahr.ListIndex = Year(Now) - 1900 End Sub Private Dim Dim Dim Dim Dim Dim Dim Sub cmdOK_Click() intYear As Integer intMonth As Integer vntDayArray As Variant objTable As Table intI As Integer intFirstDay As Integer intDayCount As Integer intYear = cmbJahr.value intMonth = cmbMonat.ListIndex + 1 vntDayArray = Array("Mo", "Di", "Mi", "Do", "Fr", "Sa", "So") Set objTable = ActiveDocument.Tables.Add(Range:=Selection.Range, NumRows:=8, NumColumns:=7) With Selection .MoveRight Unit:=wdCharacter, Count:=7, Extend:=wdExtEnd .Cells.Merge .TypeText Text:=vntMonthArray(intMonth - 1) & " " & Format(intYear, "####") .MoveRight Unit:=wdCell For intI = 1 To 7 .TypeText vntDayArray(intI - 1) .MoveRight Unit:=wdCell Next intFirstDay = WeekDay(Date:=DateSerial(Year:=intYear, Month:=intMonth, Day:=1), FirstDayOfWeek:=vbMonday) For intI = 1 To intFirstDay - 1 .MoveRight Unit:=wdCell Next intDayCount = Day(Date:=DateSerial(Year:=intYear, Month:=intMonth + 1, Day:=0)) For intI = 1 To intDayCount .TypeText Format(intI, "00") .MoveRight Unit:=wdCell Next End With With objTable .AutoFormat Format:=wdTableFormatSimple1 .Rows(2).Select With Selection .Font.ColorIndex = wdBlue While .Information(wdWithInTable) = True .MoveDown Unit:=wdLine Wend End With .PreferredWidthType = wdPreferredWidthPoints .PreferredWidth = 200 .Style = "Tabellenraster" End With In das VBA-Modul NewMacros geben Sie folgende Dialoform-Aufruf-Prozedur ein: Public Sub Monatskalender() frmMonatskalender.Show 0 End Sub Unload Me End Sub Private Sub cmdCancel_Click() Unload Me End Sub Sehen wir uns nun den VBA-Code etwas genauer an. Über den Makro-Ausführen-Dialog starten Sie nun den Aufrufmakro Monatskalender, der die Form zur Anzeige bewegt. In der Initialisierungs-Prozedur auf der neuen UserForm frmMonatskalender, welche beim Aufruf der Form automatisch ausgeführt wird, werden die Monate und Jahre aufbereitet und den ComboBoxen übergeben, sodass Sie diese bei dem angezeigten Dialog auswählen können. D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 6 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Wird nun die Schaltfläche cmdOK angeklickt, wird im Formmodul die Prozedur cmdOK_Click() ausgeführt, die die Datumstabelle erzeugt. Das aktuell gewählte Jahr wird nun der ComboBox (mit cmbJahr.value) entnommen, wie auch der gewünschte Monat. Der Variant-Variable wird ein Array der Wochentage zugewiesen, die wir dann weiter unten benötigen. Nun wird die Tabelle mit Set objTable …. erzeugt, mit 8 Zeilen und 7 Spalten. Die erste Zeile (die das Datum enthält) wird nun mit Cells.Merge so verbunden, das nur eine Zeile ohne Spalten erstellt wird. Dann werden in einer For-Schlaufe alle Wochentage in die Spalten der zweiten Zeile abgefüllt (aus Array extrahiert). In einer nächsten Schlaufe werden dann die Tage in die Zellen abgefüllt und am Ende die tabelle noch formatiert. ! Eine Besonderheit in der Enwicklungsumgebung ist die Möglichkeit ein Code zu debuggen, sprich ihn zeilenweise abarbeiten zu lassen um mitverfolgen zu können, was der laufende VBA-Code gerade anstellt. Mit der Taste F9 setzen sie an einem beliebigen Punkt einen Haltepunkt worauf die Codeausführung dort gestoppt wird. Mit der Taste F8 können Sie nun Schrittweise durch den Code fahren und beobachten was dieser im Dokument anstellt. Man kann auch mit der Maus über Variablen fahren und sieht gleich welchen Wert zB. eine Stringvariable oder ein Integer-Wert inne hat. Im untenstehenden Beispiel sehen wir den Wert der Integer-Variable intMonth= 12! Wer dieses Werkzeug versteht, hat mit der Zeit so richtig Spass daran, Makros zu schreiben, da diese Programmiersprache Visual basic for Application eine Menge an Kompfor zu bieten hat. Makroroutinen, welche immer wieder benötigt werden, wie zB. unsere Suchen/Ersetzen-Funktion die wir oben beschrieben haben, lassen sich in portierbare VBA-Module unterbringen, sodass wir diese Prozeduren in allen VBA-Projekten wieder einsetzen können. D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 7 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Ko n t ex t m en u - E in b in d u n g Leider lassen sich in Office 2010 die Kontextmenüs nicht mehr mit VBA allein anpassen. Hierzu ist eine integrierte XML-Datei notwendig, die mit Hilfe eines Gratis-Tool CustomUIEditor (unter dem Weblink: http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2009/08/06/7293.aspx downloadbar > OfficeCustomUIEditorSetup.zip!) erstellt und implementiert werden kann. Die XML-Datei darf nur bearbeitet werden, wenn die Quell-Dotm-Word-Datei geschlossen ist, da diese XML-Datei beim Speichern in die hier im CustomUIEditor geöffnete Dotm-Datei integriert wird. Die hier vorliegende Makrovorlage W14Makroprogrammierung.dotm-Datei enthält den oben abgebildeten XMLCode, der insgesamt 7 Contextmenüs abdeckt, sodass wir auch wenn wir auf eine Grafik mit einem Rechtsklick das Kontextmenü öffnen der Inhaltsverzeichnis-Makro aufgerufen werden kann. Der Einstiegsmakro befindet sich im Hauptmodul mdlmakros und sieht folgendermassen aus: Sub InhaltsverzeichnisAnzeigen(control As IRibbonControl) InhaltAnzeigen End Sub ' Kontextmenü-Aufruf (integrierte XML-Datei) S ca n n e rb il d ei n f ü g en Im AddIn von W14DlgOpen.Dotm wurde ein Makroaufruf mit einer Schaltfläche im Register [Einfügen] hinzugefügt, über welches man Direkt auf den Scanner zugreifen und Bilder einfügen kann. Hierzu wurde in der XML-Datei folgender Code hinzugefügt: <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab idMso="TabInsert"> <group id="Scannen" label="Scannen" insertAfterMso="GroupInsertIllustrations"> <button id="btnScannen" label="Bild von Scanner holen" onAction="InsertFromScanner" imageMso="OmsCustomizeLayout" size="large" supertip="Bild von Scanner holen" screentip="Scannen" /> D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 8 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] </group> </tab> </tabs> </ribbon> </customUI> Der Makro hierzu sieht folgendermassen aus: In Excel sieht der Makro etwas anders aus: ' Scanner-Bild-Einfügen In Register [Einfügen] anzeigen Public Sub InsertFromScanner(control As IRibbonControl) On Error Resume Next WordBasic.InsertImagerScan End Sub ' Scanner-Bild-Einfügen In Register [Einfügen] anzeigen Public Sub InsertFromScanner(control As IRibbonControl) SendKeys "%EGS" End Sub Habe Sie einen Scanner installiert, wird beim Aufruf dieses Makros die Twain-Schnittstelle aktiviert und der eingerichtete Scanner wird angezeigt. Über [Einfügen anpassen] kann der Scannbereich definiert werden. Wiederverw endbarer Code In diesem Abschnitt widme ich mich verschiedenen Makroprozeduren, die immer wieder in VBA-Projekten benötigt werden. Im nächsten Beispiel zeige ich die Möglichkeit einer Sortierroutine, welche auch in anderen Office-Applikationen, wie zB. in Excel oder Powerpoint verwendet werden kann. So rt ie r- F u n k t io n f ü r VB A Leider gibt es in der VBA-Entwicklungsumgebung keine Sortierfunktion, man muss diese selber implementieren. Es gibt einen Haufen von Lösungen, die wir im Internet finden, mit Vor und Nachteilen. Da ich schon länger mit VBA programmiere habe ich schon vor über 10 Jahren eine Funktion geschrieben, welche eine Sortierung eines Arrays vornimmt und dieses als Resultat zurückgibt. Es gibt immer wieder Projekte, in welchem Listenfelder-Werte sortiert angezeigt werden sollen. Mit der untenstehenden Funktion ist dies kein Problem mehr. Kopieren Sie diese Funktion in ein VBA-Modul und schon lassen sich Arrays sortieren und über diese Funktion gleich auf einem Listencontrol (Comboboxen oder Listenfenster) ausgeben. Wer den Code genauer analysiert, wird feststellen, das ich das ADODB-Objekt virtuell instanziere um Werte zu sortieren. Dies funktioniert auch mit tausenden von Datensätzen sehr schnell und zuverlässig. Details, wie diese Funktion zu gebrauchen ist kann dem nachfolgendem Beschreib entnommen werden. '/-----------------------------------------------------------------------------------------------------------'/ Autor: disi@gmx.ch Erstellt: 16.03.03 Update: 19.06.03 Version 1.00 ¦ '/ ¦ '/ Zweck: Sortiert ein als Argument übergebenes eindim. Datenarray mit ADODB! Wird die maximale Grösse der ¦ '/ zu sortierenden Records nicht angegeben (lohnt sich bei tausenden von Records), ermittelt diese ¦ '/ Sortierroutine selbständig den grössten Wert und verwendet dies dann bei der ADODB-Sortierung! ¦ '/ Mit dieser dynamischen Grössenanpassung können somit auch sehr lange Zeichenketten noch akzep¦ '/ tabel umsortiert werden. ¦ '/ ¦ '/ Ausg.: Standardmässig gibt diese Funktion ein sortiertes Array der als Parameter angebenen Arraydaten ¦ '/ zurück. Durch die optionale Angabe eines Listencontrols (ComboBox, ListBox etc) oder sogar eines ¦ '/ Textfeld-Controlelementes (TextBox, RTFText etc.) kann eine ausgeführte Sortierung gleich in das ¦ '/ angegebene Control ausgegeben werden (spart Zeit und zusätzlichen Ausgabecode!). ¦ '/ ¦ '/ Arg.1: Ein eindim. zu sortierendes Variant-Array wird als ByVal übergeben (Tastet Urarray nicht an!) ¦ '/ Das Array wird sortiert und als Funktionsrückgabe erhalten wir eine sortierte Kopie der Daten. ¦ '/ ¦ '/ Arg.2: Mit Hilfe dieses optionalen Argumentes können wir das sortierte Ergebnis gleich in ein Listen¦ '/ Box-Control einfügen lassen (DropDown, CommandBarComboBox etc.)! ¦ '/ ¦ '/ Arg.3: Dieses Argument zeigt nur Wirkung, wenn ein Listencontrol angegeben wurde und kann entweder ein ¦ '/ Integer-Wert sein oder eine Strinzeichenkette. Hier können wir einen Index vorgeben, nachdem ¦ '/ die sortierten Daten im Listencontrol vorhanden sind. ¦ '/ ¦ D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 9 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/ Arg.4: Mit einem True-Wert kann hier anstatt aufsteigend (Standard) absteigend sortiert werden. ¦ '/ ¦ '/ Arg.5: Ab einigen tausend Datensätzen bringt die Angabe der längste Stringzeichenkette enorm viel ¦ '/ Geschwindigkeitsvorteile, da die Längen- (automat.) -Berechnung nicht durchgeführt werden muss. ¦ '/-----------------------------------------------------------------------------------------------------------Public Function ArraySortAusgabe(SortArrayObjekt As Variant, Optional Optional Optional Optional lstObjListe, _ VorgabeIndex As Variant, _ bolAbsteigendSortieren As Boolean = False, _ MaxZeichenlaenge As Variant) Dim objRecordSet As Object ' ADODB.Recordset ' Object Dim SortArray As Variant ' Sortierarray-Kopie Dim strTextBox As String ' Textfeld-Ausgabezeichenkette Dim lngMaxLen As Long ' Anzahl der längsten Strings im Array Dim lngLen As Long ' Hilfsvariable für Längenscan '/---------------------------------- ADODB VIRTUELLE SORTIERUNG ---------------------------------------------On Error GoTo SortAbbruch intLstExist = -1 intTypAusgabe = 0 intIndex = -1 If IsMissing(VorgabeIndex) = False Then varVorgabe = VorgabeIndex Else varVorgabe = "" End If ' Bei Fehler unsortierte ' Funktionsrückgabe! ' Keine Ausgabe in Liste oder Textfeld SortArray = SortArrayObjekt If UBound(SortArray) > 0 Then ' Sortierarray abfüllen lngMaxLen = -1 ' Grösse der Sortierelemente initial. If IsMissing(MaxZeichenlaenge) = False Then ' Bei X-Tausenden von Datensätzen lngMaxLen = MaxZeichenlaenge ' kann mit Angaben der höchsten ZeichenElse ' anzahl in einem der Records Speed For intV = 0 To UBound(SortArray) ' herausgeholt werden, da dann diese lngLen = Len(SortArray(intV)): If lngLen > lngMaxLen Then lngMaxLen = lngLen Next ' nicht noch zuerst durchlaufen werden lngMaxLen = Iif(lngMaxLen = -1, 512, lngMaxLen) ' müssen (für automatischen Betrieb) End If Set objRecordSet = Nothing Set objRecordSet = CreateObject("ADODB.RecordSet") ' ADODB-Zugriffsobjekt With objRecordSet ' wird instanziert und .Fields.Append "rstSort", 200, lngMaxLen ' eine Feld "rstSort" .Open ' adVarChar = 200 ' wird virtuell erzeugt! For intV = 0 To UBound(SortArray) ' Sortierdaten aufnehmen .AddNew objRecordSet!rstSort = SortArray(intV) .Update ' und in Feld speichern Next .Sort = "[rstSort]" ' Nun wird RecordSet sort. intZ = 0 If IsMissing(lstObjListe) = False Then lstObjListe.Clear: intLstExist = 1 intP = IsMissing(lstObjListe) If intP = False Then If lstObjListe.ListCount > 0 Then lstObjListe.Clear End If If bolAbsteigendSortieren = False Then ' Anhand des optionalen Sortier-Arg. .MoveFirst ' Record-Cursor an den Beginn setzen Else .MoveLast ' Record-Cursor ans Ende setzen End If Do While Not Iif(bolAbsteigendSortieren = False, .EOF, .BOF) ' Je nach Sortierrichtung SortArray(intZ) = .Fields("rstSort").value ' diese in Ergebnis-Array zuweisen If IsMissing(lstObjListe) = False Then If SortArray(intZ) <> "" Then strControlTyp = TypeName(lstObjListe) ' Bei Textboxen Ausgabe mit Enter! Select Case strControlTyp Case "ComboBox", "ListBox", "CommandBarComboBox", "CommandBarPopUp" lstObjListe.AddItem SortArray(intZ) ' Sort. Werte in Liste abfüllen intTypAusgabe = 1 Case "TextBox", "RTFControl", "CommandBarButton" strTrenner = Iif(intZ = .Counts, "", vbCrLf) strTextBox = strTextBox & SortArray(intZ) & strTrenner intTypAusgabe = 2 End Select If varVorgabe <> "" Then ' das angegebene Listenfeld-Control! If TypeName(varVorgabe) = "String" Then If UCase(varVorgabe) = UCase(SortArray(intZ)) Then intIndex = lstObjListe.ListCount - 1 Else If Val(varVorgabe) = intZ Then intIndex = intZ End If End If End If End If intZ = intZ + 1 If bolAbsteigendSortieren = False Then ' Bei auf/absteigender Aufbereitung .MoveNext ' Nächster Datensatz Else .MovePrevious ' Vorheriger Datensatz End If Loop .Close ' RecordSet-Objekt schliessen If intTypAusgabe = 1 Then If intLstExist = 1 And intIndex <> -1 And varVorgabe <> "" Then _ lstObjListe.ListIndex = intIndex Else If intTypAusgabe = 2 Then lstObjListe = strTextBox ' Standardeigenschaft des Textfeldes End If End With Set objRecordSet = Nothing ' RecordSet-Objekt zerstören Else D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 10 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] If IsEmpty(SortArray) = False Then If IsMissing(lstObjListe) = False Then lstObjListe.Clear If SortArray(0) <> "" And IsMissing(lstObjListe) = False Then lstObjListe.AddItem SortArray(0) If IsMissing(VorgabeIndex) = False Then If UCase(SortArray(0)) = UCase(VorgabeIndex) Then lstObjListe.ListIndex = 0 End If End If End If ArraySortAusgabe = SortArray ' und Sortarray zurückgeben! Exit Function ' Bei Fehler virtuelles ReSortAbbruch: Set objRecordSet = Nothing ' cordset wieder entfernen! ' Bei Fehler unsortierte Daten! ArraySortAusgabe = SortArray Application.StatusBar = "Fehler in ADODB-Sortiertroutine: " & Err.Description On Error GoTo 0 ' Errormeldung ignorieren End Function So rt ie ru n g mit d em C o ll e ct io n - O b je kt Public Function Sortierung(arrSort As Variant) As Variant Dim intZ As Long Dim mySortArray As Object Dim myZielSort As Variant Set mySortArray = CreateObject("System.Collections.ArrayList") For intZ = 0 To UBound(arrSort) mySortArray.Add arrSort(intZ) Next ' Werte In Collection aufnehmen mySortArray.Sort ' Collection Sortieren ReDim myZielSort(UBound(arrSort)) For intZ = 0 To UBound(arrSort) myZielSort(intZ) = mySortArray(intZ) Next ' Ergebnis-Array abfüllen Sortierung = myZielSort ' Sortiertes Array zurückgeben mySortArray.Clear ' Collection leeren Set mySortArray = Nothing End Function ' und löschen E rmö g l ic h t Au t o v erv o ll st än d ig u n g b e i Co mb o B o x '/-----------------------------------------------------------------------------------------------------------'/ Autor: daniel Deckensattl Email: disi@gmx.ch Erstellt: 30.12.2014 Update: 30.12.2014 Ver. 1.00 ¦ '/ ¦ '/ Zweck: Dieser KeyUp-Routine ermöglicht eine Autovervollständigung bei einer ComboBox. ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub ComboBox1_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) Static NoSelectText As String Dim i As Long With If If If If ComboBox1 KeyCode = KeyCode = KeyCode = KeyCode = vbKeyUp Then Exit Sub vbKeyDown Then Exit Sub vbKeyLeft Then Exit Sub vbKeyRight Then Exit Sub If KeyCode <> vbKeyBack Then NoSelectText = Mid(.Text, 1, Len(.Text) - .SelLength) Else If NoSelectText <> "" Then NoSelectText = Mid(NoSelectText, 1, Len(NoSelectText) - 1) End If End If For i = 0 To .ListCount - 1 If Ucase(NoSelectText) = _ Ucase(Mid(.List(i), 1, Len(NoSelectText))) Then .ListIndex = i Exit For End If Next .SelStart = Len(NoSelectText) .SelLength = Len(.Text) If .ListIndex = -1 Then .Text = "" .BackColor = vbWhite Else .BackColor = vbWindowBackground End If End With End Sub W in w o rd Do ku me n t v ar i ab l e s et z en / l es en Dokumentvariablen sind eine feine Sache, da wir hier Informationen mit einer maximalen Länge von 255 Zeichen unsichtbar in ein beliebiges Worddokument schreiben und wieder lesen können. Mit der hier beschriebenen Funktion ein Kinderspiel. D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 11 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/-----------------------------------------------------------------------------------------------------------'/ Autor: disi@gmx.ch Erstellt: 01.04.03 Update: 07.05.03 Version 1.00 ¦ '/ ¦ '/ Zweck: Setzt oder liest einen Dokumentvariableninhalt eines gewünschten Zieldokumentes ¦ '/ ¦ '/ Mit DocVariable "Geschlecht", "männlich" schreiben wir in die Dokumentvariable ¦ '/ Mit strWertVonVariable = DocVariable("Geschlecht") lesen wir die Variable wieder aus ¦ '/-----------------------------------------------------------------------------------------------------------Private Function DocVariable(strDocname, Optional strDocInhalt, Optional strZielDokument) Dim int_OK As Integer Dim ZielDoku As Document Set ZielDoku = ActiveDocument ' Vorgängig auf aktuelles Dokument setzen If IsMissing(strZielDokument) = False Then ' Wurde ein Zieldoku. angegeben dann .... For intZ = 1 To Application.Documents.Count ' Dokument suchen und wenn gefunden setzen If UCase(Application.Documents(intZ).Name) = UCase(strZielDokument) Then Set ZielDoku = Application.Documents(intZ): Exit For Next End If With ZielDoku.Variables int_OK = -1 For intZ = 1 To .Count If UCase(.Item(intZ).Name) = UCase(strDocname) Then int_OK = intZ: Exit For End If Next If IsMissing(strDocInhalt) = False Then If int_OK >= 0 Then .Item(int_OK).Value = strDocInhalt Else .Add strDocname, strDocInhalt End If Else If int_OK >= 0 Then DocVariable = .Item(int_OK).Value End If End If End With End Function T ext m a rk en l e sen / s ch re ib en Wer Informationen in einen Textmarkenbereich schreiben möchte, und ihn wieder auslesen ist mit dieser Funktion bestens bedient. Der Textmarkenname bleibt nach dem Schreiben erhalten! '/---------------------------------------------------------------------------------------------'/ Autor: Daniel Deckensattl Erstellt: 31.10.2014 Update: 31.10.2014 ¦ '/ ¦ '/ Zweck: Setzt oder liest einen Textmarken-Inhalt. Mit nur einem Parameter wird gelesen, ¦ '/ und mit zwei Parameter In die Textmarke geschrieben. Der dritte Parameter erstellt ¦ '/ eine neue Textmarke und füllt den Inhalt dort hinein. ¦ '/ ¦ '/ Beispiel Lesen: TextBox1.Text = Bookmark("Titelinfo1") ¦ '/ Beispiel Schreiben: Bookmark "Titelinfo1", TextBox1.Text ¦ '/ Beispiel Schreiben: Bookmark "TitelInfo1", "Textmarkeninhalt", True (Neuerstellen) ¦ '/ Beispiel Schreiben: Bookmark "TitelInfo1", Selection.Range ¦ '/ Beispiel Schreiben: Bookmark "TitelInfo1", Selection.Range, True (Neuerstellen) ¦ '/---------------------------------------------------------------------------------------------Private Function Bookmark(strBookmarkName As String, Optional strNewValue As Variant = "XXXNurLesenXXX", _ Optional bolNewBookmark As Boolean = False) Dim myRange As Range ActiveDocument.Application.ScreenUpdating = False On Error Resume Next With ActiveDocument.Bookmarks If strNewValue = "XXXNurLesenXXX" Then strText = "" If .Exists(strBookmarkName) = True Then strText = .Item(strBookmarkName).Range End If Bookmark = strText Else If bolNewBookmark = True Then With ActiveDocument.Bookmarks .Add Range:=Selection.Range, Name:=strBookmarkName .DefaultSorting = wdSortByName .ShowHidden = False End With End If If .Exists(strBookmarkName) = True Then Application.DisplayAutoCompleteTips = True strZ = strNewValue.ComputeStatistics(Statistic:=wdStatisticCharacters) If IsEmpty(strZ) = False Then Selection.Copy Set myRange = .Item(strBookmarkName).Range myRange.Select myRange.Paste Else Set myRange = .Item(strBookmarkName).Range myRange = strNewValue End If myRange.Select .Add Range:=Selection.Range, Name:=strBookmarkName End If End If End With D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 12 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] ActiveDocument.Application.ScreenUpdating = True ActiveDocument.Application.ScreenRefresh End Function W ö rt e rb u ch u m B eg ri f f e e rw eit e rn '/-------------------------------------------------------------------------------------------------'/ Einfache Wörterbucherweiterung. Nimmt selektierten Text und schreibt diesen In Custom.Dic! ¦ '/-------------------------------------------------------------------------------------------------Sub WoerterbuchErweitern() Dim nDoc As Document Dim oRange As Range benutzer = Environ("USERNAME") Wort = Selection.Text If len(Wort) > 1 Then oPfad = "C:\Users\" & benutzer & "\AppData\Roaming\Microsoft\UProof\" 'anpassen Set nDoc = Documents.Open(oPfad & "Custom.Dic") 'ggf. Namen des Wörterbuchs anpassen nDoc.Activate Set oRange = nDoc.Range oRange.Paragraphs.Add oRange.Paragraphs.Last.Range.InsertBefore Wort nDoc.Close wdSaveChanges End if End Sub Sprache rudimentär ermittlen '/-----------------------------------------------------------------------------------------------------------'/ Anhand der im aktiven Worddokument befindlichen Spracheinstellung (Selection.LanguageID) könnte die ¦ '/ Dialogbeschriftungssprache dokumentenbezogen ermittelt werden (kann erwünscht sein). Anhand des einge¦ '/ stellte Systemdatums wird mit einem Monatsnamen-Vergleich die Sprache hier festgelegt! ¦ '/ (LanguageID = [Englisch (US) 1033] [Deutschweiz(1031) Deutschland(2055)] [Franz 3082] [Spanisch (US) 4108]¦ '/ [Italien(Schweiz 2064) & (Italien 1040)] könnte mit einer Case-Anweisung ermittelt werden! ¦ '/-----------------------------------------------------------------------------------------------------------Public Function DokumentSprache() Dim strMt As Variant, datMt As Variant datMt = "01.01." & Format(Now, "yyyy") strMt = Format(datMt, "mmmm") Select Case strMt Case "January" DokumentSprache = 3 Case "Januar" DokumentSprache = 4 Case "Gennaio" DokumentSprache = 5 Case "Janiver" DokumentSprache = 6 Case "Gennaia" DokumentSprache = 7 Case Else DokumentSprache = 3 End Select End Function ' Englisch (US) ' Deutsch ' Italienisch ' Franz ' Spanisch ' sonst Englisch Al l e F eld e r a kt u al is ie re n '/-----------------------------------------------------------------------------------------------------------'/ Aktualisiert alle Felder im aktuellen Dokument (Kopfzeile, Hauptbereich, Fusszeile und Textfelder!) ¦ '/-----------------------------------------------------------------------------------------------------------Sub AlleFelderMitTextfeldernAktualisieren() Dim rngDoc As Range Dim oDoc As Document Dim docSec As Section Dim oHF As HeaderFooter Dim shp As Shape Set oDoc = ActiveDocument For Each docSec In oDoc.Sections For Each oHF In docSec.Headers For Each shp In oHF.Shapes With shp.TextFrame If .HasText Then .TextRange.Fields.Update End If End With Next shp Next oHF For Each oHF In docSec.Footers For Each shp In oHF.Shapes With shp.TextFrame If .HasText Then .TextRange.Fields.Update End If End With Next shp Next oHF For Each rngDoc In oDoc.StoryRanges rngDoc.Fields.Update While Not (rngDoc.NextStoryRange Is Nothing) Set rngDoc = rngDoc.NextStoryRange rngDoc.Fields.Update Wend D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 13 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Next rngDoc Next docSec Set rngDoc = Nothing Set oDoc = Nothing End Sub In h alt sv e rz ei ch n i s ak t u a li si e re n m it T ab u l at o re rh a lt '/-----------------------------------------------------------------------------------------------------------'/ Prozedur: InhaltsverzeichnisAktualisieren() Erstellt: 09.12.14 Uppdate: 09.12.14 Version: 1.00 ¦ '/ ¦ '/ Zweck: Diese Makroroutine sucht im aktiven Dokument nach einem Inhaltsverzeichnis und aktualisiert ¦ '/ dieses mit Beibehaltung der Tabulatoreinstellung und kehrt zum Ausgangspunkt zurück! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub InhaltsverzeichnisAktualisieren() If ActiveDocument.TablesOfContents.Count = 0 Then Exit Sub Application.ScreenUpdating = False ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:="TempInhaltsverzeichnisAktual" For intZ = 1 To ActiveDocument.TablesOfContents.Count ActiveDocument.TablesOfContents(intZ).Range.Select Selection.MoveLeft Unit:=wdCharacter, Count:=1 intTabPos = PointsToCentimeters(Selection.ParagraphFormat.TabStops(2).Position) ActiveDocument.TablesOfContents(intZ).Update arrInhalt = Split(ActiveDocument.TablesOfContents(intZ).Range.Text, vbCr, -1, vbTextCompare) intInhaltCount = UBound(arrInhalt) For intD = 1 To intInhaltCount Selection.ParagraphFormat.TabStops(CentimetersToPoints(intTabPos)).Position = CentimetersToPoints(intTabPos) Selection.MoveDown Unit:=wdLine, Count:=1 Next Next With ActiveDocument If .Bookmarks.Exists("TempInhaltsverzeichnisAktual") = True Then .Bookmarks("TempInhaltsverzeichnisAktual").Select .Bookmarks("TempInhaltsverzeichnisAktual").Delete End If End With Application.ScreenUpdating = True End Sub Au t o t e xt - Ein t r äg e an z eig en / h in z u f ü g e n Dieser Makro benötigt die unten beschriebene TastenStatus(..) – Funktion. Bei Aufruf wird AutotextAuswahldialog von Word angezeigt. Mit gedrückter Shifttaste wird der Autotext-Hinzufügen-Dialog angezeigt! '/---------------------------------------------------------------------------------------------------------------------'/ Zeigt den Autotext-Einfüg-Dialog von Word. Bei gedrückter Shifttaste wird Neuer Autotext - Dialog angezeigt ¦ '/ Benötigt die Funktion TastenStatus(..)! ¦ '/---------------------------------------------------------------------------------------------------------------------Public Sub AutotextAnzeigenNeu() If TastenStatus(vbKeyShift) = False Then Application.Dialogs(wdDialogBuildingBlockOrganizer).Show Else Application.Dialogs(wdDialogCreateAutoText).Show End If End Sub M arki e rt ab C u r so rp o sit io n b i s u n d m it g e su ch t em W o rt '/---------------------------------------------------------------------------------------------------------------------'/ Markiert ab Cursorposition bis und mit gesuchtem Wort ¦ '/---------------------------------------------------------------------------------------------------------------------Private Function MarkierenBisZuEinemWort(strBisZumWort As String) Dim strZielwort As String Dim lngStart As Long Dim lngEnd As Long lngStart = Selection.Start lngEnd = Selection.End With Selection.Find .Forward = True .ClearFormatting .MatchWholeWord = True .MatchCase = False .Wrap = wdFindContinue .Execute FindText:=strBisZumWort End With If lngEnd >= Selection.End Then MsgBox "nach der selectierten Stelle das Suchwort: ActiveDocument.Range(lngStart, lngEnd).Select Exit Function End If " & strZielwort & " nicht gefunden!" ActiveDocument.Range(lngStart, Selection.End).Select End Function D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 14 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] H yp e rl in ks i m Do ku m en t en t f e rn en '/---------------------------------------------------------------------------------------------------------'/ Hyperlinks im aktuellen Dokument entfernen ¦ '/---------------------------------------------------------------------------------------------------------Sub NoHyperlinks() Dim x As Variant For Each x In ActiveDocument.Hyperlinks Selection.WholeStory Selection.Range.Hyperlinks(1).Delete Next x End Sub Dr u c k e ak t u e ll e W o rd se it e '/---------------------------------------------------------------------------------------------------------'/ Drucken aktuelle Word-Seite ¦ '/---------------------------------------------------------------------------------------------------------Sub DruckenAktuelleSeite() On Error Resume Next Application.PrintOut FileName:="", Range:=wdPrintCurrentPage, _ Item:=wdPrintDocumentContent, Copies:=1, Pages:="", _ PageType:=wdPrintAllPages, Collate:=True, _ Background:=True, PrintToFile:=False End Sub Dr u c k e ak t u e ll e M ark ie ru n g ei n e s W o r d d o ku m en t e s '/---------------------------------------------------------------------------------------------------------'/ Drucken aktuelle Markierung eines Word-Dokumentes ¦ '/---------------------------------------------------------------------------------------------------------Sub DruckenMarkierung() On Error Resume Next Options.PrintReverse = True Application.PrintOut FileName:="", Range:=wdPrintSelection, _ Item:=wdPrintDocumentContent, Copies:=1, Pages:="", _ PageType:=wdPrintAllPages, Collate:=True, _ Background:=True, PrintToFile:=False End Sub Dr u c k en v o n 2 S eit en p r o Bl at t '/---------------------------------------------------------------------------------------------------------'/ Drucken 2 Seiten pro Blatt ¦ '/---------------------------------------------------------------------------------------------------------Sub Drucken_2_Seiten_pro_Blatt() On Error Resume Next Options.PrintReverse = False Application.PrintOut FileName:="", _ Range:=wdPrintAllDocument, _ Item:=wdPrintDocumentContent, Copies:=1, Pages:="", _ PageType:=wdPrintAllPages, Collate:=True, _ Background:=True, PrintToFile:=False, _ PrintZoomColumn:=2, PrintZoomRow:=1, _ PrintZoomPaperWidth:=0, _ PrintZoomPaperHeight:=0 End Sub Dr u c k en v o n 4 S eit en p r o Bl at t '/---------------------------------------------------------------------------------------------------------'/ Drucken 4 Seiten pro Blatt ¦ '/---------------------------------------------------------------------------------------------------------Sub Drucken_4_Seiten_pro_Blatt() On Error Resume Next With Options .UpdateFieldsAtPrint = True .UpdateLinksAtPrint = False .DefaultTray = "Druckereinstellungen verwenden" .PrintBackground = True .PrintProperties = False .PrintFieldCodes = False .PrintComments = False .PrintHiddenText = False .PrintDrawingObjects = True .PrintDraft = False .PrintReverse = False .MapPaperSize = False End With With ActiveDocument .PrintPostScriptOverText = False .PrintFormsData = False End With Application.PrintOut FileName:="", _ Range:=wdPrintAllDocument, _ Item:=wdPrintDocumentContent, Copies:=1, Pages:="", _ PageType:=wdPrintAllPages, Collate:=True, _ Background:=True, PrintToFile:=False, _ PrintZoomColumn:=2, PrintZoomRow:=2, _ D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 15 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] PrintZoomPaperWidth:=11907, _ PrintZoomPaperHeight:=16839 End Sub Je d e W o rd se it e in e i n n eu es D o ku m en t st el le n '/---------------------------------------------------------------------------------------------------------'/ Dieses Beispiel speichert jede einzelne Seite des aktiven WORD-Dokumentes in ein neues WORD-Dokument ab ¦ '/---------------------------------------------------------------------------------------------------------Public Sub Dim Dim Dim JedeSeiteInNeuesDokument() wdDoc As Document wdDocNeu As Document wdBereich As Range ' Aktives Dokument ' Neues Dokument ' Dokument-Bereich Dim sPfad As String Dim optAnsicht As Long ' Pfadangabe für neue Dokumente ' Dokumentansicht Dim iSeitenAnz As Integer Dim i As Integer Dim iDocNum As Integer ' Anzahl der Seiten im Dokument ' Zähler ' Zähler für Dateiname Set wdDoc = ActiveDocument ' Verweis auf Dokument setzen: 'Speicher-Pfad für neue Dokumente: 'Es wird vorausgesetzt, dass das aktive Dokument gespeichert ist sPfad = wdDoc.Path & "\" & "Test_" 'Bildschirmaktualisierung deaktivieren (Flackern wird zumindest vermindert) Application.ScreenUpdating = False 'Einstellung Seiten-Ansicht sichern: 'optAnsicht = wdDoc.ActiveWindow.View.Type optAnsicht = Windows(wdDoc).View.Type Windows(wdDoc).View.Type = wdPageView ' Seiten-Ansicht SeitenLayout einstellen: wdDoc.Range(0, 0).Select ' Cursor zum Anfang des Dokuments: 'Browser-Eigenschaft einstellen, hier: "Nach Seite durchsuchen" 'Gibt ein Browser-Objekt zurück, das die Schaltfläche "Objekt für 'Durchsuchen markieren" auf der vertikalen Bildlaufleiste darstellt Application.Browser.Target = wdBrowsePage iDocNum = 0 ' Dokument-Nr. zum Speichern - Startwert setzen 'Anzahl Seiten im Dokument ermitteln iSeitenAnz = wdDoc.ComputeStatistics(wdStatisticPages) For i = 1 To iSeitenAnz 'Verweis auf den zu kopierenden Bereich setzen Set wdBereich = wdDoc.Bookmarks("\Page").Range 'Den zu kopierenden Bereich überprüfen, ob Seitenwechsel dabei ist; 'ggf. den Bereich verkleinern If Right(wdBereich.Text, 1) = Chr(12) Then wdBereich.SetRange Start:=wdBereich.Start, End:=wdBereich.End - 1 End If 'Neues Dokument öffnen, auf Basis derselben Dokumentvorlage 'wie das Original-Dokument Set wdDocNeu = Documents.Add(Template:=wdDoc.AttachedTemplate.FullName) 'oder auf Basis der Normal.dot: 'Set wdDocNeu = Documents.Add 'Formatierten Text -> neue Datei wdDocNeu.Content.FormattedText = wdBereich.FormattedText 'Dokument-Nr. zum Speichern erhöhen iDocNum = iDocNum + 1 'Neues Dokument speichern: wdDocNeu.SaveAs FileName:=sPfad & Format(iDocNum, "000") 'Neues Dokument schließen wdDocNeu.Close 'Dokument aktivieren wdDoc.Activate 'Zur nächsten Seite im Original-Dokument wechseln Application.Browser.Next Next i 'Ursprüngliche Seiten-Ansicht wieder einstellen Windows(wdDoc).View.Type = optAnsicht 'Cursor zum Anfang des Dokuments wdDoc.Range(0, 0).Select 'Bildschirmaktualisierung aktivieren Application.ScreenUpdating = True 'Verweise freigeben Set wdBereich = Nothing Set wdDocNeu = Nothing Set wdDoc = Nothing End Sub D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 16 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] S ch rif t en li st e e rst e ll en '/-----------------------------------------------------------------------------------------------------------'/ Erstellt in Word eine Liste aller Schriften ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub SchriftenlisteErstellen() Selection.InsertAfter "Ausdruck der verfügbaren Schriftarten" + String$(2, 13) Selection.Paragraphs.Alignment = wdAlignParagraphCenter With Selection.Font .Size = 18 .Bold = True .Italic = True End With Selection.Collapse direction:=wdCollapseEnd Set Tabelle = ActiveDocument.Tables.Add(Selection.Range, 1, 2) Tabelle.Cell(1, 1).SetWidth ColumnWidth:=InchesToPoints(2), RulerStyle:=wdAdjustNone Selection.InsertAfter "Schriftart" Tabelle.Cell(1, 2).SetWidth ColumnWidth:=InchesToPoints(4), RulerStyle:=wdAdjustNone Tabelle.Cell(1, 2).Range.InsertAfter "Beispiel in Schriftgröße 12" Beispiel = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz € ÄäÖöÜüߧ0123456789" _ + Chr$(34) + Chr$(132) + Chr$(147) + "@#$%&?!*" Anzahl = FontNames.Count - 1 Redim Schrift(Anzahl) For z = 0 To Anzahl Schrift(z) = FontNames(z + 1) Next For x = 0 To Anzahl Selection.Tables(1).Rows.Add Tabelle.Cell(x + 2, 1).Range.InsertAfter Schrift(x) Tabelle.Cell(x + 2, 2).Range.InsertAfter Beispiel With Tabelle.Cell(x + 2, 2).Range.Font .Name = Schrift(x) .Size = 12 End With Next x FontCounter = "Anzahl der installierten Schriften: " + CStr(Anzahl) Selection.EndKey Unit:=wdStory Selection.MoveDown Unit:=wdLine, Count:=1 Selection.TypeParagraph Selection.TypeText Text:=FontCounter End Sub W o rd - W o rt li st e in E x ce l e rs t e ll en '/-----------------------------------------------------------------------------------------------------------'/ Erstellt eine sortierte Word-Häufigkeitswortliste in einer neuen Excel-Arbeitsmappe ¦ '/-----------------------------------------------------------------------------------------------------------Sub XLWortListeGenerieren() Dim objActDoc As Document Dim objWort As Range Dim strWort As String Dim intI As Integer Dim blnVorhanden As Boolean Dim colWörter As New Collection Dim colHäufigkeiten As New Collection Dim vntWert As Integer Dim objXL As Object If Documents.Count = 0 Then MsgBox Prompt:="Es ist kein Dokument geöffnet.", Title:="Wortliste generieren" End End If System.Cursor = wdCursorWait Set objActDoc = ActiveDocument For Each objWort In objActDoc.Words strWort = Trim(objWort.Text) If Len(strWort) > 1 Then If Asc(strWort) > 31 Then If Val(strWort) = 0 Then For intI = 1 To colWörter.Count blnVorhanden = False If LCase(colWörter(intI)) = LCase(strWort) Then blnVorhanden = True vntWert = colHäufigkeiten(intI) colHäufigkeiten.Add Item:=vntWert + 1, _ Before:=intI colHäufigkeiten.Remove intI + 1 Exit For End If Next If blnVorhanden = False Then colWörter.Add Item:=strWort colHäufigkeiten.Add Item:="1" End If End If End If End If Next D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 17 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] System.Cursor = wdCursorNormal If colWörter.Count > 0 Then Set objXL = CreateObject("Excel.Application") If objXL Is Nothing Then MsgBox "Excel kann nicht gestartet werden." End End If With objXL .Visible = True .Workbooks.Add With .ActiveSheet .Columns("A:A").NumberFormat = "@" .Columns("B:B").NumberFormat = "General" With .Cells(1, 1) .value = "Wortliste: " & objActDoc.Name .Font.Size = 12 .Font.Bold = True End With For intI = 1 To colWörter.Count .Cells(intI + 1, 1) = colWörter(intI) .Cells(intI + 1, 2) = colHäufigkeiten(intI) Next .UsedRange.Select End With .Selection.Sort Key1:=.Range("A2"), Order1:=1, Header:=1 End With MsgBox Prompt:="Wortliste mit " & CStr(colWörter.Count) & _ " Einträgen in neuer Excel-Arbeitsmappe gespeichert.", _ Buttons:=vbInformation, Title:="Wortliste generieren" Set objXL = Nothing End If End Sub De- Ak t iv i e rt H yp e r lin k- Ak t iv ie ru n g Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer '/---------------------------------------------------------------------------------------------------------------------'/ Deaktiviert die Hyperlink-Aktivierung beim Eingeben einer Emailadresse oder URL. Mit gedrückter Shifttaste wird ¦ '/ Option wieder aktiviert >> Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer ¦ '/---------------------------------------------------------------------------------------------------------------------Sub HyperlinkAktivierungOnOff() With Options .AutoFormatAsYouTypeReplaceHyperlinks = TastenStatus(vbKeyShift) .AutoFormatReplaceHyperlinks = TastenStatus(vbKeyShift) End With End Sub '/---------------------------------------------------------------------------------------------------------------------'/ Funktion: TastenStatus Erstellt: 1.7.01 Update: 26.10.01 Version: 1.10 ¦ '/ Argument: APITastenKonstante Typ: Long ' vbKey.... - Konstante, wie vbKeyShift, vbKeyControl ¦ '/ Rückgabe: Boolean-Wert ' Wahr wenn Taste gedrückt ist, False wenn nicht! ¦ '/ ¦ '/ Über diese Funktion erhalten wir von einer gewünschten Keyboard-Taste dess Zustand (gedückt) wenn wir die ¦ '/ gewünschte Taste als VB-Konstanten-Argument dieser Funktion übergeben (häufig sind vbKeyControl/.KeyMenu)! ¦ '/ ¦ '/ erfordert: Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer ¦ '/---------------------------------------------------------------------------------------------------------------------Public Function TastenStatus(API_VB_TastenKonstante As Long) As Boolean TastenStatus = Cbool(GetAsyncKeyState(API_VB_TastenKonstante) And &H8000) End Function ' ermittelt Tastenstatus ' oder Maustastenstatus! G en au Ru n d e n , a u ch au f 5 R ap p en '/-------------------------------------------------------------------------------------------------'/ Rundet einen angegenen Double-Wert auf eine bestimmte Anzahl Nachkomma-Stellen und auf den ¦ '/ nächsten Rundungsfaktor. Dies ist vor allem hilfreich beim Rechnen mit Franken-Beträgen ¦ '/ ¦ '/ Beispiele: ¦ '/ ¦ '/ Runden(+1.22556 , 2 , 5 ) >>> 1.25 ¦ '/ Runden(+1.22556 , 2 , 1 ) >>> 1.23 ¦ '/ Runden(+1.22556 , 3 , 10) >>> 1.230 ¦ '/ Runden(-1.32712 , 2 , 5 ) >>> 1.35 ¦ '/ ¦ '/-------------------------------------------------------------------------------------------------Public Function Runden(pdblValue As Double, Optional plngStellen As Long = 2, Optional plngRunden As Long = 1) As String Dim dblReturn As Long Dim lngDifferenz As Long Dim intVorzeichen As Long '/*--- Vorzeichen ermitteln und anschliessen alles mit Absolutwert berechnen intVorzeichen = Sgn(pdblValue) '/*--- Wert so umwandeln, dass keine Kommastelle mehr vorhanden ist dblReturn = Abs(CLng(pdblValue * 10 ^ plngStellen)) '/*--- Differenz zum nächsten Rundungsschritt ermitteln lngDifferenz = (dblReturn Mod plngRunden) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 18 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/*--- Wenn Differenz kleiner als die Hälfte des Rundungsschrittes, dann abrunden, sonst aufrunden dblReturn = dblReturn + Iif(lngDifferenz < (plngRunden / 2), -lngDifferenz, plngRunden - lngDifferenz) '/*--- Wert richtig gerundet und formatiert zurück geben (Vorzeichen wieder hinzufügen) Runden = Format(intVorzeichen * dblReturn / 10 ^ plngStellen, "0." & String(plngStellen, "0")) End Function VB ( A) - Co d e in HT M L 4. 0 u mw an d e ln '/-----------------------------------------------------------------------------------------------------------'/ Autor: disi@gmx.ch Erstellt: 08.09.03 Update: 08.11.04 Version 1.00 ¦ '/ ¦ '/ SubFnc: Dieser Makro benutzt die Subroutine [SuchTausch(..)] um Suchbegriffe im Text auszutauschen ¦ '/ ¦ '/ Zweck: Dieser Wordmakro konvertiert einen farbigen VB.NET-Sourcecode In ein HTML-4.0-Textformat. Das ¦ '/ Ergebnis wird In <pre>...</pre> - Tags eingebettet um im Dreamweaver dann einfügen zu können. ¦ '/ ¦ '/ Ein VB.ET-Source In einem aktiven Worddokument wird hier so umgewandelt, dass VB.NET-Anweisungen ¦ '/ In hellblauer Farbe, Remarkzeilen mit hellgrüner Farbe und die Grundschrift-Farbe In weiss einge- ¦ '/ stellt wird. Alle Wordoptionen die hier umgestellt werden, werden am Ende wieder zurüchgestellt¨ ¦ '/ wie der autom. Leerzeichen-Ausgleich beim Ersetzen, die Apostroph-Autokorrektur, usw.! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub VBNETCode2HTML40() Dim myAdata As Variant, myBdata As Variant, myCdata As Variant, myDdata As Variant, bolFound As Boolean Dim strAdat As String, strBdat As String, strDocName As String, strGrundfarbe As String Dim intZ As Integer, strZ As String, strAusgabe As String, myWordCFg(2) As Variant Dim intRemarks As Integer, strFarbeTag01 As String, strFarbeTag02 As String, bolAllSelect As Boolean '-- Bildschirmaktualisierung während dem Austausch abschalten Application.ScreenUpdating = False If Selection.Paragraphs.Count = 1 Then ' Kein Text selektiert Selection.WholeStory ' dann alles selektieren End If intP = Selection.Paragraphs.Count ' Zähle anzahl Absätze Selection.MoveLeft Unit:=wdCharacter, Count:=1 ' Gehe Ein Zeichen nach Links For intZ = 1 To intP ' Alle Absätze durchsuchen Selection.Find.ClearFormatting With Selection.Find .Text = "^p" .Replacement.Text = "" .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = True .MatchWholeWord = True .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute ' Such auslösen Selection.MoveLeft Unit:=wdCharacter, Count:=1 Selection.HomeKey Unit:=wdLine, Extend:=wdExtend intP = Selection.Characters.Count If intP = 1 And Selection.Text = vbCr Then Selection.Text = " " End If Selection.EndKey Unit:=wdLine Selection.MoveRight Unit:=wdCharacter, Count:=1 Next Selection.MoveLeft Unit:=wdCharacter, Count:=1 strSE = Chr(34): bolAllSelect = False '-- Grundschriftfarbe, Aweisungsfarbe und Remarkfarbe gleich zu Beginn festlegen strFarbeStart = "<pre style=" + strSE + "FONT-SIZE: 9pt; FONT-FAMILY: Fixedsys,Courier,monospace" + strSE + _ "><FONT COLOR=" + strSE + "#FFFFFF" + strSE + " FACE=" + strSE + "Courier New" + strSE + _ " SIZE=" + strSE + "2" + strSE + "></font><br>" ' Einleitungsformat strFarbeTag01 = "<FONT COLOR=" + strSE + "#00FFFF" + strSE + ">" ' Aweisungs-Farbe strFarbeTag02 = "<FONT COLOR=" + strSE + "#00FF00" + strSE + ">" ' Remark-Farbe strGrundfarbe = "<FONT COLOR=" + strSE + "#FFFFFF" + strSE + ">" ' Grundschriftfarbe '-- Änderunge die dieser Makro an den Wordoptionen vornimmt sichern und am Ende wiederherstellen '-- Leerzeichenausgleich abschalten, auch Apostroph-Ersetzung und Bindestrich-Ersetzung myWordCFg(0) = Options.PasteAdjustWordSpacing myWordCFg(1) = Options.AutoFormatAsYouTypeReplaceQuotes myWordCFg(2) = Options.AutoFormatAsYouTypeReplaceSymbols Options.PasteAdjustWordSpacing = False Options.AutoFormatAsYouTypeReplaceQuotes = False Options.AutoFormatAsYouTypeReplaceSymbols = False '-- Alle VisualBasic-Befehle die im folgenden Array sind werden blau eingefärbt '-- Erst werden alle blau einzufärbenden Befehle gesucht und mit HTML-1.0-Farbtags ausgestattet strAdat = "For,Next, If,Then,Else,True,False,UBound,LBound,While,Wend,Boolean,Variant,Long,Byte,Integer," strAdat = strAdat + "String, Trim, Asc,Finaly,Select Case,End Select, Nothing, Each, vbCr,vbCrLf, & ,Step" strAdat = strAdat + "End Class, End Enum,End Function,End Sub,End With,End Try,End Select,End If,Enum ,ByVal" strAdat = strAdat + "Nothing,Optional ,Return , And, Or , New,Try,Catch,On Error Resume,Property,Declare" strAdat = strAdat + "Array,Dim,Public,Private,Exit,Imports ,Namespace ,Class,Inherits , As ,Friend , Instr" strAdat = strAdat + "Len, Mid,If,Class,End,With,Case,Function,Sub,On Error GoTo,Split,Cbool,Option Explicit" strAdat = strAdat + "Range,Set ,Exit Sub,Exit Function,Do ,Loop,End Select,Ucase,LCase,Replace,Replace, To " strAdat = strAdat + "Property,End Property,Const,Exit Do,Exit For,Exit Sub, End Sub,Object,Collection" strAdat = strAdat + "Option Explicit,Not,Is" '-- alle auszutauschenden Begriffe erst sammeln und dann In Array spitzen und Ersetzen starten myAdata = Split(strAdat, ",", -1, vbBinaryCompare) '-- Ausgags-Selektion als Bookmark merken, wenn nichts markiert wurde vorgängig alles Selektieren If Len(Selection.Text) < 2 Then Selection.WholeStory: bolAllSelect = True D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 19 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Selection.Font.Name = "Courier New" Selection.Font.Size = 6 If bolAllSelect = True Then Selection.HomeKey Unit:=wdStory: Selection.WholeStory With ActiveDocument.Bookmarks .Add Range:=Selection.Range, Name:="ASCII2FlashHTML10SelBeginn" .DefaultSorting = wdSortByName .ShowHidden = False End With '-- Zuerst beim Original-Text die Sonderzeichen alle ersetzen SuchTausch "<", "<", True, True, True, True SuchTausch ">", ">", True, True, True, True '-- Änderungen In alle Remark-Zeilen suchen und nach Begrifftausch wieder zurückstellen If Len(Selection.Text) > 1 Then myCdata = Split(Selection.Text, vbCr, -1, vbBinaryCompare) Else myCdata = Split(ActiveDocument.Range.Text, vbCr, -1, vbBinaryCompare) End If '-- Jetzt werde alle VB-Befehle (VBA,VB und VB.NET) blau eingefärbt For intZ = 0 To UBound(myAdata) SuchTausch myAdata(intZ), "</font>" + strFarbeTag01 + myAdata(intZ) + "</font>" + _ strGrundfarbe, True, True, True, True Next Selection.GoTo What:=wdGoToBookmark, Name:="ASCII2FlashHTML10SelBeginn" '-- Änderungen In alle Remark-Zeilen suchen und nach Begrifftausch wieder zurückstellen If Len(Selection.Text) > 1 Then myDdata = Split(Selection.Text, vbCr, -1, vbBinaryCompare) Else myDdata = Split(ActiveDocument.Range.Text, vbCr, -1, vbBinaryCompare) End If '-- Bei auftretenden Remarkzeilen wird nur immer bei der ersten Zeile grün zugewiesen strAusgabe = "" intRemarks = 0 For intZ = 0 To UBound(myCdata) - 1 strZ = Trim(myDdata(intZ)) If Len(strZ) > 1 Then '-intApoPos = Instr(2, strZ, "'", vbBinaryCompare) '-- Eine nur Remarkzeile hat ach einem Trim Einleitungszeichen als 1. Zeichen If Mid(strZ, 1, 1) = Chr(39) Then If myDdata(intZ) <> myCdata(intZ) Then myDdata(intZ) = myCdata(intZ) '-- Remark-Farbtag vor Remarkzeile setzen If intRemarks = 0 Then myDdata(intZ) = "</font>" + strFarbeTag02 + myDdata(intZ) intRemarks = intRemarks + 1 Else '-- Bei Remarkzeilen steht grüer Farbtag vor Zeile, bei Änderungen zurückstelle If intApoPos > 0 Then intApoPos = Instr(Len(myDdata(intZ)) - Len(strZ) + 1, myDdata(intZ), "'", vbBinaryCompare) myDdata(intZ) = Left(myDdata(intZ), intApoPos - 1) + "</font>" + strFarbeTag02 + _ Right(myDdata(intZ), Len(myDdata(intZ)) - (intApoPos - 1)) + "</font>" + strGrundfarbe Else If intRemarks > 0 Then myDdata(intZ) = "</font>" + strGrundfarbe + myDdata(intZ) End If End If intRemarks = 0 End If End If ' -- jetzt noch alle Enters ersetzen entweder durch <br> oder <P ALIGN="Left"> strAusgabe = strAusgabe + myDdata(intZ) + "<br>" ' vbCr dann lesbarer Next '-- Ergebnis nun im Dokument ausgeben (alter Bookmark wird autom. gelöscht, daher Neusetzen) Selection.GoTo What:=wdGoToBookmark, Name:="ASCII2FlashHTML10SelBeginn" Selection.Text = vbCrLf + vbCrLf + vbCrLf With ActiveDocument.Bookmarks .Add Range:=Selection.Range, Name:="ASCII2FlashHTML10SelBeginn" .DefaultSorting = wdSortByName .ShowHidden = False End With '-- Drei Leere Enters wurden eingefügt und Cursor wird nun In die Mitte positioniert Selection.MoveLeft Unit:=wdCharacter, Count:=1 Selection.MoveDown Unit:=wdLine, Count:=1 Selection.Text = strFarbeStart + strAusgabe + "</pre>" '-- Nachdem der konvertierte Text ausgegeben wurde, Doppelspurige Farb-Tags entfernen Selection.GoTo What:=wdGoToBookmark, Name:="ASCII2FlashHTML10SelBeginn" strDoppelte = "<FONT COLOR=" + strSE + "#FFFFFF" + strSE + "></font><FONT COLOR=" + _ strSE + "#00FFFF" + strSE + ">" SuchTausch strDoppelte, strFarbeTag01, True, True, True, True '-- Erster und letzter unnötiger Absatz wieder entfernen Selection.Characters(1).Delete Selection.GoTo What:=wdGoToBookmark, Name:="ASCII2FlashHTML10SelBeginn" Selection.Characters(Len(Selection)).Delete '-- Leerzeichen-Ausgleich wieder zurückstellen Options.PasteAdjustWordSpacing = myWordCFg(0) Options.AutoFormatAsYouTypeReplaceQuotes = myWordCFg(1) Options.AutoFormatAsYouTypeReplaceSymbols = myWordCFg(2) Application.ScreenUpdating = True ActiveWindow.ActivePane.VerticalPercentScrolled = 0 End Sub D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 20 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 08.11.02 Update: 08.11.04 Version 1.00 ¦ '/ ¦ '/ Zweck: Tauscht einen Suchbegriff durch einen anderen aus und per optionalen Arg. bedienbar. Diese sehr ¦ '/ universal gehaltene Arbeitsroutine wird von diversen Wordmakros verwendet. ¦ '/-----------------------------------------------------------------------------------------------------------Private Function SuchTausch(ByVal Suchbegriff As String, Optional ByVal Ersetzen As String = "_DefaultValueNoSettig_ThisArg", _ Optional ByVal bolNachUntenSuchen As Boolean = True, Optional ByVal bolWeitersuchen As Boolean = True, _ Optional ByVal bolWortSuche As Boolean = True, Optional ByVal bolGrossKleinBuchstabe As Boolean = False) As Boolean Selection.Find.ClearFormatting With Selection.Find .Text = Suchbegriff .Replacement.Text = Ersetzen .Forward = bolNachUntenSuchen If bolWeitersuchen = True Then .Wrap = wdFindContinue Else .Wrap = wdFindStop End If .Format = False .MatchCase = bolGrossKleinBuchstabe .MatchWholeWord = bolWortSuche .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With If Ersetzen <> "_DefaultValueNoSettig_ThisArg" Then SuchTausch = Selection.Find.Execute(Replace:=wdReplaceAll) Else SuchTausch = Selection.Find.Execute End If End Function Ak t u a li si e rt n u r Ref - F el d e r Manchmal ist es nur nötig, wenn die REF-Felder aktualisert werden müssen '/-----------------------------------------------------------------------------------------------------------'/ Aktualisiert auf Wunsch nur REF-Felder ¦ '/-----------------------------------------------------------------------------------------------------------Sub REFAktualisierung() On Error Resume Next Dim f As Field For Each f In ActiveDocument.Fields If f.Type = 3 Then f.Update Next f End Sub ' 3=wdFieldRef S ca n n e r- E in b in d u n g au ch mit W i n w o rd 2 0 13 '/---------------------------------------------------------------------------------------------------------------------'/ Scannt ein Bild und speichert temporär im Profilverzeichnis des Anwenders und fügt dies In das aktuelle Dokument ¦ '/---------------------------------------------------------------------------------------------------------------------Public Sub Scanner(control As IRibbonControl) Scannen End Sub ' Makroaufruf für Ribbon-XML-Datei (AddIn) Public Sub Scannen() Dim objWiaImg As Object Dim strDateiname On Error GoTo Abbruch Set objWiaDlg = CreateObject("WIA.CommonDialog") strDateiname = Environ("USERPROFILE") & "\Test.jpg" Set objWiaImg = objWiaDlg.ShowAcquireImage On Error Resume Next If Not objWiaImg Is Nothing Then If Dir(strDateiname) <> "" Then Kill strDateiname objWiaImg.SaveFile strDateiname Set MyDocument = ActivePresentation.Slides(1) Selection.InlineShapes.AddPicture FileName:=strDateiname, LinkToFile:=False, SaveWithDocument:=True Set MyDocument = Nothing End If Set objWiaDlg = Nothing Exit Sub Abbruch: MsgBox "Kein Scanner erreichbar", vbCritical, "Scanner fehlt" End Sub S er i en d ru ck i n ei n z e l n e Do ku men t e s p e ic h er n D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 21 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/-----------------------------------------------------------------------------------------------------------'/ Zweck: Diese Prozedur speichert Seriendruckdokumente einzel ab und schliesst sie. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub Seriendruck_in_getrennte_Dateien() Dim iBrief As Integer, sBrief As String On Error GoTo Fehler Application.Visible = False With ActiveDocument.MailMerge .DataSource.ActiveRecord = 1 Do .Destination = wdSendToNewDocument .SuppressBlankLines = True With .DataSource .FirstRecord = .ActiveRecord .LastRecord = .ActiveRecord sBrief = "C:\DeinPfad\" & .DataFields("Nachname").Value & "_" & .DataFields("Vorname").Value & ".docx" End With .Execute Pause:=False ActiveDocument.SaveAs FileName:=sBrief ActiveDocument.Close False If .DataSource.ActiveRecord < .DataSource.RecordCount Then .DataSource.ActiveRecord = wdNextRecord Else Exit Do End If Loop End With Fehler: Application.Visible = True End Sub D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 22 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Window s-Funktionen nutzen Windows besitzt eine Unmenge von API-Funktionen, über welche Dialoge von Windows aufgerufen werden können, Programme gestartet und beendet werden, Kopierfunktionen, Löschfunktionen, welche auch in VBA genutz werden können, usw.! Sehen wir uns nun ein paar wertvolle Routinen an, die es in sich haben. T ast e n st at u s ab f r ag e n Eine besonders hilfreiche Funktion die ich immer wieder in VBA-Projekten einsetze ist die Tastenstatus-Abfragefunktion TastenStatus(..) die es mir ermöglicht, festzustellen ob ein Anwender während einer Makroausführung die Umschaltaste (vbKeyShift) oder die Alt-Taste (vbKeyMenu) gedrückt hält. So sind Doppel-und Dreifachbelegungen möglich. Am Beginn, also im Kopfbereich eines VBA-Modules wird die API-Funktion deklariert, welche dann in der Funktion TastenStatus abgefragt wird und feststellt welche Taste gedrückt wurde. Wie die obige Abbildung zeigt können fast alle Tasten abgefragt werden, ob diese gedrückt werden. Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer Im VBA-Modul wird TastenStatus und ein Leerzeichen angegeben und über die Ctrl/Leertaste-Kombination kann dann eine vbKey….-Konstante ausgewählt werden. Im mittleren Teil dieser Gesamtdokumntation werde ich AddIn-Projekte vorstellen, in denen diese hier beschriebenen Funktionen zum Einsatz kommen. '/--------------------------------------------------------------------------------------------------------------'/ Funktion: TastenStatus Erstellt: 1.7.01 Update: 26.10.01 Version: 1.20 ¦ '/ Argument: APITastenKonstante Typ: Long ' vbKey.... - Konstante, wie vbKeyShift, vbKeyControl ¦ '/ Rückgabe: Boolean-Wert ' Wahr wenn Taste gedrückt ist, False wenn nicht! ¦ '/ ¦ '/ Dies ist die erste nach Aussen offene Hilfsfunktion, die in allen VBA-Projekten bequem über einen Klassenver-¦ '/ weis und Aufruf abgerufen werden kann. In diesem Beispiel kann der aktuelle Tastenabfragestatus einer als vb-¦ '/ Konstante übergebenen Taste (zb vbKeyShift) ermittelt werden. Es wird ein Wahrheitswert zurückgegeben! ¦ '/ ¦ '/ erfordert: Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer ¦ '/--------------------------------------------------------------------------------------------------------------Public Function TastenStatus(APITastenKonstante As Long) As Boolean ' ermittelt Tastenstatus TastenStatus = CBool(GetAsyncKeyState(APITastenKonstante) And &H8000) ' oder Maustastenstatus! End Function P au sen ein b in d en In manchen VBA-Projekten sind Pausen notwendig, also der Code eine Weile warten muss bis es weiter geht. Hierzu existiert eine hilfreiche Funktion die ohne API-Deklaration auskommt, wie folgt beschrieben. Optional kann ein Wahrheitswert (True oder False, also Wahr oder Falsch) angegeben werden, ob Windows im Hintergrund weiter aktiv sein soll. '/--------------------------------------------------------------------------------------------------------------'/ Eine Wartepause (in Sekunden) um die Einfach/Doppelklick-Unterscheidung ermittelbar zu machen, etc.! ¦ '/--------------------------------------------------------------------------------------------------------------Private Function Timing(Zeit As Variant, Optional bolDoEvent As Variant) Dim intDoEvent As Integer, Start As Variant ' Lokale Variablen definieren intDoEvent = Iif(IsMissing(bolDoEvent) = False, 0, 1) Start = Timer ' Startzeit speichern Do If intDoEvent = 0 Then DoEvents If Timer < Start Then Zeit = Zeit - 86400 ' Mitternachtskorrektur Loop Until (Timer - Start > Zeit) End Function T emp o rä r e r Pf ad e rm it t e ln Es gibt Situationen, wo wir eine Datei im temporären Pfad ablegen müssen um dann wieder eingelesen werden zu können. So lassen sich auch grössere Dateien von Winword zu Excel verschieben oder zu anderen Programmen. Das System liefert uns den Temporärpfad den wir immer mit Schreibrechten nutzen können. Public Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long '/---------------------------------------------------------------------------------------------------------------------'/ Die Funktion ermittelt den Temp-Pfad des Systems (per API-Funkt. GetTempPath(..)) ¦ '/---------------------------------------------------------------------------------------------------------------------- D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 23 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Public Function GetTempPfad() As String Dim strPath As String * 255 Dim lTempPathLength As Long lTempPathLength = GetTempPath(255, strPath) GetTempPfad = Left(strPath, lTempPathLength - 1) End Function Und auch hier gilt es die API-Deklaration zuoberst im VBA-Modul (Formmodul, Klassenmodul oder VB-Modul) zu deklarieren, hingegen die GetTempPfad-Routine kann beliebig stehen. Ben u t z e r- N am e Anhand des Benutzernamens können Entscheidungen in einem Makro getroffen werden, die äusserst wichtig sind. Daher hier diese Hilfsfunktion Public Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long '/--------------------------------------------------------------------------------------------------------------'/ Diese Funktion ermittelt den am System angemeldeten Benutzer-Login-Name ¦ '/--------------------------------------------------------------------------------------------------------------Public Function BenutzerLogin() Dim strBuffer As String * 25, lngResultat As Long lngResultat = GetUserName(strBuffer, 25) BenutzerLogin = Left$(strBuffer, InStr(strBuffer, Chr(0)) - 1) End Function P ro f ilv e rz ei ch n i s v o n an g e me ld et en B en u t z er '/---------------------------------------------------------------------------------------------------------'/ Liefert das Profil-Verzeichnis des angemeldeten Benutzer: ¦ '/---------------------------------------------------------------------------------------------------------Public Function GetUserProfilDirectory() GetUserProfilDirectory = Environ("USERPROFILE") End Function Co mp u t e r- N am e Der Name des Computers kann auch hilfreich sein, wenn im Makro diese Informationen benötigt werden. Public Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long '/--------------------------------------------------------------------------------------------------------------'/ Die Funktion ermittelt den Computer-Namen ¦ '/--------------------------------------------------------------------------------------------------------------Public Function GetComputerInfo() As String Dim lngResult As Long Dim strInfo As String strInfo = Space$(256) lngResult = GetComputerName(strInfo, Len(strInfo)) If InStr(strInfo, Chr$(0)) > 0 Then _ strInfo = Left$(strInfo, InStr(strInfo, Chr$(0)) - 1) GetComputerInfo = strInfo End Function Dr u c k er n a me n e rmi t t eln '/---------------------------------------------------------------------------------------------'/ Autor: Daniel Deckensattl Erstellt: 20.01.2010 Update: 20.01.2010 ¦ '/ ¦ '/ Zweck: List alle am System vorhandenen Druckernamen aus, als Ergebnis erhalten wir zB.: ¦ '/ Name: Microsoft XPS Document Writer ¦ '/ Name: FreePDF ¦ '/ Name: FAX ¦ '/ Name: Brother PC-FAX v.3.2 ¦ '/ Name: Brother MFC-J870DW Printer ¦ '/ Name: An OneNote 2010 senden ¦ '/---------------------------------------------------------------------------------------------Sub DruckerModelle() strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_Printer", , 48) For Each objItem In colItems Debug.Print "Name: " & objItem.Name Next End Sub PC - Um g e b u n g sv a r ia b len er mit t e ln '/-----------------------------------------------------------------------------------------------------------'/ Diese Funktion liest den Umgebungsvariablen-Speicher des Betriebsystems aus und sucht nach einer MSDOS¦ '/ Set-Variable zum Beispiel COMPUTERNAME=Disi_PC und gibt diesen Wert als Zeichenkette der Funktion zurück. ¦ '/ ¦ '/ Beispiele ¦ '/ ALLUSERSPROFILE=C:\ProgramData ¦ D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 24 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/ APPDATA=C:\Users\Disi\AppData\Roaming ¦ '/ CLASSPATH=.;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip ¦ '/ CommonProgramFiles=C:\Program Files (x86)\Common Files ¦ '/ CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files ¦ '/ CommonProgramW6432=C:\Program Files\Common Files ¦ '/ COMPUTERNAME = Disi_PC ¦ '/ ComSpec=C:\Windows\system32\cmd.exe ¦ '/ FP_NO_HOST_CHECK = NO ¦ '/ HOMEDRIVE = c: ¦ '/ HOMEPATH=\Users\Disi ¦ '/ INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\SDK\v1.1\include\ ¦ '/ LIB=C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\SDK\v1.1\Lib\ ¦ '/ LOCALAPPDATA=C:\Users\Disi\AppData\Local ¦ '/ LOGONSERVER=\\DISI_PC ¦ '/ NUMBER_OF_PROCESSORS = 4 ¦ '/ OS = Windows_NT ¦ '/ Path=C:\Program Files (x86)\Microsoft Office\Office14\;C:\Program Files (x86)\PC Connectivity Solution\; ¦ '/ PROCESSOR_ARCHITEW6432 = AMD64 ¦ '/ PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 42 Stepping 7, GenuineIntel ¦ '/ PROCESSOR_LEVEL = 6 ¦ '/ PROCESSOR_REVISION=2a07 ¦ '/ ProgramData=C:\ProgramData ¦ '/ ProgramFiles=C:\Program Files (x86) ¦ '/ ProgramFiles(x86)=C:\Program Files (x86) ¦ '/ ProgramW6432=C:\Program Files ¦ '/ PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ ¦ '/ PUBLIC=C:\Users\Public ¦ '/ QTJAVA=C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip ¦ '/ SESSIONNAME = Console ¦ '/ SystemDrive = c: ¦ '/ SystemRoot=C:\Windows ¦ '/ TEMP=C:\Users\Disi\AppData\Local\Temp ¦ '/ TMP=C:\Users\Disi\AppData\Local\Temp ¦ '/ USERDOMAIN = Disi_PC ¦ '/ UserName = Disi ¦ '/ USERPROFILE=C:\Users\Disi ¦ '/ VBOX_INSTALL_PATH=C:\Program Files\Oracle\VirtualBox\ ¦ '/ VS71COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\Common7\Tools\ ¦ '/ WecVersionForRosebud 0.1598 = 4 ¦ '/ windir=C:\Windows ¦ '/ windows_tracing_flags = 3 ¦ '/ windows_tracing_logfile=C:\BVTBin\Tests\installpackage\csilogfile.log ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub ErmittleMSDOSVariablen() MsgBox ErmittleUmgebungsVariable("OS") End Sub Public Function ErmittleUmgebungsVariable(VariabelName) Dim UmgZF, Indx, Mldg, PfadLänge, SetName Indx = 1: GetName = "": SetName = VariabelName & "=" LenVarName = Len(VariabelName) + 1 Do UmgZF = Environ(Indx) If Len(UmgZF) >= Len(UmgZF) Then If Left(UmgZF, LenVarName) = SetName Then w = Len(UmgZF) U = InStr(1, UmgZF, "=", 1) GetName = Right(UmgZF, w - U) Exit Do Else Indx = Indx + 1 End If Else Indx = Indx + 1 End If Loop Until UmgZF = "" ErmittleUmgebungsVariable = Trim(GetName) End Function ' Kommt ohne API aus! ' Variablen deklarieren. ' Variablen-Initialisierung ' Umgebungsvariable ' Eintrag prüfen. ' Länge bestimmen. ' Kein PATH-Eintrag, ' also hochzählen. ' Kein PATH-Eintrag, ' Gefundener Wert zurüchgeben W in d o w s- V e rs io n e r mit t el n '/--------------------------------------------------------------------------------------------------------------'/ Diese Funktion liefert auf rudimentärste Weise die aktuelle Windows-Familienversion 98/NT/W2000/W7! ¦ '/ Testen mit: MsgBox WindowsVersion ¦ '/--------------------------------------------------------------------------------------------------------------Public Function WindowsVersion() As String Select Case True Case Len(Environ$("OS")) = 0 WindowsVersion = "Win9x" Case Len(Environ$("PROGRAMFILES")) = 0 WindowsVersion = "WinNT" Case Else sText = Environ$("OS") pText = Environ$("PROGRAMFILES") If sText = "Windows_NT" And pText = "C:\Program Files (x86)" Then WindowsVersion = "Windows 7" Else WindowsVersion = "Win2000" End If End Select End Function Bil d s ch i rm au f lö s u n g er mit t e ln '/---------------------------------------------------------------------------------------------------------'/ Private Declare Function GetSystemMetrics Lib "user32.dll" (ByVal nIndex As Long) As Long ¦ '/ ¦ D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 25 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/ Liefert die aktuelle Bildschirmgrösse des Rechners ¦ '/---------------------------------------------------------------------------------------------------------Public Sub BildschirmaufloesungErmitteln() Dim DisplayResolutionY As Long Dim DisplayResolutionX As Long DisplayResolutionY = GetSystemMetrics(1) DisplayResolutionX = GetSystemMetrics(0) '// 1 = Y Resolution '// 0 = X Resolution Debug.Print DisplayResolutionY & " x " & DisplayResolutionX End Sub In t er n et - E xp lo re r m it U RL an z ei g e n '/---------------------------------------------------------------------------------------------------------'/ Öffnet eine neue Internet-Instanz und lädt gewünschte URL ¦ '/---------------------------------------------------------------------------------------------------------Public Sub InternetExplorerAnzeigen() Dim objApp As Object ' Kreiert eine Explorer-Instanz und macht diese sichtbar On Error GoTo ErrHandler Set objApp = CreateObject("InternetExplorer.Application") With objApp .Visible = True .Navigate URL:="https://www.google.ch" End With ErrHandler: 'Bei Abbruch VBA-Instanz löschen Set objApp = Nothing On Error GoTo 0 End Sub Z w isch en ab l ag e v e rw en d en '/---------------------------------------------------------------------------------------------------------'/ Mit Hilfe dieser Routinen können wir einen beliebigen, als Parameter übergebenen Text in die ¦ '/ Zwischenablage befördern [EinTextZurAblage(Textkopie)] oder zurückermitteln [EinTextVonAblage] ¦ '/---------------------------------------------------------------------------------------------------------Public Function EinTextZurAblage(ObjektInAblage) If TypeName(ObjektInAblage) = "String" Then Clipboard.SetText ObjektInAblage Else Clipboard.SetData ObjektInAblage, 2 End If End Function ' Kopiert Text in Zwischenablage Public Function EinTextVonAblage() If Clipboard.GetFormat(1) = True Then EinTextVonAblage = Clipboard.GetText(1) Else EinTextVonAblage = "" End If End Function ' Liest Text von Zwischenablage S ch alt ja h r e r mit t el n '/---------------------------------------------------------------------------------------------------------'/ Liefert nach übergebenen Jahr True oder False zurück, ob es ein Schaltjahr ist oder nicht! ¦ '/---------------------------------------------------------------------------------------------------------Function Schaltjahr(Jahreszahl) Schaltjahr = Iif((Jahreszahl Mod 4) = 0 And (Jahreszahl Mod 100) <> 0 Or (Jahreszahl Mod 400) = 0, True, False) End Function Ka le n d erw o c h e e in e s D at u m s e r mit t el n '/-----------------------------------------------------------------------------------------------------------'/ Gibt die Kalenderwoche nach DIN 1355 zurück (zB. strZ = KWoche("04.12.2014")) ¦ '/-----------------------------------------------------------------------------------------------------------Function KWoche(d As Date) As Integer Dim t& t = DateSerial(Year(d + (8 - Weekday(d)) Mod 7 - 3), 1, 1) KWoche = (d - t - 3 + (Weekday(t) + 1) Mod 7) \ 7 + 1 End Function M o n at sl et z t er '/---------------------------------------------------------------------------------------------------------'/ Liefert vom aktuellen Datum den Monatsletzten ¦ '/---------------------------------------------------------------------------------------------------------Function MonatsLetzter() Jahr = Format(Now, "yyyy") Monat = Format(Now, "mm") f = "dd.mm.yyyy" MonatsLetzter = Format(DateSerial(Jahr, Monat + 1, 0), f) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 26 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] End Function O st er n b e re ch n e n '/---------------------------------------------------------------------------------------------------------'/ Ausgehend vom Ostersonntag kann man die Feiertage berechnen: Weitere Feiertage: ¦ '/ ¦ '/ Neujahr = DateSerial(Year(Now), 1, 1) ¦ '/ Maifeiertag = DateSerial(Year(Now), 5, 1) ¦ '/ Karfreitag = Ostern(Year(Now)) - 2 ¦ '/ Ostermontag = Ostern(Year(Now)) + 1 ¦ '/ Himmelfahrt = Ostern(Year(Now)) + 39 ¦ '/ Pfingstsonntag = Ostern(Year(Now)) + 49 ¦ '/ Pfingstmontag = Ostern(Year(Now)) + 50 ¦ '/ Fronleichnam = Ostern(Year(Now)) + 60 ¦ '/ TagDeutscheEinheit = DateSerial(Year(Now), 10, 3) ¦ '/---------------------------------------------------------------------------------------------------------Function Ostern(Yr As Integer) As Date Dim d As Integer d = (((255 - 11 * (Yr Mod 19)) - 21) Mod 30) + 21 Ostern = DateSerial(Yr, 3, 1) + d + (d > 48) + 6 - ((Yr + Yr \ 4 + d + (d > 48) + 1) Mod 7) End Function Ei n f a ch e r Da t u m s ka l en d e r Dieser Kalender kann auch in anderen VBA-Projekten eingesetzt werden, wie zum Beispiel in Excel in einem Spesenformular. '/-----------------------------------------------------------------------------------------------------------'/ Autor: Daniel Deckensattl Erstellt: 08.02.13 Update: 08.02.13 Version 1.00 ¦ '/ ¦ '/ Zweck: Datumauswahl mit einem einfachen Kalender der das ausgewählte Datum im Format 05.02.2013 zurück- ¦ '/ gibt. Die getätigte Datumsauswahl wird im aktuellen Dokument ausgegeben. ¦ '/ Wird ein Doppelklick auf eine Tages-Auswahl getroffen, dann dieses Datum übernehmen, einfügen ¦ '/ und Dialog schliessen. ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub UserForm_Initialize() Dim intI As Integer Dim arrMonthArray As Variant arrMonthArray = Array("Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", _ "August", "September", "Oktober", "November", "Dezember") '-- Alle Monate In DropDown-Box abfüllen und aktueller Monat selektieren For intI = 1 To 12 cmdList02.AddItem arrMonthArray(intI - 1) Next cmdList02.ListIndex = Month(Now) - 1 '-- Alle 200 Jahre In DropDown-Box abfüllen und aktuelles Jahr selektieren For intI = 1900 To 2100 cmdList01.AddItem Format(intI, "####") Next cmdList01.ListIndex = Year(Now) - 1900 '-- Aktueller Tag In entsprechendes Textfeld ausgeben txt01.Text = Format(Day(Now), "00") frmKalender.Caption = "Datumauswahl - [" & Format(Now, "dd.mm.yyyy") & "]" DatumAnzeigen End Sub Private Function DatumAnzeigen() If cmdList01.ListIndex = -1 Then Exit Function ' Datum nun abfüllen intYear = cmdList01.List(cmdList01.ListIndex) intMonth = cmdList02.ListIndex + 1 'vntDayArray = Array("Mo", "Di", "Mi", "Do", "Fr", "Sa", "So") intFirstDay = Weekday(Date:=DateSerial(Year:=intYear, Month:=intMonth, Day:=1), FirstDayOfWeek:=vbMonday) intDayCount = Day(Date:=DateSerial(Year:=intYear, Month:=intMonth + 1, Day:=0)) intY = 1 For intI = 1 To 42 sLabCtrl = "Lab" & Format(intI, "00") If intI >= intFirstDay And intI < (intDayCount + intFirstDay) Then Me.Controls(sLabCtrl) = Format(intY, "00") intY = intY + 1 Else Me.Controls(sLabCtrl) = "" End If Next End Function '/-- Die Taste Abbrechen wurde ausgewählt und fügt kein Datum ein Private Sub cmdBut01_Click() Unload Me D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 27 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] End Sub '/-- Die Jahres-Liste wurde ausgewählt und aktualisiert Datumanzeige Private Sub cmdList01_Change() DatumAnzeigen End Sub '/-- Die Monats-Liste wurde ausgewählt und aktualisiert Datumanzeige Private Sub cmdList02_Change() DatumAnzeigen End Sub '/-- Die Taste einfügen wurde ausgewählt und fügt das Datum In die Parent-Form Private Sub cmdBut02_Click() strDatum = Format(txt01.Text, "00") & "." & Format(cmdList02.ListIndex + 1, "00") & "." & Format(cmdList01.Value, "####") Selection.Text = strDatum End Sub '/-- Nach einem Doppelklick wird ausgewähltes Datum eingefügt, der Fokus weitergereicht und die Sub-Form entladen Private Function Unloader(objEntladen As Object, objTextControl As Object) If objTextControl.Caption <> "" Then txt01.Text = objTextControl.Caption cmdBut02_Click ' frmSpesen.TextBox1.SetFocus Unload objEntladen End If End Function '/-- Klickt ein Anwender auf ein Tag-Text-Control dann diese Nummer In Tagauswahl-Textbox anzeigen Private Sub Lab01_Click() If Lab01.Caption <> "" Then txt01.Text = Lab01.Caption End Sub '/-- Bei einem Doppelklick wird ausgewählter Tag übernommen und '/--dann die Entlade-Routine aufgerufen Private Sub Lab01_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab01 End Sub Private Sub Lab02_Click() If Lab02.Caption <> "" Then txt01.Text = Lab02.Caption End Sub Private Sub Lab02_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab02 End Sub Private Sub Lab03_Click() If Lab03.Caption <> "" Then txt01.Text = Lab03.Caption End Sub Private Sub Lab03_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab03 End Sub Private Sub Lab04_Click() If Lab04.Caption <> "" Then txt01.Text = Lab04.Caption End Sub Private Sub Lab04_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab04 End Sub Private Sub Lab05_Click() If Lab05.Caption <> "" Then txt01.Text = Lab05.Caption End Sub Private Sub Lab05_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab05 End Sub Private Sub Lab06_Click() If Lab06.Caption <> "" Then txt01.Text = Lab06.Caption End Sub Private Sub Lab06_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab06 End Sub Private Sub Lab07_Click() If Lab07.Caption <> "" Then txt01.Text = Lab07.Caption End Sub Private Sub Lab07_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab07 End Sub Private Sub Lab08_Click() If Lab08.Caption <> "" Then txt01.Text = Lab08.Caption End Sub Private Sub Lab08_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab08 End Sub Private Sub Lab09_Click() If Lab09.Caption <> "" Then txt01.Text = Lab09.Caption End Sub Private Sub Lab09_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab09 End Sub Private Sub Lab10_Click() If Lab10.Caption <> "" Then txt01.Text = Lab10.Caption End Sub Private Sub Lab10_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab10 End Sub Private Sub Lab11_Click() If Lab11.Caption <> "" Then txt01.Text = Lab11.Caption End Sub Private Sub Lab11_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab11 End Sub Private Sub Lab12_Click() If Lab12.Caption <> "" Then txt01.Text = Lab12.Caption End Sub Private Sub Lab12_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab12 End Sub Private Sub Lab13_Click() If Lab13.Caption <> "" Then txt01.Text = Lab13.Caption End Sub Private Sub Lab13_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab13 End Sub Private Sub Lab14_Click() If Lab14.Caption <> "" Then txt01.Text = Lab14.Caption End Sub Private Sub Lab14_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab14 End Sub Private Sub Lab15_Click() If Lab15.Caption <> "" Then txt01.Text = Lab15.Caption End Sub Private Sub Lab15_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab15 End Sub Private Sub Lab16_Click() If Lab16.Caption <> "" Then txt01.Text = Lab16.Caption End Sub Private Sub Lab16_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab16 End Sub Private Sub Lab17_Click() If Lab17.Caption <> "" Then txt01.Text = Lab17.Caption End Sub Private Sub Lab17_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab17 End Sub Private Sub Lab18_Click() If Lab18.Caption <> "" Then txt01.Text = Lab18.Caption End Sub Private Sub Lab18_DblClick(ByVal Cancel As MSForms.ReturnBoolean) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 28 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Unloader Me, Lab18 End Sub Private Sub Lab19_Click() If Lab19.Caption <> "" Then txt01.Text = Lab19.Caption End Sub Private Sub Lab19_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab19 End Sub Private Sub Lab20_Click() If Lab20.Caption <> "" Then txt01.Text = Lab20.Caption End Sub Private Sub Lab20_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab20 End Sub Private Sub Lab21_Click() If Lab21.Caption <> "" Then txt01.Text = Lab21.Caption End Sub Private Sub Lab21_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab21 End Sub Private Sub Lab22_Click() If Lab22.Caption <> "" Then txt01.Text = Lab22.Caption End Sub Private Sub Lab22_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab22 End Sub Private Sub Lab23_Click() If Lab23.Caption <> "" Then txt01.Text = Lab23.Caption End Sub Private Sub Lab23_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab23 End Sub Private Sub Lab24_Click() If Lab24.Caption <> "" Then txt01.Text = Lab24.Caption End Sub Private Sub Lab24_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab24 End Sub Private Sub Lab25_Click() If Lab25.Caption <> "" Then txt01.Text = Lab25.Caption End Sub Private Sub Lab25_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab25 End Sub Private Sub Lab26_Click() If Lab26.Caption <> "" Then txt01.Text = Lab26.Caption End Sub Private Sub Lab26_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab26 End Sub Private Sub Lab27_Click() If Lab27.Caption <> "" Then txt01.Text = Lab27.Caption End Sub Private Sub Lab27_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab27 End Sub Private Sub Lab28_Click() If Lab28.Caption <> "" Then txt01.Text = Lab28.Caption End Sub Private Sub Lab28_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab28 End Sub Private Sub Lab29_Click() If Lab29.Caption <> "" Then txt01.Text = Lab29.Caption End Sub Private Sub Lab29_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab29 End Sub Private Sub Lab30_Click() If Lab30.Caption <> "" Then txt01.Text = Lab30.Caption End Sub Private Sub Lab30_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab30 End Sub Deckensattl Daniel [08.01.2015] Private Sub Lab31_Click() If Lab31.Caption <> "" Then txt01.Text = Lab31.Caption End Sub Private Sub Lab31_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab31 End Sub Private Sub Lab32_Click() If Lab32.Caption <> "" Then txt01.Text = Lab32.Caption End Sub Private Sub Lab32_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab32 End Sub Private Sub Lab33_Click() If Lab33.Caption <> "" Then txt01.Text = Lab33.Caption End Sub Private Sub Lab33_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab33 End Sub Private Sub Lab34_Click() If Lab34.Caption <> "" Then txt01.Text = Lab34.Caption End Sub Private Sub Lab34_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab34 End Sub Private Sub Lab35_Click() If Lab35.Caption <> "" Then txt01.Text = Lab35.Caption End Sub Private Sub Lab35_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab35 End Sub Private Sub Lab36_Click() If Lab36.Caption <> "" Then txt01.Text = Lab36.Caption End Sub Private Sub Lab36_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab36 End Sub Private Sub Lab37_Click() If Lab37.Caption <> "" Then txt01.Text = Lab37.Caption End Sub Private Sub Lab37_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab37 End Sub Private Sub Lab38_Click() If Lab38.Caption <> "" Then txt01.Text = Lab38.Caption End Sub Private Sub Lab38_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab38 End Sub Private Sub Lab39_Click() If Lab39.Caption <> "" Then txt01.Text = Lab39.Caption End Sub Private Sub Lab39_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab39 End Sub Private Sub Lab40_Click() If Lab40.Caption <> "" Then txt01.Text = Lab40.Caption End Sub Private Sub Lab40_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab40 End Sub Private Sub Lab41_Click() If Lab41.Caption <> "" Then txt01.Text = Lab41.Caption End Sub Private Sub Lab41_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab41 End Sub Private Sub Lab42_Click() If Lab42.Caption <> "" Then txt01.Text = Lab42.Caption End Sub Private Sub Lab42_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unloader Me, Lab42 End Sub Au s R eg i st r y l es en o d e r in d i es e s ch r eib e n D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 29 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/-----------------------------------------------------------------------------------------------------------'/ Mit Hilfe dieser Funktion werden Einstellungen des Anwenders aus Registry gelesen, bzw. gesetzt! ¦ '/-----------------------------------------------------------------------------------------------------------Public Function RegistryWerte(strRegZweigName, Optional strRegSectionName, Optional strRegKeyName, _ Optional strRegKeyInhalt) As Variant Dim strAntwort As String If IsMissing(strRegKeyInhalt) = True Then ' Nur lesen wenn Parameter fehlt! strAntwort = GetSetting(APPNAME:=strRegZweigName, Section:=strRegSectionName, Key:=strRegKeyName) RegistryWerte = Iif(strAntwort = "", "FALSCH", strAntwort) Else SaveSetting APPNAME:=strRegZweigName, Section:=strRegSectionName, Key:=strRegKeyName, Setting:=strRegKeyInhalt End If End Function L ie f e rt D at e in am e o d er Pf ad '/-----------------------------------------------------------------------------------------------------------'/ Liefert nur den Dateiname (intAktion = 1) oder nur den Pfad, ohne Dateinamen. strPfad=ganzer Dateipfad! ¦ '/-----------------------------------------------------------------------------------------------------------Public Function NurDateiName(strPfad, intAktion) Dim varSplit As Variant If Len(strPfad) < 3 Then NurDateiName = strPfad: Exit Function varSplit = Split(strPfad, "\", -1, vbTextCompare) If intAktion = 0 Then NurDateiName = Left(strPfad, Len(strPfad) - Len(varSplit(UBound(varSplit)))) Else NurDateiName = varSplit(UBound(varSplit)) End If End Function O u t lo o kn a ch ri ch t v e r se n d en '/---------------------------------------------------------------------------------------------------------'/ Dieses Beispiel sendet eine e-Mail über Outlook: ¦ '/---------------------------------------------------------------------------------------------------------Sub Mail_senden() Dim olApp As Object Set olApp = CreateObject("Outlook.Application") With olApp.CreateItem(0) .Recipients.Add "empfaenger@provider.de" ' Empfänger .subject = "Test-Mail" ' Betreff ' Nachricht .body = "Das ist eine e-Mail" & Chr(13) & "Viele Grüße..." & Chr(13) & Chr(13) .ReadReceiptRequested = False .Attachments.Add "c:\Dok1.doc" .Send End With Set olApp = Nothing End Sub ' Lesebestätigung aus ' Dateianhang V erz e ich n i s au sw äh l en Oftmals benötigen wir eine Verzeichnisauswahl, wo wir bestimmte Dateien ablegen oder öffnen wollen. Zuerst die API-Funktionen und Konstanten die im Header (Kopfbereich eines Moduls) hinterlegt werden müssen: Private Declare Function SHBrowseForFolder Lib "shell32.dll" _ Alias "SHBrowseForFolderA" (ByRef lpbi As BROWSEINFO) As Long Private Declare Function SHGetPathFromIDList Lib "shell32.dll" _ Alias "SHGetPathFromIDListA" (ByVal pidl As Long, _ ByVal pszPath As String) As Long Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal pv As Long) Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long Private Type BROWSEINFO hwndOwner As Long pidlRoot As Long pszDisplayName As String lpszTitle As String ulFlags As Long lpFn As Long lParam As String iImage As Long End Type Private Private Private Private Private Const Const Const Const Const MAX_PATH = 259 WM_USER As Long = &H400 BIF_RETURNONLYFSDIRS As Long = 1 BFFM_INITIALIZED As Long = 1 BFFM_SETSELECTION As Long = (WM_USER + 102) Dann die Aufruf-Prozedur: D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 30 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '------------------------------------- Ordnerauswahl ---------------------------------------------Public Function GetFolderInternal(ByVal Caption As String, ByVal Default As String) As String Dim BI As BROWSEINFO Dim ListIdx As Long Dim Path As String With BI .lpszTitle = Caption .ulFlags = BIF_RETURNONLYFSDIRS .lpFn = MakeFktnPtr(AddressOf BrowseCallbackProc) .lParam = Default End With Path = String$(MAX_PATH + 1, vbNullChar) ListIdx = SHBrowseForFolder(BI) If SHGetPathFromIDList(ListIdx, Path) Then GetFolderInternal = Left$(Path, InStr(Path, vbNullChar) - 1) End If CoTaskMemFree ListIdx End Function Public Function BrowseCallbackProc(ByVal hwnd As Long, ByVal Msg As Long, _ ByVal lParam As Long, ByVal lpData As Long) As Long On Error Resume Next If Msg = BFFM_INITIALIZED Then SendMessage hwnd, BFFM_SETSELECTION, 1&, lpData End If End Function Private Function MakeFktnPtr(ByVal FktnPtr As Long) As Long MakeFktnPtr = FktnPtr End Function Aufgerufen wird der hier beschriebene Auswahldialog mit den Zeilen: strExportOrdner = GetFolderInternal("Ordner auswählen", „C:\“) Dat ei su ch e in O rd n e r u n d d es s en Un t e ro r d n e r '/---------------------------------------------------------------------------------------------------------'/ Sucht eine gewünschte Datei In einem Ordner plus dessen Unterordner! ¦ '/ Erfordert API-Funktion: Private Declare Function SearchTreeForFile Lib "imagehlp.dll" ( _ ¦ '/ ByVal RootPath As String, _ ¦ '/ ByVal InputPathName As String, _ ¦ '/ ByVal OutputPathBuffer As String) As Long ¦ '/---------------------------------------------------------------------------------------------------------Private Sub DateiSuche() Dim Retval As Long, TmpStr As String * 256 ' Suche beginnen Retval = SearchTreeForFile("c:\windows", "Chord.wav", TmpStr) If Retval = 0 Then MsgBox "Es wurde keine Datei mit diesem Namen gefunden" Else MsgBox Left$(TmpStr, Instr(1, TmpStr, vbNullChar) - 1), , "Gefundene Datei" End If End Sub An d er e VB A- Ap p l ik at io n en au f ru f en Oft kommt es vor, das wir zum Beispiel aus Winword einen Outlook-Kontakt beziehen wollen, oder von Winword auf eine Excel-tabelle zugreifen möchten. Die hier vorgestellte Routine ermöglicht diesen Applications-Zugriff untereinander Zuerst die Header-konstanten-Deklarationen: Public enuOfficeAppName Public ClientAufrufen As Long As Integer Enum enuOfficeAppName Winword = 1 Excel = 2 Powerpoint = 3 Outlook = 4 Access = 5 Frontpage = 6 Visio = 7 CorelDraw = 8 End Enum Enum enuAppStatus appStatus = 1 appSichtbarStarten appSichtbarMitDoku appUnsichtbStarten appUnsichtbMitDoku appTaskSchliessen End Enum ' ' ' ' ' ' ' ' ' = = = = = Funktion: ..() Winword Excel Powerpoint Outlook Access Frontpage Vision Corel 2 3 4 5 6 Dann die eigentliche Zugriffs-Prozedur: D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 31 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] /-----------------------------------------------------------------------------------------------/ Mit Hilfe dieser Funktion können wir eine globalen Programm-Objektvariabel für eine Office¦ / Komponenten-Instanz mit einem Applicationsverwes einrichten. Als Rückgabecode wird ein ¦ / Application-Objekt der jeweiligen Zugriffsapplikation geliefert. ¦ / ¦ / In die globale Variable appClientPreStatus wird angegeben ob die Instanz noch nicht gelaufen ¦ / ist 1 Der Rückgabewert 0 bedeutet, dass die Appl. schon am Laufen ist, und dieser Task am Ende¦ / nicht beendet werden darf (nur der Verweis wird zerstört). Beim Rückgabewert 1 deutet dass auf¦ / eine neu erstellte Applikationsinstanz hin, auf die über die globale Objekt-Modulvariable ¦ / appClient zugegriffen werden kann. ¦ /-----------------------------------------------------------------------------------------------Enum enuAppStatus appStatus = 1 appSichtbarStarten appSichtbarMitDoku appUnsichtbStarten appUnsichtbMitDoku appTaskSchliessen End Enum As Long = = = = = 2 3 4 5 6 Enum enuOfficeAppName scWinword = 1 scExcel = 2 scPowerpoint = 3 scOutlook = 4 scAccess = 5 scFrontpage = 6 scVisio = 7 scCorelDraw = 8 End Enum ' ' ' ' ' ' ' ' ‘ Funktion: ..() Winword Excel Powerpoint Outlook Access Frontpage Vision CorelDraw '/--------------------------------------------------------------------------------------------------------------'/ Diese Funktion stellt bei Gebrauch einen Zeiger zu der gewünschten Windows-Applikation her, welche für eine ¦ '/ Datenmanipulation genutzt werden möchte (auch nur temporär nutzen!) > siehe Applications-Objekt der Anwendung¦ '/--------------------------------------------------------------------------------------------------------------Private Function ClientInstanz(strApplName As OffAppNamen, bolInstanzAnzeigen As Boolean) As Object Dim obj_appClient As Object On Error Resume Next ' aktiviert. [Berichtauswahl] mit einem zugewiesenen Wert Select Case strApplName Case 1 ClientObjekt = "Word.Application" Case 2 ClientObjekt = "Excel.Application" Case 3 ClientObjekt = "Powerpoint.Application" Case 4 ClientObjekt = "Outlook.Application" Case 5 ClientObjekt = "Access.Application" Case 6 ClientObjekt = "Visio.Application" Case 7 ClientObjekt = "Frontpage.Application" Case 8 ClientObjekt = "CorelDRAW.Application.10" Case Else ClientObjekt = "" Set ClientInstanz = obj_appClient ' Leeres Objekt zurückgeben und aussteigen Exit Function End Select appClientPreStatus = 0 Set obj_appClient = GetObject(, ClientObjekt) If obj_appClient Is Nothing Then On Error GoTo ClientFehler appClientPreStatus = 1 Set obj_appClient = CreateObject(ClientObjekt) If bolInstanzAnzeigen = True Then obj_appClient.Visible = True End If Set ClientInstanz = obj_appClient Exit Function ClientFehler: On Error GoTo 0 ' MsgBox "Word konnte nicht gestartet werden!", vbCritical, "Programmfehler" appClientPreStatus = -1 Set ClientInstanz = obj_appClient End Function Sp e rrt au g en b li c kl ic h d e n Re ch n e r mit An me ld es ch ir m '/---------------------------------------------------------------------------------------------------------'/ Sperrt sofort den Rechner und es erscheint der Anmeldeschirm des PC's ¦ '/ Erfordert API-Funktion: Private Declare Function LockWorkStation Lib "user32.dll" () As Long ¦ '/---------------------------------------------------------------------------------------------------------Private Sub WindowsSperren() Dim Retval As Long Retval = LockWorkStation End Sub Di es e F u n kt io n li ef e r t d en In h alt ein e r e xt er n e n Dat e i '/------------------------------------------------------------------------------------------------'/ Funktion liefert kommpletten Inhalt einer externen TXT-Datei ¦ '/------------------------------------------------------------------------------------------------Function getFileValues(location As String) Dim txt As String Open location For Input As #1 getFileValues = "" Do Until EOF(1) Line Input #1, txt If (getFileValues = "") Then getFileValues = txt Else getFileValues = getFileValues & vbCrLf & txt D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 32 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] End If Loop Close End Function Hi er w ir d z ei le n w ei se in e in e e xt e rn e D at ei g e s ch ri eb en : '/------------------------------------------------------------------------------------------------'/ Schreibt zeilenweise in eine externen TXT-Datei (anhängen) ¦ '/------------------------------------------------------------------------------------------------Public Sub setNewLineInFile(sNameFile, sNewLineText) Dim txt As String Dim fn As Long fn = FreeFile() Open sNameFile For Append As #fn Print #fn, sNewLineText Close #fn End Sub E xt e rn e D at ei st a rt e n ü b er D at ei an g ab e (zB. PDF-Dateipfad öffnet autom. Acrobat Reader) ' ermöglicht das Starten Private Declare Function ByVal lpOperation ByVal lpDirectory der PDF-Datei von der Dialogform heraus ShellExecute Lib "Shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, _ As String, ByVal lpFile As String, ByVal lpParameters As String, _ As String, ByVal nShowCmd As Long) As Long Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long '/---------------------------------------------------------------------------------------------------------'/ Startet die angegebene Programmdatei wie wenn ein Doppelklick über Explorer auf Datei ausgeführt wird! ¦ '/---------------------------------------------------------------------------------------------------------Public Function DateiEndungStarten(PrgArg) ' Installationsassistent beenden. Falls If PrgArg = "" Then Exit Function varSplit = Split(PrgArg, "\", -1, vbTextCompare) ' Dateiname von Pfad trennen und für strFilename = UCase(varSplit(UBound(varSplit))) ' DIR-Prüfung verwenden. If UCase(Dir(PrgArg)) = strFilename Then ' PrgArg einen Wert aufweist, wird hier If Trim(PrgArg) <> "" Then ' Die API-Doppelklickfunktiuon ShellExecute ProcessId = ShellExecute(0&, vbNullString, PrgArg, vbNullString, vbNullString, vbNormalFocus) SetForegroundWindow ProcessId ' Beenden wieder ermöglichen DateiEndungStarten = ProcessId End If ' Gestartete Applikation nach vorne holen. Else DateiEndungStarten = -1 ' -1 anstatt neue Prozess-ID zurückgeben End If ' PrgSav auf Null gesetzt. End Function Aufruf wie folgt: DateiEndungStarten "D:\Temp\MeineDoku.Pdf" O p t io n en - Di a lo g m it W S cr ip t - S en d K e ys st eu er n '/--------------------------------------------------------------------------------------------------------------'/ SendKeys über WScript abspielen (in VBA funktioniert SendKey nicht beim Optionen-Dialog!) ¦ '/--------------------------------------------------------------------------------------------------------------Public Sub WSSendkeys() Dim objWS Set objWS = CreateObject("WScript.Shell") objWS.SendKeys "%doe%y{ENTER}" End Sub ' In den Optionen [Popupsymbolleise anzeigen] ausschalten W o rd d at ei en l ad en ü b e r let z t en Vo rg ab ep f ad Ganz praktisch ist dieser Makro, der Worddateien (zB.*.DOTM) aus einem Verzeichnis lädt und dabei den Ladepfad für einen nächsten Ladevorgang speichert. '/-----------------------------------------------------------------------------------------------------------'/ Autor: daniel Deckensattl Email: disi@gmx.ch Erstellt: 08.12.2014 Update: 08.12.2014 Ver. 1.00 ¦ '/ ¦ '/ Zweck: Die Funktion GetOpenFileArray startet den Öffnendialog zur Auswahl von Worddateien. Aufgerufen ¦ '/ wird diese Funktion mit der Prozedur WorddokumenteLaden die den Pfad vorgibt! ¦ '/-----------------------------------------------------------------------------------------------------------Option Explicit Private Declare Function GetOpenFileName Lib "comdlg32.dll" _ Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long Private Type OPENFILENAME lStructSize As Long hwndOwner As Long hInstance As Long lpstrFilter As String lpstrCustomFilter As String nMaxCustFilter As Long D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 33 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] nFilterIndex As Long lpstrFile As String nMaxFile As Long lpstrFileTitle As String nMaxFileTitle As Long lpstrInitialDir As String lpstrTitle As String Flags As Long nFileOffset As Integer nFileExtension As Integer lpstrDefExt As String lCustData As Long lpfnHook As Long pTemplateName As String End Type Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Public Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const Const OFN_ALLOWMULTISELECT = &H200 OFN_CREATEPROMPT = &H2000 OFN_ENABLEHOOK = &H20 OFN_ENABLETEMPLATE = &H40 OFN_ENABLETEMPLATEHANDLE = &H80 OFN_EXPLORER = &H80000 OFN_EXTENSIONDIFFERENT = &H400 OFN_FILEMUSTEXIST = &H1000 OFN_HIDEREADONLY = &H4 OFN_LONGNAMES = &H200000 OFN_NOCHANGEDIR = &H8 OFN_NODEREFERENCELINKS = &H100000 OFN_NOLONGNAMES = &H40000 OFN_NONETWORKBUTTON = &H20000 OFN_NOREADONLYRETURN = &H8000 OFN_NOTESTFILECREATE = &H10000 OFN_NOVALIDATE = &H100 OFN_OVERWRITEPROMPT = &H2 OFN_PATHMUSTEXIST = &H800 OFN_READONLY = &H1 OFN_SHAREAWARE = &H4000 OFN_SHAREFALLTHROUGH = 2 OFN_SHARENOWARN = 1 OFN_SHAREWARN = 0 OFN_SHOWHELP = &H10 Public Function GetOpenFileArray(strFilter As String, lngFlags As Long, strDir As String) As Variant 'Function gibt ein Array zurück das alle gewählten File enthält Dim strText As String Dim vntPathAndFileNamen As Variant Dim strBuffer As String Dim lngResult As Long Dim lngI As Long Dim ComDlgOpenFileName As OPENFILENAME 'strBuffer = String$(256, 0) strBuffer = String$(256& * 256, 0) With ComDlgOpenFileName .lStructSize = Len(ComDlgOpenFileName) .Flags = lngFlags .nFilterIndex = 1 .nMaxFile = Len(strBuffer) .lpstrFile = strBuffer .lpstrFilter = strFilter .lpstrTitle = "Mit gedrückter Shift oder Strg Taste alle gewünschten Dateien markieren!" .lpstrInitialDir = strDir End With lngResult = GetOpenFileName(ComDlgOpenFileName) If lngResult <> 0 Then vntPathAndFileNamen = Split(Left$(ComDlgOpenFileName.lpstrFile, _ Instr(ComDlgOpenFileName.lpstrFile, Chr$(0) & Chr(0)) - 1), Chr(0), -1, 0) If UBound(vntPathAndFileNamen) = 0 Then strText = Chr(0) & Left$(ComDlgOpenFileName.lpstrFile, _ Instr(ComDlgOpenFileName.lpstrFile, Chr$(0) & Chr(0)) - 1) 'XX Else For lngI = 1 To UBound(vntPathAndFileNamen) strText = strText & Chr(0) & vntPathAndFileNamen(0) & "\" & vntPathAndFileNamen(lngI) Next End If GetOpenFileArray = Split(Mid$(strText, 2), Chr(0), -1, 0) Else GetOpenFileArray = "" End If End Function Public Sub WorddokumenteLaden() Dim lngI As Long Dim strDir As String Dim strFilter As String Dim strDirPath As String Dim lngFlags As Long Dim vntFileNamen As Variant Dim wdDoc As Word.Document lngFlags = OFN_FILEMUSTEXIST Or OFN_HIDEREADONLY Or OFN_PATHMUSTEXIST Or OFN_ALLOWMULTISELECT Or OFN_EXPLORER lngFlags = OFN_ALLOWMULTISELECT Or OFN_EXPLORER strFilter = "Documente (*.doc)" & Chr$(0) & "*.Do*" & Chr$(0) & Chr$(0) ' *.doc Anpassen!!!! strDirPath = GetSetting("DDTOOL", "AppCFG", "LastPath") If strDirPath <> "" Then strDir = strDirPath Else D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 34 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] strDir = "C:\" End If vntFileNamen = GetOpenFileArray(strFilter, lngFlags, strDir) If VarType(vntFileNamen) = 8200 Then For lngI = LBound(vntFileNamen) To UBound(vntFileNamen) Set wdDoc = Application.Documents.Open(vntFileNamen(lngI)) If lngI = 0 Then SaveSetting "DDTOOL", "AppCFG", "LastPath", wdDoc.Path End If DoEvents Next Else Application.StatusBar = "Es wurde keine Datei ausgewählt" End If End Sub Dat ei en i n P ap i e r ko r b lö s ch en '/--------------------------------------------------------------------------------------------------------------'/ Funktion: Kill Erstellt: 20.4.02 Update: 20.04.02 Version: 1.00 ¦ '/ ¦ '/ Papierkorb-Löschung mit Nutzung von Wildcards und Datei/Folder-Arrays-Auflistungen (systemnah) ¦ '/ ¦ '/ Argument1: True Name: AllowUndo Typ: Boolean ¦ '/ Argument2: True Name: ShowProgress Typ: Boolean ¦ '/ Argument3: True Name: Confirmation Typ: Boolean ¦ '/ Argument4: True Name: Simple Typ: Boolean ¦ '/ Argument5: True Name: SysErrors Typ: Boolean ¦ '/ Argument6: 167889000001 Name: hWnd Typ: Long ¦ '/ Argument5: True Name: UserAborts Typ: Variant ¦ '/ ¦ '/ Rückgabe: Variant-Typ ¦ '/ ¦ '/ Die hier vorgestellte Ersatzfunktion Kill verhält sich wie das VB-Original, wenn man ihr (Standard) ledig¦ '/ lich den gewünschten Dateinamen übergibt. Es können aber auch mehrere Dateien (dimensioniertes oder aktuell ¦ '/ mit der Array-Funktion zusammengestelltes) in einem Array oder eine Collection welche aus einzelnen Datei¦ '/ und Ordnerpfaden übergeben. Und sie können Wildcards (etwa "*.*" oder "*.bas") verwenden. ¦ '/ ¦ '/ Die gewünschte Funktionalität legen Sie in den einzelnen optionalen Parametern fest. Sollen die Dateien in ¦ '/ den Papierkorb verschoben werden, setzen Sie AllowUndo gleich True. Soll der Windows-übliche Fortschritts¦ '/ dialog mit Möglichkeit zum Abbrechen des Vorgangs angezeigt werden, setzen Sie ShowProgress gleich True. Die ¦ '/ Rückfrage, ob wirklich gelöscht werden soll, legen Sie mit Confirmation gleich True fest. Eine etwas verein ¦ '/ fachte Fortschrittsanzeige, bei der die Anzeige der gerade bearbeiteten Dateinamen unterbleibt, wählen Sie ¦ '/ mit Simple gleich True. Wenn Sie im Falle eines Fehlers die Windows-Anzeige dieses Fehlers beibehalten ¦ '/ wollen, setzen Sie SysErrors gleich True. ¦ '/ ¦ '/ In hWnd übergeben Sie die hWnd-Eigenschaft eines Forms, damit Windows den Löschvorgang Ihrer Anwendung zuzu- ¦ '/ ordnen weiss. Ist die Leerung fehlgeschlagen, gibt die Funktion den Wert True zurück. ¦ '/ ¦ '/ Unabhängig davon, wie Sie den letztgenannten Parameter setzen, gibt die Funktion Kill den Wert True zurück, ¦ '/ wenn ein Fehler aufgetreten ist. Allerdings lässt sich der Fehler nicht näher spezifizieren - Sie müssen auf ¦ '/ andere Weise prüfen, was schief gegangen sein könnte (Datei nicht vorhanden, gesperrt u.a.). Hat der Anwender¦ '/ bei den gelegentlichen Rückfragen des Systems (Löschen einer Systemdatei o.ä.) beispielsweise einzelne ¦ '/ Dateien übersprungen, können Sie diese Information über den Parameter UserAborts erhalten, in der Sie dazu ¦ '/ eine Variable übergeben müssen. Allerdings müssen Sie auch hierbei wieder selbst herausfinden, welche Dateien¦ '/ übersprungen worden sind. ¦ '/--------------------------------------------------------------------------------------------------------------Public Function Optional Optional Optional Optional Optional Optional Optional Kill(Files As Variant, _ ByVal AllowUndo As Boolean, _ ByVal ShowProgress As Boolean, _ ByVal Confirmation As Boolean, _ ByVal Simple As Boolean, _ ByVal SysErrors As Boolean, _ ByVal hwnd As Long, _ UserAborts As Variant _ ) As Boolean Dim l As Long Dim nFileOperations As SHFILEOPSTRUCT Const Const Const Const Const Const FO_DELETE = &H3 FOF_ALLOWUNDO = &H40 FOF_SILENT = &H4 FOF_NOCONFIRMATION = &H10 FOF_SIMPLEPROGRESS = &H100 FOF_NOERRORUI = &H400 With nFileOperations If IsArray(Files) Then For l = LBound(Files) To UBound(Files) .pFrom = .pFrom & Files(l) & vbNullChar Next 'l .pFrom = .pFrom & vbNullChar ElseIf VarType(Files) = vbObject Then If TypeOf Files Is Collection Then For l = 1 To Files.Count .pFrom = .pFrom & Files(l) & vbNullChar Next 'l .pFrom = .pFrom & vbNullChar End If ElseIf VarType(Files) = vbString Then .pFrom = Files If Right$(.pFrom, 1) <> vbNullChar Then .pFrom = .pFrom & vbNullChar End If If Mid$(.pFrom, Len(.pFrom) - 1, 1) <> vbNullChar Then .pFrom = .pFrom & vbNullChar D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 35 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] End If End If If AllowUndo Then .fFlags = FOF_ALLOWUNDO End If If Not ShowProgress Then .fFlags = .fFlags Or FOF_SILENT End If If Not Confirmation Then .fFlags = .fFlags Or FOF_NOCONFIRMATION End If If Simple Then .fFlags = .fFlags Or FOF_SIMPLEPROGRESS End If If Not SysErrors Then .fFlags = .fFlags Or FOF_NOERRORUI End If .wFunc = FO_DELETE .hwnd = hwnd Kill = Not CBool(SHFileOperation(nFileOperations)) If Not IsMissing(UserAborts) Then UserAborts = CBool(.fAnyOperationsAborted) End If End With End Function T ime r- F u n kt io n Eine etwas spezielle API-Funktion ist der Timer, welcher periodisch aufgerufen wird. Hierzu benötigen wir zwei API-Funktionen, sehen wir uns zuerst die Deklarationen an: Public Declare Function SetTimer Lib "user32.dll" (ByVal hwnd As Long, ByVal nIDEvent As Long, _ ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long Public Declare Function KillTimer Lib "user32.dll" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long Public Const WM_TIMER = &H113 ' Timer-Ereignis trifft ein Nachdem diese beiden API-Funktionen deklariert sind, kann die SetTimer-Funktion aufgerufen werden. Hier im Beispiel in der Sub-Routine TimerManagen(Aktivieren/Deaktivieren) wo sie im Sekundentakt (1000 Millisekunden) die Prozedur TimerWordaction aufruft. '/-----------------------------------------------------------------------------------------------------------'/ Der Timer für die Dokumentenwechselüberwachung kann hier per Funktionsaufruf gestartet oder mit Angaben ¦ '/ eines opt. False-Parameters entladen werden. Dies war nötig um bei Textbaustein-Kopieraktionen keine Pro- ¦ '/ bleme zu bekommen, indem vor einer Aktion der Timer entladen und erst nach ausgeführter Aktion wieder ge- ¦ '/ laden wird! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub TimerManagen(Optional bolStarten As Boolean = True) If bolStarten = True Then If lngActionEvent = 0 Then lngActionEvent = VBA_Bibliothek.SetTimer(0&, 0&, 1000, AddressOf mdlAutotexte.TimerWordaction) End If Else If lngActionEvent > 0 Then VBA_Bibliothek.KillTimer 0&, lngActionEvent lngActionEvent = 0 End If End If End Sub Die TimerWordAction – Routine illustriert, wie die CallBack-Funktion aufgebaut sein muss, - in roter Farbe dann der VBA-Code der unterschiedlich sein kann. '/-----------------------------------------------------------------------------------------------------------'/ Lädt der Anwender ein neues Dokument oder eine Vorlage in den Speicher, dann prüft diese API-Timer-Ereig- ¦ '/ nisfunktion alle 1000 ms, ob neue Autotexteinträge hinzugekommen sind, oder gar wegfallen sollen. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub TimerWordaction(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) Dim intCounter As Integer On Error Resume Next If uMsg = WM_TIMER Then intCounter = Application.Documents.Count If intCounter = 0 Then TimerManagen False If intAnzahlDokumente <> intCounter Then TimerManagen False frmAutotexte.DokumentWechsel TimerManagen True End If End If End Sub Die obigen Timer-Funktionen sind sehr heikel, es darf kein Fehler (im roten Bereich) auftreten, da sonst Schutzverletzungen vorkommen. Ich habe diese Routine zB. in meiner AddIn-Vorlage W14ProjektManagement.dotm eingebaut, die laufend kontrolliert, ob eine Worddatei hinzugeladen oder entfernt D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 36 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung Deckensattl Daniel [08.01.2015] MS-Office 2010 VBA-Programmierung wurde um die betroffenen Listenfenster autom. zu aktualisieren, was W14ProjektManagement.XLSM) – VBA-mittel allein nicht zu bewerkstelligen ist. mit Word (oder Excel- Im weiter unten beschriebenen PopUp-Menü für VBA habe ich diesen Timer auch implementiert (darf kein Fehler darin vorkommen!) der während der PopUp-Menüanzeige prüft, ob der Kontextmenübreich mit der Maus noch überfahren wird, sonst ausblenden). Während der Programmierung an einem VBA-Projekt sollte diese API-Timerfunktion deaktiviert werden, man vermeidet so Schutzverletzungen und erst wenn das Projekt einwandfrei läuft, sollte der Timer wieder aktiviert werden! M au sp o sit io n l es en / set z en Public Declare Function GetMessagePos Lib "user32" () As Long ' Mauskoordinaten Public Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long ! '/--------------------------------------------------------------------------------------------------------------'/ Diese Funktion gibt die aktuellen Mauskoordinaten (in Pixel) getrennt durch einen Doppelpunkt zurück! ¦ '/ werden die Pixel-Longwert-Argumente lngLinkePos & lngObenPos optional angegeben, kann der Mauszeiger ¦ '/ an dieser gewünschten Screen-Position gesetzt werden (in Pixel angeben oder manuell umrechnen!). ¦ '/--------------------------------------------------------------------------------------------------------------Public Function MauspositionSteuern(Optional longLinkePos As Variant, Optional longObenPos As Variant) As Variant Dim lngResultat As Long, PosLSetzen As Long, PosOSetzen As Long, varCtrl(2) As Variant On Error GoTo Abbruch PosLSetzen = -1: PosOSetzen = -1 If IsMissing(longLinkePos) = False Then ' Wurde ein Linker Positionierungswert angegeben PosLSetzen = Iif(longLinkePos < 0, 0, longLinkePos) ' dann Wert auf Minus prüfen & ev. korrigieren ! End If If IsMissing(longObenPos) = False Then PosOSetzen = Iif(longObenPos < 0, 0, longObenPos) End If ' Wurde ein Top Positionierungswert angegeben ' dann Wert auf Minus prüfen & ev. korrigieren ! lngResultat = GetMessagePos() lngPosLSetzen = Val(LoWord(lngResultat)) lngPosOSetzen = Val(HiWord(lngResultat)) ' Aktuelle Mauspositionswerte festhalten ' Linke Bildschirmposition der Maus ' Obere Bildschirmposition der Maus If PosLSetzen < 0 And PosOSetzen < 0 Then ' Bei keiner Argumentübergabe wird nur Resultat MauspositionSteuern = Array(lngPosLSetzen, lngPosOSetzen) ' zurückgegeben (Array(0)=Links/(1)=Top) Else If PosLSetzen >= 0 And PosOSetzen >= 0 Then ' Bei zwei vorhandenen Argumenten Mausposition neu SetCursorPos PosLSetzen, PosOSetzen ' den übergebenen Koordinaten zuweisen MauspositionSteuern = Array(PosLSetzen, PosOSetzen) ' Die optionalen TOP/LEFT-Werten zuweisen! Else If PosLSetzen >= 0 And PosOSetzen < 0 Then ' Im Falle nur eines angegebenen Argumentes, in SetCursorPos PosLSetzen, lngPosOSetzen ' diesem Fall die linke Mausposition-Verschiebung MauspositionSteuern = Array(PosLSetzen, lngPosOSetzen) ' mit bestehendem TOP-Wert zuweisen! Else SetCursorPos lngPosLSetzen, PosOSetzen ' Im Falle nur eines angegebenen Argumentes, in MauspositionSteuern = Array(lngPosLSetzen, PosOSetzen) ' diesem Fall die obere Mausposition End If ' Verschiebung mit bestehendem LEFT-Wert arbeiten! End If End If Exit Function Abbruch: MauspositionSteuern = Array(-1, -1) ' Array mit Minuswerten im Fehlerfall zurückgeben! End Function Public Function LoWord(dWert As Long) As Integer If (dWert And &H8000&) = 0 Then LoWord = dWert And &H7FFF& Else LoWord = &H8000 Or (dWert And &H7FFF&) End If End Function ' API-Rückgabewerte ermitteln Public Function HiWord(dWert As Long) As Integer If (dWert And &H8000&) = 0 Then HiWord = dWert / &H10000 Else HiWord = (dWert And &H7FFF&) / &H10000 End If End Function Bin ä r- D ez i m al- Ko n v e rt er '/---------------------------------------------------------------------------------------------------------------------'/ Wandelt einen übegebenen Dezimalwert In eine binäre Zahl um und umgekehrt! ¦ '/---------------------------------------------------------------------------------------------------------------------Public Function DezimalBinaerKonverter(ByVal Dec As Long, ByVal NumDigitsMin As Long, Optional bolInDezimal = True) As String Dim lngI As Long, lngLen As Long, lngRes As Long On Error GoTo DecBinError ' Bei Fehler In Zahl abbrechen If bolInDezimal = True Then ' Binärstring zerlegen lngLen = Len(Bin) For lngI = lngLen To 1 Step -1 ' Wir gehen von rechts nach links vor (LSB -> MSB) lngRes = lngRes + Iif(Mid$(Bin, i, 1) = "1", 2 ^ (lngLen - lngI), 0) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 37 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung Next lngI DezimalBinaerKonverter = lngRes Else Do If (Dec And 2 ^ lngI) > 0 Then lngRes = "1" & lngRes Dec = Dec - 2 ^ lngI Else lngRes = "0" & lngRes End If lngI = lngI + 1 Loop Until Dec = 0 MS-Office 2010 VBA-Programmierung ' ' ' ' Deckensattl Daniel [08.01.2015] Binären String zusammensetzen Bit ist zu setzen "1" setzen Subtrahieren für Abbruchbedingung ' "0" setzen ' Nächste Position ' Abbruchbedingung prüfen ' Falls minimale Länge unterschritten, mit "0" auffüllen DezimalBinaerKonverter = Format$(lngRes, String(NumDigitsMin, "0")) End If DecBinExit: Exit Function DecBinError: With Err .Raise .Number, .Source, .Description, .HelpFile, .HelpContext End With Resume DecBinExit End Function F r ei e r Sp ei ch e rp lat z er mit t e ln '/---------------------------------------------------------------------------------------------------------------------'/ Ermittelt freien Platz auf einem angegbenen Laufwerk. ZB.: MsgBox GetNewFreespace("D:\"). Erforder API-Funktionen: ¦ '/ ¦ '/ Private Declare Function GetDiskFreeSpaceEx Lib "kernel32" Alias _ ¦ '/ "GetDiskFreeSpaceExA" (ByVal lpRootPathName As String, _ ¦ '/ lpFreeBytesAvailableToCaller As LARGE_INTEGER, lpTotalNumberOfBytes _ ¦ '/ As LARGE_INTEGER, lpTotalNumberOfFreeBytes As LARGE_INTEGER) As Long ¦ '/ ¦ '/ Private Type LARGE_INTEGER ¦ '/ lowpart As Long ¦ '/ highpart As Long ¦ '/ End Type ¦ '/---------------------------------------------------------------------------------------------------------------------Private Dim Dim Dim Dim Dim Dim Dim Function GetNewFreespace(sLW As String) lResult As Long liAvailable As LARGE_INTEGER liTotal As LARGE_INTEGER liFree As LARGE_INTEGER dblAvailable As Double dblTotal As Double dblFree As Double 'Determine the Available Space, Total Size And Free Space of a drive lResult = GetDiskFreeSpaceEx(sLW, liAvailable, liTotal, liFree) 'Convert the return values from LARGE_INTEGER To doubles dblAvailable = CLargeInt(liAvailable.lowpart, liAvailable.highpart) dblTotal = CLargeInt(liTotal.lowpart, liTotal.highpart) dblFree = CLargeInt(liFree.lowpart, liFree.highpart) 'Display the results Debug.Print "Available Space: " & dblAvailable & " bytes (" & _ Format(dblAvailable / 1024 ^ 3, "0.00") & " G) " & vbCr & _ "Total Space: " & dblTotal & " bytes (" & _ Format(dblTotal / 1024 ^ 3, "0.00") & " G) " & vbCr & _ "Free Space: " & dblFree & " bytes (" & _ Format(dblFree / 1024 ^ 3, "0.00") & " G) " GetNewFreespace = dblFree & " bytes (" & Format(dblFree / 1024 ^ 3, "0.00") & " G)" End Function Private Function CLargeInt(Lo As Long, Hi As Long) As Double 'This Function converts the LARGE_INTEGER data type To a double Dim dblLo As Double, dblHi As Double If Lo < 0 Then dblLo = 2 ^ 32 + Lo Else dblLo = Lo End If If Hi < 0 Then dblHi = 2 ^ 32 + Hi Else dblHi = Hi End If CLargeInt = dblLo + dblHi * 2 ^ 32 End Function M it Ex p lo r e r O rd n e r Ö f f n en Mit diesen Makro wird ein Explorer am gewünschten Pfad geöffnet '/---------------------------------------------------------------------------------------------------------------------' Mit Explorer Ordner öffnen ¦ '/---------------------------------------------------------------------------------------------------------------------- D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 38 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Public Sub STARTUPOrdneropen() Dim Pfad As String Pfad = "C:\Users\" & Environ("USERNAME") & "\AppData\Roaming\Microsoft\Word\STARTUP" Shell "Explorer.exe " & Pfad, vbNormalFocus End Sub Public Sub VORLAGENOrdneropen() Dim Pfad As String Pfad = Application.Options.DefaultFilePath(wdUserTemplatesPath) Shell "Explorer.exe " & Pfad, vbNormalFocus End Sub ' anpassen S ch l i es st a ll e o f f e n e n In t e rn et E xp l o r e r '/---------------------------------------------------------------------------------------------------------------------'/ Schliesst alle offenen Internetexporer ¦ '/---------------------------------------------------------------------------------------------------------------------Sub AlleIntenetexplorerSchliessen() Dim objWMI As Object, objProcessList As Object, objProcess As Object Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") Set objProcessList = objWMI.ExecQuery("Select * from Win32_Process " & _ "Where Name = 'iexplore.exe'") For Each objProcess In objProcessList Call objProcess.Terminate(0) Next Set objProcessList = Nothing Set objWMI = Nothing End Sub URL - V al id ie ru n g 'Für 64 Bit Systeme muss übrigens wie folgt deklariert werden (URLs validieren): #If VBA7 Then Private Declare PtrSafe Function InternetCheckConnection Lib "wininet.dll" _ Alias "InternetCheckConnectionA" (ByVal url As String, _ ByVal dwFlags As Long, ByVal dwReserved As Long) As Long #Else Private Declare Function InternetCheckConnection Lib "wininet.dll" _ Alias "InternetCheckConnectionA" (ByVal url As String, _ ByVal dwFlags As Long, ByVal dwReserved As Long) As Long #End If ' URLs validieren Public Sub UrlTesten() ' liefert 1 = existiert , 0 = nicht erreichbar Debug.Print InternetCheckConnection("http://deckensattl.goip.de/", 1, 0) Debug.Print InternetCheckConnection("http://www.google.ch/", 1, 0) End Sub F a rb au sw ah l- Di al o g v o n W in d o w s n u t z e n '/---------------------------------------------------------------------------------------------------------------------'/ Farbauswahl-Dialog von Windows In Word-UserForm anzeigen und auswählen. Folgende API-Deklarationen sind nötig: ¦ '/ ¦ '/ Private Declare Function ChooseColor_Dlg Lib "comdlg32.dll" _ ¦ '/ Alias "ChooseColorA" (lpcc As CHOOSECOLOR_TYPE) As Long ¦ '/ ¦ '/ Private Type CHOOSECOLOR_TYPE ¦ '/ lStructSize As Long ¦ '/ hwndOwner As Long ¦ '/ hInstance As Long ¦ '/ rgbResult As Long ¦ '/ lpCustColors As Long ¦ '/ flags As Long ¦ '/ lCustData As Long ¦ '/ lpfnHook As Long ¦ '/ lpTemplateName As String ¦ '/ End Type ¦ '/ ¦ '/ ' Anwender kann alle Farben wählenPrivate Const CC_ANYCOLOR = &H100 ¦ '/ ' Nachrichten können "abgefangen" werdenPrivate Const CC_ENABLEHOOK = &H10 ¦ '/ ' Dialogbox TemplatePrivate Const CC_ENABLETEMPLATE = &H20 ¦ '/ ' Benutzt Template, ignoriert aber den Template-Namen ¦ '/ Private Const CC_ENABLETEMPLATEHANDLE = &H40 ' Vollauswahl aller Farben anzeigen ¦ '/ Private Const CC_FULLOPEN = &H2 ¦ '/ ' Deaktiviert den Button zum Öffnen der Dialogbox-Erweiterung ¦ '/ Private Const CC_PREVENTFULLOPEN = &H4 ' Vorgabe einer Standard-Farbe ¦ '/ Private Const CC_RGBINIT = &H1 ' Hilfe-Button anzeigen ¦ '/ Private Const CC_SHOWHELP = &H8 ' nur Grundfarben auswählbar ¦ '/ Private Const CC_SOLIDCOLOR = &H80 ¦ '/---------------------------------------------------------------------------------------------------------------------Private Sub CommandButton1_Click() Dim CC_T As CHOOSECOLOR_TYPE, Retval As Long Static BDF(16) As Long ' Einige BDF(0) = BDF(1) = BDF(2) = Farben vordefinieren (Benutzerdefinierte Farben) RGB(255, 0, 255) RGB(125, 125, 125) RGB(90, 90, 90) ' Handle von Word-Form ermitteln If Val(Application.Version) >= 9 Then hWndForm = FindWindow("ThunderDFrame", Me.Caption) Else D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 39 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] hWndForm = FindWindow("ThunderXFrame", Me.Caption) End If With CC_T .lStructSize = Len(CC_T) ' Strukturgröße '.hInstance = App.hInstance ' Anwendungs-Instanz .hwndOwner = hWndForm ' Fenster-Handle ' Flags .flags = CC_RGBINIT Or CC_ANYCOLOR Or CC_FULLOPEN Or CC_PREVENTFULLOPEN .rgbResult = RGB(0, 255, 0) ' Farbe voreinstellen .lpCustColors = VarPtr(BDF(0)) ' Benutzerdefinierte Farben zuweisen End With Retval = ChooseColor_Dlg(CC_T) ' Dialog anzeigen If Retval <> 0 Then ' gewählte Farbe als Hintergrund setzen Me.BackColor = CC_T.rgbResult Else MsgBox "Das Auswählen einer Farbe ist fehlgeschlagen," & _ "oder Sie haben Abbrechen gedrückt", vbCritical, "Fehler" End If End Sub W o rd r eg i st e r ak t iv i e r en Private Declare Function AccessibleChildren Lib "oleacc.dll" ( _ ByVal paccContainer As Object, _ ByVal iChildStart As Long, _ ByVal cChildren As Long, _ ByRef rgvarChildren As Variant, _ ByRef pcObtained As Long) As Long Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" ( _ ByRef psa() As Any) As Long Private Private Private Private Const Const Const Const CHILDID_SELF As Long = &H0& STATE_SYSTEM_UNAVAILABLE As Long = &H1& STATE_SYSTEM_INVISIBLE As Long = &H8000& STATE_SYSTEM_SELECTED As Long = &H2& Private Enum RoleNumber ROLE_SYSTEM_CLIENT = &HA& ROLE_SYSTEM_PANE = &H10& ROLE_SYSTEM_GROUPING = &H14& ROLE_SYSTEM_TOOLBAR = &H16& ROLE_SYSTEM_PAGETAB = &H25& ROLE_SYSTEM_PROPERTYPAGE = &H26& ROLE_SYSTEM_GRAPHIC = &H28& ROLE_SYSTEM_STATICTEXT = &H29& ROLE_SYSTEM_TEXT = &H2A& ROLE_SYSTEM_BUTTONDROPDOWNGRID = &H3A& ROLE_SYSTEM_PAGETABLIST = &H3C& End Enum Private Enum NavigationDirection NAVDIR_FIRSTCHILD = &H7& End Enum Public Sub SwitchTabMain() ' Registername aktivieren If Not SwitchTab("Verweise") Then _ Call MsgBox("Kein Tab ''Verweise'' gefunden.", vbCritical, "Fehler") End Sub Private Function SwitchTab(ByVal pvstrTabName As String) As Boolean Dim objRibbonTab As IAccessible Set objRibbonTab = GetAccessible(CommandBars("Ribbon"), _ ROLE_SYSTEM_PAGETAB, pvstrTabName) If Not objRibbonTab Is Nothing Then If ((objRibbonTab.accState(CHILDID_SELF) And (STATE_SYSTEM_UNAVAILABLE _ Or STATE_SYSTEM_INVISIBLE)) = 0) Then Call objRibbonTab.accDoDefaultAction(CHILDID_SELF) SwitchTab = True End If End If End Function Private Function GetAccessible( _ ByRef probjElement As IAccessible, _ ByVal pvenmRoleWanted As RoleNumber, _ ByVal pvstrNameWanted As String, _ Optional ByVal opvblnGetClient As Boolean) As IAccessible Dim Dim Dim Dim avntChildrenArray() As Variant objChild As IAccessible, objReturnElement As IAccessible ialngChild As Long strNameComparand As String, strName As String, strValue As String On Error Resume Next strValue = probjElement.accValue(CHILDID_SELF) On Error GoTo 0 strName = probjElement.accName(CHILDID_SELF) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 40 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Select Case strValue Case "Ribbon", "Quick Access Toolbar", _ "Ribbon Tabs List", "Lower Ribbon", "Status Bar" strNameComparand = strValue Case vbNullString, "Ribbon Tab", "Group" strNameComparand = strName Case Else strNameComparand = strName End Select If probjElement.accRole(CHILDID_SELF) = pvenmRoleWanted And _ strNameComparand = pvstrNameWanted Then Set objReturnElement = probjElement Else avntChildrenArray = GetChildren(probjElement) If Cbool(SafeArrayGetDim(avntChildrenArray)) Then For ialngChild = LBound(avntChildrenArray) To UBound(avntChildrenArray) If TypeOf avntChildrenArray(ialngChild) Is IAccessible Then Set objChild = avntChildrenArray(ialngChild) Set objReturnElement = GetAccessible(objChild, _ pvenmRoleWanted, pvstrNameWanted) If Not objReturnElement Is Nothing Then Exit For End If Next End If End If If opvblnGetClient Then Set objReturnElement = objReturnElement.accNavigate( _ NAVDIR_FIRSTCHILD, CHILDID_SELF) Set GetAccessible = objReturnElement Set objReturnElement = Nothing Set objChild = Nothing End Function Private Function GetChildren(ByRef probjElement As IAccessible) As Variant() Const FIRST_CHILD As Long = 0& Dim lngChildCount As Long, lngReturn As Long Dim avntChildrenArray() As Variant lngChildCount = probjElement.accChildCount If lngChildCount > 0 Then ReDim avntChildrenArray(lngChildCount - 1) Call AccessibleChildren(probjElement, FIRST_CHILD, _ lngChildCount, avntChildrenArray(0), lngReturn) End If GetChildren = avntChildrenArray End Function D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 41 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Po p Up - Ko n t e xt m en i n VB A Leider unterstützt Winword auf Benutzerdialogformen keine Kontextmenüs, welche den gewohnten windowskonformen Umgang mit den Kopieren/Ausschneiden/Einfügen-Aktionen bietet. Mit wenigen API-Funktionen wurde eine eigen Lösung eingebaut mit demselben Effekt, wie ein normales Kontextmenü. Es ist sogar erlaubt, die Kontextfläche während der Anzeige zu verschieben, falls sie einem gerade die Sicht nimmt. Alle Editierfelder, welche mit Werten gefüllt werden können so wie gewohnt kopiert oder ausgeschnitten werden. Ich habe die ganze PopUp-Funktionalität in zwei portierbare Module (frmPopUp und mdlPopUp) gepackt um sie so jederzeit auch in anderen Projekten einsetzen zu können. Einzig individuelle Menüpunkte müssen mit eigenen Makroprozeduren verknüpft werden (MenuKontext()-Prozedur!) und natürlich die MouseUp-Verbindungen der auszustattenden PopUp-Controls müssen mit der global verfügbaren PopUp-Aufruffunktion KontextMenü() verknüpft werden. Kurzbeschreib Durch den fehlenden Menüeditor ist es wie schon angedeutet nicht möglich in einem TextBoxControlelement ein PopUp-Menü anzuzeigen. Aus diesem Grund habe ich eine leere Form genommen, ihr die '/----- Kontextmenü-Ereignisse ------------------------------------------------------------------Titelleiste '/-----------------------------------------------------------------------------------------------------------'/ Hier wird rechter Mausklick für PopUp-Menu-Anzeige abgefangen ¦ per API'/-----------------------------------------------------------------------------------------------------------Funktion Private Sub KontextMenu(QeullControl, Optional lngMenuFontColor As enuColor, Optional lngMenuBackColor As enuColor) DokuStart.StandardPopUp QeullControl, lngMenuFontColor, lngMenuBackColor abgeschnit End Sub ten und Private Sub DTB01_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) If Button = 2 Then KontextMenu DTB01, scViolett, scGelb ' Farbwechsel im PopUp als demonstration soviele End Sub neue leere Label-Controls erzeugt, wie Menüpunkte übergeben worden sind. Im Anschluss daran wird dann über die ganze Kontextform ein Klicklabel gesetzt, über welches wir die darunterliegenden Menüpunkte “errechnen“, wenn varMenuNamen = Array("Kopieren", "Ausschneiden", "Einfügen", "Alles Markieren", "Rückgängig") varMenuMakro = Array("Doku_Makro1", "Doku_Makro2", "Doku_Makro3", "Doku_Makro4", "Doku_Makro5") der Anwender auf eines der Kontextmenüs klickt. Was passiert '/-------- PopUp Hilfsvariablen ---------------------------------------varMenuNamen As Variant ' enthält ein Array voller Menunamen nun wenn im MouseUp-Ereignis des Public Public varMenuMakro As Variant ' enthält ein Array voller Makronamen hWndForm As Long ' Handle für Titelbeschneidung gewünschten Controls, auf welchem das Public Public bCaption As Boolean ' alter Zustand Public intPopXAchse As Integer PopUp erscheinen soll, die rechte Maustaste Public intPopYAchse As Integer '' X-Achsen-Koordinaten Y-Achsen-Koordinaten gedrückt wird (Button=2)? In unserem '/-------- PopUp-Konstanten -------------------------------------------Projekt wird die KontextMenu(..)-Hilfsfunktion Public enuColor As Long Public Enum enuColor ' Function StandardPopUp aufgerufen, die dann die PopUp-AnzeigescSchwarz = &H0& scWeiss = &HFFFFFF Prozedur anstösst. Dieser Prozedur wird im scHellgrau = &HE0E0E0 scDunkelgrau = &HFF8080 einfachsten Fall das Control als Object beim scBlau = &HFF0000 scDunkelblau = &H800000 ersten Argument angegeben. Mit dem scHellblau = &HFF8080 scCyan = &HFFFF00 zweiten und dritten optionalen Parameter scGruen = &HC000& scDunkelgruen = &H8000& können wir die Menühintergrundfarbe und scHellgruen = &HFF00& scRot = &HFF& die selektierte Menüschriftfarbe direkt scDunkelrot = &H80& scHellrot = &H8080FF beeinflussen. Fehlen diese Farbangaben scGelb = &HFFFF& scDunkelgelb = &H8080& scViolett = &HC000C0 wird die klassische blaue Farbe als scDunkelviolett = &H800080 scHellviolett = &HFF00FF Balkenmarkierung eingesetzt mit gelber scOrange = &H80FF& scHellorange = &H80C0FF Schriftfarbe (beim Überfahren der Maus). scDunkelorange = &H40C0& End Enum Die nächstseitig abgebildete PopUp-AufrufD:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 42 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung Deckensattl Daniel [08.01.2015] MS-Office 2010 VBA-Programmierung Funktion nimmt das Quellcontrol entgegen und bildet gleich zu Beginn der prozedur zwei MakronamenArrays in welchen die Menübezeichner und im anderen Array die auszuführenden Makronamen abgelegt werden, die mit den einzelnen Menüs verknüpft werden. Anhand dieser Arrayelemente werden dann in der PopUp-Dialogform die Menüpunkte dynamisch aufgebaut und mit den eigenen, als Public definierten (eindeutige Namensbezeichner verwenden!) Makroprozeduren verknüpft. In einem weiteren Schritt werden die Balkenfarben, also die Labelhintergrundfarben und die Schriftfarbe (bei der Balkenanzeige) angegeben, welche beim Überfahren des Menüpunktes angezeigt '/---------------------------------------------------------------------------------------------------------'/ Diese in der formTBSEdit-Dialogform instanzierte API-Timerfunktion wird alle 250 ms aufgerufen und kon- ¦ '/ trolliert die aktuellen Maus-Bewegungskoordinaten des RTF-Kontextmenu (formPopUp) um es auszublenden, ¦ '/ wenn der Anwender mit der Maus die Kontextfläche mit der Maus verlässt. ¦ '/---------------------------------------------------------------------------------------------------------Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) Dim CP As POINTAPI Dim intGefunden As Integer If uMsg = WM_TIMER Then GetCursorPos CP intGefunden = -1 If CP.X < (1.3338 * frmPopUp.Left) Or CP.X > ((1.3338 * frmPopUp.Left) + (1.3338 * frmPopUp.Width)) Then intGefunden = 1 If CP.Y < (1.3338 * frmPopUp.Top) Or CP.Y > ((1.3338 * frmPopUp.Top) + (1.3338 * frmPopUp.Height)) Then intGefunden = 1 If intGefunden < 0 Then Exit Sub KillTimer 0&, frmPopUp.hEvent Unload frmPopUp End If End Sub '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 25.04.2001 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Ein Standard-Kontextmenü für einzeilige Textfeld-Controls > Kopieren, Ausschneiden, Einfügen, markieren! ¦ '/ In dieser Routine sind keine Anpassungen nötig, die vorgeschaltete KontextMenu()-Funktion liefert die be- ¦ '/ nötigten Parameter selber. Hier wird die PopUp-Dialogform vorbereitet und angezeigt. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub StandardPopUp(InitialObjekt As Object, lngX, lngY, Optional lngSelMenuBackColor As enuColor, _ Optional lngSelMenuFontColor As enuColor, _ Optional lngSelMenuFontBackColor As enuColor, _ Optional lngMenuBackColor As enuColor, _ Optional intMenubreiteInPixel) Dim CP As POINTAPI Dim lngFocus As Long On Error Resume Next GetCursorPos CP '/-------- automatische Breiteneinstellung wenn keine erzwungene Formbreite angegeben wurde -----------------If IsMissing(intMenubreiteInPixel) = True Then intLenX = -1 For intZ = 0 To UBound(varMenuNamen) intR = Len(varMenuNamen(intZ)) If intR > intLenX Then intLenX = intR Next lngMenuPtBreite = Iif(intLenX < 0, 100, intLenX * 6) Else lngMenuPtBreite = Iif(intMenubreiteInPixel > 0, intMenubreiteInPixel, 100) End If lngMenuSelColor lngMenuFntColor lngMenuFntBkCol lngMenuBackColo = = = = Iif(lngSelMenuBackColor <> 0, lngSelMenuBackColor, &H800000) Iif(lngSelMenuFontColor <> 0, lngSelMenuFontColor, &HFFFFFF) Iif(lngSelMenuFontBackColor <> 0, lngSelMenuFontBackColor, &H12&) Iif(lngMenuBackColor <> 0, lngMenuBackColor, &H8000000A) Load frmPopUp Set frmPopUp.frmParentForm = InitialObjekt.Parent strAktivesControl = InitialObjekt.Name frmPopUp.Left = (CP.X / 1.44) frmPopUp.Top = (CP.Y / 1.44) + Iif(CP.Y > 200, -10, -10) frmPopUp.Show InitialObjekt.Enabled = False InitialObjekt.Enabled = True InitialObjekt.SetFocus ' ' ' ' Standardfarbe Standardfarbe Standardfarbe Standardfarbe Blau = &H800000 Weiss = &HFFFFFF Schwarz = &H12& Grau = &H8000000A ' Fokus wieder reichen End Sub '/-----------------------------------------------------------------------------------------------------------'/ Diese öffentlichen Makronamen müssen eindeutig vergeben werden, um Konflikte mit anderen gleichzeitig ¦ '/ genutzten Dokumentvorlagen zu vermeiden (diese arbeiten mit den dynamischen PopUp-Elementen)! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub Doku_Makro1() SendKeys "^c", False End Sub ' Auswahl in Zwischenablage kopieren werden sollen. Auch die Breite des Kontextmenüs kann in Pixel als viertes optionales Argument angegeben werden, - ohne Angaben wird die Breite automatisch berechnet, anhand des längsten Menütextes, der im Array gefunden wird! Im Allgemeinteil des VBA-Modules auf welchem die StandardPopUp- abgelegt wurde müssen auch die nebenan abgebildeten globalen Variablen mitsamt der Farb-Enumerationskonstante vorhanden sein. Per GetCursorPos()-API-Funktion und der TypenVariabel POINTAPI wird die aktuelle Mausposition ermittelt und diese Angaben der geladenen, aber D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 43 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] noch nicht angezeigten Dialogform übergeben. Die Show-Anweisung bringt dann den schon im Hintergrund initialisierten Dialog zur Anzeige. Hier die beiden vollständigen VBA-Module (Formmodul frmPopUp und VBA-Modul mdlPopUp): [VBA-Modul]: mdlPopUp '/-----------------------------------------------------------------------------------------------------------'/ Funktion: PopUp-Menü für Winword Erstellt: 25.04.2001 Ver.: 1.50 ¦ '/ Autor: deckensattl.daniel@bluewin.ch Update: 12.05.2003 ¦ '/ ¦ '/ Zweck: Mit einem VB-Modul [mdlPopUp] und einer titelleistenlosen Dialogform [frmPopUp] habe ich einen ¦ '/ PopUp-Menü-Ersatz entwickelt, der in jedes beliebige Projekt integriert werden kann! ¦ '/ In einem ersten Schritt werden die genannten beiden Module in das gewünschte VBA-Projekt im¦ '/ portiert. In einem zweiten Schritt müssen dann die mit einem PopUp-Menü auszustatteten Controls ¦ '/ über die jeweiligen MousUp-Ereignisse mit der globalen Funktion [KontextMenu(..)] verbinden, ¦ '/ was wir wie das untenstehende Beispiel mit folgendem Code erreichen: ¦ '/ ¦ '/ Private Sub cmbOLc01_MouseUp(ByVal Button As Integer, _ ¦ '/ ByVal Shift As Integer, _ ¦ '/ ByVal X As Single, _ ¦ '/ ByVal Y As Single) ¦ '/ If Button = 2 Then mdlPopUp.KontextMenu cmbOLc01, X, Y, Blau, Gelb, Schwarz, Grau ¦ '/ End Sub ¦ '/ ¦ '/ Das 1. Arg. enthält das Controlobjekt, welches mit einem dynamischen PopUpmenü ausgestattet ¦ '/ werden soll. Das 2. und 3. Arg. sind die X und Y - Koordinaten die hier von der MouseUp¦ '/ Funktion geliefert und einfach durchgeschlauft werden. ¦ '/ Die Farbwert-Parameter 4 - 7 enthalten Long-Werte von den einzelnen PopUp-Menü-Hintergrund / ¦ '/ Vordergrund- und Schriftfarben die individuell gesetzt werden können. ¦ '/ Das letzte optionale Argument [intMenubreiteInPixel] ermöglicht eine gezielte Menübreiten¦ '/ Anpassung wenn erwünscht. Im Normalfall wird diese Breite anhand des breitesten Menüeintrages ¦ '/ der Menübezeichner automatisch eingestellt. ¦ '/ ¦ '/ Der dritte und letzte Schritt besteht darin eigene Makrofunktionen mit Leben zu füllen, die ¦ '/ dann vom PopUp-Menu aufgerufen werden sollen. In der Function [KontextMenu(..)] müssen dann ¦ '/ die Namen der Makroprozeduren und die PopUp-Menübezeichner in den PopUp-Arrays mit den eigenen ¦ '/ gewünschten Prozeduren korrespondieren. ¦ '/ ¦ '/ Unsere frmPopUp-Form ohne Titelleiste (per API entfernt) sieht wie ein Kontextmenü aus. Die ¦ '/ Menüpunkte selber bestehen aus dynamisch erstellten Label-Controls, dessen Hintergrundfarben¦ '/ und die Schriftfarben von Aussen parameterisiert pro PopUp-Aufruf angepasst werden kann. ¦ '/ ¦ '/ Um nicht für jedes Menü eine eigene Ereignis-Funktion einbauen zu müssen, habe ich über die ¦ '/ dyn. erstellten Menü-Labels (über die ganze Form) ein transparentes Label [PopUpAuswahl] pla- ¦ '/ ziert, und stelle dann rechnerisch so sicher (im MouseMove-Ereignis werden die Mauskoordinaten ¦ '/ laufend (alle 500 ms) aktualisiert) welche Label vom Anwender ausgewählt wurde. ¦ '/ Andererseits werden die Mauspositionen (Left und Top) auch dazu verwendet, festzustellen, ob ¦ '/ sich die Maus überhaupt noch über der Pseudo-Kontext befindet, wenn nicht, dann wird sie aus¦ '/ geblendet und der API-Timer mit KillTimer(..) wieder deaktiviert. ¦ '/ ¦ '/ Hinweis: Vorsicht beim Debuggen innerhalb eines PopUp-Aufrufes, da zu dieser Zeit ein sensibler API¦ '/ Timer (TimerProc(..)) läuft, der ein Abbruch im Debug-Modus mit einer Schutzverletzung dankt. ¦ '/ Innerhalb dieser periodisch aufgerufenen Timerfunktion muss alles fehlerfrei laufen, ansonsten ¦ '/ muss der API-Timer inaktiviert werden und der Ausblendmechanismus erfolgt dann zB. im Doppel¦ '/ klickereignis des transparenten-Klicklaber [PopUpAuswahl]. ¦ '/-----------------------------------------------------------------------------------------------------------'/-------- PopUp Hilfsvariablen -----------------------------------------------------------------------------Public varMenuNamen Public varMenuMakro Public lngMenuBackColo As Variant As Variant As Long ' enthält ein Array voller Menunamen ' enthält ein Array voller Makronamen ' Kontext-Hintergrundfarbe Public Public Public Public Public Public Public Public Public Public Public As As As As As As As As As As As ' ' ' ' ' ' ' ' ' ' ' lngMenuPtBreite lngMenuSelColor lngMenuFntColor lngMenuFntBkCol strAktivesControl hEvent hWndForm bCaption intPopXAchse intPopYAchse varPasteBug Long Long Long Long String Long Long Boolean Integer Integer Variant Menübreite für Std.Menü festlegen Selektionfarbe für Menuhintergrund Selektionfarbe für Menuschriftfarbe Unselektierte Fontfarbe Name des gerade aktiven Controls Enthält SetTimer-Prozessnummer für diese Form Handle für Titelbeschneidung alter Zustand X-Achsen-Koordinaten Y-Achsen-Koordinaten Sicher Absatzwerte und zurück (Bug) '/-------- PopUp-Konstanten ---------------------------------------------------------------------------------Public enuColor Public Enum enuColor Schwarz = &H12& Weiss = &HFFFFFF Hellgrau = &HE0E0E0 Dunkelgrau = &HFF8080 Blau = &HFF0000 Dunkelblau = &H800000 Hellblau = &HFF8080 Cyan = &HFFFF00 Gruen = &HC000& Grau = &H8000000A Dunkelgruen = &H8000& Hellgruen = &HFF00& Rot = &HFF& Dunkelrot = &H80& Hellrot = &H8080FF Gelb = &HFFFF& Dunkelgelb = &H8080& As Long ' Function StandardPopUp D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 44 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Violett = &HC000C0 Dunkelviolett = &H800080 Hellviolett = &HFF00FF Orange = &H80FF& Hellorange = &H80C0FF Dunkelorange = &H40C0& End Enum '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 25.04.2001 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Unsere PopUp-Funktionalität wurde mit zwei Modulen [mdlPopUp] [frmPopUp] realisiert. Die globale Funktion ¦ '/ [KontextMenu(..)], die nachfolgend aufgeführt ist, ist die eigentliche PopUp-Startroutine, in welcher ¦ '/ die einzelnen individuellen PopUp-Menüelemente bis auf einzelne Formcontrols herab, zentral definiert ¦ '/ sind und auch hier angepasst werden müssen, falls weitere Menüs (mit einem weiteren Makroaufruf) hinzu¦ '/ gefügt werden. ¦ '/ ¦ '/ Wichtig ist die eindeutige Namensvergabe bei den PopUp-Makroprozeduren die der Anwender durch Klick aus- ¦ '/ führt (müssen pro Projekt anders lauten) sodass auch mehrere Projekte geladen sein können, ohne sich ge- ¦ '/ genseitig störend zu beeinflussen. ¦ '/ ¦ '/ Die Funktionsargumente sind einfach gehalten, zwingend sind nur die ersten drei Parameter. Das 1. Arg. ¦ '/ enthält das Qeullcontrol auf welchem das PopUp-Menü erscheinen soll. Die X und Y - Mauskoordinaten ent¦ '/ nehmen wir der MouseUp-Ereignisprozedur (Weiterreichen) und sind notwendig für die Anzeige des Dialoges! ¦ '/ ¦ '/ Die Farb-Argumente 4 - 7 können per Enumerationskonstanten-Vorgaben per Punktoperator ausgewählt, oder ¦ '/ aber individuell mit einem (Hex) beliebigen Farbwert belegt werden. Das letzte Argument ist auch nicht ¦ '/ zwingend erforderlich, da die Menübreite anhand des längsten Menütextes automatisch eingestellt wird. ¦ '/ Dies kann mit Hilfe dieses achten Parameters durch eine Pixelangabe überschrieben werden. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub KontextMenu(InitialObjekt As Object, lngX, lngY, Optional lngSelMenuBackColor As enuColor, _ Optional lngSelMenuFontColor As enuColor, _ Optional lngSelMenuFontBackColor As enuColor, _ Optional lngMenuBackColor As enuColor, _ Optional intMenubreiteInPixel) Dim myForm As Object '/---------Standard-Kontextmenu-Einträge inkl. damit verknüpfter Makro definieren ----------------Select Case InitialObjekt.Name Case "rtfTBSInfos" ' Anhand eines bestimmten Controls anderes Menü zuweisen varMenuNamen = Array("Kopieren", "Ausschneiden", "Einfügen", "Alles markieren", _ "Text in Word einfügen") varMenuMakro = Array("W14Autotexte_Makro1", "W14Autotexte_Makro2", "W14Autotexte_Makro3", _ "W14Autotexte_Makro4", "W14Autotexte_Makro5") Case Else varMenuNamen = Array("Kopieren", "Ausschneiden", "Einfügen", "Alles markieren") varMenuMakro = Array("W14Autotexte_Makro1", "W14Autotexte_Makro2", "W14Autotexte_Makro3", _ "W14Autotexte_Makro4") End Select StandardPopUp InitialObjekt, lngX, lngY, lngSelMenuBackColor, lngSelMenuFontColor, _ lngSelMenuFontBackColor, lngMenuBackColor, intMenubreiteInPixel End Sub '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 25.04.2001 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Sind die beiden Module [mdlPopUp] [frmPopUp] vorhanden und ist die MouseUp-Ereignisroutine eines PopUp¦ '/ Controls mit der PopUp-Aufruffunktion KontextMenu() verbunden, werden die in dieser Aufrufroutine auf¦ '/ geführten Makronamen und Menübezeichner in den jeweiligen Arrays (den eigen Wünschen anpassen) bei einem ¦ '/ Klick auf dieses Kontextmenü verwendet. Die dazugehörigen Makroprozeduren (hier mit OLKontakte_ beginnend)¦ '/ folgen ab hier und werden auch individuell bestimmt. In diesem Projekt sind die klassischen Kopieren, ¦ '/ Ausschneiden, Einfügen und Alles markieren-Funktionalitäten erwünscht. ¦ '/ ¦ '/ Diese öffentlichen Makronamen müssen eindeutig vergeben werden, um Konflikte mit anderen gleichzeitig ¦ '/ genutzten Dokumentvorlagen zu vermeiden (welche auch mit diesen dynamischen PopUp-Elementen arbeiten)! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub W14Autotexte_Makro1() SendKeys "^c", False End Sub ' Auswahl in Zwischenablage kopieren Public Sub W14Autotexte_Makro2() SendKeys "^x", False End Sub ' In Zwischenablage auschneiden Public Sub W14Autotexte_Makro3() SendKeys "^v", False End Sub ' Aus Zwischenablage einfügen Public Sub W14Autotexte_Makro4() SendKeys "^a", False End Sub ' Alles Markieren Public Sub W14Autotexte_Makro5() SendKeys "^c", False Application.Selection.Paste End Sub ' Text in Word einfügen '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 25.04.2001 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Ein Standard-Kontextmenü für einzeilige Textfeld-Controls > Kopieren, Ausschneiden, Einfügen, markieren! ¦ '/ In dieser Routine sind keine Anpassungen nötig, die vorgeschaltete KontextMenu()-Funktion liefert die be- ¦ '/ nötigten Parameter selber. Hier wird die PopUp-Dialogform vorbereitet und angezeigt. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub StandardPopUp(InitialObjekt As Object, lngX, lngY, Optional lngSelMenuBackColor As enuColor, _ Optional lngSelMenuFontColor As enuColor, _ Optional lngSelMenuFontBackColor As enuColor, _ Optional lngMenuBackColor As enuColor, _ Optional intMenubreiteInPixel) On Error Resume Next Dim CP As POINTAPI D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 45 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Dim lngFocus As Long GetCursorPos CP '/-------- automatische Breiteneinstellung wenn keine erzwungene Formbreite angegeben wurde -----------------If IsMissing(intMenubreiteInPixel) = True Then intLenX = -1 For intZ = 0 To UBound(varMenuNamen) intR = Len(varMenuNamen(intZ)) If intR > intLenX Then intLenX = intR Next lngMenuPtBreite = Iif(intLenX < 0, 100, intLenX * 5) Else lngMenuPtBreite = Iif(intMenubreiteInPixel > 0, intMenubreiteInPixel, 100) End If lngMenuSelColor lngMenuFntColor lngMenuFntBkCol lngMenuBackColo = = = = Iif(lngSelMenuBackColor <> 0, lngSelMenuBackColor, &H800000) Iif(lngSelMenuFontColor <> 0, lngSelMenuFontColor, &HFFFFFF) Iif(lngSelMenuFontBackColor <> 0, lngSelMenuFontBackColor, &H12&) Iif(lngMenuBackColor <> 0, lngMenuBackColor, &H8000000A) InitialObjekt.Enabled = False Load frmPopUp Set frmPopUp.frmParentForm = InitialObjekt.Parent strAktivesControl = InitialObjekt.Name frmPopUp.Left = (CP.X / 1.44) - 10 frmPopUp.Top = (CP.y / 1.44) + ((CP.y / 16) - 10) InitialObjekt.Enabled = True frmPopUp.Show InitialObjekt.Enabled = False InitialObjekt.Enabled = True If IsNull(InitialObjekt) = False Then InitialObjekt.SetFocus ' ' ' ' Blau = &H800000 Weiss = &HFFFFFF Schwarz = &H12& Grau = &H8000000A ' Fokus zuweisen End Sub '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 12.01.1999 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Eine Wartepause (in Sekunden) um die Einfach/Doppelklick-Unterscheidung ermittelbar zu machen! ¦ '/-----------------------------------------------------------------------------------------------------------Public Function Timing(Zeit!, Optional bolDoEvent As Variant) Dim intDoEvent As Integer, Start As Variant intDoEvent = Iif(IsMissing(bolDoEvent) = False, 0, 1) Start = Timer Do If intDoEvent = 0 Then DoEvents If Timer < Start Then Zeit = Zeit - 86400 Loop Until (Timer - Start > Zeit) End Function ' Lokale Variablen definieren ' Startzeit speichern ' Mitternachtskorrektur '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 25.04.2001 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Diese in der frmOLKOntakt-Dialogform instanzierte API-Timerfunktion wird alle 250 ms aufgerufen und kon- ¦ '/ trolliert die aktuellen Maus-Bewegungskoordinaten des Kontextmenu (frmPopUp) um es auszublenden, ¦ '/ wenn der Anwender mit der Maus die Kontextfläche mit der Maus verlässt. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Dim intG As Integer, lngStartTop As Long, lngStartLeft As Long, lngEndeTop If uMsg = &H113 Then GetCursorPos CP intG = -1 lngStartTop = 1.3338 * frmPopUp.Top lngStartLeft = 1.3338 * frmPopUp.Left lngEndeTop = lngStartTop + (1.3338 * frmPopUp.Height) lngEndeLeft = lngStartLeft + (1.3338 * frmPopUp.Width) If CP.y < lngStartTop Or CP.y > lngEndeTop Then intG = 1 If CP.X < lngStartLeft Or CP.X > lngEndeLeft Then intG = 1 If intG < 0 Then Exit Sub VBA_Bibliothek.KillTimer 0&, hEvent Unload frmPopUp hEvent = 0 End If End Sub Long, ByVal lParam As Long) As Long, lngEndeLeft As Long, CP As POINTAPI ' ' ' ' ' ' Ermittle Mauskoordinaten Resultat in CP.X + CP.Y Obere Form-Startposition Linke Form-Startposition Top-Endposition nach Form Left-Endposition nach Form ' Arbeitsbereich vergleichen ' innerhalb dann Exit Sub ' Sonst Timer deaktivieren '/-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 25.04.2001 Update: 01.04.2002 Ver.: 1.50 ¦ '/ ¦ '/ Mit Hilfe dieser Prozedur wird die Titelleiste einer gewünschten Form (Fensterhandler) ausgebendet! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub SetUserFormStyle() Dim frmStyle As Long If hWndForm = 0 Then Exit Sub frmStyle = GetWindowLong(hWndForm, GWL_STYLE) If bCaption Then frmStyle = frmStyle Or WS_CAPTION Else frmStyle = frmStyle And Not WS_CAPTION End If SetWindowLong hWndForm, GWL_STYLE, frmStyle DrawMenuBar hWndForm End Sub [VBA-Formmodul]: frmPopUp /-----------------------------------------------------------------------------------------------------------'/ Autor: deckensattl.daniel@bluewin.ch Erstellt: 29.04.2003 Update: 12.05.2003 Ver.: 2.00 ¦ '/ ¦ '/ Zweck: PopUp-Menü für Winword ¦ '/ ¦ D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 46 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] '/ Ablauf: Um in unserem Editor mit dem gewohnten Kopieren/Ausschneiden/Einfügen-Dialog im Editierfeld ¦ '/ arbeiten zu können, bedarfte es etwas Nachhilfe, da VBA keine PopUp-Menüs von Haus aus unter¦ '/ stützt (kein Menüeditor bei den UserForms!). Unsere formPopUp-Form ohne Titelleiste (per API ¦ '/ entfernt) sieht wie ein Kontextmenü aus. Die Menüpunkte selber bestehen aus dynamisch erstell- ¦ '/ ten Label-Controls, dessen Hintergrundfarben- und die Schriftfarbe von Aussen parameterisiert ¦ '/ pro PopUp-Aufruf angepasst werden kann. ¦ '/ Um nicht für jedes Menü eine eigene Ereignis-Funktion einbauen zu müssen, habe ich über die ¦ '/ dyn. erstellten Menü-Labels (über die ganze Form) ein transparentes Label [PopUpAuswahl] pla- ¦ '/ ziert, und stelle dann rechnerisch so sicher (im MouseMove-Ereignis werden die Mauskoordinaten ¦ '/ laufend (alle 500 ms) aktualisiert) welche Label vom Anwender ausgewählt wurde. ¦ '/ Andererseits werden die Mauspositionen (Left und Top) auch dazu verwendet, festzustellen, ob ¦ '/ sich die Maus überhaupt noch über der Pseudo-Kontext befindet, wenn nicht, dann wird sie aus¦ '/ geblendet und der API-Timer mit KillTimer(..) wieder deaktiviert. ¦ '/ ¦ '/ Hinweis: Vorsicht beim Debuggen innerhalb eines PopUp-Aufrufes, da zu dieser Zeit ein sensibler API¦ '/ Timer (TimerProc(..)) läuft, der ein Abbruch im Debug-Modus mit einer Schutzverletzung dankt. ¦ '/ Innerhalb dieser periodisch aufgerufenen Timerfunktion muss alles fehlerfrei laufen, ansonsten ¦ '/ muss der API-Timer inaktiviert werden und der Ausblendmechanismus erfolgt dann zB. im Doppel¦ '/ klickereignis des transparenten-Klicklaber [PopUpAuswahl]. ¦ '/-----------------------------------------------------------------------------------------------------------Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer Option Explicit Public strAktivesCtrl Public frmParentForm Dim Mycmd As String As Object As control ' Gemeinsam verwendete Temporär-Stringvariabel ' Unter dem PopUp-Dailog vorhandene Dialogform! ' Modulspezifisches Label-Instanzen-Objekt '/-----------------------------------------------------------------------------------------------------------'/ Bei der Forminitialisierung wird die Fenster-Handlenr. der Form ermittelt und dann die Titelleiste ent¦ '/ fernt. Dann wird die entstandene Leerfläche eliminiert und der API-Timer (Mausbereich) eingerichtet. ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub UserForm_Initialize() On Error GoTo Abbruch If Val(Application.Version) >= 9 Then mdlPopUp.hWndForm = VBA_Bibliothek.FindWindow("ThunderDFrame", Me.Caption) Else mdlPopUp.hWndForm = VBA_Bibliothek.FindWindow("ThunderXFrame", Me.Caption) End If mdlPopUp.bCaption = False PopUpAufbau VBA_Bibliothek.SetUserFormStyle frmPopUp.Height = frmPopUp.Height - 10 If mdlPopUp.hEvent <> 0 Then VBA_Bibliothek.KillTimer 0&, mdlPopUp.hEvent mdlPopUp.hEvent = 0 End If mdlPopUp.hEvent = VBA_Bibliothek.SetTimer(0&, 0&, 500, AddressOf mdlPopUp.TimerProc) Exit Sub Abbruch: MsgBox Err.Description End Sub '/-----------------------------------------------------------------------------------------------------------'/ Diese Funktion baut dynamisch ein Kontextmenu auf unserer frmPopUp-Form auf. Die Menüs werden als Array ¦ '/ vor Aufruf des Dialoges zuerst zusammengestellt (varMenuNamen). In einem zweiten Array mit gleich viel ¦ '/ Elementen wie das erste Array (varMenuMakro) folgen die Makronamen, welche mit den Menus verknüpft sind. ¦ '/ Zudem kann die Selektionsfarbe des Kontextmenu-Hintergrund & der Balkenschriftfarbe angegeben werden (Lng)¦ '/ Wichtig sind die eindeutigen Makronamen, welche mit den Labels verknüpft werden, da diese als Public de- ¦ '/ finiert sein müssen (wird per Application.Run gestartet!) und auch funktionieren müssen, wenn z.B. in ¦ '/ einem zweiten offenen Wordprojekt auch dieselbe PopUp-Funktion implementiert ist. ¦ '/-----------------------------------------------------------------------------------------------------------Private Function PopUpAufbau() Dim strControlName As String, intStartPosTop As Integer Dim intZ As Integer, TmpLab As Object, intG As Integer On Error GoTo Abbruch intG = ((UBound(varMenuNamen) + 1) * 12) + 20 frmPopUp.Width = lngMenuPtBreite PopUpAuswahl.Caption = "" frmPopUp.Height = intG PopUpAuswahl.Height = intG frmPopUp.BackColor = lngMenuBackColo intStartPosTop = 1 For intZ = 0 To UBound(varMenuNamen) strControlName = "labADynMenu" & Format(intZ + 1, "00") Set Mycmd = frmPopUp.Controls.Add("Forms.Label.1", strControlName, True) Mycmd.Left = 1 Mycmd.Top = intStartPosTop Mycmd.Width = Iif(lngMenuPtBreite > 0, lngMenuPtBreite, 100) Mycmd.Height = 12 Mycmd.Caption = " " & varMenuNamen(intZ) Mycmd.ForeColor = lngMenuFntBkCol intStartPosTop = intStartPosTop + 12 Next frmPopUp.PopUpAuswahl.ZOrder msoBringToFront Exit Function Abbruch: MsgBox Err.Description End Function '/-----------------------------------------------------------------------------------------------------------'/ Klickt der Anwender einmal kurz auf die Kontextform, wird die Auswahl (Aktion) im TBS übernommen. Bleibt ¦ '/ der Anwender jedoch mit der linken Maustaste fortwährend auf der Form, kann er diese beliebig auf dem ¦ '/ Desktop verschieben, bis er mit der Maus loslässt. Fährt er dann mit der Maus ausserhalb des per API¦ '/ Timer-Funktion überwachten Kontextmenübereiches, wird die Form (mit Arbeitsvertrag.TimerProc) entladen! ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub PopUpAuswahl_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal y As Single) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 47 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] On Error GoTo Abbruch If hWndForm = 0 Then Exit Sub If Button = 1 Then mdlPopUp.Timing 0.25 If VBA_Bibliothek.TastenStatus(VK_LBUTTON) = True Then VBA_Bibliothek.ReleaseCapture VBA_Bibliothek.SendMessage hWndForm, WM_NCLBUTTONDOWN, HTCAPTION, 0 Else PopUpAuswahl_Click End If End If Exit Sub Abbruch: MsgBox Err.Description End Sub '/-----------------------------------------------------------------------------------------------------------'/ Bei einer getroffenen Kontext-Aktionsauswahl wird diese Klickroutine ausgeführt > Weitergabe & Unload ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub PopUpAuswahl_Click() Dim intPopWahl As Integer intPopWahl = Int((mdlPopUp.intPopXAchse) / 12) + 1 frmPopUp.Hide PopKlick intPopWahl End Sub '/-----------------------------------------------------------------------------------------------------------'/ ... eine getroffenen Kontextmenü-Aktionsauswahl führt die gewünschte Aktion am RTF-Text aus! ¦ '/-----------------------------------------------------------------------------------------------------------Private Function PopKlick(KlickNr) On Error Resume Next ' On Error GoTo Abbruch deaktiviert > wegen SetTimer !! frmParentForm.SetFocus frmParentForm.Controls(mdlPopUp.strAktivesControl).SetFocus Unload frmPopUp Application.Run MacroName:=varMenuMakro(KlickNr - 1) Exit Function Abbruch: MsgBox Err.Description End Function '/-----------------------------------------------------------------------------------------------------------'/ Wird mit der Maus über das Kontextmenü gefahren, werden alle darunterliegenden Labels auf ihre Standard- ¦ '/ Werte (BackColor & ForeColor) zurückgesetzt und nur das farbig untermalen, welches unter der Maus liegt! ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub PopUpAuswahl_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal y As Single) Dim ControlObjekt As Object Dim intPopWahl As Integer On Error GoTo Abbruch mdlPopUp.intPopXAchse = X mdlPopUp.intPopXAchse = y AlleControlsDeaktivieren intPopWahl = Int((mdlPopUp.intPopXAchse - 1) / 12) + 1 strAktivesCtrl = "labADynMenu" & Format(intPopWahl, "00") If intPopWahl > (UBound(varMenuNamen) + 1) Or intPopWahl = 0 Then ' Ausserhalb des Klickraums, Kontextmenu wird nun ausgeblendet frmPopUp.Hide Else Set ControlObjekt = frmPopUp.Controls(strAktivesCtrl) ControlObjekt.BackStyle = 1 ' fehlt Farbe wird blaue Hintergrundfarbe gesetzt, Fontfarbe sonst weiss ControlObjekt.BackColor = Iif(Val(mdlPopUp.lngMenuSelColor) = 0, &H800000, mdlPopUp.lngMenuSelColor) ControlObjekt.ForeColor = Iif(Val(mdlPopUp.lngMenuFntColor) = 0, &H80000005, mdlPopUp.lngMenuFntColor) End If Exit Sub Abbruch: ' MsgBox Err.Description Unload Me End Sub '/-----------------------------------------------------------------------------------------------------------'/ Bei angezeigter PopUp-Form werden beim Überfahren mit der Maus alle Farben zurückgesetzt ¦ '/-----------------------------------------------------------------------------------------------------------Private Function AlleControlsDeaktivieren() Dim intP As Integer Dim ControlObjekt As Object For intP = 0 To UBound(varMenuNamen) strAktivesCtrl = "labADynMenu" & Format(intP + 1, "00") Set ControlObjekt = frmPopUp.Controls(strAktivesCtrl) ControlObjekt.BackStyle = 0 ' Transparenter Hintergrund ControlObjekt.ForeColor = lngMenuFntBkCol ' Schwarze Schriftfarbe ControlObjekt.BackColor = &H8000000F ' Grauer Hintergrund vorgeben Next End Function '/-----------------------------------------------------------------------------------------------------------'/ Wird das Kontextmenü geschlossen wird per Terminate-Ereignis die API-Timer-Funktion deaktiviert!!! ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub UserForm_Terminate() If mdlPopUp.hEvent <> 0 Then VBA_Bibliothek.KillTimer 0&, mdlPopUp.hEvent mdlPopUp.hEvent = 0 End If End Sub '/-----------------------------------------------------------------------------------------------------------'/ Wird während der Kontextmenüanzeige die ESC-Taste gedrückt wird Form sofort ausgeblendet. ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) If KeyCode = 27 Then Unload Me D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 48 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] End Sub '/-----------------------------------------------------------------------------------------------------------'/ Wird auf die Form ein Doppelklick getätigt, dann wird dieser sogleich ausgeblendet ¦ '/-----------------------------------------------------------------------------------------------------------Private Sub UserForm_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Unload Me End Sub '/---------- PopUp-Ende -----------------------------------------------------------------------------------'/---------------------------------------------------------------------------------------------------------------------'/ Funktion: TastenStatus Erstellt: 1.7.01 Update: 26.10.01 Version: 1.10 ¦ '/ Argument: APITastenKonstante Typ: Long ' vbKey.... - Konstante, wie vbKeyShift, vbKeyControl ¦ '/ Rückgabe: Boolean-Wert ' Wahr wenn Taste gedrückt ist, False wenn nicht! ¦ '/ ¦ '/ Über diese Funktion erhalten wir von einer gewünschten Keyboard-Taste dess Zustand (gedückt) wenn wir die ¦ '/ gewünschte Taste als VB-Konstanten-Argument dieser Funktion übergeben (häufig sind vbKeyControl/.KeyMenu)! ¦ '/---------------------------------------------------------------------------------------------------------------------Private Function TastenStatus(API_VB_TastenKonstante As Long) As Boolean TastenStatus = CBool(GetAsyncKeyState(API_VB_TastenKonstante) And &H8000) End Function ' ermittelt Tastenstatus ' oder Maustastenstatus! In h alt sv e rz ei ch n i s an z eig en Um in einem grösseren Dokument schnell navigieren zu können eignet sich ein VBA-Dialog bestens, über welcher alle Überschriften angezeigt werden können um dann per Doppelklick angesprungen zu werden. Dieser Makro ist in diesem Dokument (W14Makroprogrammierung.dotm) enthalten und kann auch erweitert werden. Eine Besonderheit ist die Grössenanpassung des Dialoges, welches man zu Laufzeit an den Dialogform-Ränder vornehmen kann. Sehen wir uns diesen Wordmakro etwas genauer an. Im Haupt-VBA-Modul befinden sich zwei API-Funktionen, welche für die Grössenanpassung (Resize) der Dialogform zuständig sind. Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Public Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long Public Const HWND_TOPMOST = -1 Weiter gehört zur Grössenanpassung auch die Klasse clsUserForm, die mehrere API-Funktionen beherbergt um eben diese Vergrösserung zu ermöglichen. In dem Formmodul hat es folgende Variablen die ebenfalls zur Grössenanpassung gehören: Private m_objUserForm Private m_blnFormInit As clsUserForm As Boolean Private Sub UserForm_Activate() Set m_objUserForm = New clsUserForm Set m_objUserForm.Form = Me End Sub ' ermöglicht Dialog-Grössenanpassung ' Grössenanpassungs-Klasse instanzieren Private Sub UserForm_Terminate() ' Deinitialisierungsroutine beim Ende If bolSetTimerFunktionDeaktiviren = False Then TimerManagen False Set m_objUserForm = Nothing End Sub Private Sub UserForm_Resize() ' ' Bei Grössenänderungen, Positionen Code für die Formcontrols – Anpassung der Position und Grösse End Sub Hier der ganze Makrocode im Überblick: D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 49 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] [VBA-Modul]: mdlMakros '/-----------------------------------------------------------------------------------------------------------'/ Autor: daniel Deckensattl Email: disi@gmx.ch Erstellt: 03.12.2014 Update: 05.12.2014 Ver. 1.00 ¦ '/ ¦ '/ Zweck: Dieser Autostart-Makro ermöglicht das Navigieren im aktuellen Worddokument. ¦ '/-----------------------------------------------------------------------------------------------------------Public Declare Function SetTimer Lib "user32.dll" (ByVal hwnd As Long, ByVal nIDEvent As Long, _ ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long Public Declare Function KillTimer Lib "user32.dll" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Public Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long Public Public Public Public Const HWND_TOPMOST = -1 Const WM_TIMER = &H113 lngProgActionEvent As Long sBookmarkShortName As String ' Timer-Ereignis trifft ein Public Sub AutoOpen() ' Beim Öffnen des Dokumentes aufgerufen strDlgVisible = GetSetting("VBAProggen", "AppCFG", "DialogVisible") If strDlgVisible = "" Or strDlgVisible = "Wahr" Then InhaltAnzeigen End Sub Public Sub InhaltAnzeigen() frmBookmarksViewer.Show 0 End Sub Sub InhaltsverzeichnisAnzeigen(control As IRibbonControl) InhaltAnzeigen End Sub ' Zeigt Makro im Nicht-Modalen Modus an ' Kontextmenü-Aufruf (integrierte XML-Datei) '/-----------------------------------------------------------------------------------------------------------'/ Lädt der Anwender ein neues Dokument oder eine Vorlage in den Speicher, dann prüft diese API-Timer-Ereig- ¦ '/ nisfunktion alle 1000 ms, ob neue Textmarken hinzugekommen sind, oder gar wegfallen sollen. ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub TimerWordaction(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) Dim intCounter As Integer On Error Resume Next If uMsg = WM_TIMER Then If Selection.BookmarkID > 0 Then If ActiveDocument.Bookmarks.Count >= 1 Then For Each aBookmark In ActiveDocument.Bookmarks strName = aBookmark.Name If Selection.Range.BookmarkID = aBookmark.Range.BookmarkID Then Application.StatusBar = "BookmarkID: " & Selection.Range.BookmarkID & " Name: " & strName If sBookmarkShortName <> strName Then sBookmarkShortName = strName frmBookmarksViewer.getBookmarkInList strName End If End If Next aBookmark End If End If End If End Sub '/-----------------------------------------------------------------------------------------------------------'/ Der Timer für die Dokumentenwechselüberwachung kann hier per Funktionsaufruf gestartet oder mit Angaben ¦ '/ eines opt. False-Parameters entladen werden. Dies war nötig um bei Textbaustein-Kopieraktionen keine Pro- ¦ '/ bleme zu bekommen, indem vor einer Aktion der Timer entladen und erst nach ausgeführter Aktion wieder ge- ¦ '/ laden wird! ¦ '/-----------------------------------------------------------------------------------------------------------Public Sub TimerManagen(Optional bolStarten As Boolean = True) If bolStarten = True Then If lngProgActionEvent = 0 Then lngProgActionEvent = SetTimer(0&, 0&, 1000, AddressOf TimerWordaction) End If Else If lngProgActionEvent > 0 Then KillTimer 0&, lngProgActionEvent lngProgActionEvent = 0 End If End If End Sub [VBA-Formmodul]: frmBookmarksViewer '/-----------------------------------------------------------------------------------------------------------'/ Autor: daniel Deckensattl Email: disi@gmx.ch Erstellt: 03.12.2014 Update: 05.12.2014 Ver. 1.00 ¦ '/ ¦ '/ Zweck: Dieses Formmodul enthält alle Dialogelemente die für die Anzeige nötig sind. Kommen neue Über¦ '/ schriften im Dokument hinzu, wird dies beim Dialog angezeigt ¦ '/-----------------------------------------------------------------------------------------------------------Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer '/------------------------------------------------------------------- Schliessen deaktivieren ---------------Private Declare Function FindWindow Lib "user32" Alias _ "FindWindowA" (ByVal lpClassName As String, ByVal _ lpWindowName As String) As Long D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 50 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Private Declare Function GetSystemMenu Lib "user32" (ByVal _ hwnd As Long, ByVal bRevert As Long) As Long Private Declare Function DeleteMenu Lib "user32" (ByVal _ hMenu As Long, ByVal nPosition As Long, ByVal wFlags _ As Long) As Long Private Declare Function DrawMenuBar Lib "user32" (ByVal _ hwnd As Long) As Long Private Const SC_CLOSE As Long = &HF060 Private hWndForm As Long Private bCloseBtn As Boolean ' Per API das Icon Schliessen deaktivieren ' da sonst die SeTimer-Funktion nicht sauber ' entfernt wird! '/-------------------------------------------------------------------------------------------------------------Public varAllBookmarks Public varAllBookmarksText As Variant As Variant ' sammelt ' sammelt alle Bookmark-Namen alle Bookmark-Inhalte Public bolSetTimerFunktionDeaktiviren As Boolean ' unterbindung der SetTimer-Funktion Private m_objUserForm Private m_blnFormInit As clsUserForm As Boolean ' ermöglicht Dialog-Grössenanpassung Private Sub UserForm_Activate() Set m_objUserForm = New clsUserForm Set m_objUserForm.Form = Me End Sub ' Grössenanpassungs-Klasse instanzieren Private Sub UserForm_Initialize() bolSetTimerFunktionDeaktiviren = False ' Initialisierungsroutine beim Start '/---------------- Schliessen deaktivieren --------------If Val(Application.Version) >= 9 Then hWndForm = FindWindow("ThunderDFrame", Me.Caption) Else hWndForm = FindWindow("ThunderXFrame", Me.Caption) End If bCloseBtn = False SetUserFormStyle '/-------------------------------------------------------strDlgVisible = GetSetting("VBAProggen", "AppCFG", "DialogVisible") ckbDlgShow.Value = Iif(strDlgVisible = "" Or strDlgVisible = "Wahr", True, False) setNewBookmark "TempAusgangsOrt" AlleUeberschriftenSammeln ' Überschriften mit Textmarken austatten ActiveDocument.Bookmarks("TempAusgangsOrt").Select ActiveDocument.Bookmarks("TempAusgangsOrt").Delete Application.StatusBar = "BookmarkID: " & Selection.Range.BookmarkID If bolSetTimerFunktionDeaktiviren = False Then TimerManagen True End Sub Private Sub UserForm_Terminate() ' Deinitialisierungsroutine beim Ende If bolSetTimerFunktionDeaktiviren = False Then TimerManagen False Set m_objUserForm = Nothing End Sub Private Function AlleUeberschriftenSammeln() Dim strUeberschriftSammeln As String On Error GoTo Abbruch ActiveDocument.Application.ScreenUpdating = False lstInhalt.Clear Redim varAllBookmarks(1000) Redim varAllBookmarksText(1000) ' Listenfeld komplett löschen Selection.HomeKey Unit:=wdStory ' Am Dokumentenbeginn starten Selection.GoTo What:=wdGoToHeading ' Erste Überschrift selektieren Selection.EndKey Unit:=wdLine, Extend:=wdExtEnd Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtEnd strUeberschrift = Selection intZ = 0 While Len(strUeberschrift) > 1 ' Nur Absatz dann 1 Zeichen If lstInhalt.ListCount = 0 Then Selection.HomeKey Unit:=wdStory End If Selection.GoTo What:=wdGoToHeading ' Gehe zur nächsten Überschrift Selection.EndKey Unit:=wdLine, Extend:=wdExtEnd ' und selektiert bis Absatzende Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtEnd strUeberschrift = Selection If Len(Selection) < 2 Then ' Wird nichts mehr gefunden, dann strUeberschrift = "" ' Schlaufe beenden und zu Textbeginn Selection.HomeKey Unit:=wdStory ' fahren Else ' Überschrift gefunden nun Textmarke vergeben und in Listenfeld einfügen strUeberschriftSammeln = strUeberschrift strTextmarkenname = getCleanBookmarkName(strUeberschrift) ' Textmarkenname bilden (max. 32 Zeichen) setNewBookmark strTextmarkenname lstInhalt.AddItem strUeberschrift ' Textmarke setzten ' in Listenfenster darstellen D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 51 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung varAllBookmarks(intZ) = strTextmarkenname varAllBookmarksText(intZ) = strUeberschrift intZ = intZ + 1 Selection.MoveRight Unit:=wdCharacter, Count:=2 End If Deckensattl Daniel [08.01.2015] ' Name der Textmarke speichern ' Inhalt der Textmarke (für Sortierung) speichern ' Zwei Zeichen nach rechts fahren Wend Redim Preserve varAllBookmarks(intZ - 1) Redim Preserve varAllBookmarksText(intZ - 1) Selection.HomeKey Unit:=wdStory ' zum Dokumentenbeginn fahren ActiveDocument.Application.ScreenUpdating = True ' zum Dokumentenbeginn fahren Selection.HomeKey Unit:=wdStory Exit Function Abbruch: Application.StatusBar = Err.Description & " : " & strTextmarkenname ' möglichen Fehler in Statusbar anzeigen End Function '/-- Störenden Enter am Ende des Strings entfernen Private Function OhneEnter(Wert) sRes = Wert If InStr(1, Wert, vbCr, vbTextCompare) > 0 Then sRes = Left(sRes, Len(sRes) - 1) End If OhneEnter = sRes End Function '/-- Erstellt eine neue Textmarke Private Function setNewBookmark(strBookmarkname) With ActiveDocument.Bookmarks .Add Range:=Selection.Range, Name:=strBookmarkname .DefaultSorting = wdSortByName .ShowHidden = False End With End Function '/-- Die Listenanzeige beenden Private Sub btnCancel_Click() Unload frmBookmarksViewer End Sub '/-- Dialogstart beim Öffnen des Dokumentes verhindern/zulassen Private Sub ckbDlgShow_Click() SaveSetting "VBAProggen", "AppCFG", "DialogVisible", ckbDlgShow.Value End Sub '/-- Sortierung auf Wunsch einleiten Private Sub ckbSort_Click() If ckbSort.Value = True Then ArraySortAusgabe varAllBookmarksText, lstInhalt varAllBookmarks = ArraySortAusgabe(varAllBookmarks) Else AlleUeberschriftenSammeln End If End Sub '/-- Wird die Schaltfläche [Gehe zur selektierten Textmarke...] doppelgeklickt, dann zur Textmarke springen Private Sub btnGoTo_Click() If TastenStatus(vbKeyShift) = True Then For Each aBookmark In ActiveDocument.Bookmarks aBookmark.Delete Next aBookmark lstInhalt.Clear Application.StatusBar = "Alle Textmarken gelöscht" Else If lstInhalt.ListIndex = -1 Then Exit Sub ActiveDocument.Bookmarks(varAllBookmarks(lstInhalt.ListIndex)).Select Application.StatusBar = "BookmarkID: " & Selection.Range.BookmarkID & " Name: " & getBookmarkName(Selection.Range.BookmarkID) End If End Sub '/-- Wird das Listenfenster doppelgeklickt, dann zur Textmarke springen Private Sub lstInhalt_DblClick(ByVal Cancel As MSForms.ReturnBoolean) btnGoTo_Click End Sub '/-- löscht alle störenden Sonderzeichen aus Textmarkenname der verwendet werden soll Private Function getCleanBookmarkName(strNewTitel) sRes = strNewTitel If InStr(1, sRes, " ", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, " ") If InStr(1, sRes, "-", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "-") If InStr(1, sRes, "_", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "_") If InStr(1, sRes, ".", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, ".") If InStr(1, sRes, ":", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, ":") If InStr(1, sRes, ";", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, ";") If InStr(1, sRes, "+", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "+") If InStr(1, sRes, "<", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "<") If InStr(1, sRes, ">", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, ">") If InStr(1, sRes, "&", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "&") If InStr(1, sRes, "*", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "*") If InStr(1, sRes, "=", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "=") If InStr(1, sRes, "?", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "?") If InStr(1, sRes, "%", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "%") If InStr(1, sRes, ",", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, ",") If InStr(1, sRes, "/", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "/") If InStr(1, sRes, "\", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "\") If InStr(1, sRes, "(", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "(") If InStr(1, sRes, ")", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, ")") If InStr(1, sRes, "¦", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "¦") If InStr(1, sRes, "'", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, "'") If InStr(1, sRes, """", vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, """") If InStr(1, sRes, vbCr, vbTextCompare) > 0 Then sRes = delSearchCharacter(sRes, vbCr) D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 52 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] getCleanBookmarkName = sRes End Function '/-- löscht gewünschtes Sonderzeichen aus Textmarkenname der verwendet werden soll Private Function delSearchCharacter(strTitel, strCharacter) sRes = strTitel If InStr(1, strTitel, strCharacter, vbTextCompare) > 0 Then aRes = Split(strTitel, strCharacter, -1, vbTextCompare) sRes = "" For intZ = 0 To UBound(aRes) sRes = sRes & aRes(intZ) Next Else sRes = strTitel End If delSearchCharacter = sRes End Function '/-- Wird von der SetTimer-Funktion aufgerufen und selektiert Listeneintrag wenn nötig Public Function getBookmarkInList(strBookmarkShortName) For intZ = 0 To UBound(varAllBookmarks) If strBookmarkShortName = varAllBookmarks(intZ) Then lstInhalt.ListIndex = intZ Exit For End If Next If ActiveDocument.Bookmarks.Count <> lstInhalt.ListCount Then TimerManagen False AlleUeberschriftenSammeln If ckbSort.Value = True Then ckbSort_Click TimerManagen True End If End Function '/-- liefert anhand der übergebenen BookmarID den Bookmark-Namen Private Function getBookmarkName(intBookmarkID As Integer) Dim aBookmark As Bookmark sRes = "" For Each aBookmark In ActiveDocument.Bookmarks strName = aBookmark.Name If intBookmarkID = aBookmark.Range.BookmarkID Then sRes = strName End If Next aBookmark getBookmarkName = sRes End Function '/---------------------------------------------------------------------------------------------'/ Autor: Daniel Deckensattl Erstellt: 31.10.2014 Update: 31.10.2014 ¦ '/ ¦ '/ Zweck: Setzt oder liest einen Textmarken-Inhalt. Mit nur einem Parameter wird gelesen, ¦ '/ und mit zwei Parameter in die Textmarke geschrieben ¦ '/ Beispiel Lesen: TextBox1.Text = Bookmark("Titelinfo1") ¦ '/ Beispiel Schreiben: Bookmark "Titelinfo1", TextBox1.Text ¦ '/---------------------------------------------------------------------------------------------Private Function Bookmark(strBookmarkname As String, Optional strNewValue As String = "XXXNurLesenXXX") With ActiveDocument.Bookmarks If strNewValue = "XXXNurLesenXXX" Then strText = "" If .Exists(strBookmarkname) = True Then strText = .Item(strBookmarkname).Range End If Bookmark = strText Else If .Exists(strBookmarkname) = True Then Application.DisplayAutoCompleteTips = True Set MyRange = .Item(strBookmarkname).Range MyRange.Text = strNewValue MyRange.Select .Add Range:=Selection.Range, Name:=strBookmarkname End If End If End With End Function Private Sub UserForm_Resize() If m_objUserForm.gIsIconic = True Then Exit Sub ' Bei Grössenänderungen, Positionen ' und Grösse der Controls anpassen! Const cMinHght As Single = 100 Const cMinWdth As Single = 258 Const cGap As Single = 6 Dim sngTxtBoxHght As Single Dim sngTxtBoxWdth As Single If Me.Height < cMinHght Then Me.Height = cMinHght If Me.Width < cMinWdth Then Me.Width = cMinWdth Me.lstInhalt.Height = Me.InsideHeight - 60 Me.lstInhalt.Width = Me.InsideWidth - 15 Me.btnGoto.Move 8, Me.InsideHeight - (Me.btnGoto.Height + 10) Me.btnCancel.Move Me.InsideWidth - Me.btnCancel.Width - cGap, Me.InsideHeight - (Me.btnCancel.Height + 10) Me.ckbDlgShow.Move 10, Me.InsideHeight - (Me.ckbDlgShow.Height + 30) Me.ckbSort.Move Me.InsideWidth - (Me.ckbSort.Width + 5), Me.InsideHeight - (Me.ckbSort.Height + 30) End Sub '/-------------------------------------- Schliessen deaktivieren ----------------------------------------------- D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 53 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Private Sub SetUserFormStyle() Dim frmStyle As Long Dim hSysMenu As Long If hWndForm = 0 Then Exit Sub If bCloseBtn hSysMenu = Else hSysMenu = DeleteMenu End If Then GetSystemMenu(hWndForm, 1) GetSystemMenu(hWndForm, 0) hSysMenu, SC_CLOSE, 0& DrawMenuBar hWndForm End Sub '/--------------------------------------------------------------------------------------------------------------'/ Funktion: TastenStatus Erstellt: 1.7.01 Update: 26.10.01 Version: 1.20 ¦ '/ Argument: APITastenKonstante Typ: Long ' vbKey.... - Konstante, wie vbKeyShift, vbKeyControl ¦ '/ Rückgabe: Boolean-Wert ' Wahr wenn Taste gedrückt ist, False wenn nicht! ¦ '/ ¦ '/ Dies ist die erste nach Aussen offene Hilfsfunktion, die in allen VBA-Projekten bequem über einen Klassenver-¦ '/ weis und Aufruf abgerufen werden kann. In diesem Beispiel kann der aktuelle Tastenabfragestatus einer als vb-¦ '/ Konstante übergebenen Taste (zb vbKeyShift) ermittelt werden. Es wird ein Wahrheitswert zurückgegeben! ¦ '/--------------------------------------------------------------------------------------------------------------Public Function TastenStatus(APITastenKonstante As Long) As Boolean ' ermittelt Tastenstatus TastenStatus = CBool(GetAsyncKeyState(APITastenKonstante) And &H8000) ' oder Maustastenstatus! End Function '/-----------------------------------------------------------------------------------------------------------'/ Autor: disi@gmx.ch Erstellt: 16.03.03 Update: 19.06.03 Version 1.00 ¦ '/ ¦ '/ Zweck: Sortiert ein als Argument übergebenes eindim. Datenarray mit ADODB! Wird die maximale Grösse der ¦ '/ zu sortierenden Records nicht angegeben (lohnt sich bei tausenden von Records), ermittelt diese ¦ '/ Sortierroutine selbständig den grössten Wert und verwendet dies dann bei der ADODB-Sortierung! ¦ '/ Mit dieser dynamischen Grössenanpassung können somit auch sehr lange Zeichenketten noch akzep¦ '/ tabel umsortiert werden. ¦ '/ ¦ '/ Ausg.: Standardmässig gibt diese Funktion ein sortiertes Array der als Parameter angebenen Arraydaten ¦ '/ zurück. Durch die optionale Angabe eines Listencontrols (ComboBox, ListBox etc) oder sogar eines ¦ '/ Textfeld-Controlelementes (TextBox, RTFText etc.) kann eine ausgeführte Sortierung gleich in das ¦ '/ angegebene Control ausgegeben werden (spart Zeit und zusätzlichen Ausgabecode!). ¦ '/ ¦ '/ Arg.1: Ein eindim. zu sortierendes Variant-Array wird als ByVal übergeben (Tastet Urarray nicht an!) ¦ '/ Das Array wird sortiert und als Funktionsrückgabe erhalten wir eine sortierte Kopie der Daten. ¦ '/ ¦ '/ Arg.2: Mit Hilfe dieses optionalen Argumentes können wir das sortierte Ergebnis gleich in ein Listen¦ '/ Box-Control einfügen lassen (DropDown, CommandBarComboBox etc.)! ¦ '/ ¦ '/ Arg.3: Dieses Argument zeigt nur Wirkung, wenn ein Listencontrol angegeben wurde und kann entweder ein ¦ '/ Integer-Wert sein oder eine Strinzeichenkette. Hier können wir einen Index vorgeben, nachdem ¦ '/ die sortierten Daten im Listencontrol vorhanden sind. ¦ '/ ¦ '/ Arg.4: Mit einem True-Wert kann hier anstatt aufsteigend (Standard) absteigend sortiert werden. ¦ '/ ¦ '/ Arg.5: Ab einigen tausend Datensätzen bringt die Angabe der längste Stringzeichenkette enorm viel ¦ '/ Geschwindigkeitsvorteile, da die Längen- (automat.) -Berechnung nicht durchgeführt werden muss. ¦ '/-----------------------------------------------------------------------------------------------------------Public Function ArraySortAusgabe(SortArrayObjekt As Variant, Optional Optional Optional Optional lstObjListe, _ VorgabeIndex As Variant, _ bolAbsteigendSortieren As Boolean = False, _ MaxZeichenlaenge As Variant) Dim objRecordSet As Object ' ADODB.Recordset ' Object Dim SortArray As Variant ' Sortierarray-Kopie Dim strTextBox As String ' Textfeld-Ausgabezeichenkette Dim lngMaxLen As Long ' Anzahl der längsten Strings im Array Dim lngLen As Long ' Hilfsvariable für Längenscan '/---------------------------------- ADODB VIRTUELLE SORTIERUNG ---------------------------------------------On Error GoTo SortAbbruch intLstExist = -1 intTypAusgabe = 0 intIndex = -1 If IsMissing(VorgabeIndex) = False Then varVorgabe = VorgabeIndex Else varVorgabe = "" End If ' Bei Fehler unsortierte ' Funktionsrückgabe! ' Keine Ausgabe in Liste oder Textfeld SortArray = SortArrayObjekt If UBound(SortArray) > 0 Then ' Sortierarray abfüllen ' Grösse der Sortierelemente initial. lngMaxLen = -1 If IsMissing(MaxZeichenlaenge) = False Then ' Bei X-Tausenden von Datensätzen lngMaxLen = MaxZeichenlaenge ' kann mit Angaben der höchsten ZeichenElse ' anzahl in einem der Records Speed For intV = 0 To UBound(SortArray) ' herausgeholt werden, da dann diese lngLen = Len(SortArray(intV)): If lngLen > lngMaxLen Then lngMaxLen = lngLen Next ' nicht noch zuerst durchlaufen werden lngMaxLen = Iif(lngMaxLen = -1, 512, lngMaxLen) ' müssen (für automatischen Betrieb) End If Set objRecordSet = Nothing Set objRecordSet = CreateObject("ADODB.RecordSet") With objRecordSet .Fields.Append "rstSort", 200, lngMaxLen .Open ' adVarChar = 200 For intV = 0 To UBound(SortArray) .AddNew objRecordSet!rstSort = SortArray(intV) ' ' ' ' ADODB-Zugriffsobjekt wird instanziert und eine Feld "rstSort" wird virtuell erzeugt! ' Sortierdaten aufnehmen D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 54 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] .Update ' und in Feld speichern Next .Sort = "[rstSort]" ' Nun wird RecordSet sort. intZ = 0 If IsMissing(lstObjListe) = False Then lstObjListe.Clear: intLstExist = 1 intP = IsMissing(lstObjListe) If intP = False Then If lstObjListe.ListCount > 0 Then lstObjListe.Clear End If If bolAbsteigendSortieren = False Then ' Anhand des optionalen Sortier-Arg. ' Record-Cursor an den Beginn setzen .MoveFirst Else ' Record-Cursor ans Ende setzen .MoveLast End If Do While Not Iif(bolAbsteigendSortieren = False, .EOF, .BOF) ' Je nach Sortierrichtung ' diese in Ergebnis-Array zuweisen SortArray(intZ) = .Fields("rstSort").Value If IsMissing(lstObjListe) = False Then If SortArray(intZ) <> "" Then ' Bei Textboxen Ausgabe mit Enter! strControlTyp = TypeName(lstObjListe) Select Case strControlTyp Case "ComboBox", "ListBox", "CommandBarComboBox", "CommandBarPopUp" lstObjListe.AddItem SortArray(intZ) ' Sort. Werte in Liste abfüllen intTypAusgabe = 1 Case "TextBox", "RTFControl", "CommandBarButton" strTrenner = Iif(intZ = .Counts, "", vbCrLf) strTextBox = strTextBox & SortArray(intZ) & strTrenner intTypAusgabe = 2 End Select If varVorgabe <> "" Then ' das angegebene Listenfeld-Control! If TypeName(varVorgabe) = "String" Then If UCase(varVorgabe) = UCase(SortArray(intZ)) Then intIndex = lstObjListe.ListCount - 1 Else If Val(varVorgabe) = intZ Then intIndex = intZ End If End If End If End If intZ = intZ + 1 If bolAbsteigendSortieren = False Then ' Bei auf/absteigender Aufbereitung .MoveNext ' Nächster Datensatz Else .MovePrevious ' Vorheriger Datensatz End If Loop .Close ' RecordSet-Objekt schliessen If intTypAusgabe = 1 Then If intLstExist = 1 And intIndex <> -1 And varVorgabe <> "" Then _ lstObjListe.ListIndex = intIndex Else If intTypAusgabe = 2 Then lstObjListe = strTextBox ' Standardeigenschaft des Textfeldes End If End With Set objRecordSet = Nothing ' RecordSet-Objekt zerstören Else If IsEmpty(SortArray) = False Then If IsMissing(lstObjListe) = False Then lstObjListe.Clear If SortArray(0) <> "" And IsMissing(lstObjListe) = False Then lstObjListe.AddItem SortArray(0) If IsMissing(VorgabeIndex) = False Then If UCase(SortArray(0)) = UCase(VorgabeIndex) Then lstObjListe.ListIndex = 0 End If End If End If ArraySortAusgabe = SortArray ' und Sortarray zurückgeben! Exit Function SortAbbruch: ' Bei Fehler virtuelles ReSet objRecordSet = Nothing ' cordset wieder entfernen! ' Bei Fehler unsortierte Daten! ArraySortAusgabe = SortArray Application.StatusBar = "Fehler in ADODB-Sortiertroutine: " & Err.Description On Error GoTo 0 ' Errormeldung ignorieren End Function [VBA-Klassenmodul]: clsUserForm Option Explicit Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal _ lpWindowName As String) As Long Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex _ As Long) As Long Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex _ As Long, ByVal dwNewLong As Long) As Long Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function SetFocus Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function IsIconic Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function IsZoomed Lib "user32" (ByVal hwnd As Long) As Long Private Const GWL_STYLE As Long = (-16) Private Const WS_THICKFRAME As Long = &H40000 Private Const WS_SYSMENU As Long = &H80000 Private Const WS_MINIMIZEBOX As Long = &H20000 Private Const WS_MAXIMIZEBOX As Long = &H10000 Private Const SW_SHOW As Long = 5 D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 55 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung Private m_objUserForm Private m_hWndForm MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] As Object As Long Private Sub Class_Terminate() Set m_objUserForm = Nothing End Sub Public Property Set Form(ByVal objForm As Object) Dim nStyle As Long Set m_objUserForm = objForm m_hWndForm = FindWindow(vbNullString, m_objUserForm.Caption) If m_hWndForm <> 0 Then nStyle = GetWindowLong(m_hWndForm, GWL_STYLE) nStyle = nStyle Or WS_THICKFRAME Or WS_SYSMENU Or _ WS_MINIMIZEBOX Or WS_MAXIMIZEBOX SetWindowLong m_hWndForm, GWL_STYLE, nStyle ShowWindow m_hWndForm, SW_SHOW DrawMenuBar m_hWndForm SetFocus m_hWndForm End If End Property Public Property Get gIsIconic() As Boolean If m_hWndForm <> 0 Then gIsIconic = CBool(IsIconic(m_hWndForm)) End If End Property Public Property Get gIsZoomed() As Boolean If m_hWndForm <> 0 Then gIsZoomed = CBool(IsZoomed(m_hWndForm)) End If End Property [VBA-Klassenmodul]: ThisDocument Private Sub Document_New() strDlgVisible = GetSetting("VBAProggen", "AppCFG", "DialogVisible") If strDlgVisible = "" Or strDlgVisible = "Wahr" Then mdlMakros.InhaltAnzeigen End Sub D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 56 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Inhaltsverzeichnis Inhalt MS-Office 2010 Programmierung 1 Erste Schritte mit VBA 1 VBA-Editor aktivieren 2 Einstiegsmakros 3 Zoommodus anpassen 3 Suchen / Ersetzen - Makro 4 Makros entschlanken 4 Datumstabelle einfügen lassen 5 Kontextmenu-Einbindung 8 Scannerbild einfügen 8 Wiederverwendbarer Code 9 Sortier-Funktion für VBA 9 Sortierung mit dem Collection-Objekt 11 Ermöglicht Autovervollständigung bei ComboBox 11 Winword Dokumentvariable setzen/lesen 11 Textmarken lesen / schreiben 12 Wörterbuch um Begriffe erweitern 13 Alle Felder aktualisieren 13 Inhaltsverzeichnis aktualisieren mit Tabulatorerhalt 14 Autotext-Einträge anzeigen / hinzufügen 14 Markiert ab Cursorposition bis und mit gesuchtem Wort 14 Hyperlinks im Dokument entfernen 15 Drucke aktuelle Wordseite 15 Drucke aktuelle Markierung eines Worddokumentes 15 Drucken von 2 Seiten pro Blatt 15 Drucken von 4 Seiten pro Blatt 15 Jede Wordseite in ein neues Dokument stellen 16 Schriftenliste erstellen 17 Word-Wortliste in Excel erstellen 17 De-Aktiviert Hyperlink-Aktivierung 18 Genau Runden, auch auf 5 Rappen 18 VB(A)-Code in HTML 4.0 umwandeln 19 Aktualisiert nur Ref-Felder 21 Scanner-Einbindung auch mit Winword 2013 21 Seriendruck in einzelne Dokumente speichern 21 Windows-Funktionen nutzen 23 Tastenstatus abfragen 23 Pausen einbinden 23 Temporärer Pfad ermitteln 23 D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 57 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Benutzer-Name 24 Profilverzeichnis von angemeldeten Benutzer 24 Computer-Name 24 Druckernamen ermitteln 24 PC-Umgebungsvariablen ermitteln 24 Windows-Version ermitteln 25 Bildschirmauflösung ermitteln 25 Internet-Explorer mit URL anzeigen 26 Zwischenablage verwenden 26 Schaltjahr ermitteln 26 Monatsletzter 26 Ostern berechnen 27 Einfacher Datumskalender 27 Aus Registry lesen oder in diese schreiben 29 Liefert Dateiname oder Pfad 30 Outlooknachricht versenden 30 Verzeichnis auswählen 30 Dateisuche in Ordner und dessen Unterordner 31 Andere VBA-Applikationen aufrufen 31 Sperrt augenblicklich den Rechner mit Anmeldeschirm 32 Diese Funktion liefert den Inhalt einer externen Datei 32 Hier wird zeilenweise in eine externe Datei geschrieben: 33 Externe Datei starten über Dateiangabe 33 Optionen-Dialog mit WScript-SendKeys steuern 33 Worddateien laden über letzten Vorgabepfad 33 Dateien in Papierkorb löschen 35 Timer-Funktion 36 Mausposition lesen / setzen 37 Binär-Dezimal-Konverter 37 Freier Speicherplatz ermitteln 38 Mit Explorer Ordner Öffnen 38 Schliesst alle offenen InternetExplorer 39 URL-Validierung 39 Farbauswahl-Dialog von Windows nutzen 39 Wordregister aktivieren 40 PopUp-Kontextmen in VBA 42 Inhaltsverzeichnis anzeigen 49 Inhaltsverzeichnis Updateinformationen D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm 57 59 Seite 58 von 59 W14Makroprogrammierung VBA-Bibliothek und Schulung MS-Office 2010 VBA-Programmierung Deckensattl Daniel [08.01.2015] Up d at e in f o r mat io n en Beschreibung der Anpassungen Updatedatum Weitere Funktionen dokumentiert 08.01.2015 Kontextmenü eingebaut (XML-Dateiintegration) 05.12.2014 Inhaltverzeichnis-VBA-Manager erstellt 05.12.2014 Inhaltsverzeichnis erstellt 04.12.2014 Diverse Prozeduren eingefügt 04.12.2014 Grunddokumentation erstellt 03.12.2014 D:\Daten\Office\DDDot\VBA-Vorlagen\W14Makroprogrammierung\W14Makroprogrammierung.dotm Seite 59 von 59