Office-Zwischenablage mit VBA Löschen 2

    • VBA: Excel

      Office-Zwischenablage mit VBA Löschen 2

      Hallo liebe Community,

      Bei meinem ersten Beitrag "Office-Zwischenablage mit VBA löschen" hatte ich einen Weg beschrieben wie man Office Clipboard über VBA und API leeren kann
      Nun habe ich einen anderen Weg gefunden (Internet) und das will ich euch nicht vorenthalten.
      Ganz ohne API-Funktionen geht es leider nicht. Diesmal werden wir uns der Schnittstelle Microsoft Active Accessibility (% windir%\system32\oleacc.dll) bedienen um die Position aller sichtbaren Controls (Buttons) zu ermitteln.
      Der Code, den ich zur Verfügung stelle, läuft unter Excel 2010 (deutsche Version) 32bit.
      Meine Bemühungen den Code unter 64Bit-Excel zum Laufen zu bringen scheiterten jedoch. Beim Aufruf der Funktionen "Function GetWndText(ByVal hWnd As Long) As String" und/oder "Function FindChildWindow(ByVal hParent As Long, Optional cls As String = "", Optional title As String = "") As Long“ ist Excel jedes Mal abgestürzt.
      Ich würde mich freuen, wenn jemand den Code auf 64Bit-Excel portieren kann.
      Wer probieren will, kann den Quelcode kopieren und in einem allgemeinen Modul einfügen. Mit "Sub ClearOfficeClipboard ()" können Sie Office-Zwischenablage leeren. Mit "Sub Clear_Word_ClipBoard_From_Excel ()" kann die Office- Zwischenablage von Excel aus über "Word" gelöscht werden.

      Viel Spaß


      'Code


      Spoiler anzeigen

      Visual Basic-Quellcode

      1. Option Explicit
      2. Option Compare Text
      3. ''verwendung
      4. 'Sie brauchen einen Verweis auf "Accessibility" (% windir%\system32\oleacc.dll)
      5. 'Der Code funktioniert nur bei der deutschen Version von Office. _
      6. Für andere Sprachen müssen Sie den korrekten Wert für drei _
      7. 'Zeichenfolgen finden, die lokalisiert sind:
      8. '1) "Zusammenstellen und Einfügen 2.0" "Collect and Paste 2.0"
      9. '2) "Alle löschen" "Clear All"
      10. '3) "Office ClipBoard" "Office ClipBoard"
      11. Const CHILDID_SELF = 0&
      12. Const ROLE_TITLEBAR = &H1&
      13. Const ROLE_MENUBAR = &H2&
      14. Const ROLE_SCROLLBAR = &H3&
      15. Const ROLE_GRIP = &H4&
      16. Const ROLE_SOUND = &H5&
      17. Const ROLE_CURSOR = &H6&
      18. Const ROLE_CARET = &H7&
      19. Const ROLE_ALERT = &H8&
      20. Const ROLE_WINDOW = &H9&
      21. Const ROLE_CLIENT = &HA&
      22. Const ROLE_MENUPOPUP = &HB&
      23. Const ROLE_MENUITEM = &HC&
      24. Const ROLE_TOOLTIP = &HD&
      25. Const ROLE_APPLICATION = &HE&
      26. Const ROLE_DOCUMENT = &HF&
      27. Const ROLE_PANE = &H10&
      28. Const ROLE_CHART = &H11&
      29. Const ROLE_DIALOG = &H12&
      30. Const ROLE_BORDER = &H13&
      31. Const ROLE_GROUPING = &H14&
      32. Const ROLE_SEPARATOR = &H15&
      33. Const ROLE_TOOLBAR = &H16&
      34. Const ROLE_STATUSBAR = &H17&
      35. Const ROLE_TABLE = &H18&
      36. Const ROLE_COLUMNHEADER = &H19&
      37. Const ROLE_ROWHEADER = &H1A&
      38. Const ROLE_COLUMN = &H1B&
      39. Const ROLE_ROW = &H1C&
      40. Const ROLE_CELL = &H1D&
      41. Const ROLE_LINK = &H1E&
      42. Const ROLE_HELPBALLOON = &H1F&
      43. Const ROLE_CHARACTER = &H20&
      44. Const ROLE_LIST = &H21&
      45. Const ROLE_LISTITEM = &H22&
      46. Const ROLE_OUTLINE = &H23&
      47. Const ROLE_OUTLINEITEM = &H24&
      48. Const ROLE_PAGETAB = &H25&
      49. Const ROLE_PROPERTYPAGE = &H26&
      50. Const ROLE_INDICATOR = &H27&
      51. Const ROLE_GRAPHIC = &H28&
      52. Const ROLE_STATICTEXT = &H29&
      53. Const ROLE_TEXT = &H2A&
      54. Const ROLE_PUSHBUTTON = &H2B&
      55. Const ROLE_CHECKBUTTON = &H2C&
      56. Const ROLE_RADIOBUTTON = &H2D&
      57. Const ROLE_COMBOBOX = &H2E&
      58. Const ROLE_DROPLIST = &H2F&
      59. Const ROLE_PROGRESSBAR = &H30&
      60. Const ROLE_DIAL = &H31&
      61. Const ROLE_HOTKEYFIELD = &H32&
      62. Const ROLE_SLIDER = &H33&
      63. Const ROLE_SPINBUTTON = &H34&
      64. Const ROLE_DIAGRAM = &H35&
      65. Const ROLE_ANIMATION = &H36&
      66. Const ROLE_EQUATION = &H37&
      67. Const ROLE_BUTTONDROPDOWN = &H38&
      68. Const ROLE_BUTTONMENU = &H39&
      69. Const ROLE_BUTTONDROPDOWNGRID = &H3A&
      70. Const ROLE_WHITESPACE = &H3B&
      71. Const ROLE_PAGETABLIST = &H3C&
      72. Const ROLE_CLOCK = &H3D&
      73. Type tGUID
      74. lData1 As Long
      75. nData2 As Integer
      76. nData3 As Integer
      77. abytData4(0 To 7) As Byte
      78. End Type
      79. Type AccObject
      80. objIA As IAccessible
      81. lngChild As Long
      82. End Type
      83. 'Global objButton As AccObject
      84. Dim accButton As AccObject
      85. Const WM_GETTEXT = &HD
      86. Public lngChild As Long, strClass As String, strCaption As String
      87. Declare Function AccessibleObjectFromWindow Lib "oleacc" _
      88. (ByVal hWnd As Long, ByVal dwId As Long, _
      89. riid As tGUID, ppvObject As Object) As Long
      90. Declare Function AccessibleChildren Lib "oleacc" _
      91. (ByVal paccContainer As IAccessible, ByVal iChildStart As Long, _
      92. ByVal cChildren As Long, rgvarChildren As Variant, _
      93. pcObtained As Long) As Long
      94. Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
      95. ByVal lpClassName As String, _
      96. ByVal lpWindowName As String) As Long
      97. Declare Function GetParent Lib "user32" (ByVal hWnd As Long) As Long
      98. Declare Function EnumChildWindows Lib "user32" (ByVal hwndParent _
      99. As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
      100. Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, _
      101. ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
      102. Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, _
      103. ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
      104. Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
      105. ByVal hWnd2 As Long, ByVal lpClass As String, ByVal lpCaption As String) As Long
      106. Private Declare PtrSafe Sub Sleep Lib _
      107. "kernel32.dll" (ByVal dwMilliseconds As Long)
      108. '' Fensterklassenname
      109. Function GetWndClass(ByVal hWnd As Long) As String
      110. Dim buf As String, retval As Long
      111. buf = Space(256)
      112. retval = GetClassName(hWnd, buf, 255)
      113. GetWndClass = Left(buf, retval)
      114. End Function
      115. 'Fenstertitel
      116. Function GetWndText(ByVal hWnd As Long) As String
      117. Dim buf As String, retval As Long
      118. buf = Space(256)
      119. retval = SendMessage(hWnd, WM_GETTEXT, 255, buf)
      120. GetWndText = Left(buf, InStr(1, buf, Chr(0)) - 1)
      121. End Function
      122. 'Die Rückruffunktion von EnumChildWindows
      123. Function EnumChildWndProc(ByVal hChild As Long, ByVal lParam As Long) As Long
      124. Dim found As Boolean
      125. EnumChildWndProc = -1
      126. If strClass > "" And strCaption > "" Then
      127. found = StrComp(GetWndClass(hChild), strClass, vbTextCompare) = 0 And _
      128. StrComp(GetWndText(hChild), strCaption, vbTextCompare) = 0
      129. ElseIf strClass > "" Then
      130. found = (StrComp(GetWndClass(hChild), strClass, vbTextCompare) = 0)
      131. ElseIf strCaption > "" Then
      132. found = (StrComp(GetWndText(hChild), strCaption, vbTextCompare) = 0)
      133. Else
      134. found = True
      135. End If
      136. If found Then
      137. lngChild = hChild
      138. EnumChildWndProc = 0
      139. Else
      140. EnumChildWndProc = -1
      141. End If
      142. End Function
      143. 'Das Fensterhandle eines untergeordneten Fensters auf der Grundlage seiner Klasse und Titel finden
      144. Function FindChildWindow(ByVal hParent As Long, Optional cls As String = "", Optional title As String = "") As Long
      145. lngChild = 0
      146. strClass = cls
      147. strCaption = title
      148. Call EnumChildWindows(hParent, AddressOf EnumChildWndProc, 0)
      149. FindChildWindow = lngChild
      150. End Function
      151. 'Ruft die IAccessible-Schnittstelle aus einem Fensterhandle
      152. Function IAccessibleFromHwnd(hWnd As Long) As IAccessible
      153. Dim oIA As IAccessible
      154. Dim tg As tGUID
      155. Dim lReturn As Long
      156. With tg
      157. .lData1 = &H618736E0
      158. .nData2 = &H3C3D
      159. .nData3 = &H11CF
      160. .abytData4(0) = &H81
      161. .abytData4(1) = &HC
      162. .abytData4(2) = &H0
      163. .abytData4(3) = &HAA
      164. .abytData4(4) = &H0
      165. .abytData4(5) = &H38
      166. .abytData4(6) = &H9B
      167. .abytData4(7) = &H71
      168. End With
      169. 'Ruft das IAccessible Objekt für die Form
      170. lReturn = AccessibleObjectFromWindow(hWnd, 0, tg, oIA)
      171. Set IAccessibleFromHwnd = oIA
      172. End Function
      173. 'Rekursiv auf der Suche nach einem AccessibleChild mit angegebenen AccName und AccRole
      174. 'in der accessibility-Struktur (accessibility tree)
      175. Function FindAccessibleChild(oParent As IAccessible, strName As String, lngRole As Long) As AccObject
      176. Dim lHowMany As Long
      177. Dim avKids() As Variant
      178. Dim AHowMany As Long, i As Integer
      179. Dim oChild As IAccessible
      180. FindAccessibleChild.lngChild = CHILDID_SELF
      181. If oParent.accChildCount = 0 Then
      182. Set FindAccessibleChild.objIA = Nothing
      183. Exit Function
      184. End If
      185. lHowMany = oParent.accChildCount
      186. ReDim avKids(lHowMany - 1) As Variant
      187. AHowMany = 0
      188. If AccessibleChildren(oParent, 0, lHowMany, avKids(0), AHowMany) <> 0 Then
      189. MsgBox "Error retrieving accessible children!"
      190. 'MsgBox "Fehler beim Abrufen"
      191. Set FindAccessibleChild.objIA = Nothing
      192. Exit Function
      193. End If
      194. On Error Resume Next
      195. For i = 0 To AHowMany - 1
      196. If IsObject(avKids(i)) Then
      197. If StrComp(avKids(i).accName, strName) = 0 And avKids(i).accRole = lngRole Then
      198. Set FindAccessibleChild.objIA = avKids(i)
      199. Exit For
      200. Else
      201. Set oChild = avKids(i)
      202. FindAccessibleChild = FindAccessibleChild(oChild, strName, lngRole)
      203. If Not FindAccessibleChild.objIA Is Nothing Then
      204. Exit For
      205. End If
      206. End If
      207. Else
      208. If StrComp(oParent.accName(avKids(i)), strName) = 0 And oParent.accRole(avKids(i)) = lngRole Then
      209. Set FindAccessibleChild.objIA = oParent
      210. FindAccessibleChild.lngChild = avKids(i)
      211. Exit For
      212. End If
      213. End If
      214. Next i
      215. End Function
      216. Function FindAccessibleChildInWindow(hwndParent As Long, strName As String, lngRole As Long) As AccObject
      217. Dim oParent As IAccessible
      218. Set oParent = IAccessibleFromHwnd(hwndParent)
      219. If oParent Is Nothing Then
      220. Set FindAccessibleChildInWindow.objIA = Nothing
      221. Else
      222. FindAccessibleChildInWindow = FindAccessibleChild(oParent, strName, lngRole)
      223. End If
      224. End Function
      225. 'Generic Routine, die Fenster-Handle des aktiven Fensters einer Office-Anwendung
      226. Function GetOfficeAppHwnd(app As Object) As Long
      227. GetOfficeAppHwnd = FindWindow(vbNullString, GetOfficeAppWindowTitle(app))
      228. End Function
      229. ''Ruft das Fenster-Handle von Office ClipBoard
      230. 'Sie können die Fenster-Klasse und den Titel mit Spy, Inspect32 oder anderen Werkzeugen herausfinden
      231. Function GetOfficeTaskPaneHwnd(app As Object) As Long
      232. GetOfficeTaskPaneHwnd = FindChildWindow(GetOfficeAppHwnd(app), _
      233. "MsoCommandBar", "Office ClipBoard") '"Office ClipBoard"
      234. End Function
      235. 'Das Fenster Titel des Zwischenablage-Fensters scheint sprachabhängig zu sein,
      236. Function GetOfficeClipboardHwnd(app As Object) As Long
      237. GetOfficeClipboardHwnd = FindChildWindow(GetOfficeAppHwnd(app), , "Zusammenstellen und Einfügen 2.0") '"Collect and Paste 2.0"
      238. End Function
      239. 'Generic Routine
      240. '
      241. Function GetOfficeAppWindowTitle(app As Object) As String
      242. On Error GoTo ErrorHandler
      243. Select Case app.Name
      244. Case "Microsoft Word"
      245. GetOfficeAppWindowTitle = app.ActiveWindow.Caption & " - " & app.Name
      246. Case Else
      247. GetOfficeAppWindowTitle = app.Name & " - " & app.ActiveWindow.Caption
      248. End Select
      249. Exit Function
      250. ErrorHandler:
      251. MsgBox "Unsupported Office application!" 'Nicht unterstützte Office-Anwendung!
      252. GetOfficeAppWindowTitle = ""
      253. End Function
      254. 'Mit Active Accessibility Office-Zwischenablage löschen
      255. 'Voraussetzung Annahme:
      256. 'Dies läuft in Word oder Excel als Makro und die globalen Application-Objekte verfügbar
      257. Sub ClearOfficeClipboard()
      258. 'Static accButton As AccObject
      259. If accButton.objIA Is Nothing Then
      260. Dim fShown As Boolean
      261. fShown = CommandBars("Office ClipBoard").Visible
      262. ' Range("A1").Copy
      263. Sleep (1200)
      264. If Not (fShown) Then
      265. CommandBars("Office ClipBoard").Enabled = True
      266. CommandBars("Office ClipBoard").Visible = True
      267. End If
      268. accButton = FindAccessibleChildInWindow(GetOfficeClipboardHwnd(Application), "Alle löschen", ROLE_PUSHBUTTON) 'Clear All
      269. End If
      270. If accButton.objIA Is Nothing Then
      271. MsgBox "Unable to locate the ""Clear All"" button!"
      272. Else
      273. accButton.objIA.accDoDefaultAction accButton.lngChild
      274. 'MsgBox "Alles erledigt. Die Office Zwischenablage entleert"
      275. Set accButton.objIA = Nothing
      276. End If
      277. 'Ausgangzustand wiederherstellen
      278. CommandBars("Office ClipBoard").Visible = fShown
      279. Application.CutCopyMode = False
      280. End Sub
      281. ''' Mit Active Accessibility, die Office-Zwischenablage löschen
      282. '' Eingabe: app - als Application-Objekt von einer Office-Anwendung
      283. '' Annahme: Aufgabenbereich Zwischenablage wird in der Office-Anwendung gezeigt (app-Objekt)
      284. Function ClearOfficeClipboard_(app As Object) As Boolean
      285. Dim oButton As AccObject, fShow As Boolean
      286. oButton = FindAccessibleChildInWindow(GetOfficeClipboardHwnd(app), "Alle löschen", ROLE_PUSHBUTTON) 'Alle löschen 'Clear All
      287. If oButton.objIA Is Nothing Then
      288. MsgBox "Unable to locate the ""Clear All"" button!" '"Kann die Taste 'Alle Löschen' nicht lokalisieren"
      289. ClearOfficeClipboard_ = False
      290. Else
      291. oButton.objIA.accDoDefaultAction oButton.lngChild
      292. ClearOfficeClipboard_ = True
      293. End If
      294. End Function
      295. Sub Clear_Word_ClipBoard_From_Excel()
      296. Dim wdAnw As Object
      297. Dim wdDok As Object
      298. Dim Fehler
      299. 'Dim Wapp As Word.Application
      300. On Error Resume Next
      301. Set wdDok = GetObject(, "Word.Application") 'Word Instanz suchen
      302. Fehler = Err.Number
      303. On Error GoTo 0
      304. If Fehler = 429 Then
      305. Set wdAnw = CreateObject("Word.Application") 'Word Instanz generieren
      306. wdAnw.Visible = True 'word zeigen
      307. If wdAnw.Documents.Count <= 0 Then 'wenn kein dokument
      308. wdAnw.Documents.Add 'dokument zufügen
      309. End If
      310. Sleep (1000)
      311. Else
      312. Set wdAnw = GetObject(, "Word.Application") 'Word Instanz verbinden
      313. If wdAnw.Documents.Count <= 0 Then 'wenn kein dokument
      314. wdAnw.Documents.Add 'dokument zufügen
      315. End If
      316. Sleep (1000)
      317. End If
      318. If ClearOfficeClipboard_(wdAnw) Then
      319. MsgBox "Office-Zwischenablage ist geleert"
      320. End If
      321. 'ObjektVerweise nothing
      322. If Not wdAnw Is Nothing Then
      323. wdAnw.ActiveDocument.Saved = True
      324. wdAnw.ActiveDocument.Close
      325. wdAnw.Quit
      326. End If
      327. If Not wdAnw Is Nothing Then
      328. Set wdDok = Nothing
      329. Set wdAnw = Nothing
      330. End If
      331. End Sub


      ------------
      Dieser Code ist eine Erweiterung und basiert auf diesem Blog-Post: blogs.msdn.com/b/guowu/archive/2004/12/22/330231.aspx
      ------------

      Edit by hal2000:
      - Expander + Code-Tags eingefügt.
      - Quelle hinzugefügt.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hal2000“ ()