stephan35 Posté(e) le 31 janvier 2007 Posté(e) le 31 janvier 2007 Bonjour, Suite à mon echec avec adolisp (plantage récurrent d'autocad lors d'accès simultané à odbc), je cherche un moyen d'accèder aux bases de donnes *.mdb et *.dbf avec des commandes VLISP . Y a-til un tuto ? Quelqu'un peut-il me fournir un exemple ? Merci
Bred Posté(e) le 1 février 2007 Posté(e) le 1 février 2007 Salut,je ne suis pas sûr, mais cheche sur internet une fonction nommé "ADOLISP_ConnectToDB". Si vous êtes persuadés de tout savoir sur un sujet, c''est que vous en ignorez quelque chose...
stephan35 Posté(e) le 1 février 2007 Auteur Posté(e) le 1 février 2007 à BRED Salut,je ne suis pas sûr, mais cheche sur internet une fonction nommé "ADOLISP_ConnectToDB". Ben alors , on ne lit pas bien la question ?Question : Suite à mon echec avec [surligneur] adolisp [/surligneur] (plantage récurrent d'autocad lors d'accès simultané à odbc), je cherche un moyen d'accèder aux bases de donnes *.mdb et *.dbf avec des commandes VLISP . Donc je relance le truc ! Y-a-t-il une solution pour se connecter aux bases de données avec VLISP (autre que ADOLISP) ? Merci !
Bred Posté(e) le 1 février 2007 Posté(e) le 1 février 2007 Je ne comprends pas alors... désolé... mais je persiste ..."ADOLISP_ConnectToDB" est une routine lisp , ou justement je cherche un moyen d'accèder aux bases de donnes *.mdb et *.dbf avec des commandes VLISP .Y a-til un tuto ?Quelqu'un peut-il me fournir un exemple ?tu peux t'en servir comme exemple, et le corriger si tu t'en sent capable vu que ça plante...... ;;; A library to be used to access a database from Visual LISP ;;; in AutoCAD 2000 or higher using ActiveX Data Objects ;;; (ADO) ;; Load the ActiveX stuff for Visual LISP if it isn't already ;; loaded (vl-load-com) ;;; In case this file gets compiled into a separate-namespace ;;; VLX, export the functions that should be visible. The ;;; following has no effect unless the document is compiled ;;; into a separate-namespace VLX. (vl-doc-export 'ADOLISP_ConnectToDB) (vl-doc-export 'ADOLISP_DoSQL) (vl-doc-export 'ADOLISP_DisconnectFromDB) (vl-doc-export 'ADOLISP_ErrorPrinter) (vl-doc-export 'ADOLISP_GetTablesAndViews) (vl-doc-export 'ADOLISP_variant-value) ;;; Set up some variables that must be global (within ;;; this file) ;;; Define a VB data type that Visual LISP forgot (if (not vlax-vbDecimal) (setq vlax-vbDecimal 14) ) ;;; Set a flag if we are running in AutoCAD 2000 (not 2000i, ;;; 2002, ...) (if (< (atof (getvar "ACADVER")) 15.05) (setq ADOLISP_IsAutoCAD2000 T) ) ;; Import the ADO type library if it hasn't already been loaded. (if (null ADOMethod-Append) (cond ;; If we can find the library in the registry ... ((and (setq ADOLISP_ADODLLPath (vl-registry-read "HKEY_CLASSES_ROOT\\ADODB.Command\\CLSID" ) ) (setq ADOLISP_ADODLLPath (vl-registry-read (strcat "HKEY_CLASSES_ROOT\\CLSID\\" ADOLISP_ADODLLPath "\\InProcServer32" ) ) ) (findfile ADOLISP_ADODLLPath) ) ;; Import it (vlax-import-type-library :tlb-filename ADOLISP_ADODLLPath :methods-prefix "ADOMethod-" :properties-prefix "ADOProperty-" :constants-prefix "ADOConstant-" ) ) ;; Or if we can find it where we expect to find it ... ((setq ADOLISP_ADODLLPath (findfile (if (getenv "systemdrive") (strcat (getenv "systemdrive") "\\program files\\Fichiers communs\\system\\ado\\msado15.dll" ) "c:\\program files\\Fichiers communs\\system\\ado\\msado15.dll" ) ) ) ;; Import it (vlax-import-type-library :tlb-filename ADOLISP_ADODLLPath :methods-prefix "ADOMethod-" :properties-prefix "ADOProperty-" :constants-prefix "ADOConstant-" ) ) ;; Can't find the library, tell the user (T (alert (strcat "Cannot find\n\"" (if ADOLISP_ADODLLPath ADOLISP_ADODLLPath "msado15.dll" ) "\"" ) ) ) ) ) ;;; A routine to connect to a database ;;; Arguments: ;;; ConnectString: Either the name of a .UDL file, including ;;; the ".UDL", or an OLEDB connection string. ;;; If this argument is the name of a UDL ;;; file without a full path, it is searched ;;; for in the current directory, the AutoCAD ;;; search path, and the AutoCAD Data Source ;;; Location. ;;; UserName: The user name to use when connecting. ;;; May be a null string if the user name is ;;; specified in the first argument or the ;;; first argument is a UDL file name. ;;; Password: The password to use when connecting. ;; May be a null string if the password is ;;; supplied in the first argument or the ;;; first argument is a UDL file name. ;;; Return value: ;;; If anything fails, NIL. Call (ADOLISP_ErrorPrinter) to ;;; print error messages to the command line. ;;; Otherwise, an ADO Connection Object. (defun ADOLISP_ConnectToDB (ConnectString UserName Password / IsUDL FullUDLFileName ConnectionObject TempObject ReturnValue ) ;; Assume no error (setq ADOLISP_ErrorList nil ADOLISP_LastSQLStatement nil ) ;; If the connect string is a UDL file name ... (if (= ".UDL" (strcase (substr ConnectString (- (strlen ConnectString) 3)) ) ) (progn ;; Set a flag that it's a UDL file (setq IsUDL T) ;; Try to find it (cond ((setq FullUDLFileName (findfile ConnectString))) ;; Didn't find it in the current directory or ;; the AutoCAD search path, try the AutoCAD ;; Data Source location ((setq FullUDLFileName (findfile (strcat (vlax-get-property (vlax-get-property (vlax-get-property (vlax-get-acad-object) "Preferences" ) "Files" ) "WorkspacePath" ) "\\" ConnectString ) ) ) ) ;; Didn't find it, store an error message (t (setq ADOLISP_ErrorList (list (list (cons "ADOLISP connection error" (strcat "Can't find \"" ConnectString "\"" ) ) ) ) ) ) ) ) ) ;; If the first argument is a UDL file name... ... (if IsUDL ;; If we found it ... (if FullUDLFileName (progn ;; Create an ADO connection object (setq ConnectionObject (vlax-create-object "ADODB.Connection")) ;; Try to open the connection. If there is an error ... (if (vl-catch-all-error-p (setq TempObject (vl-catch-all-apply 'vlax-invoke-method (list ConnectionObject "Open" (strcat "File Name=" FullUDLFileName) UserName Password ADOConstant-adConnectUnspecified ) ) ) ) (progn ;; Save the error information (setq ADOLISP_ErrorList (ADOLISP_ErrorProcessor TempObject ConnectionObject) ) ;; Release the connection object (vlax-release-object ConnectionObject) ) ;; It worked, store the connection object in our return ;; value (setq ReturnValue ConnectionObject) ) ) ) ;; The connect string is not a UDL file name. (progn ;; Create an ADO connection object (setq ConnectionObject (vlax-create-object "ADODB.Connection")) ;; Try to open the connection. If there is an error ... (if (vl-catch-all-error-p (setq TempObject (vl-catch-all-apply 'vlax-invoke-method (list ConnectionObject "Open" ConnectString UserName Password ADOConstant-adConnectUnspecified ) ) ) ) (progn ;; Save the error information (setq ADOLISP_ErrorList (ADOLISP_ErrorProcessor TempObject ConnectionObject) ) ;; Release the connection object (vlax-release-object ConnectionObject) ) ;; It worked, store the connection object in our return value (setq ReturnValue ConnectionObject) ) ) ) ReturnValue ) ;;; A function to execute an arbitrary SQL statement ;;; (replacable parameters are not supported). ;;; Arguments: ;;; ConnectionObject: An ADO Connection Object. ;;; SQLString: the SQL statement to execute. ;;; Return value: ;;; If anything fails, NIL. Call (ADOLISP_ErrorPrinter) to ;;; print error messages to the command line. Otherwise: ;;; If the SQL statement is a "select ..." statement that ;;; could return rows, returns a list of lists. The first sub-list ;;; is a list of the column names. If any rows were returned, ;;; the subsequent sub-lists contain the returned rows in the same ;;; order as the column names in the first sub-list. ;;; If the SQL statement is a "delete ...", "update ...", or ;;; "insert ..." that cannot return any rows: ;;; If the program is running in AutoCAD 2000, T ;;; If the program is running in AutoCAD 2000i or ;;; later, the integer number of rows affected. (defun ADOLISP_DoSQL (ConnectionObject SQLStatement / RecordSetObject FieldsObject FieldNumber FieldCount FieldList RecordsAffected TempObject ReturnValue CommandObject IsError ) ;; Assume no error (setq ADOLISP_ErrorList nil ADOLISP_LastSQLStatement SQLStatement ) ;; If we are working in AutoCAD 2000 ... (if ADOLISP_IsAutoCAD2000 ;; Then we can't use the Execute method of the Command ;; object because returning values in parameters (of a ;; function loaded from an external library) is broken. (progn ;; Create an ADO Recordset and set the cursor and lock ;; types (setq RecordSetObject (vlax-create-object "ADODB.RecordSet")) (vlax-put-property RecordSetObject "cursorType" ADOConstant-adOpenKeyset ) (vlax-put-property RecordSetObject "LockType" ADOConstant-adLockOptimistic ) ;; Open the recordset. If there is an error ... (if (vl-catch-all-error-p (setq TempObject (vl-catch-all-apply 'vlax-invoke-method (list RecordSetObject "Open" SQLStatement ConnectionObject nil nil ADOConstant-adCmdText ) ) ) ) ;; Save the error information (progn (setq ADOLISP_ErrorList (ADOLISP_ErrorProcessor TempObject ConnectionObject) ) (setq IsError T) (vlax-release-object RecordSetObject) ) ;; Otherwise, set an indicator that it worked (setq RecordsAffected T) ) ) ;; We're in AutoCAD 2000i or above, we can use the ;; Execute method of the Command object and see ;; how many records are affected by an UPDATE, INSERT, ;; or DELETE (progn ;; Create an ADO command object and store the query ;; and connection (setq CommandObject (vlax-create-object "ADODB.Command")) (vlax-put-property CommandObject "CommandText" SQLStatement) (vlax-put-property CommandObject "ActiveConnection" ConnectionObject ) ;; Create an ADO Recordset (setq RecordSetObject (vlax-create-object "ADODB.RecordSet")) ;; Open the recordset. If there is an error ... (if (vl-catch-all-error-p (setq TempObject (vl-catch-all-apply 'vlax-invoke-method (list CommandObject "Execute" 'RecordsAffected nil ADOConstant-adCmdText ) ) ) ) ;; Save the error information (progn (setq ADOLISP_ErrorList (ADOLISP_ErrorProcessor TempObject ConnectionObject) ) (setq IsError T) (vlax-release-object CommandObject) (vlax-release-object RecordSetObject) ) ;; No error, save the recordset (setq RecordSetObject TempObject) ) ) ) ;; If there were no errors ... (if (not IsError) ;; If the recordset is closed ... (if (= ADOConstant-adStateClosed (vlax-get-property RecordsetObject "State") ) ;; Then the SQL statement was a "delete ..." or an ;; "insert ..." or an "update ..." which doesn't ;; return any rows. (progn (setq ReturnValue RecordsAffected) ;; And release the recordset and command; we're done. (vlax-release-object RecordSetObject) (if (not ADOLISP_IsAutoCAD2000) (vlax-release-object CommandObject) ) ) ;; The recordset is open, the SQL statement ;; was a "select ...". (progn ;; Get the Fields collection, which ;; contains the names and properties of the ;; selected columns (setq FieldsObject (vlax-get-property RecordSetObject "Fields" ) ;; Get the number of columns FieldCount (vlax-get-property FieldsObject "Count") FieldNumber -1 ) ;; Get the names of all the columns in a list (while (> FieldCount (setq FieldNumber (1+ FieldNumber))) (setq FieldList (cons (vlax-get-property (vlax-get-property FieldsObject "Item" FieldNumber) "Name" ) FieldList ) ) ) ;; Initialize the return value (setq ReturnValue (list (reverse FieldList))) ;; If there are any rows in the recordset ... (if (not (and (= :vlax-true (vlax-get-property RecordSetObject "BOF") ) (= :vlax-true (vlax-get-property RecordSetObject "EOF") ) ) ) ;; We're about to get tricky, hang on! Create the ;; final results list ... (setq ReturnValue ;; By appending the list of rows to the list of ;; fields. (append (list (reverse FieldList)) ;; Uses Douglas Wilson's elegant ;; list-transposing code from ;; http://xarch.tu-graz.ac.at/autocad/lisp/ ;; to create the list of rows, because ;; GetRows returns items in column order (apply 'mapcar (cons 'list ;; Set up to convert a list of lists ;; of variants to a list of lists of ;; items that AutoLISP understands (mapcar '(lambda (InputList) (mapcar '(lambda (Item) (ADOLISP_variant-value Item) ) InputList ) ) ;; Get the rows, converting them from ;; a variant to a safearray to a list (vlax-safearray->list (vlax-variant-value (vlax-invoke-method RecordSetObject "GetRows" ADOConstant-adGetRowsRest ) ) ) ) ) ) ) ) ) ;; Close the recordset and release it and the ;; command (vlax-invoke-method RecordSetObject "Close") (vlax-release-object RecordSetObject) (if (not ADOLISP_IsAutoCAD2000) (vlax-release-object CommandObject) ) ) ) ) ;; And return the results ReturnValue ) ;;; A function to close a connection and release ;;; the connection object. ;;; Argument: ;;; An ADO Connection Object. ;;; Return value: ;;; Always returns T (defun ADOLISP_DisconnectFromDB (ConnectionObject) (setq ADOLISP_ErrorList nil ADOLISP_LastSQLStatement nil ) (vlax-invoke-method ConnectionObject "Close") (vlax-release-object ConnectionObject) T ) ;;;------------------------------------------------------------ ;;; ADOLISP utility functions ;;; A function to print the list of errors generated ;;; by the ADOLISP_ErrorProcessor function. The functions ;;; are separate so ADOLISP_ErrorProcessor can be called ;;; while a DCL dialog box is displayed and then ;;; ADOLISP_ErrorPrinter can be called after the dialog ;;; box has been removed. ;;; No arguments, no return value. (defun ADOLISP_ErrorPrinter () (if ADOLISP_LastSQLStatement (prompt (strcat "\nLast SQL statement:\n\"" ADOLISP_LastSQLStatement "\"\n\n" ) ) ) (foreach ErrorList ADOLISP_ErrorList (prompt "\n") (foreach ErrorItem ErrorList (prompt (strcat (car ErrorItem) "\t\t" (cdr ErrorItem) "\n") ) ) ) (prompt (strcat "\nLast SQL statement:\n" ADOLISP_LastSQLStatement "\n" ) ) (prin1) ) ;;; A function to obtain the names of all ;;; the tables and views in a database. ;;; (Views are called "Queries" in Microsoft Access.) ;;; Argument: ;;; ConnectionObject: An ADO Connection Object ;; Return value: ;;; A list of two lists. ;;; The first list contains the table names. ;;; The second list contains the view names. (defun ADOLISP_GetTablesAndViews (ConnectionObject / TempObject TablesList TempList ViewsList ) (setq ADOLISP_ErrorList nil ADOLISP_LastSQLStatement nil ) (setq RecordSetObject (vlax-create-object "ADODB.RecordSet")) ;; If we fail getting a recordset of the tables and views ... (if (vl-catch-all-error-p (setq RecordSetObject (vl-catch-all-apply 'vlax-invoke-method (list ConnectionObject "OpenSchema" ADOConstant-adSchemaTables ) ) ) ) ;; Save the error information (setq ADOLISP_ErrorList (ErrorProcessor RecordSetObject ConnectionObject) ) (progn ;; Got the recordset! If there are records ... (if (< 0 (vlax-get-property RecordSetObject "RecordCount")) (progn ;; We're about to get tricky, hang on! Convert the ;; recordset object to a LISP list ... (setq TempList ;; Uses Douglas Wilson's elegant ;; list-transposing code from ;; http://xarch.tu-graz.ac.at/autocad/lisp/ ;; to create the list of rows, because ;; GetRows returns items in column order (apply 'mapcar (cons 'list ;; Set up to convert a list of lists ;; of variants to a list of lists of ;; items that AutoLISP understands (mapcar '(lambda (InputList) (mapcar '(lambda (Item) (ADOLISP_variant-value Item) ) InputList ) ) ;; Get the rows, converting them from ;; a variant to a safearray to a list (vlax-safearray->list (vlax-variant-value (vlax-invoke-method RecordSetObject "GetRows" ADOConstant-adGetRowsRest ) ) ) ) ) ) ) ;; Now filter out the system tables and ;; sort the tables and views into the ;; correct lists (foreach Item TempList (cond ((= (nth 3 Item) "VIEW") (setq ViewsList (cons (nth 2 Item) ViewsList)) ) ((= (nth 3 Item) "TABLE") (setq TablesList (cons (nth 2 Item) TablesList)) ) ) ) ) ) ;; Close the recordset (vlax-invoke-method RecordSetObject "Close") ) ) (vlax-release-object RecordSetObject) (list TablesList ViewsList) ) ;;;------------------------------------------------------------ ;;; ADOLISP Support functions ;;; A function to assemble all errors into a list of lists of ;;; dotted pairs of strings ("name" . "value") (defun ADOLISP_ErrorProcessor (VLErrorObject ConnectionObject / ErrorsObject ErrorObject ErrorCount ErrorNumber ErrorList ErrorValue ) ;; First get Visual LISP's error message (setq ReturnList (list (list (cons "Visual LISP message" (vl-catch-all-error-message VLErrorObject) ) ) ) ;; Get the ADO errors object and quantity ErrorObject (vlax-create-object "ADODB.Error") ErrorsObject (vlax-get-property ConnectionObject "Errors") ErrorCount (vlax-get-property ErrorsObject "Count") ErrorNumber -1 ) ;; Loop over all the ADO errors ... (while (< (setq ErrorNumber (1+ ErrorNumber)) ErrorCount) ;; Get the error object of the current error (setq ErrorObject (vlax-get-property ErrorsObject "Item" ErrorNumber) ;; Clear the list of items for this error ErrorList nil ) ;; Loop over all possible error items of this error (foreach ErrorProperty '("Description" "HelpContext" "HelpFile" "NativeError" "Number" "SQLState" "Source" ) ;; Get the value of the current item. If it's a number ... (if (numberp (setq ErrorValue (vlax-get-property ErrorObject ErrorProperty) ) ) ;; Convert it to a string for consistency (setq ErrorValue (itoa ErrorValue)) ) ;; And store it (setq ErrorList (cons (cons ErrorProperty ErrorValue) ErrorList)) ) ;; Add the list for the current error to the return value (setq ReturnList (cons (reverse ErrorList) ReturnList)) ) ;; Set up the return value in the correct order (reverse ReturnList) ) ;;; A function to convert a variant to a value. Knows ;;; about more variant types than vlax-variant-value (defun ADOLISP_variant-value (VariantItem / VariantType) (cond ;; If it's a Currency data type or a Decimal data type ... ((or (= vlax-vbCurrency (setq VariantType (vlax-variant-type VariantItem)) ) ;; Note that I defined vlax-vbDecimal ;; at the beginning of the file (= vlax-vbDecimal VariantType) ) ;; Convert it to a double before getting its value (vlax-variant-value (vlax-variant-change-type VariantItem vlax-vbDouble) ) ) ;; If it's a date, time, or date/time variable type ... ((= vlax-vbDate VariantType) ;; Convert it to a string (assuming it's a Microsoft ;; Access type Julian date) (1900BasedJulianToCalender (vlax-variant-value VariantItem)) ) ;; If it's a boolean value (yes/no, true/false, ...) ... ((= vlax-vbBoolean VariantType) ;; Convert it to the string "True" or "False" (if (= :vlax-true (vlax-variant-value VariantItem)) "True" "False" ) ) ;; Otherwise, just turn vlax-variant-value loose on it (t (vlax-variant-value VariantItem)) ) ) Si vous êtes persuadés de tout savoir sur un sujet, c''est que vous en ignorez quelque chose...
stephan35 Posté(e) le 1 février 2007 Auteur Posté(e) le 1 février 2007 Coucou bred ! Je corrige ma demande !Hormis la méthode vlisp de fleming http://acad.fleming-group.com/index.html que tu viens de me fournir ............. :cool: Que j'ai trituré dans tous les sens, au risque de planté ma base de registre ... (msado15.dll) ;) Que j'ai vérifié sur d'autres postes et que cela ne fonctionne pas non plus ! Que je me suis dit, et bien ou ouvre la base et on fait ce que l'on a à faire, puis on la referme aussi tôt ! et bien non, car autocad plante si un autre executable exploite odbc en même temps ! Un à la fois mes enfants ! Conclusion : [surligneur] N'y aurait-il pas une autre solution, car celle-ci empêche tout autre executable d'accèder à une base de donnée via odbc , y compris autocad lui même ....... :o gregnegne ! [/surligneur] Que j'ai une autre solution qui dit : quand tu travailles avec autocad tu ne fais rien d'autres ! Mais elle ne me plait pas ! AAAAAAAAUUUUUUUU SSSEEEEECCCCOOOOOUUUUUURRRRRRSSSSSSS ! Ps: AutoDesk m'a envoyer boulé !Allé voir votre fournisseurPs2 : Mon fournisseur m'a envoyé boulé !N'est pas compris dans le contrat de maintenance ......gregnegne ! Merci !
Didier-AD Posté(e) le 5 février 2007 Posté(e) le 5 février 2007 Il me semble que VB, je dis bien VB, pas VBA accède bien aux bases de données, sinon il n'y aurait pas tant d'applications de BD écrites en VBet en VB on peut accéder à AutoCAD également ... je ne prétends pas que c'est l'idéal mais s'il te faut absolument trouver une solution....
stephan35 Posté(e) le 6 février 2007 Auteur Posté(e) le 6 février 2007 Bonjour à tous Je suis heureux de vous annoncer que mon accès à la base de données Via ADOLisp fonctionne à nouveau, cependant, [surligneur] n'utiliser pas le moteur dbase *.dbf [/surligneur] car il provoque l'arrêt des autres processus ODBC (y compris Borland BDE) ! Ceci est un bug microsoft ! Donc j'ai changé mon type de base de donnée , je suis passé en *.mdb .... (je serre les fesses ;) ) A bientôt !
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant