vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Zippen wie die Profis!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

Fortgeschrittene Programmierung
Ist 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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel