es ist zum Verzweifeln.
Beim Erstellen eines User-Controls (native Code, VB6 SP5) wirft der
Compiler obige Fehlermeldung mit folgender Erläuterung:
"Nicht jede Variable, die in einer Klassenbibliothek oder einer
Objektbibliothek enthalten ist, kann von jeder Programmiersprache
verwendet werden. Für diesen Fehler gibt es die folgende Ursache und
Lösung:
Sie haben versucht, eine Variable zu verwenden, die in einer
Klassenbibliothek oder Objektbibliothek mit einem Datentyp definiert
worden ist, der von Visual Basic nicht unterstützt wird.
Sie können in einem Visual Basic-Programm keine Variable verwenden,
deren Typ Visual Basic nicht kennt."
Leider ist er nicht so nett, mir mitzuteilen wo oder um welche Variable
oder welchen Typ es sich handelt.
Eingebunden sind:
Verweise:
Microsoft Access 9.0 Object Library
Microsoft DAO 3.60 Object Library
Microsoft Data Source Interfaces (msdatsrc.tlb)
Microsoft ActiveX Data Objects 2.6 Library
Komponenten:
keine
Um es gleich vorwegzunehmen: alles hat bis vor kurzem noch funktioniert
(mit obigen Verweisen und deren Gebrauch). Nach ein paar Änderungen -
peng.
Habe alle Deklarationen durchgeflöht - keine war auffällig im Sinne der
Fehlermeldung (wenn ich die richtig verstanden habe). Einzig merkwürdig
ist, das z.B. bei
Dim rs as adodb.Recordset
das adodb klein bleibt. Das war vorher aber auch schon so.
Wer kann mir einen Hinweis geben, wo ich hinfassen muß, um das in den
Griff zu bekommen.
Ulrich
Beispiel:
Microsoft DAO 3.60 Object Library
Microsoft ActiveX Data Objects 2.6 Library
...
Dim rs as Recordset
...
rs.Open "Tabelle", cnn
rs wird von VB als DAO-Recordset interpretiert, die Open-Methode mit der
ADO-Connection funktioniert so aber nicht.
Peter
"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> schrieb im
Newsbeitrag news:3BB63134...@t-online.de...
Peter Fleischer schrieb:
> Ulrich,
> wenn du zwei Objektbibliotheken mit sich überschneidenden Definitionen
> nutzt, dann musst du unbedingt in deinen Deklarationen den richtigen
> Bibliotheksnamen voransetzen. Wenn du das nicht machst, kann es
> passieren, dass die falsche Definition genutzt wird, da VB in der
> Reihenfolge der Verweise auflöst.
Ja. ist klar. Habe im Code nur qualifizierte Namen verwendet (also
DAO.Recordset, ADODB.Recordset etc.). Trotzdem gibts Probleme.
Neuester Stand:
Habe jetzt einige Verweise und Code-Teile aus dem Projekt entfernt.
Enthalten sind jetzt noch folgende Verweise (und Code, der Objekte aus
den verwiesenen Bibliotheken benutzt):
Microsoft Data Source Interfaces (msdatsrc.tlb)
Microsoft ActiveX Data Objects 2.6 Library
Leider ohne Erfolg.
Ulrich
so eine Meldung habe ich auch gerade bei einem Projekt bekommen. In meinem
Fall hat mir aber der Objekt-Browser angezeigt, welche Variable das war.
Hast du mal versucht, im Objekt-Browser alle Mitglieder der verwendeten
Bibliotheken abzuklappern?
Gruß,
Lukas
habs gefunden.
In einem Klassenmodul (das OCX enthält UserControls, einige Klassen und
ein Standardmodul) war folgender Code:
Public Sub SetActionFind(ByVal Criterium As String, _
Optional ByVal SkipRows As Long = 0, _
Optional ByVal SearchForward As Boolean = True,
_
Optional ByVal StartBookmark As Variant =
Empty)
SetAction ukadcActionFind, Criterium, SkipRows, SearchForward,
StartBookmark
End Sub
Der Defaultteil für StartBookmark ist zwar überflüssig (da eh zu Empty
initalisiert wird), aber ich bevorzuge diese Schreibweise aus Gründen
der besseren Lesbarkeit.
Wenn nun in:
Public Sub SetActionFind(ByVal Criterium As String, _
Optional ByVal SkipRows As Long = 0, _
Optional ByVal SearchForward As Boolean = True,
_
Optional ByVal StartBookmark As Variant)
abgeändert, wird ohne Fehlermeldung kompiliert.
Dies läßt mich nun doch etwas ratlos zurück. Wie passt das bitte zur
Fehlermeldung? Wieso ergibt das überhaupt einen Fehler? Wieso wird die
fehlerhafte Stelle nicht angezeigt? Mit anderen Worten: was soll der
Quatsch?
Ulrich
es geht hier bei mir auschließlich um MS-Bibliotheken, die für die
Automatisierung gedacht sind. Die sollten also auch nur
automatisierungsfeste Typen verwenden. Außerdem habe ich bis jetzt nur
eine Handvoll Typen aus diesen Bibliotheken verwendet, und zwar alles
Typen, die ich schon immer verwendet habe (wie z.B. ein Recordset-Objekt
und ähnliches). Sollte also nicht in Frage kommen. Hab die Ursache eh
schon gefunden, (siehe weiter unten im Thread).
Was mich interessieren würde: Du verwendest anscheinend eine Bibliothek,
welche Nicht-Automatisierungstypen verwendet. Wie wird denn ein solcher
Typ im Objektbrowser angezeigt? Ich dachte, der benutzt COM-"Reflection"
(Typelibs). Und ein COM-Typ sollte automatisierungsfest sein. Wenn er es
also nicht ist, wie kann ihn dann der Objektbrowser anzeigen?
Ulrich
> Dies läßt mich nun doch etwas ratlos zurück. Wie passt das bitte zur
> Fehlermeldung? Wieso ergibt das überhaupt einen Fehler? Wieso wird die
> fehlerhafte Stelle nicht angezeigt? Mit anderen Worten: was soll der
> Quatsch?
das keyword "Empty" hat nix mit COM zu tun, deshalb paßt's auch nich in die
von vb erzeugte IDL, weiß der geier, was vb da beim kompilieren tut
warum nix vernünftige meldung: auch VB hat reichlich buckz, nich nur die von
dir verzapfte software :-)
Steffen Ramlow schrieb:
[...]
> das keyword "Empty" hat nix mit COM zu tun, deshalb paßt's auch nich in die
> von vb erzeugte IDL, weiß der geier, was vb da beim kompilieren tut
Lt. Doku ist Empty ein Schlüsselwort, welches einen Wert vom Typ
Variant, Untertyp Empty repräsentiert.
Hm, in meiner Unschuld habe ich angenommen, daß, da ein Variant ja eine
Struktur ist, die in COM des öfteren zu finden ist, VB auch nur in COM
definierte Untertypen verwendet.
Der Code:
Public Sub testA()
Dim v As Variant
v = Empty
If VarType(v) = vbEmpty Then MsgBox "Empty"
End Sub
wird anstandslos übersetzt,
Public Sub testB(Optional ByVAl v as Variant = Empty)
End Sub
dagegen nicht.
Nach Deiner Erklärung müßte das daran liegen, daß in testA die
Verwendung von Empty nicht die Schnittstelle beeinflußt. Hm, scheint
Sinn zu machen. Bedeutet dann außerdem, daß der Aufrufer von testB den
Wert vom Typ Empty bereitstellen müßte. Und da der Aufrufer außerhalb
der Bibliothek sein kann, müßte diesem der Variantuntertyp Empty bekannt
sein, welcher aber anscheinend nicht in COM definiert ist.
Da gibt es aber noch ein kleines Problem:
Dim vvv as Variant
Public Sub testC(Optional ByVal v As Variant)
Dim vv As Variant
MsgBox "VarType(v): " & CStr(VarType(v)) & vbCrLf & _
"VarType(vv): " & CStr(VarType(vv)) & vbCrLf & _
"VarType(vvv): " & CStr(VarType(vvv))
End Sub
wird ebenfalls anstandslos übersetzt und ergibt, wenn von außerhalb und
innerhalb der Bibliothek aufgerufen, jeweils für v den Subtype vbError
(10), für vv und vvv den Subtype vbEmpty (0). Der gleiche Code in einer
Standardexe mit Aufruf in derselben liefert das gleiche Ergebnis. Das
heißt, innerhalb einer Prozedur muß bei dem Versuch, auszuwerten, ob
eine Variant initialisiert ist, zwischen einem lokalen oder globalen
Variant und einem übergebenen Variant unterschieden werden.
Andererseits ist in einer Standardexe
Dim vvv as Variant
Public Sub testD(Optional ByVal v As Variant = Empty)
Dim vv As Variant
MsgBox "VarType(v): " & CStr(VarType(v)) & vbCrLf & _
"VarType(vv): " & CStr(VarType(vv)) & vbCrLf & _
"VarType(vvv): " & CStr(VarType(vvv))
End Sub
problemlos möglich und ergibt dreimal den Subtype Empty.
Oh Wirrwarr.
> warum nix vernünftige meldung: auch VB hat reichlich buckz, nich nur die von
> dir verzapfte software :-)
Meine Software hat nur Features :-)
Ulrich
habe noch ein bißchen gestöbert.
Aus
Plattform-SDK
COM and ActiveX Object Services
Automation
Data Types, Structures, and Enumerations
IDispatch Data Types and Structures
VARIANT and VARIANTARG:
[...]
typedef struct tagVARIANT {
VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
unsigned char bVal; // VT_UI1.
short iVal;
[...]
The vt value governs the interpretation of the union as follows:
Value
VT_EMPTY
Description
No value was specified. If an optional argument to an Automation method
is left blank, do not pass a VARIANT of type VT_EMPTY. Instead, pass a
VARIANT of type VT_ERROR with a value of DISP_E_PARAMNOTFOUND
[...]
Scheint so zu sein, daß VT_EMPTY durchaus COM-bekannt ist, aber es bei
einer optionalen Parameterübergabe nicht verwendet werden darf. Der
Callee muß sich darauf verlassen können, daß er im Falle eines fehlenden
Argumentes einen Variant vom Typ vbError überreicht bekommt. Das könnte
der Grund sein, warum VB eine explizite Belegung mit Empty nicht zuläßt.
Ulrich
> Der
> Callee muß sich darauf verlassen können, daß er im Falle eines fehlenden
> Argumentes einen Variant vom Typ vbError überreicht bekommt. Das könnte
> der Grund sein, warum VB eine explizite Belegung mit Empty nicht zuläßt.
Quark.
Der Caller stünde vor einem Problem, wenn in der Methodendeklaration via
Defaultwertzuweisung von ihm verlangt werden würde, ein Empty-Variant im
Falle des Fehlens zu übergeben. Das ergäbe einen Widerspruch zu der
Regel im vorigen Post.
Ob das nun der wirkliche Grund ist, warum VB sich einerseits strikt an
COM hält, andererseits (siehe testD weiter oben), solange alles in der
Familie bleibt, Fünfe auch mal grade sein läßt?
Ulrich
--
Steffen Ramlow: s.ra...@gmx.de
Enterprise Development: http://www.dev-purgatory.org/
"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message
news:3BB93279...@t-online.de...
Steffen Ramlow schrieb:
>
> ich würde mal sagen: beim kompilieren wird angenommen: vbEmpty = VT_EMPTY <>
> Empty
Aber Empty = VARIANT mit VARTYPE vt = VT_EMPTY.
Ulrich
"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message
news:3BB9D0E8...@t-online.de...
> Aber Empty = VARIANT
wo steht das denn?
Steffen Ramlow schrieb:
> > Aber Empty = VARIANT
>
> wo steht das denn?
Doku:
A)
Das Schlüsselwort Empty wird als Variant-Untertyp verwendet und zeigt
einen nicht initialisierten Variablenwert an
B)
Der Wert Empty
Manchmal müssen Sie bestimmen, ob einer Variablen überhaupt ein Wert
zugewiesen wurde. Eine Variant-Variable hat den Wert Empty, solange ihr
noch kein Wert zugewiesen wurde. Der Wert Empty ist ein besonderer Wert
und unterscheidet sich von 0, einer Nullzeichenfolge ("") und dem Wert
Null.
[...]
Sie können eine Variant-Variable auf den Wert Empty zurücksetzen, indem
Sie ihr das Schlüsselwort Empty zuweisen.
C)
Empty
Zeigt an, daß einer Variablen vom Typ Variant kein Anfangswert
zugewiesen worden ist. Eine Variable vom Typ Empty wird durch eine Null
(0) in einem numerischen Kontext oder durch eine Null-Zeichenfolge ("")
in einem Zeichenfolgenkontext dargestellt.
und:
D)
If VarType(Empty) = vbEmpty Then MsgBox "Empty"
lässt die Messagebox aufpoppen. Da ein Wert vom VarType vbEmpty nur ein
Variant sein kann, muß Empty ein Variant vom VarType vbEmpty sein.
Ulrich
"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message
news:3BB9FEF6...@t-online.de...
> muß Empty ein Variant vom VarType vbEmpty sein.
ju, oke
aber was sollz, is halt so
Steffen Ramlow schrieb:
> > muß Empty ein Variant vom VarType vbEmpty sein.
>
> ju, oke
> aber was sollz, is halt so
Wo Du Recht hast, hast Du recht :-)
Ulrich
> ich würde mal sagen: beim kompilieren wird angenommen: vbEmpty = VT_EMPTY
<>
> Empty
Logo. Der Wert Empty ist wirklich etwas anderes als die VarType-Konstante
vbEmpty (alias VT_EMPTY)...
Viele Grüße
Harald M. Genauck
ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
>> No value was specified. If an optional argument to an Automation method
>> is left blank, do not pass a VARIANT of type VT_EMPTY. Instead, pass a
>> VARIANT of type VT_ERROR with a value of DISP_E_PARAMNOTFOUND
>> [...]
> Scheint so zu sein, daß VT_EMPTY durchaus COM-bekannt ist, aber es bei
> einer optionalen Parameterübergabe nicht verwendet werden darf. Der
> Callee muß sich darauf verlassen können, daß er im Falle eines fehlenden
> Argumentes einen Variant vom Typ vbError überreicht bekommt. Das könnte
> der Grund sein, warum VB eine explizite Belegung mit Empty nicht zuläßt.
Daher auch die IsMissing-Funktion - sie funktioniert ja auch nur mit
optionalen Variant-Parametern.
Außerdem:
Private Sub Command1_Click()
XY
End Sub
Private Sub XY(Optional abc As Variant)
Debug.Print VarType(abc)
End Sub
->> ergibt 10, als vbError!
Da aber auch optionale Parameter bei Methoden von VB-Objekten, etwa bei der
Add-Methode der Collection als "Nichts" das vbError erwarten, funktioniert
so auch das Durchreichen von Nichts ohne Probleme und Gemeutere:
Sub MyAdd(Item As Irgendwas, Optional Key As Variant)
IrgendeineCollection.Add Item, Key
End Sub
Wo bist Du denn in den letzten Woche abgeblieben? Urlaub? Hab Dich schon
vermisst und war kurz vor der Vermisstenanzeige ;-).
Zum Thema:
> Da aber auch optionale Parameter bei Methoden von VB-Objekten, etwa bei der
> Add-Methode der Collection als "Nichts" das vbError erwarten, funktioniert
> so auch das Durchreichen von Nichts ohne Probleme und Gemeutere:
>
> Sub MyAdd(Item As Irgendwas, Optional Key As Variant)
> IrgendeineCollection.Add Item, Key
> End Sub
Ist das generell so, also z.B. auch bei ADO-Objekten?
Beispiel:
Public Sub SetActionFind(ByVal Criterium As String, _
Optional ByVal SkipRows As Long = 0, _
Optional ByVal SearchForward As Boolean = True,
_
Optional ByVal StartBookmark As Variant)
Dim RS as ADODB.RecordSet
Dim Direction as Long
If SearchForward Then Direction = adSearchForward Else Direction =
adSearchBackWard
Rs.Find Criterium, SkipRows, Direction, StartBookmark
End Sub
StartBookmark setzt eine Position im Recordset, ab der die Suche
beginnen soll. Der Parameter ist in der Find Methode als optionaler
Variant deklariert.
Bisher habe ich das so gelöst, daß ich auswerte, ob ein Wert für
Startbookmark übergeben wurde und dann entsprechend zwei verschiedene
Aufrufe von Find durchführe, einen mit und einen ohne diesen Parameter.
Deinen Ausführungen gemäß könnt ich mir das sparen.
Ulrich
> Wo bist Du denn in den letzten Woche abgeblieben? Urlaub? Hab Dich schon
> vermisst und war kurz vor der Vermisstenanzeige ;-).
Habe einen Murphy-Kurs gemacht... ;-)
> > Da aber auch optionale Parameter bei Methoden von VB-Objekten, etwa bei
der
> > Add-Methode der Collection als "Nichts" das vbError erwarten,
funktioniert
> > so auch das Durchreichen von Nichts ohne Probleme und Gemeutere:
> >
> > Sub MyAdd(Item As Irgendwas, Optional Key As Variant)
> > IrgendeineCollection.Add Item, Key
> > End Sub
> Ist das generell so, also z.B. auch bei ADO-Objekten?
Wenn diese im Sinne der bisherigen Ausführungen "ordentlich" programmiert
bzw. deren TLBs ok sind, dann dürfte das auch bei ADO funktionieren.
Garantieren kann ich es natürlich nicht.
> Bisher habe ich das so gelöst, daß ich auswerte, ob ein Wert für
> Startbookmark übergeben wurde und dann entsprechend zwei verschiedene
> Aufrufe von Find durchführe, einen mit und einen ohne diesen Parameter.
> Deinen Ausführungen gemäß könnt ich mir das sparen.
Das war früher auch meine Taktik, bis ich gemerkt habe, dass es auch
"automatisch" geht. Allerdings mit einem Vorbehalt: Es geht nur bei
optionalen Variant-Parametern! Optionale Parameter anderer Datentypen
übermitteln jeweils ihren Standard-Initialisierungswert, wenn sie
weggelassen werden und nicht eine Vorbelegung angegeben ist.