Anzeige
Archiv - Navigation
1756to1760
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Screenshot von PDF erstellen und einfüge

Screenshot von PDF erstellen und einfüge
05.05.2020 12:00:54
PDF
Hallo,
ich bräuchte mal eure Hilfe, ich habe mir in letzter Zeit schon einiges selbst beigebracht in Sachen VBA und konnte vieles erstellen.
Jetzt würde ich gerne ein Makro erstellen was ein PDF öffnet, dort von einer Seite einen Screenshot macht und diesen an einer bestimmten Stelle in meinem Tabellenblatt positioniert. Das einfügen und Positionieren von Bildern per VBA bekomme ich ja noch hin. Beim Scrennshot hört es dann aber auf.
Die PDF liegen immer in einem Pfad, den ich auch selber erzeugen kann was auch kein Problem ist. Die PDF haben feste Namen. Die PDF haben immer 1 - 3 Seiten. Hat die PDF nur eine Seite brauch ich den Screenshot von Seite 1. Hat die PDF 2 oder 3 Seiten brauche ich von jeder Seite außer der letzten einen Screenshot.
Wenn ich weiß wie ich von einer bestimmten Seite ein PDF erzeuge und wenn ich weiß wie ich die Seiten einer PDF zähle bekomme ich das vielleicht auch selber zusammen gebastelt.
vielen Dank schon mal für eventuelle Hilfe.
Gruß Sven

26
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Screenshot von PDF erstellen und einfüge
05.05.2020 15:50:42
PDF
Hallo Sven,
mir ist leider nicht bekannt, wie ich ganz einfach einen Screenshot von einer PDF-Seite machen könnte. Vielleicht hat ja jemand eine einfache Lösung
Einen Screenshot von einem Bildschirm(ausschnitt) zu machen ist bei Zuhilfenahme einiger API-Funktionen recht easy, das ganze jedoch passend aus einer PDF-Seite zu kreieren, schon deutlich schwieriger.
Mit nachfolgendem Code kannst Du zumindest im ersten Schritt eine PDF-Datei öffnen und einen Screenshot der ersten Seite in Deine Excelzeile ausgeben lassen.
Die Frage ist hierbei nur, was genau kopiert werden soll.
Im Code kannst Du die x/y-Positionen genau festlegen.
Könnte so passen, wenn die Seiten immer gleich aussehen und gleich in der richtigen Skalierung usw. angezeigt werden, weil eine dynamische Abfrage der Einstellungen des PDF habe ich nicht eingebaut.
Auch kann ich derzeit keine bestimmte Seite aktivieren.
Den Aufruf über evtl. Pageparameter will Shell nicht machen. Man könnte ggf. über keybdevent bzw. SendKeys in einer Schleife mehrere Seiten ansteuern.
Schau erst mal, ob Du es Dir so oder so ähnlich gedacht hattest.....
Code in die Zwischenablage
Option Explicit
'StartUp
Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
        ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
        ByVal lpParameters As String, ByVal lpDirectory As String, _
        ByVal nShowCmd As Long) As LongPtr
'DC-Funktionen
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" ( _
        ByVal hdc As LongPtr) As LongPtr
Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" ( _
        ByVal hdc As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
Private Declare PtrSafe Function SelectObject Lib "gdi32" ( _
        ByVal hdc As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare PtrSafe Function BitBlt Lib "gdi32" (ByVal hDestDC As LongPtr, _
        ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
        ByVal nHeight As Long, ByVal hSrcDC As LongPtr, ByVal xSrc As Long, _
        ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare PtrSafe Function StretchBlt Lib "gdi32" ( _
        ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long, _
        ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As LongPtr, _
        ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, _
        ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare PtrSafe Function DeleteDC Lib "gdi32" ( _
        ByVal hdc As LongPtr) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" ( _
        ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
'Window-Funktionen
Private Declare PtrSafe Function SetForegroundWindow Lib "user32" ( _
        ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
        ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" ( _
        ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, _
        ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type
'Clipboard-Funktionen
Private Declare PtrSafe Function OpenClipboard Lib "user32" ( _
        ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long
Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" ( _
        ByVal wFormat As Long) As Long
Private Declare PtrSafe Function SetClipboardData Lib "user32" ( _
        ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const SRCCOPY = &HCC0020
Private Const SW_MAXIMIZE = 3
Private Const WM_CLOSE = &H10
Private Const CF_BITMAP = 2
Sub PDF_ScreenShot()
'öffnet eine PDF-Datei und erstellt einen Screenshot, fügt diesen in Excel ein
 Dim sPathFile As String
 Dim rZiel As Range, rRette As Range, tRect As RECT
 Dim srcDC As LongPtr, trgDC As LongPtr, hBmp As LongPtr, hwnd As LongPtr
 Dim iLeft As Long, iTop As Long, iWidth As Long, iHeight As Long
 Dim i As Integer
 
'##### Hier die Quell/Zieldaten einstellen #####
 Set rZiel = ActiveCell                                             'Einfügeziel angeben
 sPathFile = "C:\Users\voltm\Documents\Adobedokumente\Auftragsbestätigung.pdf" 'PDF-Datei mit Pfad angeben
'###############################################
 
 If Dir$(sPathFile) <> "" Then
  ShellExecute 0&, "Open", sPathFile, 0, 0, SW_MAXIMIZE             'Datei öffnen im Vollbildmodus
'Warten bis PDF-Laden fertig und Handle ermitteln
  i = 0
  Do
   Sleep 100: i = i + 1
   hwnd = FindWindow("AcrobatSDIWindow", vbNullString)              'Windowhandel ermitteln
   If i > 100 Then
      MsgBox "Timeout: Prozedur wird abgebrochen!", vbCritical, "PDF-Screenshot"
      Exit Sub
   End If
   If hwnd <> 0 Then
     SetForegroundWindow hwnd
     Sleep 100
     If GetForegroundWindow() = hwnd Then Exit Do                   'PDF fertig geladen
   End If
  Loop
  Sleep 500
  GetWindowRect hwnd, tRect                                         'Windowkoordinaten holen
'##### Hier die Ausschnittsdaten einstellen #####
  iLeft = 100: iTop = 200
  iWidth = tRect.Right - iLeft - 100
  iHeight = tRect.Bottom - iTop - 50
'################################################
'Jetzt den Screenshot machen
  srcDC = GetDC(GetDesktopWindow())
  trgDC = CreateCompatibleDC(srcDC)                                 'Device Context erstellen
  hBmp = CreateCompatibleBitmap(srcDC, iWidth, iHeight)             'Bildausschnitt zuordnen
  SelectObject trgDC, hBmp                                          'Bild auswählen
  BitBlt trgDC, 0, 0, iWidth, iHeight, srcDC, iLeft, iTop, SRCCOPY  'Pixel kopieren
  OpenClipboard 0&: EmptyClipboard                                  'Zwischenablage öffnen
  SetClipboardData 2, hBmp: CloseClipboard                          'Bild rein und Zwischenablage schließen
  DeleteDC trgDC:   ReleaseDC hBmp, srcDC                           'Device Context schließen
'Bild ist jetzt in Zwischenablage
  If IsClipboardFormatAvailable(CF_BITMAP) Then
    Set rRette = ActiveCell
    rZiel.Select: ActiveSheet.Paste: rRette.Select                  'Screenshot einfügen
'Kein Bitmap in Zwischenablage
  Else
   MsgBox "Es wurde kein Bild kopiert!", vbCritical, "PDF-Screenshot"
  End If
  PostMessage hwnd, WM_CLOSE, 0&, 0&                                'PDF-Anwendung schließen
 Else
'Keine Datei gefunden
   MsgBox "Die PDF-Datei wurde nicht gefunden!", vbCritical, "PDF-Screenshot"
 End If
 Exit Sub
Fehler:
 MsgBox "Es ist der Fehler '" & Error & "' aufgetreten!", vbCritical, "PDF-Screenshot""
End Sub

viele Grüße
Karl-Heinz

Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 07:06:53
PDF
Hallo Karl-Heinz,
danke schonmal für deine Mühen. Das Makro funktioniert auch so wie bei dir beschrieben. Das Problem ist dabei, das scheinbar: ShellExecute 0&, "Open", sPathFile, 0, 0, SW_MAXIMIZE
nicht den Vollbildmodus aktiviert. Sondern das PDF Programm nur maximiert. Weshalb nur ein Teil der ersten Seite auf dem Bildschirm zu sehen ist. Mit diesem Teil funktioniert der Screenshot aber Einwandfrei.
Wenn ich aber im Adobe Reader die Standard Öffnung auf einzelne Seite in Fenstergröße einstelle dann ist zumindest schonmal die ganze Seite zu sehen.
Allerding macht er den Screenshot vom kompletten PDF Programm und nicht nur von der Seite. Also auch den grauen Bereich daneben alle Toolbars etc.
Ich weiß nicht ob es daran liegt das nicht im Vollbildmodus geöffnet wurde. Oder ob du genau das meintest mit einstellen der x/y Position. Dann könnte das eventuell klappen. Da es immer A4 Blätter sind die eingescannt wurden. Und ich brauche immer die komplette Seite.
Da bräuchte ich dann aber noch eine genaue Erklärung.
Vielleicht gibt es dafür ja noch eine Lösung.
Wie gesagt vielen Dank schonmal.
Gruß Sven
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 07:44:13
PDF
Hallo Karl-Heinz,
Ich nochmal. Habe mir das nochmal angeguckt und nach dem ersten Kaffee wurde es auch besser :-) Ich habe die Einstellungen mit den Koordinaten hinbekommen, so das er jetzt zumindest den Teil als Screenshot einfügt den ich haben will.
Für den Anfang super und vielen Dank.
Eine frage dazu, funktioniert die Einstellung jetzt nur optimal auf dem Bildschirm wo ich das eingestellt habe? Oder ist das egal? Nutze die Datei auf unterschiedlichen PCs.
Soweit so gut.
Vielleicht gibt es ja auch noch eine Lösung für mehrere Seiten.
Gruß Sven
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 08:52:22
PDF
Hallo Sven,
die Koordinaten, die Du eingestellt hast, gelten nur für den aktuellen Bildschirm. Bei anderen PC's könnten andere Auflösungen und Abmaße zu anderen Ergebnissen führen. Die Auflösung kann man abfragen und darauf reagieren. Seitdem ich Privatier bin, habe ich aber nur noch einen PC, da ist probieren schlecht.
Für ein anderes Programm hatte ich mal (vor langer Zeit) auch die Einstellungen der PDF-Seite berücksichtigt (Rand, Zusatzinformationen usw.). Man sieht, es ist da mehr möglich aber auch sehr aufwändig und man müsste sich erst viel Knowhow aneignen.
Mein Tipp bei mehreren PC's (falls es immer die geichen sind): Computernamen ermitteln und per Select die entsprechenden Koordinaten vorgeben....
Bzgl. der mehreren Seiten tüftel ich auch im Eigeninteresse noch dran rum, wenn ich Zeit dazu finde. Das kann aber noch etwas dauern....
bis dahin
KH
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 10:05:29
PDF
Hallo Karl Heinz,
das habe ich mir fast gedacht. Ist für den Anfang aber nicht so schlimm. Da kann ich erstmal mit arbeiten.
Dafür habe ich das Problem mit der Seite gelöst. Vielleicht hilft dir das auch weiter. Dann hat sich deine Hilfe wenigstens gelohnt :-)
Ich habe den Bereich ausgewechselt:
'##### Hier die Quell/Zieldaten einstellen #####
Set rZiel = ActiveCell                                             'Einfügeziel angeben
'sPathFile = "C:\Users\sven.roettjer\Documents\Bilder einfügen test\test.pdf" 'PDF-Datei mit  _
Pfad angeben
Const strAcroRd As String = "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" _
'Pfad vom Adobe Reade
sPathFile = "C:\Users\sven.roettjer\Documents\Bilder einfügen test\test.pdf"    'Pfad von der  _
PDF
Seite = 2
If Dir$(sPathFile)  "" Then
'ShellExecute 0&, "Open", sPathFile, strParameter, 0, SW_MAXIMIZE             'Datei öffnen  _
im Vollbildmodus
Shell Chr(34) & strAcroRd & Chr(34) & " /A page=" & Seite & " " & Chr(34) & sPathFile & Chr(34), vbMaximizedFocus     'Datei öffnen im Vollbildmodus und auf Seite

Wenn man so arbeitet dann öffnet er auf der Richtigen Seite. Zwar auch nicht so schön, weil theoretisch ja der Adobe Reader immer wo anders liegen kann, bzw eine andere Version etc. Aber es funktioniert.
Vielleicht weiß ja auch jemand wie man das machen kann ohne den Adobe Reader mit Pfad aufrufen zu müssen.
Falls ich mir nochmal was mit den Auflösungen überlegen will, habe ich noch nie gemacht bis jetzt, reichte es dann die Auflösung auszulesen, und die Quasi mit einem Prozentualen Umrechnungsfaktor auf die Koordinaten umzurechnen? Nach dem Motto Auflösung von PC2 ist 40% größer als PC1, Koordinaten auch um 40% vergrößern? Natürlich jeweils für X und Y? Oder stelle ich mir das gerade Falsch vor?
Vielen Dank auf jedenfall erstmal.
Vielleicht hat ja auch noch jemand anders andere Lösungen, aber für den Anfang super.
Gruß Sven
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 11:39:17
PDF
Hallo Sven,
danke für Deine Rückmeldung.
Die Übergabe der Anfangsseite via DOS-Parameter war mir bekannt. Ich hatte ja schon geschrieben, dass sie mit Shellexecute nicht funktioniert und an Shell wollte ich nicht ran. Hier muss man das Tool ja auch jedesmal neu aufrufen wenn man eine andere Seite haben will und wie Du ja auch schreibst, kann die Acrobat-Programmdatei auch mal woanders liegen.
Mein Zwischenstand ist, über keybd_event VK_NEXT, 0&, 0&, 0& die Seiten weiterzuschalten. Das klappt super, weil wegen des Screenshots die PDF-Seite ja ohnehin im Vordergrund liegen muss.
Jetzt fehlt eigentlich nur noch eine intelligente Schleifen-Steuerung und Festlegung der Vorgaben zu den Zielen; soll ja wohl nicht immer an die gleiche Stelle eingefügt werden?!
PS: Falls eine Verkleinerung des Screenshots mal sein müsste, das ist natürlich auch möglich...
Wenn Du also noch Bedarf haben solltest, teile noch mit, wo die Screenshots dann abgelegt werden sollen. Momentan werden sie ja einfach ins aktive Feld gesetzt.
VG KH
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 12:05:34
PDF
Hallo Karl-Heinz,
danke für die Rückmeldung.
Eine Schleifensteuerung für die Platzierung habe ich Bereit, die Berechnet direkt anhand der Größe der Fläche wo es hin soll die größe des Screenshots wenn er eingefügt werden soll.
Den Code muss ich ja dann nur noch mit deinem Code an der Stelle Screenshot "einfügen" austauschen.
Das soltle also kein Problem sein, da mein alter Code darauf basiert hat das ich die Screenshots manuell erstelle.
Hier mal der Code, der ist sicherlich nicht der schönste, und lässt sich evtl sogar vereinfachen aber er funktioniert. Habe mir das größtenteils selber zusammengesucht durch das Forum. Da ich noch nicht ganz so gut bin.
Set WS = ActiveSheet
With WS
.Unprotect
.Range("H2").Interior.Color = xlNone
.Paste
If TypeName(Selection) = "Picture" Then
If Range("L1").Value = "" Then
RDown = 56
RTop = 11
RBreite = Range("A:H").Width
With Selection
If (Range(Cells(RTop, 1), Cells(RDown, 1)).Height / (RBreite - 50))  "" Then
ActiveCell.Clear
MsgBox "Kein Bild in der Zwischenablage"
End If
End If
End With
End Sub
Interessant wäre jetzt noch ein Code der erkennt wie viel Seiten die PDF hat, um zu wissen wie Oft die schleife laufen muss.
Wie genau baue ich das kb_event ein?
Gruß Sven
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 12:22:22
PDF
Hi Sven,
hier ein Fragment, wie ich mir das gedacht habe. Ziele und die jeweilige Seitenangabe liegen in einem Array... (Vorsicht, das ist hier ist unvollständig)

'##### Hier die Ausschnittsdaten einstellen #####
  iLeft = 100: iTop = 200
  iWidth = tRect.Right - iLeft - 100
  iHeight = tRect.Bottom - iTop - 50
'################################################
'Jetzt den Screenshot machen
  For i = 0 To iAnzScreenshots - 1
   SetForegroundWindow hwnd
'x. Seite einstellen
   keybd_event VK_HOME, 0&, 0&, 0&                       'Erste Seite als Startpunkt
   For j = 1 To iSeite(i) - 1
     DoEvents: Sleep 50
     keybd_event VK_NEXT, 0&, 0&, 0&                     'Nächste Seite
   Next j

Die Ermittlung der Seitenanzahl kriegen wir vielleicht auch noch hin (Ggf. API). Ist halt alles aufwändig.
viele Grüße
Karl-Heinz
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 12:31:16
PDF
Hallo Sven,
leider habe ich gerade bemerkt, dass PageDown nicht die Seite weiterschaltet, sondern nur einen Abschnitt weiter und der hängt von der Größe ab. Kann man vielleicht mit leben wenn man mehrfach drücken lässt, war aber nicht so gedacht.
VG KH
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 13:15:47
PDF
Hallo Karl Heinz,
mit Page Down meinst du die Bild Runter Taste? Die wir mit dem keybd_event auslösen oder? Also unter meinen Einstellungen Blätter ich damit immer genau eine Seite weiter wenn das gemeint ist.
Ich habe wegen den Seitenzahlen noch mal gegoogelt. Aber das hast du ja Sicherlich auch. Ich habe auf einer anderen Seite folgende Funktion gefunden die Erfolgreich die Seitenzahl ermittelt.
Private Function GetPageCount( _
ByVal pvstrFileName As String) As Long
Dim strText As String
Dim strLinearized As String, astrCount() As String
Dim ialngIndex As Long
Dim objFileSystemObject As Object, objTextFile As Object
Dim objRegEx As Object, objMatch As Object, objItem As Object
Dim blnFound As Boolean
GetPageCount = -1
Set objFileSystemObject = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFileSystemObject.OpenTextFile(pvstrFileName, 1, False, 0)
Do Until objTextFile.AtEndOfStream
strText = objTextFile.ReadLine
strText = Replace(strText, vbLf, vbNullString)
If CBool(InStr(1, strText, "/Linearized")) Then
If Len(strText) > 20 Then
strLinearized = strText
blnFound = True
Exit Do
End If
End If
If CBool(InStr(1, strText, "/Count ")) Then
ReDim Preserve astrCount(ialngIndex)
astrCount(ialngIndex) = strText
ialngIndex = ialngIndex + 1
blnFound = True
End If
Loop
Call objTextFile.Close
Set objTextFile = Nothing
Set objFileSystemObject = Nothing
If blnFound Then
Set objRegEx = CreateObject("VBScript.RegExp")
With objRegEx
.MultiLine = True
.Global = True
.IgnoreCase = False
If strLinearized  vbNullString Then
.Pattern = "\/N.?(\d+).?"
Set objMatch = .Execute(strLinearized)
If objMatch.Count > 0 Then _
GetPageCount = CLng(objMatch(0).SubMatches(0))
Else
If ialngIndex = 1 Then
.Pattern = "\/Count.?(\d+)"
Set objMatch = .Execute(astrCount(0))
If objMatch.Count = 1 Then
GetPageCount = CLng(objMatch(0).SubMatches(0))
Else
For Each objItem In objMatch
GetPageCount = WorksheetFunction.Max( _
GetPageCount, CLng(objItem.SubMatches(0)))
Next
End If
Else
.Pattern = "\/Count.?(-?\d+)"
For ialngIndex = 0 To UBound(astrCount)
Set objMatch = .Execute(astrCount(ialngIndex))
GetPageCount = WorksheetFunction.Max( _
GetPageCount, CLng(objMatch(0).SubMatches(0)))
Next
End If
End If
End With
Set objMatch = Nothing
Set objRegEx = Nothing
End If
End Function
Also Testweise hat das bei mir Funktioniert.
Er müsste ja auch immer Screenshot machen, dann einfügen und dann den nächsten oder sehe ich das falsch? Sonst würden die sich ja gegenseitig überschreiben.
Echt super Nett das du dir soviel Zeit nimmst.
Gruß Sven
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 14:36:48
PDF
Hallo Sven,
das GetPageCount hatte ich auch gesehen aber nicht ausprobiert. Habe ich nur kurz überflogen und dachte, das brauchen wir nicht. Macht die PDF-Datei noch mal extra auf (Textmodus und sucht darin) und frisst Zeit.
Funktioniert das gut?
Werde ich dann doch mal ausprobieren, kann aber erst später hier weitermachen...
Also unter meinen Einstellungen Blätter ich damit immer genau eine Seite weiter wenn das gemeint ist.
Das hatte ich gemeint. Dann ist es bei Dir ja gut....
viele Grüße
Karl-Heinz
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 15:19:21
PDF
Hallo Karl Heinz,
naja was heißt gut, so viel Erfahrung habe ich nicht. Bei mir gibt es nur geht oder geht nicht. Und da das beim Test mit 3 PDF unter einer Sek gedauert hat, dachte ich joa geht.
Wenn du natürlich eine bessere Methode findest, würde ich die natürlich auch gerne kennenlernen.
Ich versuche gerade aus allen Bestandteilen ein funktionierendes Makro zu basteln, nur so kann man ja auch mehr lernen.
Bei mir funktioniert das mit dem:
keybd_event VK_NEXT, 0&, 0&, 0&

nicht.
Er sagt immer Variable nicht definiert und geht dann zu VK_NEXT. Aber das ist ja eigentlich keine Variable. Was genau übersehe ich denn da?
Gruß Sven
Anzeige
AW: Screenshot von PDF erstellen und einfüge
06.05.2020 18:05:34
PDF
Hallo Sven,
die Funktion zur Ermittlung der Seiten funktioniert gut und schnell. Habe keine bessere, aber andere Idee.
Ich hatte noch nie mit dem Texteditor in eine PDF geguckt. Hätte ich mal machen sollen, da sthet ja doch so einiges drin.
Habe mir deshalb trotzdem mal eine eigene Seitenzahlermittlung geschrieben, die für zwei Varianten (hoffentlich für alle) funktiniert und deutlich weniger Code benötigt.
Kannst sie ja auch mal ausprobieren, wenn Du möchtest. Ist im u.a. Code enthalten.
Ansonsten sende ich Dir mal meinen Zwischenstand zur Info oder weiteren Verwendung. Weiß nicht, was Du schon alles gemacht hast.
Ggf. wäre auch ein Hochladen Deiner Datei oder eMail-Zusendung mal interessant, wenn Du möchtest.
Bis auf die Ausgabe der Screenshots und/oder der Skalierung derselben (fehlt noch) müsste schon fast alles funktionieren...
PS: Zu Deiner Frage zu VK_NEXT, die Konstante muss natürlich gesetzt sein. S. u.a. Code
Code in die Zwischenablage
Option Explicit
Const VK_NEXT = &H22
Const VK_HOME = &H24
'StartUp
Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
        ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
        ByVal lpParameters As String, ByVal lpDirectory As String, _
        ByVal nShowCmd As Long) As LongPtr
Private Declare PtrSafe Sub keybd_event Lib "user32" ( _
        ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, _
        ByVal dwExtraInfo As Long)
'DC-Funktionen
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" ( _
        ByVal hdc As LongPtr) As LongPtr
Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" ( _
        ByVal hdc As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
Private Declare PtrSafe Function SelectObject Lib "gdi32" ( _
        ByVal hdc As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare PtrSafe Function BitBlt Lib "gdi32" (ByVal hDestDC As LongPtr, _
        ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
        ByVal nHeight As Long, ByVal hSrcDC As LongPtr, ByVal xSrc As Long, _
        ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare PtrSafe Function StretchBlt Lib "gdi32" ( _
        ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long, _
        ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As LongPtr, _
        ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, _
        ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare PtrSafe Function DeleteDC Lib "gdi32" ( _
        ByVal hdc As LongPtr) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" ( _
        ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
'Window-Funktionen
Private Declare PtrSafe Function SetForegroundWindow Lib "user32" ( _
        ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
        ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" ( _
        ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, _
        ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type
'Clipboard-Funktionen
Private Declare PtrSafe Function OpenClipboard Lib "user32" ( _
        ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long
Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" ( _
        ByVal wFormat As Long) As Long
Private Declare PtrSafe Function SetClipboardData Lib "user32" ( _
        ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const SRCCOPY = &HCC0020
Private Const SW_MAXIMIZE = 3
Private Const WM_CLOSE = &H10
Private Const CF_BITMAP = 2
Sub PDF_ScreenShot()
'öffnet eine PDF-Datei und erstellt einen Screenshot, fügt diesen in Excel ein
 Dim sPath As String, sFile As String, sTxt As String, sData As String
 Dim rZiel() As Range, rRette As Range, tRect As RECT
 Dim srcDC As LongPtr, trgDC As LongPtr, hBmp As LongPtr
 Dim hwnd As LongPtr, hThrdID As LongPtr
 Dim iLeft As Long, iTop As Long, iWidth As Long, iHeight As Long
 Dim i As Integer, j As Integer, iAnzScreenshots As Integer
'##### Hier die Quell/Zieldaten einstellen #####
 sPath = "C:\Users\voltm\Documents\Adobedokumente\"      'Pfad angeben
 sFile = "Auftragsbestätigung.pdf"                       'PDF-Datei angeben
'###############################################
 
 If Dir$(sPath & sFile) <> "" Then                       'Datei vorhanden?
 
'Anzahl der Seiten ermitteln
  iAnzScreenshots = GetPageCount(sPath & sFile) - 1
  If iAnzScreenshots < 0 Then iAnzScreenshots = 0
 
  ReDim rZiel(iAnzScreenshots)
'##### Hier die Zielpositionen einstellen #####
  For i = 0 To iAnzScreenshots
    Set rZiel(i) = ActiveCell.Offset(0, i)               'Einfügeziel(e) angeben
  Next i
'##############################################
  ShellExecute 0&, "Open", sPath & sFile, 0, 0, 3        'Datei öffnen im Vollbildmodus
'Warten bis PDF-Laden fertig und Handle ermitteln
  i = 0
  Do
   Sleep 100: i = i + 1
   hwnd = FindWindow("AcrobatSDIWindow", vbNullString)   'Windowhandle ermitteln
   If i > 100 Then
     sTxt = "Timeout: Prozedur wird abgebrochen!": GoTo MsgTxt
   End If
   If hwnd <> 0 Then
     SetForegroundWindow hwnd
     Sleep 100
     If GetForegroundWindow() = hwnd Then Exit Do        'PDF fertig geladen?
   End If
  Loop
  Sleep 500: GetWindowRect hwnd, tRect                   'Windowkoordinaten holen
'##### Hier die Ausschnittsdaten einstellen #####
  iLeft = 100: iTop = 200
  iWidth = tRect.Right - iLeft - 100
  iHeight = tRect.Bottom - iTop - 50
'################################################
'Jetzt den Screenshot machen
  For i = 0 To iAnzScreenshots
   SetForegroundWindow hwnd                              'PDF in den Vordergrund
'x. Seite einstellen
   keybd_event VK_HOME, 0&, 0&, 0&                       'Erste Seite als Startpunkt
   For j = 1 To i
     DoEvents: Sleep 50
     keybd_event VK_NEXT, 0&, 0&, 0&                     'Nächste Seite
   Next j
 Sleep 2000
   srcDC = GetDC(GetDesktopWindow())                     'Device Context holen
   trgDC = CreateCompatibleDC(srcDC)                     'Device Context erstellen
   hBmp = CreateCompatibleBitmap(srcDC, iWidth, iHeight) 'Bildausschnitt zuordnen
   SelectObject trgDC, hBmp                              'Bild auswählen
   BitBlt trgDC, 0, 0, iWidth, iHeight, _
          srcDC, iLeft, iTop, SRCCOPY                    'Pixel 1:1 kopieren
   OpenClipboard 0&: EmptyClipboard                      'Zwischenablage öffnen
   SetClipboardData 2, hBmp: CloseClipboard              'Bild rein, Zwischenablage schließen
   DeleteDC trgDC:   ReleaseDC hBmp, srcDC               'Device Context schließen
   If IsClipboardFormatAvailable(CF_BITMAP) Then
'Bild ist jetzt in der Zwischenablage
     Set rRette = ActiveCell                             'Akt. Zelle retten
     rZiel(i).Select: ActiveSheet.Paste: rRette.Select   'Screenshot einfügen
   Else
'Kein Bitmap in der Zwischenablage
     sTxt = "Es wurde kein Bild kopiert!"
     If i = 0 Then GoTo MsgTxt
   End If
  Next i
 
  PostMessage hwnd, WM_CLOSE, 0&, 0&                     'PDF-Anwendung schließen
 
 Else
'Keine Datei gefunden
   sTxt = "Die PDF-Datei wurde nicht gefunden!": GoTo MsgTxt
 End If
 Exit Sub
Fehler:
 sTxt = "Es ist der Fehler '" & Error & "' aufgetreten!""
MsgTxt:
 MsgBox sTxt, vbCritical, "PDF-Screenshot"
End Sub
Private Function GetPageCount(ByVal sFile As String) As Long
'Ermittelt die Seitenanzahl einer PDF-Datei
 Dim sData As String, S1 As String, S2 As String, iFF As Byte
 On Error Resume Next
 iFF = FreeFile
 Open sFile For Binary Access Read As #iFF
 sData = Space(LOF(iFF)): Get #iFF, , sData: Close #iFF
 S1 = "/Type /Pages"
 If InStr(sData, S1) > 0 Then
    S2 = "/Count"
 Else
    S1 = "/Linearized": If InStr(sData, S1) > 0 Then S2 = "/N"
 End If
 GetPageCount = Val(Left$(Trim$(Split(Split(sData, S1)(1), S2)(1)), 2))
End Function

viele Grüße
Karl-Heinz

AW: Screenshot von PDF erstellen und einfüge
07.05.2020 08:23:41
PDF
Guten Morgen Karl Heinz,
erst einmal noch mal Danke, kann ich gar nicht oft genug sagen.
Ich habe deinen Code eben gerade getestet, und er fügt nur einen Screenshot ein. Egal wie viel Seiten die PDF hat. Bei der GetPageCount von die kommt 0 raus wenn ich das per Hand durch gehe. Kann das eventuell an der PDF Version liegen? Meine ist 1.6 wenn ich das mit Txt Editor öffne.
Danke für die Erklärung das die Konstanten rein müssen, ja so ist es Logisch, gibt es eine Liste welche &H für welche Taste ist?
Meine komplette Datei darf ich leider nicht Hochladen, könnte nur die Sachen um die es geht Anonymisieren aber dann bringt es glaube ich nichts mehr. Weil letztlich gibt es für jede PDF einen Reiter wo die PDF eingefügt werden. Und in einem Modul ist dann mein Code, da kann ich hier auch meinen Code reinkopieren, ich denke das hat den selben Effekt. Ansonsten sag noch mal bescheid.
Deshalb habe ich in meinem Code die PDF mal nach den Reitern umbenannt und lasse Ihn die so Automatisch suchen.
Mit folgendem Code funktioniert das jetzt auf jeden Fall wie gedacht.
Option Explicit
Const VK_NEXT = &H22
Const VK_HOME = &H24
Private Declare PtrSafe Sub keybd_event Lib "user32" ( _
ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, _
ByVal dwExtraInfo As Long)
'StartUp
Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As LongPtr
'DC-Funktionen
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" ( _
ByVal hdc As LongPtr) As LongPtr
Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" ( _
ByVal hdc As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
Private Declare PtrSafe Function SelectObject Lib "gdi32" ( _
ByVal hdc As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare PtrSafe Function BitBlt Lib "gdi32" (ByVal hDestDC As LongPtr, _
ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal hSrcDC As LongPtr, ByVal xSrc As Long, _
ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare PtrSafe Function StretchBlt Lib "gdi32" ( _
ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As LongPtr, _
ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, _
ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare PtrSafe Function DeleteDC Lib "gdi32" ( _
ByVal hdc As LongPtr) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" ( _
ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
'Window-Funktionen
Private Declare PtrSafe Function SetForegroundWindow Lib "user32" ( _
ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" ( _
ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, _
ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As  _
RECT) As Long
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
'Clipboard-Funktionen
Private Declare PtrSafe Function OpenClipboard Lib "user32" ( _
ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long
Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" ( _
ByVal wFormat As Long) As Long
Private Declare PtrSafe Function SetClipboardData Lib "user32" ( _
ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const SRCCOPY = &HCC0020
Private Const SW_MAXIMIZE = 3
Private Const WM_CLOSE = &H10
Private Const CF_BITMAP = 2
Sub PDF_ScreenShot()
'öffnet eine PDF-Datei und erstellt einen Screenshot, fügt diesen in Excel ein
Dim rZiel As Range, rRette As Range, tRect As RECT
Dim srcDC As LongPtr, trgDC As LongPtr, hBmp As LongPtr, hwnd As LongPtr
Dim iLeft As Long, iTop As Long, iWidth As Long, iHeight As Long, AnzahlScreens As Long
Dim i, j As Integer
Dim sPathFile As String, Seite As Long
Dim WS As Worksheet
Dim RTop, RDown, RBreite
'Seitenzahlen der PDF in ein Array
Const FOLDER_PATH = "C:\PDF einfügen test\" 'Ordner in dem sich die PDF's nefinden
Dim strFileName As String
Dim lngRow As Long
Dim MyArray(2, 1) As Variant
ActiveWorkbook.Unprotect
With Application
.ScreenUpdating = False
.EnableEvents = False
.Calculation = xlCalculationManual
.DisplayStatusBar = True
End With
strFileName = Dir$(FOLDER_PATH & "*.pdf")
Do Until strFileName = vbNullString
Application.StatusBar = strFileName
MyArray(lngRow, 0) = strFileName
MyArray(lngRow, 1) = GetPageCount(FOLDER_PATH & strFileName)
lngRow = lngRow + 1
strFileName = Dir$
Loop
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = xlCalculationAutomatic
.StatusBar = False
End With
'Zugehöriges Tabellenblatt auswählen ---> wo PDF eingefügt werden soll
For j = 0 To 2
Set WS = Worksheets(Left(MyArray(j, 0), Len(MyArray(j, 0)) - 4))
Seite = MyArray(j, 1)
AnzahlScreens = 0
'##### Hier die Quell/Zieldaten einstellen #####
sPathFile = "C:\Users\sven.roettjer\Documents\Bilder einfügen test\" & MyArray(j, 0) 'PDF- _
Datei mit Pfad ermitteln
If Dir$(sPathFile)  "" Then
ShellExecute 0&, "Open", sPathFile, 0, 0, SW_MAXIMIZE             'Datei öffnen im  _
Vollbildmodus
'Warten bis PDF-Laden fertig und Handle ermitteln
i = 0
Do
Sleep 100: i = i + 1
hwnd = FindWindow("AcrobatSDIWindow", vbNullString)              'Windowhandel ermitteln
If i > 100 Then
MsgBox "Timeout: Prozedur wird abgebrochen!", vbCritical, "PDF-Screenshot"
Exit Sub
End If
If hwnd  0 Then
SetForegroundWindow hwnd
Sleep 100
If GetForegroundWindow() = hwnd Then Exit Do                   'PDF fertig geladen
End If
Loop
Sleep 500
GetWindowRect hwnd, tRect                                         'Windowkoordinaten holen
'##### Hier die Ausschnittsdaten einstellen #####
iLeft = 605: iTop = 140
iWidth = tRect.Right - iLeft - 700
iHeight = tRect.Bottom - iTop - 30
For i = 1 To Seite      'Anzahl Screenshots
'Jetzt den Screenshot machen
srcDC = GetDC(GetDesktopWindow())
trgDC = CreateCompatibleDC(srcDC)                                 'Device Context  _
erstellen
hBmp = CreateCompatibleBitmap(srcDC, iWidth, iHeight)             'Bildausschnitt  _
zuordnen
SelectObject trgDC, hBmp                                          'Bild auswählen
BitBlt trgDC, 0, 0, iWidth, iHeight, srcDC, iLeft, iTop, SRCCOPY  'Pixel kopieren
OpenClipboard 0&: EmptyClipboard                                  'Zwischenablage öffnen
SetClipboardData 2, hBmp: CloseClipboard                          'Bild rein und  _
Zwischenablage schließen
DeleteDC trgDC:   ReleaseDC hBmp, srcDC                           'Device Context schließ _
en
keybd_event VK_NEXT, 0&, 0&, 0&
'Bild ist jetzt in Zwischenablage
If IsClipboardFormatAvailable(CF_BITMAP) Then     'Screenshot einfügen
With WS
.Unprotect
.Activate
.Range("H2").Interior.Color = xlNone
.Paste
RBreite = Range("A:H").Width
If TypeName(Selection) = "Picture" Then
If AnzahlScreens = 0 Then
RDown = 56
RTop = 11
With Selection
If (Range(Cells(RTop, 1), Cells(RDown, 1)).Height / (RBreite - 50))  "" Then
ActiveCell.Clear
MsgBox "Kein Bild in der Zwischenablage"
End If
End If
End With
'Kein Bitmap in Zwischenablage
Else
MsgBox "Es wurde kein Bild kopiert!", vbCritical, "PDF-Screenshot"
End If
Next i
'Kein Bitmap in Zwischenablage
PostMessage hwnd, WM_CLOSE, 0&, 0&                                'PDF-Anwendung schließen
Else
'Keine Datei gefunden
MsgBox "Die PDF-Datei wurde nicht gefunden!", vbCritical, "PDF-Screenshot"
End If
Next j
Exit Sub
Fehler:
MsgBox "Es ist der Fehler '" & Error & "' aufgetreten!", vbCritical, "PDF-Screenshot"""
End Sub
Private Function GetPageCount( _
ByVal pvstrFileName As String) As Long
Dim strText As String
Dim strLinearized As String, astrCount() As String
Dim ialngIndex As Long
Dim objFileSystemObject As Object, objTextFile As Object
Dim objRegEx As Object, objMatch As Object, objItem As Object
Dim blnFound As Boolean
GetPageCount = -1
Set objFileSystemObject = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFileSystemObject.OpenTextFile(pvstrFileName, 1, False, 0)
Do Until objTextFile.AtEndOfStream
strText = objTextFile.ReadLine
strText = Replace(strText, vbLf, vbNullString)
If CBool(InStr(1, strText, "/Linearized")) Then
If Len(strText) > 20 Then
strLinearized = strText
blnFound = True
Exit Do
End If
End If
If CBool(InStr(1, strText, "/Count ")) Then
ReDim Preserve astrCount(ialngIndex)
astrCount(ialngIndex) = strText
ialngIndex = ialngIndex + 1
blnFound = True
End If
Loop
Call objTextFile.Close
Set objTextFile = Nothing
Set objFileSystemObject = Nothing
If blnFound Then
Set objRegEx = CreateObject("VBScript.RegExp")
With objRegEx
.MultiLine = True
.Global = True
.IgnoreCase = False
If strLinearized  vbNullString Then
.Pattern = "\/N.?(\d+).?"
Set objMatch = .Execute(strLinearized)
If objMatch.Count > 0 Then _
GetPageCount = CLng(objMatch(0).SubMatches(0))
Else
If ialngIndex = 1 Then
.Pattern = "\/Count.?(\d+)"
Set objMatch = .Execute(astrCount(0))
If objMatch.Count = 1 Then
GetPageCount = CLng(objMatch(0).SubMatches(0))
Else
For Each objItem In objMatch
GetPageCount = WorksheetFunction.Max( _
GetPageCount, CLng(objItem.SubMatches(0)))
Next
End If
Else
.Pattern = "\/Count.?(-?\d+)"
For ialngIndex = 0 To UBound(astrCount)
Set objMatch = .Execute(astrCount(ialngIndex))
GetPageCount = WorksheetFunction.Max( _
GetPageCount, CLng(objMatch(0).SubMatches(0)))
Next
End If
End If
End With
Set objMatch = Nothing
Set objRegEx = Nothing
End If
End Function

Wie schon erwähnt habe ich noch nicht soviel Erfahrung, falls dir was auffältt wie ich den Code eleganter oder besser Formulieren kann sag gerne Bescheid.
Den Teil werde ich noch optimieren:
                    If (Range(Cells(RTop, 1), Cells(RDown, 1)).Height / (RBreite - 50)) 
Das war noch aus einem anderen Code wo ich Bilder einfüge wo die Größe vorher nicht bekannt ist. Das brauche ich ja jetzt nicht das ja durch die Skalierung die Größe des Screenshots immer gleich ist. Das ist mir bewusst.
Der Vorteil an der Countfunktion ist auch das ich so gleich die Dateinamen mit in dem Array habe. Falls du noch eine neue Version von deinem Code hast der kürzer und einfacher ist bin ich auch darauf gespannt.
Ansonsten würde mich halt nur noch interessieren wie genau ich das mache mit dem auf Auflösung reagieren. Hab ich ja noch nie gemacht. Ist jetzt auch nicht so wichtig und eilt definitiv nicht aber würde mich durchaus interessieren. Dann wäre es wirklich ein Makro was ich bedenkenlos überall nutzen kann.
Gruß Sven
AW: Screenshot von PDF erstellen und einfüge
07.05.2020 09:12:37
PDF
Moin Sven,
werde erst im Laufe des Tages dazu kommen, mir Deinen Code näher anzusehen und weiterzumachen.
Zur Ermittlung der Seiten:
Habe gerade die Versionen 1.3, 1.4, 1.6 getestet, wobei eine 1.3er keinen Page-Wert herausgegeben hat.
Das ist wohl versionsabhängig, aber da von zwei 1.3er eine nicht funktioniert hat und sonst alle (auch die 1.6er), ist da noch ein anderer Unterschied. Muss da noch mal näher schauen.
Aber es gibt ja die Version von den anderen für's erste.....
Wenn Du magst, schau doch mal in Deine PDF, ob da "/Linearized" oder "/Type /Pages" oder sonst ein Hinweis auf die Seitenzahl drin steht...
Ich habe hier eine Datei mit allen Declares zu Funktionen und Konstanten. Kann man sich aus dem Netz runterladen.
Für die Keycodes ist auch diese Seite hier gut:
https://www.vbarchiv.net/api/api_kybd_event.html
viele Grüße
Karl-Heinz
AW: Screenshot von PDF erstellen und einfüge
07.05.2020 09:32:53
PDF
Hallo Karl-Heinz,
ja gar kein Problem. Das eilt nicht. Ich habe gerade mal geguckt und ich habe verschiedene PDF Typen.
Bei den PDF die aus dem Scanner kommen, sie sind Version 1.4, gibs die Info: /Pages 1 0 R
Allerdings steht da immer 1 0 R, egal wie viel seiten.
Bei den anderen gibs die Info Linearized 1. Da kann ich das aber gerade nicht kontrollieren, da ich von der Sorte auf die schnelle keine PDF mit mehr als einer Seite finde.
Danke für den Tipp und die datei.
Gruß Sven
AW: Screenshot von PDF erstellen und einfüge
07.05.2020 09:08:22
PDF
Achja eine Anmerkung noch.
Es klappt weder in deinem Code noch in meinem das die PDF auf amximum geöffnet wird. Ist mir vorher nie aufgefallen weil ich den immer so geschlossen habe. Schließe ich den aber in einem kleinem Fenster wird er auch in einem kleinem Fenster geöffnet, weshalb die Screenshots dann antürlich nicht wie gewünscht funktionieren.
Hast du da eventuell noch eine Idee?
Gruß Sven
AW: Screenshot von PDF erstellen und einfüge
07.05.2020 09:22:00
PDF
Kann können wir noch ShowWindow hWnd, SW_Maximize einbauen.
Dann sollte das gehen.
Declare PtrSafe Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
Const SW_MAXIMIZE = 3
VG KH
AW: Screenshot von PDF erstellen und einfüge
07.05.2020 09:41:42
PDF
Hallo Karl-Heinz,
Die Function muss ich ja oben da mit einfügen wo die 'Window Funktionen sind oder?
Und die Const haben wir ja schon als Private Const eingefügt.
Oder ist das falsch? Falls es Richtig ist funktioniert es so auf jedenfall auch nicht.
Gruß
Sven
AW: Screenshot von PDF erstellen und einfüge
07.05.2020 16:25:39
PDF
Hallo Sven,
damit unsere hier geposteten Code-Ausschnitte nicht immer länger werden, habe ich in anliegeder Datei mal
  • Meinen Code zur Information reingesetzt
  • Deinen Code mit ein paar Ergänzungen ebenfalls hier eingesetzt
  • Eine kleine Sub zur Ermittlung der Koordinaten unter der Maus bereitgestellt
In meinem Code fange ich für die Weiterschaltung zur aktuell gewünschten Seite immer wieder von der ersten Seite aus an und ich skaliere den aktuellen Screenshot genau in das Zielfeld (Resizing)
Es war mir jetzt doch zu müßig, anhand Deines Codes genau herauszufinden, wie Du das machst bzw. wie Du das haben möchtest.
Die relevanten Änderungen in Deinem Code findest Du jeweils mit dem Stichwort 'KHV
Insbesondere die Ermittlung der Bildschirmauflösung (was immer man damit jetzt machen will), die ShowWindow-Funktion (wobei der Start ja eigentlich schon im Vollmodus erfolgt)
PS: Mit der Sub CheckMausPos kannst Du einfach und pixelgenau feststellen, bei welchen Bildschirmkoordinaten Dein Screenshot beginnt und endet.
PDF-Screenshot.xlsb
Die Ermittlung der Seitenzahl klappt jetzt bei allen 15 getesteten PDF-Dateien mit Version 1.3 bis 1.7. Es gibt mehrere verschiedene Abbildungen der Seitenangaben, die Version hat damit nichts zu tun.
Ob jetzt wirklich alles abgedeckt ist, weiß ich nicht.
Code in die Zwischenablage
Private Function GetPageCount(ByVal sFile As String) As Long
'Ermittelt die Seitenanzahl einer PDF-Datei
 Dim sData As String, S As String, n As Byte, iFF As Byte, L As Long
 On Error Resume Next
 iFF = FreeFile: Open sFile For Binary Access Read As #iFF  'Datei öffnen
 L = LOF(iFF): If L > 1000 Then L = 1000
 sData = Replace(Input(L, #1), " ", "")
 For n = 1 To 2
  S = "/Linearized,/N"
  If InStr(sData, Split(S, ",")(0)) = 0 Then S = "/Type/Pages,/Count"
  GetPageCount = Val(Left$(Trim$(Split(Split(sData, Split(S, ",")(0))(1), Split(S, ",")(1))(1)), 3))
  If GetPageCount = 0 Then GetPageCount = Val(Left$(Trim$(Split(sData, "/Count")(1)), 3))
  If GetPageCount > 0 Or L = LOF(iFF) Then Exit For
  sData = Replace(sData & Input(LOF(iFF) - L, #1), " ", "")  'Restzeichen lesen
 Next n
 Close #1
End Function
viele Grüße
Karl-Heinz

AW: Screenshot von PDF erstellen und einfüge
08.05.2020 14:36:20
PDF
Hallo Karl-Heinz,
gute Idee mit der Datei.
Also deine Seitenzählfunction funktioniert auch bei mir einwandfrei. Super Danke. Habe ich getestet in dem ich Sie in den Code in meiner Datei reinkopiert habe.
Die anderen Sachen kann ich leider nicht Testen, da er sagt: DLL Einsprungpunkt wurde nicht gefunden.
Gruß Sven
AW: Screenshot von PDF erstellen und einfüge
08.05.2020 15:37:36
PDF
Hi Sven,
sehr schön, doch noch ein Erfolg. Vielen Dank für die Rückmeldung
Welche "anderen Sachen" meinst Du genau, meine Screenshot-Sub?
Also bei mir läuft alles, werde die nächsten Tage hier und da noch ein wenig rumtüfteln, um noch ein paar mehr Erkenntnisse bzgl. PDF zu erhalten.
Wenn noch Bedarf besteht, kannst Du Dich ja gerne noch mal melden.
Viele Grüße
Karl-Heinz
AW: Screenshot von PDF erstellen und einfüge
11.05.2020 15:17:12
PDF
Hallo Karl Heinz,
Entschuldigung das ich mich erst jetzt wieder melde. Hatte am Wochenende viel zu tun.
Ja genau den Screenshot sub z.b. Wenn ich denn starten will sagt er immer Laufzeitfehler 453: DLL Einsprungpunkt Get SystemMetrics in user32 nicht gefunden. Beim Sub Check MausPos das gleiche mit DLL-Einsprungpunkt GetCursorPos usw, es geht kein Sub in der Datei.
Aber habe das Problem jetzt gelöst, wenn ich denn Code komplett in eine neue Datei kopiere, funktioniert er. So konnte ich Ihn testen und es klappt super.
Vielen Dank nochmal.
Ja an der anderen Art den Screenshot zu machen wäre ich auch noch interessiert. Vielleicht kann ich das für meine Zwecke besserverwenden, und falls nicht habe ich zumindest was gelernt.
Vielen Dank Schonmal.
Gruß Sven
AW: Screenshot von PDF erstellen und einfüge
11.05.2020 19:09:58
PDF
Hallo Sven,
hier noch mal eine Datei mit der abgewandelten Screenshot-Version; nicht vom Desktop sondern vom PDF-Fenster und hier aus dem Mittelfenster.
Über "WindowFromPoint" wird das entsprechende Handle ermittelt, anhand dessen dann die Koordinaten ermittelt werden können...
PDF-Screenshot.xlsb
viele Grüße aus Hessen
Karl-Heinz
AW: Screenshot von PDF erstellen und einfüge
08.05.2020 17:11:03
PDF
Hallo Sven,
es gibt noch ein paar Neuigkeiten.
Gerade habe ich meinen Screenshot nicht (wie im aktuellen Tool) vom Desktop (wirklicher Screenshot aus dem Bildspeicher), sondern vom PDF-Fenster gemacht.
Und hier genauer gesagt, sogar vom Innenfenster, also ohne Kopf, Fuß und Seitenteile des Acrobat.
Der kopierte Inhalt ist deshalb immer nur vom PDF-Fenster, auch wenn andere Fenster darüber liegen sollten. Funktioniert sogar, wenn das PDF-Fenster nicht exakt oben links am Bildschirm liegt
Kommt aktuell nicht vor, da wir vor dem Kopieren ja in den Vordergrund schalten.
Möglicherwiese muss man seine Koordinaten aber trotzdem eingeben, da ein ggf. grauer Bereich zum Innenfenster gehört...
Wenn Dich die neue Vorgehensweise interessieren sollte, stelle ich gern noch mal ein Tool hier ein.
Mit der bisherigen Vorgehensweise kann man natürlich auch gut leben.
viele Grüße
Karl-Heinz
AW: Screenshot von PDF erstellen und einfüge
09.05.2020 10:11:47
PDF
Hallo Sven,
hier noch ein Nachtrag. Es hatte sich eine kleine Unschärfe eingeschlichen, die wahrscheinlich keine Auswirkungen hat, aber nicht sauber programmiert war:
Es muss statt Close #1 => Close #iff heißen.
Gleichzeitig noch mal eine modifizierte Version:
Code in die Zwischenablage
Private Function GetPageCount(ByVal sFile As String) As Long
'Ermittelt die Seitenanzahl einer PDF-Datei
 Dim sData As String, S As String
 Dim n As Byte, iFF As Byte, L As Long, i As Long
 On Error Resume Next
 iFF = FreeFile
 Open sFile For Binary Access Read As #iFF       'Datei öffnen
 L = LOF(iFF): If L > 1000 Then L = 1000
 For n = 1 To 2
  sData = sData & Replace(Input(L, #1), " ", "") 'Erst mal nur 1000 Byte lesen
  S = "/Linearized /N"                           '1. Variante testen
  If InStr(sData, Split(S)(0)) = 0 Then S = "/Type/Pages /Count"
  i = Val(Split(Split(sData, Split(S)(0))(1), Split(S)(1))(1))
  If i = 0 Then i = Val(Split(sData, "/Count")(1))
  If i > 0 Or n = 2 Then Exit For
  L = LOF(iFF) - L                               'Restzeichen lesen
 Next n
 GetPageCount = i
 Close #iFF
End Function
viele Grüße
Karl-Heinz

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige