{"id":55000383,"date":"2023-08-01T00:00:00","date_gmt":"2023-09-12T17:14:07","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=383"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"COMAddIn_fuer_Word_PDFExport","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/COMAddIn_fuer_Word_PDFExport\/","title":{"rendered":"COM-Add-In f&uuml;r Word: PDF-Export"},"content":{"rendered":"<p><b>Nachdem wir bereits gezeigt haben, wie man COM-Add-Ins f&uuml;r die Verwendung in anderen Office-Anwendungen nutzen kann, wollen wir nun auch einmal eines f&uuml;r Word programmieren. Die Aufgabe lautet, die verschiedenen Funktionen, die wir im Artikel &#8220;Word: PDF per VBA erzeugen&#8221; definiert haben, in Word f&uuml;r alle Dokumente bereitzustellen. Dazu erstellen wir ein neues COM-Add-In mit der Entwicklungsumgebung twinBASIC. Das COM-Add-In soll seine Funktionen per Ribbon bereitstellen, sodass der Benutzer mit wenigen Mausklicks die gew&uuml;nschten Exporte erzeugen kann. Dazu geh&ouml;rt der Export des vollst&auml;ndigen Dokuments, aller Seiten einzeln, eines bestimmten Bereichs, der aktuellen Seite oder auch von Bereichen, die durch bestimmte Formatierungen eingeleitet werden.<\/b><\/p>\n<p>Im Artikel <b>Word: PDF per VBA erzeugen <\/b>(<b>www.vbentwickler.de\/384<\/b>) haben wir einige Methoden gezeigt, wie wir den Inhalt von Word-Dokumenten in PDF-Dokumente exportieren k&ouml;nnen. Diese sehen wie folgt aus:<\/p>\n<ul>\n<li>Komplettes Dokument als PDF speichern<\/li>\n<li>Jede Seite als eigenes PDF-Dokument extrahieren<\/li>\n<li>Bereiche nach Seitenzahl exportieren<\/li>\n<li>Exportieren der aktuellen Seite<\/li>\n<li>Aufteilen nach Eigenschaften wie &Uuml;berschriften<\/li>\n<li>Speichern des markierten Textes in ein eigenes PDF-Dokument<\/li>\n<\/ul>\n<p>Diese Funktionen wollen wir nun in ein COM-Add-In integrieren, das die Funktionen f&uuml;r alle Dokumente in einem eigenen Tab im Ribbon anzeigt (siehe Bild 1). Hier sehen wir auch die M&ouml;glichkeit, die Seitenzahlen zum Exportieren eines Bereichs zu exportieren. Au&szlig;erdem k&ouml;nnen wir angeben, ob das PDF nach dem Export direkt ge&ouml;ffnet werden soll.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_04\/pic_383_001.png\" alt=\"Das Ribbon-Tab f&uuml;r die Exportfunktionen\" width=\"700\" height=\"228,9141\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Das Ribbon-Tab f&uuml;r die Exportfunktionen<\/span><\/b><\/p>\n<h2>Voraussetzungen<\/h2>\n<p>COM-Add-Ins wie dieses erstellen wir mit dem Tool <b>twinBASIC<\/b>, das f&uuml;r die Erstellung von 32-Bit-Anwendungen kostenlos verf&uuml;gbar ist. Mehr dazu findest Du in Artikeln wie <b>twinBASIC: Visual Basic f&uuml;r die Zukunft <\/b>(<b>www.vbentwickler.de\/310<\/b>) und <b>COM-Add-Ins mit twinBASIC <\/b>(<b>www.vbentwickler.de\/311<\/b>).<\/p>\n<p>Da dort die Basics zum Erstellen von COM-Add-Ins bereits ausf&uuml;hrlich dokumentiert wurden, konzentrieren wir uns hier auf die f&uuml;r unseren Anwendungszweck spezifischen Teile der Programmierung.<\/p>\n<h2>Starten des COM-Add-Ins<\/h2>\n<p>Beim Starten des COM-Add-Ins wird die Methode <b>OnConnection <\/b>der Schnittstelle <b>IDTExtentibility2 <\/b>aufgerufen (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>OnConnection(ByVal Application<span style=\"color:blue;\"> As Object<\/span>, ByVal ConnectMode<span style=\"color:blue;\"> As <\/span>ext_ConnectMode, ByVal AddInInst<span style=\"color:blue;\"> As Object<\/span>, _\r\n         ByRef custom<span style=\"color:blue;\"> As Variant<\/span>()) Implements IDTExtensibility2.OnConnection\r\n     <span style=\"color:blue;\">Set<\/span> objWord = Application\r\n     <span style=\"color:blue;\">Set<\/span> objWordEvents = Application\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Diese Prozedur wird beim Starten von Word aufgerufen<\/span><\/b><\/p>\n<p>Diese dient normalerweise dazu, einer Objektvariablen wie der folgenden einen Verweis auf die Anwendung hinzuzuf&uuml;gen, die das Add-In aufgerufen hat, in diesem Fall <b>Word.Application<\/b>. Diese landet in einem Standardmodul namens <b>mdlWord.twin<\/b>, weil wir von verschiedenen Modulen aus auf diese Variable zugreifen wollen:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>objWord<span style=\"color:blue;\"> As <\/span>Word.Application<\/pre>\n<p>Andererseits ben&ouml;tigen wir in diesem Fall aber auch die M&ouml;glichkeit, beim &Ouml;ffnen eines neuen Dokuments oder beim Wechseln zu einem anderen Dokument auf das entsprechende Ereignis zu reagieren. Das ist notwendig, weil wir in die beiden Felder <b>Erste Seite <\/b>und <b>Letzte Seite <\/b>des Ribbons die erste und die letzte Seite des aktuellen Dokuments eintragen wollen. Dazu deklarieren wir also noch eine Variable namens <b>objWordEvents<\/b>, diesmal mit dem Schl&uuml;sselwort <b>WithEvents<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents objWordEvents<span style=\"color:blue;\"> As <\/span>Word.Application<\/pre>\n<p>Diese f&uuml;llen wir und gleichzeitig implementieren wir die beiden Ereignisse <b>DocumentOpen <\/b>und <b>DocumentChange <\/b>f&uuml;r diese Variable:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objWordEvents_DocumentOpen(ByVal Doc<span style=\"color:blue;\"> As <\/span>_\r\n         Word.Document)\r\n     RibbonAktualisieren\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n     \r\n<span style=\"color:blue;\">Private Sub <\/span>objWordEvents_DocumentChange()\r\n     RibbonAktualisieren\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Beide rufen die folgende Prozedur auf, welche das aktuelle Dokument referenziert, sofern dieses &uuml;berhaupt vorhanden ist. Dann ermitteln wir die erste und die letzte Seite und schreiben diese in die Variablen <b>lngErsteSeite <\/b>und <b>lngLetzteSeite<\/b>. Diese Variablen deklarieren wir wiederum im Standardmodul <b>mdlWord.twin<\/b>.<\/p>\n<p>Schlie&szlig;lich rufen wir die <b>Invalidate<\/b>-Methode der mit <b>objRibbon <\/b>referenzierten Ribbon-Definition auf, damit diese die anzuzeigenden Werte mit den entsprechenden <b>get&#8230;<\/b>-Callbackfunktionen erneut aufruft:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>RibbonAktualisieren()\r\n     <span style=\"color:blue;\">Dim <\/span>objDocument<span style=\"color:blue;\"> As <\/span>Word.Document\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objRibbon Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objDocument = objWord.ActiveDocument\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objDocument Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n             lngErsteSeite = 1\r\n             lngLetzteSeite = objWord.ActiveDocument. _\r\n                 ComputeStatistics(wdStatisticPages)\r\n             objRibbon.Invalidate\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Ribbon des COM-Add-Ins definieren<\/h2>\n<p>Damit kommen wir zu einem wichtigen Element, n&auml;mlich der Schnittstelle zum Aufrufen der Funktionen des COM-Add-Ins. Diese definieren wir in der Funktion <b>GetCustomUI<\/b>, die beim Starten von Word automatisch aufgerufen wird. Hier setzen wir in der Variablen <b>strXML <\/b>die Ribbon-Definition zusammen und geben diese dann zur&uuml;ck (siehe Listing 2).<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>GetCustomUI(ByVal RibbonID<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span> Implements IRibbonExtensibility.GetCustomUI\r\n     <span style=\"color:blue;\">Dim <\/span>strXML<span style=\"color:blue;\"> As String<\/span>\r\n     strXML &= \"&lt;customUI xmlns=\"\"http:\/\/schemas.microsoft.com\/office\/2006\/01\/customui\"\" loadImage=\"\"loadImage\" _\r\n         & \"\"\" onLoad=\"\"onLoad\"\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"  &lt;ribbon startFromScratch=\"\"false\"\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"    &lt;tabs&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"      &lt;tab id=\"\"tab\"\" label=\"\"amvWordPDFExport\"\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"        &lt;group id=\"\"grp\"\" label=\"\"amvWordPDFExport\"\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;button id=\"\"btnExportKomplett\"\" size=\"\"large\"\" label=\"\"Komplett exportieren\"\" image=\" _\r\n         & \"\"\"word_pdf_book.ico\"\" onAction=\"\"onAction\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;button id=\"\"btnExportEinzelneSeiten\"\" size=\"\"large\"\" label=\" _\r\n         & \"\"\"Alle Seiten einzeln exportieren\"\" image=\"\"word_book_pdfs.ico\"\" onAction=\"\"onAction\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;button id=\"\"btnExportAktuelleSeite\"\" size=\"\"large\"\" label=\"\"Aktuelle Seite exportieren\"\" \" _\r\n         & \"image=\"\"word_pdf.ico\"\" onAction=\"\"onAction\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;button id=\"\"btnExportAktuelleMarkierung\"\" size=\"\"large\"\" label=\" _\r\n         & \"\"\"Aktuelle Markierung exportieren\"\" image=\"\"word_pdf_range.ico\"\" onAction=\"\"onAction\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;separator id=\"\"sep1\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;editBox id=\"\"txtErsteSeite\"\" label=\"\"Erste Seite\"\" onChange=\"\"onChange\"\" getText=\" _\r\n         & \"\"\"getText\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;editBox id=\"\"txtLetzteSeite\"\" label=\"\"Letzte Seite\"\" onChange=\"\"onChange\"\" getText=\" _\r\n         & \"\"\"getText\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;button id=\"\"btnExportBereich\"\" size=\"\"large\"\" label=\"\"Bereich exportieren\"\" image=\" _\r\n         & \"\"\"word_pdf_pages.ico\"\" onAction=\"\"onAction\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;checkBox id=\"\"chkOeffnen\"\" label=\"\"PDF nach Erstellen &ouml;ffnen\"\" getPressed=\" _\r\n         & \"\"\"GetPressedCheckBox\"\" onAction=\"\"onActionCheckBox\"\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"        &lt;\/group&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"      &lt;\/tab&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"    &lt;\/tabs&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"  &lt;\/ribbon&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"&lt;\/customUI&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     Return strXML\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000383\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000383?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000383\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"22c77db969\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem wir bereits gezeigt haben, wir man COM-Add-Ins f&uuml;r die Verwendung in anderen Office-Anwendungen nutzen kann, wollen wir nun auch einmal eines f&uuml;r Word programmieren. Die Aufgabe lautet, die verschiedenen Funktionen, die wir im Artikel &#8220;Word: PDF per VBA erzeugen&#8221; definiert haben, in Word f&uuml;r alle Dokumente bereitzustellen. Dazu erstellen wir ein neues COM-Add-In mit der Entwicklungsumgebung twinBASIC. Das COM-Add-In soll seine Funktionen per Ribbon bereitstellen, sodass der Benutzer mit wenigen Mausklicks die gew&uuml;nschten Exporte erzeugen kann. Dazu geh&ouml;rt der Export des vollst&auml;ndigen Dokuments, aller Seiten einzeln, eines bestimmten Bereichs, der aktuellen Seite oder auch von Bereichen, die durch bestimmte Formatierungen eingeleitet werden.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662023,66042023,44000004],"tags":[],"yst_prominent_words":[],"class_list":["post-55000383","post","type-post","status-publish","format-standard","hentry","category-662023","category-66042023","category-Loesungen"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000383","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000383"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000383\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000383"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}