| |
Fortgeschrittene ProgrammierungIst das möglich? VB.NET in VBA umwandeln? | | | Autor: Jens- | Datum: 13.07.17 15:34 |
| Hallo zusammen,
da ich auf dieser Seite sehr ähnliche Themen gefunden habe wie meines wollte ich um Hilfe fragen, um einen Code der mir leider nur in VB.NET vorliegt in VBA zu überführen. Kennt sich da jemand aus?
Schafft das jemand in diesem Forum?
Ich habe versucht einen Anfang zu machen, weiss aber nicht ob das was ich gemacht habe richtig oder falsch ist. Als System nutze ich Win10, Excel 2013, VBA.
Hier der Originalcode in VB.NET inklusive der Verbesserung weiter unten im Thread.
Quelle:https://stackoverflow.com/questions/103725/is-there-a-way-to-programmatically-determine-if-a-font-file-has-a-specific-unico
EDIT: Den habe ich wieder raus genommen weil ich die Meldung bekommen habe "Nachrichtentext ist zu lang".
Und hier das was ich bis jetzt daraus gemacht habe:
In einem separaten Klassenmodul habe ich definiert:
Klassenmodulname: FontRange
Option Explicit
Public Low As UInt16
Public High As UInt16 Dann in einem mormalen Modul sicht es jetzt so aus:
Public Function GetUnicodeRangesForFont(ByVal font As font) As Collection '(Of
' FontRange)
Public Declare PtrSafe Function GetFontUnicodeRanges Lib "gdi32.dll" (ByVal _
hds As IntPtr, ByVal lpgs As IntPtr) As UInteger
'<DllImport("gdi32.dll")> _
'Public Shared Function GetFontUnicodeRanges(ByVal hds As IntPtr, ByVal
' lpgs As IntPtr) As UInteger
End Function
Public Declare PtrSafe Function SelectObject Lib "gdi32.dll" (ByVal hDC As _
IntPtr, ByVal hObject As IntPtr) As IntPtr
'<DllImport("gdi32.dll")> _
'Public Shared Function SelectObject(ByVal hDc As IntPtr, ByVal hObject As
' IntPtr) As IntPtr
End Function
RegServe App.Path & "\" & gdi32.dll, True
Dim g As Graphics
Dim hDC, hFont, old, glyphSet As IntPtr
Dim size As UInteger
Dim GURFF As FontRange
Set GURFF = New FontRange
Set GetUnicodeRangesForFont = New Collection
Dim fontRanges As Collection '(Of FontRange)
Dim frs As FontRange
Set fontRanges = New Collection
Set frs = New FontRange
Dim i As Integer
Dim count As Integer
g = Graphics.FromHwnd(IntPtr.Zero)
hDC = g.GetHdc()
hFont = font.ToHfont()
old = SelectObject(hDC, hFont)
size = GetFontUnicodeRanges(hDC, IntPtr.Zero)
glyphSet = Marshal.AllocHGlobal(CInt(size))
GetFontUnicodeRanges(hDc, glyphSet)
'fontRanges = New List(Of FontRange)
count = Marshal.ReadInt32(glyphSet, 12)
For i = 0 To count - 1
Dim range As FontRange
Set range = New FontRange
range.Low = Unsign(Marshal.ReadInt16(glyphSet, 16 + (i * 4)))
range.High = range.Low + Unsign(Marshal.ReadInt16(glyphSet, 18 + (i * _
4)) - 1)
fontRanges.Add (range)
Next
SelectObject(hDc, old)
Marshal.FreeHGlobal (glyphSet)
g.ReleaseHdc (hDC)
g.Dispose()
GetFontUnicodeRanges = fontRanges
End Function
Private Function Unsign(ByVal Input As Int16) As UInt16
If Input > -1 Then
Unsign = CType(Input, UInt16)
Else
Unsign = UInt16.MaxValue - (Not Input)
End If
End Sub
Public Function CheckIfCharInFont(ByVal character As String, ByVal font As _
font) As Boolean
RegServe App.Path & "\" & gdi32.dll, True
Dim intval As UInt16
Dim ranges As Collection '(Of FontRange)
Dim fr As FontRange
Set fr = New FontRange
Set ranges = New Collection
Dim isCharacterPresent As Boolean
Dim range As Object
intval = Convert.ToUInt16(character)
ranges = GetUnicodeRangesForFont(font)
isCharacterPresent = False
For Each range In ranges
If intval >= range.Low And intval <= range.High Then
isCharacterPresent = True
Exit For
End If
Next range
CheckIfCharInFont = isCharacterPresent
End Function Probleme macht denke ich:
1. die Einbindung der dll's. Das ist für mich ganz neu.
2. Die Variablendeklaration font beim Funktionsaufruf CheckIfCharInFont
3. Und die bei mir noch rot markierten Stellen (sieht man wenn man den Code in VBA übernimmt).
Ich würde mich riesig freuen, wenn mir hier jemand helfen könnte.
Vielen Dank. | |
Re: Ist das möglich? VB.NET in VBA umwandeln? | | | Autor: Blackbox | Datum: 13.07.17 16:59 |
| Hallo,
wenn man von den .NET spezifischen Pointer-Verkünstlungen (die ja in .NET verpöhnt sind) mal absieht ist das ein ganz normaler Zugriff auf die WinAPI.
Das kannst Du ja fast 1:1 in VBA übernehmen. Fur das Graphics-Objekt nimmst du ganz normale long Variable für zB: hdc = GetDC(hWnd).
Die Dll's für VBA:
Public Declare Function GetFontUnicodeRanges Lib "gdi32.dll" (ByVal _
hds As Long, ByVal lpgs As Long) As Long
Public Declare Function SelectObject Lib "gdi32.dll" (ByVal hDC As _
Long, ByVal hObject As Long) As Long
Public Declare Function GetDC Lib "gdi32.dll" (Byval hWnd As Long) As Long
VBA kennt die Klasse Collection.
Font bekommst Du mit GetFond( ... ) API.
AllocHGlobal ist eine WinAPI
vielleicht kommst Du mit diesen Tipps weiter, ansonsten melde Dich | |
Re: Ist das möglich? VB.NET in VBA umwandeln? | | | Autor: Jens- | Datum: 13.07.17 21:15 |
| Hallo Backbox,
vielen Dank für deine Antwort. Du gibst mir Hoffnung. Leider ist das vielleicht etwas unter gegangen, aber der Code im ersten Post war schon die von mir - so gut es geht - bearbeitete Version. Der Origianalcode sieht so aus (siehe unten).
1. Bezüglich der einen gdi32.dll: Muss die nicht noch "eingebunden" werden? Ich hatte mir dafür folgenden Code überlegt gehabt:
RegServe App.Path & "\" & gdi32.dll, True App.Path zeigt doch vermutlich in C:\Windows\System32\ wo ich diese dll vermute, richtig?
2. Ich habe die Vermutung bei der Zeile:
GetFontUnicodeRanges(hdc, glyphSet) handelt es sich um eine Rekursion??? Wie geht das in VBA? So:
GetFontUnicodeRanges = GetFontUnicodeRanges(hdc, glyphSet) 3. Ich bin mir nicht sicher was du mit Pointer in diesem Code meinst?
4. Die zwei APIs die du ansprichst habe ich auch noch nicht verstanden was ich damit machen muss.
Hier der original Code (ohne Veränderungen) in VB.NET
<DllImport("gdi32.dll")> _
Public Shared Function GetFontUnicodeRanges(ByVal hds As IntPtr, ByVal lpgs As _
IntPtr) As UInteger
End Function
<DllImport("gdi32.dll")> _
Public Shared Function SelectObject(ByVal hDc As IntPtr, ByVal hObject As _
IntPtr) As IntPtr
End Function
Public Structure FontRange
Public Low As UInt16
Public High As UInt16
End Structure
Public Function GetUnicodeRangesForFont(ByVal font As Font) As List(Of _
FontRange)
Dim g As Graphics
Dim hdc, hFont, old, glyphSet As IntPtr
Dim size As UInteger
Dim fontRanges As List(Of FontRange)
Dim count As Integer
g = Graphics.FromHwnd(IntPtr.Zero)
hdc = g.GetHdc()
hFont = font.ToHfont()
old = SelectObject(hdc, hFont)
size = GetFontUnicodeRanges(hdc, IntPtr.Zero)
glyphSet = Marshal.AllocHGlobal(CInt(size))
GetFontUnicodeRanges(hdc, glyphSet)
fontRanges = New List(Of FontRange)
count = Marshal.ReadInt32(glyphSet, 12)
For i As Integer = 0 To count - 1
Dim range As FontRange = New FontRange
range.Low = Unsign(Marshal.ReadInt16(glyphSet, 16 + (i * 4)))
range.High = range.Low + Unsign(Marshal.ReadInt16(glyphSet, 18 + (i * 4)) - _
1)
fontRanges.Add(range)
Next
SelectObject(hdc, old)
Marshal.FreeHGlobal(glyphSet)
g.ReleaseHdc(hdc)
g.Dispose()
Return fontRanges
End Function
Public Function CheckIfCharInFont(ByVal character As Char, ByVal font As Font) _
As Boolean
Dim intval As UInt16 = Convert.ToUInt16(character)
Dim ranges As List(Of FontRange) = GetUnicodeRangesForFont(font)
Dim isCharacterPresent As Boolean = False
For Each range In ranges
If intval >= range.Low And intval <= range.High Then
isCharacterPresent = True
Exit For
End If
Next range
Return isCharacterPresent
End Function
Protected Function Unsign(ByVal Input As Int16) As UInt16
If Input > -1 Then
Return CType(Input, UInt16)
Else
Return UInt16.MaxValue - (Not Input)
End If
End Function Vielen Dank für deine Hilfe, ich hoffe wir bekommen das zusammen hin. | |
Re: Ist das möglich? VB.NET in VBA umwandeln? | | | Autor: Jens- | Datum: 16.07.17 22:12 |
| Hallo Blackbox,
ich hoffe dir geht es gut. Kannst du mir noch helfen?
Viele Grüße
Jens | |
Re: Ist das möglich? VB.NET in VBA umwandeln? | | | Autor: markusxy | Datum: 17.07.17 12:20 |
| @Jens
Was willst du mit dem Code überhaupt erreichen?
Warum nimmst du nicht einfach eine entsprechende Schriftart und fertig?
Beitrag wurde zuletzt am 17.07.17 um 12:22:41 editiert. | |
Re: Ist das möglich? VB.NET in VBA umwandeln? | | | Autor: Jens- | Datum: 17.07.17 15:35 |
| Hallo markusxy,
vielen Dank für deine Nachfrage. Die ist natürlich sehr berechtigt wenn man den Kontext nicht kennt.
Ich habe eine Excelliste in der sind alle 196.607 Unicode Zeichen aufgelistet. Für diese versuche ich für eine bestimmte Schriftart - in Zukunft soll der Abgleich vermutlich für alle auf einem System gegebenen Schrftarten erfolgen - die Zeilen heraus zu filtern, die von der jeweiligen Schriftart nicht angezeigt werden. Also ein Fragezeichen in einer Box oder ein Rechteck dargestllt wird. D.h. eine Tabelle könnte so aussehen:
|Unicode(Dez)| Schriftart A | Schriftart B | Unterstützung in A | Unterstützung in B|
|127742 | [?] | [?] | Nein | Nein|
|127743 | [?] | [?] | Nein | Nein|
|127744 | [?] | 🌀 | Nein | Ja|
Aber die Klärung ob das Zeichen in der jeweiligen Schriftart angezeigt wird fehlt mir noch.
Wozu das ganze: Um eine spezielle Software nur mit den Unicode Zeichen "zu füttern" die in der jeweiligen Schriftart auch bekannt sind.
Irgend eine Idee wie ich die Excel-Liste entsprechend filtern kann, so dass die [?] und [] nicht mehr enthalten sind bei der jeweiligen Schriftart?
Vielen Dank für deine Hilfe.
Grüße
Jens | |
Re: Ist das möglich? VB.NET in VBA umwandeln? | | | Autor: markusxy | Datum: 17.07.17 16:16 |
| Grundsätzlich würde ich die Daten nicht in Excel führen (Excel ist ja unendlich langsam), sondern in einer Datenbank oder eventuell in einer schlichten binären Datei.
Ich kenne mich in .net nicht aus, aber der Code ist nicht kompliziert.
Wie du siehst gibt es auch keine Funktionen in .net und er muss auch direkt auf die API zugreifen, was in VBA keinen Unterschied machen würde.
Ich gehe da eher den Weg, dass ich in der MSDN nachsehe, um zu verstehen wie die Funktionen arbeiten und welche Möglichkeiten es gibt und erstelle eine eigene Logik. Danach suche ich dann gerne auch nach Beispielen. Die Frage ist halt ob man sich die Zeit nehmen möchte, da immer ein gewisse Aufwand damit verbunden ist.
Nur wie verwendest du die Daten dann in der Software?
Und womit programmierst du die SW?
Hier gibts eine Übersicht über die Funktionen.
Beitrag wurde zuletzt am 17.07.17 um 16:21:58 editiert. | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
vb@rchiv CD Vol.6 vb@rchiv Vol.6
Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
Online-Update-Funktion Entwickler-Vollversionen u.v.m.Jetzt zugreifen Tipp des Monats Neu! sevPopUp 2.0
Dynamische Kontextmenüs!
Erstellen Sie mit nur wenigen Zeilen Code Kontextmenüs dynamisch zur Laufzeit. Vordefinierte Styles (XP, Office, OfficeXP, Vista oder Windows 8) erleichtern die Anpassung an die eigenen Anwendung... Weitere Infos
|