Von: access-weekly-html-request@cgn.smarttools.de im Auftrag von SmartTools Publishing [access-weekly-html-reply@smarttools.de]
Gesendet: Freitag, 27. Mai 2005 02:30
An: Access Weekly Abonnenten
Betreff: SmartTools Access Weekly vom 27.5.2005

Ausgabe vom 27. Mai 2005

 In dieser Ausgabe

Access-News & Downloads
Access-Tipp der Woche
Access-Helpline
Newsletter-Tipp
 Access-News & Downloads

News: Total Visual CodeTools 2003: Unsere Sonderaktion für Entwicklertools gilt nur noch wenige Tage

Mit den Total Visual CodeTools 2003 erweitern Sie Access 2003, 2002/XP und 2000 um eine umfangreiche Sammlung neuer Tools und Assistenten, die Ihnen die tägliche Programmier-Arbeit wesentlich erleichtern werden. Die Total Visual CodeTools 2003 integrieren sich direkt in die Entwicklungsumgebung und lassen sich jederzeit per Mausklick aufrufen. Zum Beispiel:

  • Code Cleanup zur automatischen Aufbereitung und Standardisierung von vorhandenem Code.
  • Automatische CodeBuilder für Recordsets, SQL-Statements, Message-Boxen, Select-Case-Anweisungen etc.
  • Starten Sie den Code Delivery Wizard bevor Sie eine Datenbank weitergeben. Der Assistent fügt automatisch Zeilennummern hinzu (für punktgenaue Fehlermeldungen), entfernt Debugging-Code, den Sie übersehen haben und macht auf Wunsch den Sourcecode für unbefugte Dritte unlesbar.
Ab sofort ist die neue Version 2003 der Total Visual CodeTools mit vielen erweiterten Funktionen und zusätzlichen Assistenten verfügbar. Nur noch bis zum 31.5.2005 gilt für Access Weekly-Abonnenten außerdem ein Sonderpreis mit 10% Rabatt!

Ausführliche Informationen finden Sie unter:

http://www.add-in-world.com/katalog/tv_code2003/

Download-Tipp: Flexible Formulare per SQL

Normalerweise liefern Tabellen oder Abfragen die Datenbasis für Ihre Formulare in Access. Häufig möchten Sie jedoch eine Selektion von Datensätzen bearbeiten, die bestimmten Kriterien entsprechen. In der Regel definieren Sie dann einen Formularbasierten Filter, der die entsprechenden Datensätze zusammenfasst - beispielsweise alle Kunden aus Belgien oder alle Artikel mit einem Preis kleiner 5,00 EUR. Schneller und komfortabler wäre in solchen Fällen der Einsatz einer kurzen SQL-Anweisung wie "select * from Kunden where Land='Belgien'" - allerdings bietet Access keine Möglichkeit, SQL-Statements schnell einzugeben und das Ergebnis direkt in einem Formular anzuzeigen.

SmartTools SQL für Formulare hilft weiter: Das Add-In steht Ihnen in allen Datenbanken über das Menü Extras-Add-Ins zur Verfügung und erlaubt die Eingabe und Zuordnung von SQL-Anweisungen für das aktuell geöffnete Formular. Nach dem Aufruf geben Sie einfach eine entsprechende SQL-Anweisung ein und klicken auf Ok - anschließend können Sie die selektierten Datensätze wie gewohnt im Formular durchblättern und bearbeiten.

Das Add-In merkt sich die durchgeführten Abfragen, so dass Sie auf die am häufigsten benötigten Anweisungen jederzeit mit wenigen Mausklicks zugreifen können. Möchten Sie dem Formular wieder die ursprüngliche Datenbasis, also die beim Entwurf festgelegte Tabelle oder Abfrage, zuordnen, klicken Sie im Add-In einfach auf Zurücksetzen. Sie finden den kostenlosen Download unter:

 SmartTools SQL für Formulare

Techinfo: 'Table'-Variablen mit SQL Server nutzen

Über gespeicherten Prozeduren führen Sie häufig Funktionen aus, die Daten in temporären Tabellen ablegen und/oder verarbeiten. Nach Abschluss der Arbeiten sind diese temporären Tabellen wieder zu löschen. Das benötigt nicht nur unnötig Zeit sondern beeinträchtigt auch die Performance des SQL Servers. Wenig bekannt ist die Tatsache, dass ab SQL Server 2000 Variablen vom Datentyp "Table" anstelle von temporären Tabellen eingesetzt werden können. Dadurch können Sie sich (und dem SQL Server) den Umgang mit temporären Tabellen sparen und schonen gleichzeitig die Performance des Servers. Den Einsatz von "Table"-Variablen in der Praxis erläutert eine Techinfo des SQL Server-Spezialisten Mike Gunderloy unter der folgenden Adresse:

'Table'-Variablen mit SQL Server nutzen

 Access-Tipp der Woche

Schriftartenauswahl leicht gemacht, Teil 1
Versionen: Access 2003, 2002/XP, 2000 und 97

In Ihren Datenbank-Anwendungen möchten Sie vielleicht eine Lösung anbieten, über die ein Anwender eine individuelle Schriftart für die Anzeige von Formularen oder den Ausdruck von Berichten wählen kann. Leider stellt Access keine Funktionen bereit, mit denen sich ein Listen-Steuerelement oder ein Kombinationsfeld mit einer entsprechenden Schriftartenauswahl füllen lässt. Lösen können Sie das Problem, mit Hilfe von API-Funktionen oder, im Fall von Access 97, durch den Einsatz "geheimer" Funktionen, die die Access-Programmierer in MSACCESS.EXE versteckt haben - mehr dazu später. Der erste und zweite Teil dieses Tipps der Woche stellt zunächst die notwendigen Basisroutinen vor. Der dritte Teil zeigt dann praktische Beispiele.

Access 2003, 2002/XP und 2002:
Aber beginnen wir mit einigen Grundlagen: Basis der Lösung für Access 2003, 2002/XP und 2000 ist die API-Funktion "EnumFontFamilies()": Diese API-Funktion wird nur ein einziges Mal aufgerufen. Dabei ist ihr unter anderem die Adresse einer speziellen "EnumFontFamProc"-Funktion als Parameter zu übergeben. Diese spezielle Funktion wird anschließend für jede verfügbare Schriftart einmal aufgerufen und kann beispielsweise dazu genutzt werden, den ihr als Parameter übergebenen Schriftnamen in ein Array zu schreiben. Aus diesem Array lassen sich die Schriftnamen dann beispielsweise über eine CallBack-Funktion in ein Listen-Steuerelement oder ein Kombinationsfeld übertragen und zur Auswahl anzeigen. "EnumFontFamilies()" liefert die Schriftarten für einen bestimmten "Device Context" (Bildschirm, Drucker) beispielsweise anhand des Handles (hWnd) eines Anwendungsfensters. Für den Einsatz von "EnumFontFamilies()" sind somit zwei weitere API-Funktionen "GetDC()" und "ReleaseDC()" notwendig, die einen Verweis auf den jeweiligen Device Context liefern bzw. diesen Context wieder freigeben.

Die benötigten Deklarationen, Prozeduren und Funktionen für den Einsatz mit Access 2003, 2002/XP und 2000 fassen Sie in einem Modul "modFontList" wie folgt zusammen:

  1. Legen Sie ein neues Modul "modFontList" an.
  2. Geben Sie die folgenden Deklarationen im allgemeinen Teil des Moduls ein:
Private Const LF_FACESIZE = 32

Private Type LOGFONT
  lfHeight As Long
  lfWidth As Long
  lfEscapement As Long
  lfOrientation As Long
  lfWeight As Long
  lfItalic As Byte
  lfUnderline As Byte
  lfStrikeOut As Byte
  lfCharSet As Byte
  lfOutPrecision As Byte
  lfClipPrecision As Byte
  lfQuality As Byte
  lfPitchAndFamily As Byte
  lfFaceName(LF_FACESIZE) As Byte
End Type

Private Type NEWTEXTMETRIC
  tmHeight As Long
  tmAscent As Long
  tmDescent As Long
  tmInternalLeading As Long
  tmExternalLeading As Long
  tmAveCharWidth As Long
  tmMaxCharWidth As Long
  tmWeight As Long
  tmOverhang As Long
  tmDigitizedAspectX As Long
  tmDigitizedAspectY As Long
  tmFirstChar As Byte
  tmLastChar As Byte
  tmDefaultChar As Byte
  tmBreakChar As Byte
  tmItalic As Byte
  tmUnderlined As Byte
  tmStruckOut As Byte
  tmPitchAndFamily As Byte
  tmCharSet As Byte
  ntmFlags As Long
  ntmSizeEM As Long
  ntmCellHeight As Long
  ntmAveWidth As Long
End Type

Declare Function EnumFontFamilies Lib "gdi32" _
        Alias "EnumFontFamiliesA" _
       (ByVal hDC As Long, _
        ByVal lpszFamily As String, _
        ByVal lpEnumFontFamProc As Long, _
        LParam As Any) As Long

Private Declare Function GetDC Lib "user32" _
        (ByVal hWnd As Long) As Long

Private Declare Function ReleaseDC Lib "user32" _
        (ByVal hWnd As Long, _
         ByVal hDC As Long) As Long

Public intNumFonts As Integer
Public arrFontNames() As String

  • Geben Sie im Anschluss daran die folgenden Funktionen ein:
Public Function CreateFontList() As Integer
  Dim R As Variant, hDC As Long, I As Integer

  intNumFonts = 0
  Erase arrFontNames()
  hDC = GetDC(Application.hWndAccessApp)
  EnumFontFamilies hDC, vbNullString, _
                   AddressOf EnumFontFamProc, 0&
  ReleaseDC Application.hWndAccessApp, hDC
  CreateFontList = intNumFonts

End Function

Function EnumFontFamProc(lpNLF As LOGFONT, _
                         lpNTM As NEWTEXTMETRIC, _
                         ByVal FontType As Long, _
                         LParam As Long) As Long
  Dim strAPIName As String
  Dim strFontname As String

  On Error Resume Next
  strAPIName = StrConv(lpNLF.lfFaceName, vbUnicode)
  If InStr(strAPIName, vbNullChar) <> 0 Then
    strFontname = Left$(strAPIName, _
                        InStr(strAPIName, vbNullChar) - 1)
  Else
    strFontname = strAPIName
  End If
  ReDim Preserve arrFontNames(intNumFonts)
  arrFontNames(intNumFonts) = strFontname
  intNumFonts = intNumFonts + 1
  EnumFontFamProc = 1

End Function

  • Speichern Sie das Modul.
Access 97:
Die oben gezeigte Lösung kann NICHT mit Access 97 eingesetzt werden! "EnumFontFamilies()" muss, wie bereits erläutert, als Parameter die Adresse einer speziellen "EnumFontFamProc"-Funktion übergeben werden. Das ist nur per AddressOf- Operator möglich, der jedoch erst ab Access 2000 zur Verfügung steht. Der Umweg über API-Funktionen ist mit Access 97 allerdings auch nicht nötig: Wenig bekannt ist die Tatsache, dass Access 97 über verschiedene "geheime Funktionen" verfügt. Um in den eigenen Assistenten Funktionen ausführen zu können, die sich per VBA nicht oder nur umständlich realisieren lassen, haben die Programmierer von Microsoft sich in Access 97 eine eigene kleine "API-Welt" geschaffen. Über diese externen, nicht dokumentierten Funktionen und Prozeduren lassen sich eine ganze Reihe an Aufgaben recht komfortabel und ohne viel Aufwand erledigen. Um auf die externen Routinen zugreifen zu können, müssen die betreffenden Prozeduren und Funktionen im allgemeinen Teil eines Moduls entsprechend deklariert sein. Für den Einsatz mit Access 97 gehen Sie wie folgt vor:

  1. Legen Sie ein neues Modul "modFontList" an.
  2. Geben Sie die folgenden Deklarationen im allgemeinen Teil des Moduls ein:
Private Type accexeFontInfo
    IsRasterFont As Long
    strFontname As String * 32
End Type

Private Declare Function accexeNumFonts _
                  Lib "msaccess.exe" _
                  Alias "#61" _
                 (ByVal ic As Long) As Long

Private Declare Function accexeReadFonts _
                  Lib "msaccess.exe" _
                  Alias "#62" _
                 (ByVal ic As Long, _
                  arrFonts() As accexeFontInfo) As Long

Private Declare Function CreateIC Lib "gdi32" _
                  Alias "CreateICA" _
                 (ByVal lpDriverName As String, _
                  ByVal lpDeviceName As String, _
                  ByVal lpOutput As String, _
                  lpInitData As Any) As Long

Private Declare Function DeleteDC Lib "gdi32" _
                 (ByVal hdc As Long) As Long

"accexeNumFonts()" und "accexeReadFonts()" sind "geheime" Funktionen, über die sich die Anzahl verfügbarer Schriften und deren Namen über eine spezielle Struktur "accexeFontInfo" ermitteln lassen. Den Funktionen ist als Parameter "ic" jeweils ein "Information Context" zu spezifizieren, für den Schriftarten-Informationen ermittelt werden sollen - also beispielsweise "Bildschirm" oder "Drucker". Diesen Kontext stellen wir für den Bildschirm (DISPLAY) über eine "normale" API-Funktion "CreateIC()" zur Verfügung beziehungsweise geben diesen "Information Context" über "DeleteDC()" wieder frei (nicht verwirren lassen: "DeleteDC()" kann sowohl für einen "Device Context" als auch für einen "Information Context" eingesetzt werden).

  • Geben Sie danach die folgende Funktion ein:
Function CreateFontList() As Integer
  Dim R As Variant
  Dim ic As Long
  Dim I As Integer
  Dim arrTemp() As accexeFontInfo

  CreateFontList = 0
  ic = CreateIC("DISPLAY", "", "", 0)
  intNumFonts = accexeNumFonts(ic)
  If intNumFonts > 0 Then
    ReDim arrTemp(0 To intNumFonts - 1)
    intNumFonts = accexeReadFonts(ic, arrTemp())
    ReDim arrFontNames(intNumFonts)
    For I = 0 To intNumFonts - 1
      If InStr(arrTemp(I).strFontname, _
               vbNullChar) <> 0 Then
        arrFontNames(I + 1) = _
          Left$(arrTemp(I).strFontname, _
                InStr(arrTemp(I).strFontname, _
                vbNullChar) - 1)
      Else
        arrFontNames(I + 1) = arrTemp(I).strFontname
      End If
    Next I
    SortFontList arrFontNames(), 1, intNumFonts
    CreateFontList = intNumFonts
  End If
  DeleteDC ic

End Function

  • Speichern Sie das Modul.
Damit verfügen Sie nun zunächst über die wichtigste Routine für die Realisierung einer Schriftartenauswahl: "CreateFontList()" schreibt die Namen verfügbarer Schriftarten über die spezielle "EnumFontFamProc"-Funktion beziehungsweise den Aufruf der "geheimen" Funktion "accexeReadFonts()" in das Array "arrFontNames()". Wenn Sie nun einmal die folgenden Anweisungen im Direktbereich bzw. im Testfenster der VBA-Entwicklungsumgebung eintippen, können Sie die ersten Informationen zur Schriftartenauswahl abrufen:

? CreateFontList()
? arrFontNames(1..n)

"? CreateFontList()" gibt aus, wie viele Schriftarten gefunden wurden, mit "? arrFontNames(1..n)" können Sie dann einen Schriftnamen im Bereich "1" bis "Anzahl Schriften" abrufen.

In zweiten Teil dieses Tipps der Woche erweitern wir die Lösung um eine Sortierung und stellen eine universell einsetzbare CallBack-Funktion für Listenfelder vor, mit der Sie schnell und einfach eine Schriftartenauswahl realisieren können.

ANZEIGE 
Formatierte Memofelder für Ihre Datenbanken

Mit Total Access Memo können Sie endlich formatierten Text in Ihren Datenbanken anzeigen, bearbeiten und ausdrucken:

  • Sie erhalten ein neues Steuerelement, das Sie mit zwei Mausklicks in Formulare und Berichte einfügen können
  • Ihre Memofelder werden zu einer kleinen Textverarbeitung mit allen wichtigen Format-Funktionen. Sie können sogar eingebettete Objekte und Grafiken verwenden.
  • Sie können das neue Steuerelement beliebig oft mit beliebig vielen Datenbanken an andere Anwender weitergeben
Weitere Informationen finden Sie unter:

Total Access Memo für Access 2003, 2002/XP und 2000

Total Access Memo für Access 97


 Access-Helpline

Haben Sie Fragen zu Access 2003, 2002/XP, 2000 und 97? Dann wenden Sie sich mit einer genauen Problembeschreibung (bitte keine Datenbanken schicken!) an:

access-helpline@smarttools.de

Unser Redaktionsteam wählt in jeder Ausgabe Fragen aus und beantwortet Sie an dieser Stelle im Newsletter.

Standardeinstellungen für neue Steuerelemente setzen
Versionen: Access 2003, 2002/XP, 2000 und 97

 FRAGE:  Beim Entwurf von Formularen muss ich zum Beispiel bei Bezeichnungsfeldern jedes Mal die Ausrichtung auf "Rechtsbündig" oder die Schrift für verschiedene Steuerelemente (Felder, Listen etc.) auf unsere Hausschrift "Gill Sans" einstellen. Dadurch geht viel Zeit verloren. Kann man in Access Standards für Steuerelemente definieren?
G. Hölberger

 ANTWORT:  Um die Standardwerte für einen Steuerelemente-Typ, beispielsweise für ein Bezeichnungsfeld, zu setzen, gehen Sie wie folgt vor:

  1. Öffnen Sie ein beliebiges Formular im Entwurfsmodus.
  2. Markieren Sie das Steuerelement "Bezeichnungsfeld" in der Toolbox.
  3. Wählen Sie das Menü Ansicht-Eigenschaften an.
Access zeigt daraufhin ein Eigenschaftenfenster mit dem Titel "Standard: Bezeichnungsfeld" an. Alle Einstellungen, die Sie jetzt vornehmen, werden zukünftig für neue Bezeichnungsfelder verwendet. Wenn Sie hier also als Schrift "Gill Sans" und als Ausrichtung "Rechtsbündig" einstellen und später ein neues Bezeichnungsfeld anlegen, sind diese Eigenschaften hier automatisch vorgegeben. Auf diese Art können Sie für alle Steuerelemente wie Schaltflächen Listen, Kombinationsfelder etc. die gewünschten Standards setzen. Das Ganze funktioniert übrigens auch in Berichten.

Excel-Probleme bei Office Automation
Versionen: Access 2003, 2002/XP, 2000 und 97

 FRAGE:  Ich arbeite mit Office XP und dem Betriebssystem Windows XP. Die Access-Datenbank ist in ein Front-End und ein Back-End aufgeteilt. Das Back-End sowie die freigegebene Excel-Arbeitsmappe liegen auf einem Windows 2003-Server. Ich habe folgendes Problem: Wenn ich Excel aus meinem Access-Programm starte, Änderungen vom Programm durchführen lasse und anschließend Excel wieder beende, bleibt es immer im Speicher und ich kann Excel nicht mehr nutzen. Es muss erst die Access-Anwendung geschlossen werden, dann funktioniert Excel wieder. Der Befehl "Set Exlobj = Nothing" ist anscheinend ohne Wirkung?
H. Gimmler

 ANTWORT:  Wenn Sie aus Ihrer Datenbank Excel per "CreateObject()" starten, reicht die Dereferenzierung per "Set Exlobj = Nothing" nicht aus. Sie müssen Excel über die Methode "Quit" explizit beenden. Ergänzen Sie Ihre Routine wie folgt, dann funktioniert es wie erwartet:

.....
Set Exlobj= CreateObject("Excel.Application")
.....
Exlobj.Quit
Set Exlobj = Nothing
.....

ANZEIGE 
Erweiterte Version des OLXDuplicateChecker findet ab sofort Duplikate in allen Ordnern

Der bewährte OLXDuplicateChecker kann jetzt noch mehr! Ab sofort finden und entfernen Sie nicht nur doppelte Adressen, sondern auch beliebige andere Duplikate aus anderen Ordnern in Outlook oder auf dem Exchange Server. Mit wenigen Mausklicks finden Sie:

  • doppelte E-Mail
  • doppelte Aufgaben
  • doppelte Termine
  • doppelte Journal-Einträge
  • und natürlich doppelte Adressen
Mit dem OLXDuplicateChecker können Sie all diese Duplikate innerhalb weniger Sekunden ausfindig machen und löschen.

Den OLXDuplicateChecker gibt es in einer Einzelplatzversion zum Löschen von Duplikaten aus Ihrer persönlichen Ordnerdatei (PST):

http://www.add-in-world.com/katalog/olxduplicatepst/

...und in einer Serverversion, wenn Sie Duplikate aus Ordnern auf dem Exchange-Server entfernen möchten:

http://www.add-in-world.com/katalog/olxduplicatesvr/


Änderungen per Recordset vornehmen
Versionen: Access 2003, 2002/XP, 2000 und 97

 FRAGE:  Ich setze in meinem Formular ein Textfeld ein, in das ich einen Status wie zum Beispiel "Erledigt", "Nächste Woche anrufen" oder "Besuch notwendig" eingebe. Das Formular filtere ich nach bestimmten Kriterien und klicke dann auf eine Schaltfläche Status setzen, um die Eingabe in ein Feld "fldStatus" für die ausgewählten Datensätze zu schreiben. Dazu nutze ich ein Recordset, das ich per "RecordsetClone" entsprechend initialisiere:

.....
Set rs = Me.RecordsetClone
While Not rs.BOF
  rs("fldStatus") = Me.txtStatus
  rs.MoveNext
Wend
rs.Close
.....

Leider bleibt die Ausführung dieser Routine wirkungslos. Was mache ich falsch?
I. Meiners

 ANTWORT:  Bevor Sie das Feld eines Recordsets ändern können, müssen Sie die Änderung einleiten und die Änderung anschließend explizit zurückschreiben. Ergänzen Sie Ihre Routine wie folgt:

While Not rs.BOF
  rs.Edit
  rs("fldStatus") = Me.txtStatus
  rs.Update
  rs.MoveNext
Wend

"rs.Edit" leitet die Änderung ein, "rs.Update" sorgt dafür, dass die Änderung dauerhaft gespeichert wird.

 Newsletter-Tipp

Office-Tipps kostenlos per E-Mail

Der SmartTools Office Insider ist Ihr monatlicher News-Service für Microsoft Office. Hier finden Sie aktuelle Informationen zu Access, Excel, Word & Co, eine Fülle von Download-Links sowie detaillierte Tipps zu neuen Patches und Updates. So verpassen Sie nichts, was Sie unbedingt zu Microsoft Office wissen müssen.

  • Aktuelle Meldungen über neue Lösungen und Add-Ins für Office 2003, 2002/XP, 2000 und 97
  • Berichte über Updates und Bugfixes.
  • Tipps und effektivere Arbeitstechniken zu Access, Excel, Word & Co.
  • Kostenlose Downloads zu Office 2003, 2002/XP, 2000 und 97
  • Antworten auf Ihre Fragen zu Microsoft Office.
Und das beste am SmartTools Office Insider: Er ist vollkommen kostenlos!

Klicken Sie hier für Ihr kostenloses Abo!

 Abonnementverwaltung

Um SmartTools Access Weekly abzubestellen, senden Sie einfach das Kommando "unsubscribe" an die Adresse

access-weekly-html-request@smarttools.de

Bitte beachten Sie, daß das Kommando im Nachrichtentext stehen muß (nicht im Betreff) und Sie keine Mail im HTML-Format senden dürfen. Weitere Informationen zur Verwaltung der Liste erhalten Sie mit dem Kommando "help" an dieselbe Adresse.

Copyright © 2005 SmartTools Publishing Thomas Tai
Luisenstrasse 52, 49565 Bramsche
Telefon: 05461/91052, Fax: 05461/2609
E-Mail: access-weekly@smarttools.de
Internet: http://www.smarttools.de/