IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Projets ADP Discussion :

Migrer une base MSAccess en projet ADP SQL Server [Tutoriel]


Sujet :

Projets ADP

  1. #21
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut Bonjour Nico !
    Merci beaucoup pour cette réponse...

    On est surement nombreux à se faire piéger en démarrant une appli Access : on n'imagine jamais que Microsoft a rendu les choses aussi compliquées pour passer à MS SQL Server.

    Je règle le problème DAO/ADO, et je crois qu'il me faudra aussi faire sauter mes db.CreateQueryDef si patiemment assemblées en DAO.

    Soit... iif(msql) et MODE_ADO peuvent se combiner utilement !

    Le "chef", c'est l'Araignée ??

    Amitiés!

    phil

  2. #22
    Expert confirmé Avatar de nico84
    Homme Profil pro
    Consultant/développeur ERP
    Inscrit en
    Mai 2008
    Messages
    3 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant/développeur ERP
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 3 087
    Points : 5 203
    Points
    5 203
    Par défaut
    Citation Envoyé par harpyopsis Voir le message
    On est surement nombreux à se faire piéger en démarrant une appli Access : on n'imagine jamais que Microsoft a rendu les choses aussi compliquées pour passer à MS SQL Server.
    On commence avec access parce que c'est facile et Bim
    Heureusement, autant la base de données est pourrie, autant le VBA n'a pratiquement pas de limites... tant qu'on ne veut pas faire du web ce qui est quand même une limite énorme aujourd'hui


    Citation Envoyé par harpyopsis Voir le message
    Soit... iif(msql) et MODE_ADO peuvent se combiner utilement !
    Amha à partir du moment où on utilise SQL server il faut abandonner DAO et donc le problème devient uniquement les différences de syntaxe SQL. Mais j'avoue ne pas avoir lu le tuto (j'ai migré ADO en 2013 sans passer par la case adp)


    Citation Envoyé par harpyopsis Voir le message
    Le "chef", c'est l'Araignée ??
    Le chef de file, au minimum
    Utilisez Planet, gestion d'entreprise gratuite pour TPE / PME

  3. #23
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut
    Citation Envoyé par nico84 Voir le message
    On commence avec access parce que c'est facile et Bim
    Heureusement, autant la base de données est pourrie, autant le VBA n'a pratiquement pas de limites... tant qu'on ne veut pas faire du web ce qui est quand même une limite énorme aujourd'hui
    Absolument d'accord ! Mais il n'y a pas de web pour moi dans ce domaine particulier, heureusement ! Sauf la réplication MS SQL et FTP entre utilisateurs sur le VPS.

    Citation Envoyé par nico84 Voir le message
    Amha à partir du moment où on utilise SQL server il faut abandonner DAO et donc le problème devient uniquement les différences de syntaxe SQL. Mais j'avoue ne pas avoir lu le tuto (j'ai migré ADO en 2013 sans passer par la case adp)
    Oui, le tuto est très agréable à lire et il reste d'actualité malgré la disparition d'ADP.

    Il donne une bonne idée du cauchemar des + au lieu de &, des 1/0 au lieu de -1/0 pour True/False... Ils doivent vraiment l'avoir fait exprès chez BG !

    Citation Envoyé par nico84 Voir le message
    Le chef de file, au minimum
    L’Argyronète ? Cela va de soie !

  4. #24
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut
    Hello Nico !

    C'est bizarre, "le Chef" ne se montre pas depuis deux jours... serait il en vacances ?

    Je viens de convertir environ 270 requêtes diverses de DAO en ADO sans trop de problèmes, et tout se met bien en forme pour la dualité Access/MS SQL.

    Mais je tombe sur un os pour les quelques dernières DAO pourtant super-simples, mais qui sont du type RecordsetClone. Elles me servent par exemple à "Sélectionner tout" / "Désélectionner tout" ("Cocher tout" / "Décocher tout") pour une case à cocher dans un sous-formulaire continu filtré.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Private Sub CheckSelectAll_AfterUpdate()
     
    Dim dbDao As dao.Database, rs As dao.Recordset, MyBool As Boolean
        Set dbDao = CurrentDb()
        Set rs = Me.Form.RecordsetClone
        MyBool = Me.CheckSelectAll.Value
     
    rs.MoveFirst
    Do While Not rs.EOF
        rs.Edit
        rs!Selected = MyBool
        rs.Update
        rs.MoveNext
    Loop
     
    Set rs = Nothing
    Set dbDao = Nothing
    End Sub
    La transposition en ADO se passe très mal

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Private Sub CheckSelectAll_AfterUpdate()
     
    Dim Cnn As adodb.Connection, rsAdo As adodb.Recordset, MyBool As Boolean, MySQL As String
        Set Cnn = CurrentProject.Connection
        Set rsAdo = New adodb.Recordset
        MyBool = Me.CheckSelectAll.Value
        MySQL = "Quel recordset mettre ici???"
        rsAdo.Open MySQL, Cnn, adOpenKeyset, adLockOptimistic
     
    rsAdo.MoveFirst
    Do While Not rsAdo.EOF
        rsAdo!Selected = MyBool
        rsAdo.MoveNext
    Loop
     
    Set rsAdo = Nothing
    Set Cnn = Nothing
    End Sub
    J’ai potassé un peu partout mais en vain.

    rsAdo.Open Me.RecordsetClone, Cnn ne marche bien-sûr pas, ce serait trop beau !

    Il semble que l'objet rsAdo ne puisse ouvrir qu'une chaine SQL, non pas un autre recordset.

    Or, allez donc reconstituer la chaine SQL d'un gros RecordSource filtré, ordonné et refiltré d'un sous-formulaire ! RecordsetClone était idéal !

    Que faire ?

    Continuer à torturer ADO, ou trouver une autre méthode pour ce "Cocher tout" / "Décocher tout" ?

    As-tu déjà rencontré ce cas d'ADO rebelle ?

    Amitiés,

    phil

    PS Je n'arrive pas à ouvrir le lien "Planet" de ta signature...

  5. #25
    Expert confirmé Avatar de nico84
    Homme Profil pro
    Consultant/développeur ERP
    Inscrit en
    Mai 2008
    Messages
    3 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant/développeur ERP
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 3 087
    Points : 5 203
    Points
    5 203
    Par défaut
    Bonjour,

    Citation Envoyé par harpyopsis Voir le message
    C'est bizarre, "le Chef" ne se montre pas depuis deux jours... serait il en vacances ?
    Chacun fait c'qui lui plait, c'est le principe d'un site d'entraide bénévole

    Citation Envoyé par harpyopsis Voir le message
    Mais je tombe sur un os pour les quelques dernières DAO pourtant super-simples, mais qui sont du type RecordsetClone. Elles me servent par exemple à "Sélectionner tout" / "Désélectionner tout" ("Cocher tout" / "Décocher tout") pour une case à cocher dans un sous-formulaire continu filtré.
    Ca peut se faire par update + requery sinon

    Citation Envoyé par harpyopsis Voir le message
    As-tu déjà rencontré ce cas d'ADO rebelle ?
    En 2 mots j'ai considéré que (sauf rares exceptions) les forms, leurs recordsets, les états et tout l'IHM, étant gérés par access, restaient en DAO. Donc quand j'utilise recordsetclone c'est le clone du recordset DAO de la form et ça ne pose pas de problème. La conversion DAO > ADO a donc principalement concerné mon code VBA
    La plupart du temps mes fenêtres sont alimentées par des requetes suffisamment simples pour que DAO reste performant. Quand ce n'est pas le cas, soit je simplifie ma fenêtre, soit j'utilise un recordset ADO mais alors il est en lecture seule donc c'est très limitant (ou alors j'ai pas tout compris).
    Si j'ai bien suivi, ce sont les projets adp qui permettaient d'avoir des recordsets "natifs en ADO" or mon projet est un accdb...


    Citation Envoyé par harpyopsis Voir le message
    PS Je n'arrive pas à ouvrir le lien "Planet" de ta signature...
    Ah c'est bizarre... Le site date de 2012 et je ne sais plus le modifier il se trouve ici normalement

    J'espère avoir fait avancer le schmilblik sans dire trop de bêtises !
    Utilisez Planet, gestion d'entreprise gratuite pour TPE / PME

  6. #26
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut
    Merci pour cette réponse, Nico !

    C'est certainement moi qui dis les plus grosses bêtises. Et le pire c'est lorsque je les mets à exécution figure-toi !

    Mais dans ce cas particulier (préparation du code VBA pour double compatibilité avec tables Access aussi bien qu'avec tables MS SQL), je trouve que mes nouvelles requêtes ADO marchent aussi bien que les DAO.

    En suivant les tutos du "Chef", naturellement ! Juste en ADO : il faut s'habituer aux curseurs et aux adLock...

    L'occasion de travailler en projet adp ne s'est jamais présentée. J'aurais bien voulu. Mais ce système est tombé à l'eau aussi, tout comme Sharepoint. Pas facile de prévoir avec MS !

    Je ne comprends pas ce que tu veux dire avec

    Ca peut se faire par update + requery sinon
    Dans cet exemple, il s'agit de cocher / décocher d'un coup toutes les cases Yes/No ("à envoyer", etc)...

    Non, ça va mieux avec une image, la voici ! Ici c'est pour faire des Avoirs sur des items de BLs...

    Nom : CheckUncheckAll.JPG
Affichages : 124
Taille : 24,5 Ko

    Je ne peux quand même pas laisser le code DAO ! Ca va bugger quand l'appli travaillera avec les tables de MS SQL, non ??

    Si ??

    Je ne sais pas quoi faire...


  7. #27
    Rédacteur/Modérateur
    Avatar de argyronet
    Homme Profil pro
    Panseur de bobos en solutions ETL
    Inscrit en
    Mai 2004
    Messages
    5 123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Panseur de bobos en solutions ETL
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 5 123
    Points : 12 169
    Points
    12 169
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    Désolé pour mon silence mais j'avais pris un abonnement au parfum N° 19 de COVID, l'eau de la mondialisation et cette souscription britannique m'a mis chaos.

    Merci pour vos commentaires.
    Il est vrai que le modèle ADP était de loin pratique et simple à mettre en oeuvre.
    Cependant, il fallait tout de même passer par ADO pour attaquer les différents éléments constitutifs de la base SQL Server.

    Concernant la probable compilation conditionnelle de DAO à ADO je n'en vois l’intérêt qu'à partir du moment où vous avez fait le choix de ne vous servir d'Access comme frontal applicatif et où il existe plusieurs bases de type différent.

    Dès l'instant que vous attaquez une base externe, quelle qu'elle soit, il vous faut passer par ADO.

    Et quoi qu'il en soit, en admettant que vous en ayez tout de même besoin de DAO, cas de figure exceptionnel où vous auriez à la fois des tables attachées Access (Dorsale) et des tables attachées SQL Server (ou autres), vous pouvez :
    • et d’une référencer les deux références ADO et DAO
    • et de deux, et dans ce cas systématiquement "qualifier" vos appels :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Dim oRSLocal As DAO.Recordset
    Dim oRSSQLSrv As ADODB.Recordset
    Il vous appartient alors de trouver des conventions typographiques propres à votre application qui vous permettent de ne pas vous tromper de qualifiant selon le contexte.

    Et pour reprendre l'exemple de nico84, je me permettrais de "critiquer" sa méthode d'écriture qui ne permet pas un débogage facile et simple d'une part et coupler celle-ci à des fonctions génériques d'autre part... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Dim n As Integer, s As String, rst As New ADODB.Recordset
    ...
    rst.open "SELECT r.nop as operation, max(jour) as finie_le, r.libelle, round(r.tprepa/o.qliv+r.tprevu,2) as prevu_unit, r.poste, o.cd_of, o.qliv, round(sum(t)/o.qliv,2) as reel_unit " _
    & "FROM ((operations r inner join [OF] o on o.draw_ref=r.draw_ref) left join of_taches t on t.cd_of=o.cd_of) left join pointages p on p.cd_tache=t.cd_tache " _
    & "WHERE o.etat='T' and o.qliv>0 and o.date_fin>=dateadd(" & IIf(msql, "m,-" & n & ",get", "'m',-" & n & ",") & "date()) and t.nop=r.nop and r.draw_ref='" & x_draw_ref _
    & "' GROUP BY r.nop, r.libelle, r.tprepa, r.tprevu, r.poste, o.cd_of, o.qliv HAVING " & IIf(msql, "coalesce", "nz") & "(sum(t),0)+r.tprepa+r.tprevu>0.01 ORDER BY 1,2,6;", cnx, adOpenStatic
    ici, il serait judicieux de stocker la requête découpée en variables Select et condition Where séparées.

    Et dans ce type de fonction où justement le choix décisif de potentielle multibases, il faut alors envisager de créer des fonctions spécifiques associées aux variables subséquentes...

    Je n'y ai pas réfléchi en profondeur mais par exemple et pour éviter les forêt de Ifs voici ce que tu pourrais faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    Public Function DateAddEx(ByVal Interval As String, ByVal AddValue As Long, ByVal DBType As GE_DB_TYPE, Optional ByVal WhatDate As Variant) As Variant
    Dim strTempDateAdd                                     As String
    Dim strWhatDate                                        As String
     
        If IsMissing(WhatDate) Then
            Select Case DBType
                Case MSAccessDatabase
                    strWhatDate = "DATE()"
                Case OracleDatabase
                    strWhatDate = "SYSDATE"
                Case MYSQLDatabase, SQLServerDatabase
                    strWhatDate = "GETDATE()"
            End Select
        Else
            Select Case DBType
                Case MSAccessDatabase
                    strWhatDate = EnquoteStringSQL(WhatDate, "#")
                Case SQLServerDatabase
                    strWhatDate = "CONVERT(DATETIME,'" & Format(WhatDate, "dd/mm/yyyy") & "',103)"
                Case MYSQLDatabase, OracleDatabase
                    strWhatDate = "TO_DATE('" & Format(WhatDate, "mm/dd/yyyy") & "', 'YYYY/MM/DD HH:MI:SS')"
            End Select
        End If
        strTempDateAdd = "DATEADD(" & Interval & "," & AddValue & "," & strWhatDate & ")"
     
        DateAddEx = strTempDateAdd
    End Function
    '-------------------------------------------------------------------------------------------------------------
    Public Function GetNzValue(ByVal Value As Variant, ByVal DBType As GE_DB_TYPE, Optional ByVal ResultIfNull As Variant, Optional DataNullValueType As GE_DATA_TYPE) As Variant
    Dim strTemp                                            As String
    Dim strNullValue                                       As String
     
        If (Not IsMissing(ResultIfNull)) Then
            Select Case DataNullValueType
                Case TypeText
                    strNullValue = EnquoteStringSQL(ResultIfNull)
                Case TypeDate
                    Select Case DBType
                        Case MSAccessDatabase
                            strNullValue = EnquoteStringSQL(ResultIfNull, "#")
                        Case SQLServerDatabase
                            strNullValue = "CONVERT(DATETIME,'" & Format(ResultIfNull, "dd/mm/yyyy") & "',103)"
                        Case MYSQLDatabase, OracleDatabase
                            strNullValue = "TO_DATE('" & Format(ResultIfNull, "mm/dd/yyyy") & "', 'YYYY/MM/DD HH:MI:SS')"
                    End Select
                Case Else
                    strNullValue = ResultIfNull
            End Select
        Else
            strNullValue = "NULL"
        End If
     
        Select Case DBType
            Case MSAccessDatabase
                strTemp = "NZ(" & Value & ", " & strNullValue & ")"
            Case MYSQLDatabase, SQLServerDatabase
                strTemp = "COALESCE(" & Value & ", " & strNullValue & ")"
            Case OracleDatabase
                strTemp = "NVL(" & Value & ", " & strNullValue & ")"
        End Select
        GetNzValue = strTemp
    End Function
    '-------------------------------------------------------------------------------------------------------------
    Public Function EnquoteStringSQL(ByVal Value As Variant, Optional ByVal EnquoteChar As String = "'") As String
    Const TEMP_CHAR                                        As String = "#"
    Dim strTemp                                            As String
     
        strTemp = Trim(Replace(Value, "'", TEMP_CHAR))
        If InStr(1, strTemp, TEMP_CHAR) Then
            If Left(strTemp, 1) = TEMP_CHAR Then
                strTemp = Mid(strTemp, 2)
            End If
            If Right(strTemp, 1) = TEMP_CHAR Then
                strTemp = Left(strTemp, Len(strTemp) - 1)
            End If
            strTemp = EnquoteChar & Replace(strTemp, TEMP_CHAR, Chr(39) & Chr(39)) & EnquoteChar
        Else
            strTemp = EnquoteChar & Trim(Value) & EnquoteChar
        End If
        EnquoteStringSQL = strTemp
     
    End Function

    Ainsi, ton appel de fonction pourrait être simplifié de la sorte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    Public Enum GE_DB_TYPE
        MSAccessDatabase = 1
        MYSQLDatabase = 3
        SQLServerDatabase = 5
        OracleDatabase = 7
    End Enum
     
    Public Enum GE_DATA_TYPE
        TypeText = 10
        TypeDate = 8
        TypeNumeric = 19
    End Enum
     
    Public Const MY_DB_TYPE = GE_DB_TYPE.MYSQLDatabase
     
    '-------------------------------------------------------------------------------------------------------------
    Public Function GetCurConnection() As ADODB.Connection
    Dim oConn                                              As ADODB.Connection
     
        Set oConn = New ADODB.Connection
        '[....]
        Set GetCurConnection = oConn
    End Function
    '-------------------------------------------------------------------------------------------------------------
    Sub test_OpenMyQuery()
    Const X_DRAW_REF = "TididiDoudou"
    Dim SQLSelect                                          As String
    Dim SQLWhere                                           As String
    Dim SQLGroup                                           As String
    Dim N                                                  As Integer
     
     
    Dim oRS                                                As ADODB.Recordset
     
        Set oRS = New ADODB.Recordset
     
        N = 12
     
        SQLSelect = "SELECT R.NOP AS OPERATION, MAX(JOUR) AS FINIE_LE, R.LIBELLE, ROUND(R.TPREPA/O.QLIV+R.TPREVU,2) AS PREVU_UNIT, R.POSTE, O.CD_OF, O.QLIV, ROUND(SUM(T)/O.QLIV,2) AS REEL_UNIT "
        SQLSelect = SQLSelect & "FROM ((OPERATIONS R INNER JOIN [OF] O ON O.DRAW_REF=R.DRAW_REF) LEFT JOIN OF_TACHES T ON T.CD_OF=O.CD_OF) LEFT JOIN POINTAGES P ON P.CD_TACHE=T.CD_TACHE "
        SQLWhere = "WHERE O.ETAT='T' AND O.QLIV>0 AND O.DATE_FIN>=" & DateAddEx("M", -N, MY_DB_TYPE) & " AND T.NOP=R.NOP AND R.DRAW_REF='" & X_DRAW_REF & "' "
        SQLGroup = "GROUP BY R.NOP, R.LIBELLE, R.TPREPA, R.TPREVU, R.POSTE, O.CD_OF, O.QLIV HAVING GetNzValue(SUM(T), " & MY_DB_TYPE & ", 0, " & TypeNumeric & ") + R.TPREPA+R.TPREVU>0.01 ORDER BY 1,2,6;"
     
        If OpenMyQuery(SQLSelect & SQLWhere & SQLGroup, oRS, strError) = False Then
            MsgBox strError, vbExclamation
        Else
            '[...]
            'Code continues here...
        End If
     
    End Sub
    Euh je n'ai écrit ces exemple que de mémoire (et forcé des valeurs pour l'exemple) et il est probable que des adaptations soient nécessaires pour les fonctions génériques.

    Je vous laisse tester pour voir si cela peut correspondre à vos attentes.

    Argy
    Ce qui donne son sens à la communication, c´est la réponse que l´on obtient. Si vous n´obtenez pas la réponse voulue, communiquez différemment.

    Ils comptent sur vous...
    Web Site@Mail
    Tutoriels : Déployez vos applications Access 2010 à 2019 */* Réalisez un Assistant de présaisie...
    MDB Viewer : Visionneuse Access v4.0
    *** Je recherche des profils (2 ans min.) Java EE, Fullstack, Front, .Net, Mobile... pour CDI ***

  8. #28
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut
    Bonsoir Argy et un grand merci pour ce message.

    Tes exemples de code permettant d'utiliser la syntaxe des diverses DB sont extras !

    Mais je n'en suis pas encore là... et je suis au désespoir!

    Que ferais-tu à ma place pour "cocher /décocher tout" comme dans mon dernier post, sachant que la table source contient plusieurs dizaines de milliers de lignes et que ce "cocher /décocher tout" ne doit s'appliquer qu'aux seuls enregistrements filtrés dans le formulaire (recordcount très variable) ?

    DAO ? ADO ? ou les deux ? Il faut que ça marche indifféremment avec des tables accdb ou avec MS SQL Server !

    Nom : CheckUncheckAll.JPG
Affichages : 111
Taille : 24,5 Ko

    Une requête "UPDATE..." me semble difficilement praticable !



  9. #29
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut Eureka
    Bonjour Argy et Nico !

    Bon, ça va : je viens de trouver pour ce cas précis, qui ne concerne que les lignes d'un bon de livraison, sans filtre.

    La solution était là devant mes yeux sur l'image : le WHERE peut tout simplement être l'ID du bon de livraison!

    Voilà !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Private Sub CheckSelectAll_AfterUpdate()
     
        DoCmd.RunSQL "UPDATE BLItems SET BLItems.ForRefund = " & Me.CheckSelectAll.Value & " " & _
                        "WHERE (((BLItems.BLID)=" & Me.BLID.Value & "));"
     
        Me.Form.Refresh
     
    End Sub
    Ce cas était simple, car il n'y a pas de Filtre. Je vais m'attaquer à d'autres "cocher /décocher tout", dont certains ont des filtres assez complexes qu'il me faudra recomposer manuellement... Ah, RecordsetClone était si pratique !

    J'ai vu ici (stackoverflow) que :

    You have two options:

    1) Update the records using SQL. Something like UPDATE tblItems SET IsSelected = FALSE WHERE ... (Replace tblItems with your table and IsSelected with the field the checkbox is bound to.) Then you should refresh your subform with .Requery

    2) Use RecordsetClone. This is actually a copy of the records shown in your subform which you can loop through and update.
    Est-ce que vraiment il n'existe aucune "troisième voie" qui permette de mimer "RecordsetClone" en ADO ???

    Qu'en pensez-vous ?

    merci pour tout !

    phil

  10. #30
    Expert confirmé Avatar de nico84
    Homme Profil pro
    Consultant/développeur ERP
    Inscrit en
    Mai 2008
    Messages
    3 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant/développeur ERP
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 3 087
    Points : 5 203
    Points
    5 203
    Par défaut
    Bonjour à tous les 2

    Merci Argy pour l'idée, je vais l'utiliser. C'est vrai que mes iif ne sont pas très lisibles mais mon exemple concerne une de mes requetes les plus compliquées

    Phil je suis surpris que tes recordsets soient tous en ADO car ça complique et limite beaucoup.
    Pour moi quand on définit la source de la fenêtre par ses propriétés ou quand on écrit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.recordset="SELECT..."
    Alors c'est du DAO : la syntaxe est celle d'access même quand la table est Oracle, SQL server ou autre (c'est JET qui convertit) et le clone fonctionne comme d'hab'

    Voici un exemple de recordset ADO si sql server, DAO si access :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Dim reca As ADODB.Recordset, tri As String
    If msql Then 'ADO
    112   Sr = "SELECT 0 as cas, code, date_in, Qin, adrs, iif(cd_cde='1', 'entrée main', cd_cde) as motif, lot, " & IIf(voir_prix, "pu_euro as masse", "masse") & ", qui, cd_bl_lg, lg, cd_bl as cd, qout, setat" _
          & " FROM bl_lg WHERE code='" & c & "' " _
          & "UNION ALL SELECT [type], m.code, date_out, -m.Qout, adrs, l.cd_cde+'>'+motif, m.lot, null, m.qui, m.cd_bl_lg, lg, m.cd_mvt, 0, l.setat" _
          & " FROM mvts m inner join bl_lg l on m.cd_bl_lg=l.cd_bl_lg WHERE m.code='" & c & "' " _
          & "UNION ALL SELECT -b.nature, b.code, b.date_out, -b.Qout, b.adrs, coalesce(l.cd_cde+'>','') + iif(b.cd_cde='1', 'BL '+cast(cd_blc as nvarchar), b.cd_cde), b.lot, null, b.qui, b.cd_bl_lg, b.lg, b.cd_blc_lg, 0, l.setat" _
          & " FROM blc_lg b left join bl_lg l on l.cd_bl_lg=b.cd_bl_lg WHERE (b.nature=1 or (b.nature=3 and b.Qout<0) or b.nature=5) and b.code='" & c & "' " _
          & " ORDER BY " & tr
    114   Set reca = New ADODB.Recordset
    116   reca.Open Sr, cnx, adOpenStatic, adLockReadOnly 'coté serveur, lecture seule
    118   Set Me.Recordset = reca 'ATTENTION cette méthode ne se met pas à jour par requery :(
          Set reca = Nothing
        Else 'DAO si access
    120   Sr = "SELECT 0 as cas, code, date_in, Qin, adrs, iif(cd_cde='1', 'entrée main', cd_cde) as motif, lot, " & IIf(voir_prix, "pu_euro as masse", "masse") & ", qui, cd_bl_lg, lg, cd_bl as cd, qout, setat" _
          & " FROM bl_lg WHERE code='" & c & "' " _
          & "UNION ALL SELECT [type], m.code, date_out, -m.Qout, adrs, l.cd_cde & '>' & motif, m.lot, null, m.qui, m.cd_bl_lg, lg, m.cd_mvt, 0, l.setat" _
          & " FROM mvts m inner join bl_lg l on l.cd_bl_lg=m.cd_bl_lg WHERE m.code='" & c & "' " _
          & "UNION ALL SELECT -b.nature, b.code, b.date_out, -b.Qout, b.adrs, nz(l.cd_cde & '>','') & iif(b.cd_cde='1', 'BL ' & cstr(cd_blc), b.cd_cde), b.lot, null, b.qui, b.cd_bl_lg, b.lg, b.cd_blc_lg, 0, l.setat" _
          & " FROM blc_lg b left join bl_lg l on l.cd_bl_lg=b.cd_bl_lg WHERE (b.nature=1 or (b.nature=3 and b.Qout<0) or b.nature=5) and b.code='" & c & "' " _
          & "ORDER BY " & tr
    122   Me.RecordSource = Sr
    Tu as converti tous tes recordsets en ADO comme ça ?
    Utilisez Planet, gestion d'entreprise gratuite pour TPE / PME

  11. #31
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut
    Bonjour Argy et Nico !

    Oui j'ai converti tous mes recordsets (270) en ADO...

    C'est peut-être une erreur, je n'en sais rien.
    (Je suis absolument seul comme un rat pour travailler ici, sans aucun échange avec aucun programmeur expérimenté, essentiellement avec vous sur les forum... Il y a bien une école de programmation ici à Bali (Le Wagon, Bootcamp propr Boris Paillard, Paris) mais pratiquement tous les expats sont partis et il n'y a plus personne avec qui discuter depuis un an. De toute façon, ils enseignent essentiellement du Ruby, des applis pour iPhone, Wordpress et un peu de Python. Très peu de DBase.)

    Il me reste juste un ou deux DAO qui sont du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Set rs = CurrentDb.OpenRecordset(dbDao.TableDefs(i).Name)
    Pour lesquels j'hésite encore. Ce sera pour demain !

    Bref, Nico, mon nouveau code fonctionne parfaitement avec les tables accdb. J'espère que ce sera bon pour des tables MS SQL au moment de tester. Le code me semble même un peu plus rapide et en tout cas il est plus homogène. J'ai bien-sur des backups s'il fallait revenir en DAO!

    Je dois m'attaquer maintenant à 76 QueryDefs... J'ai cru comprendre qu'il faut les dégager aussi. J'ai bon ?

    Une bonne partie me servaient à faire des domain aggregate (Fr?) de table-fille pour mettre à jour une table-mère, puisque Access ne permet pas de faire Update sur domain aggregate en une seule requête. Il faut donc passer par la création d'une table temporaire. J'ai bon ?

    Le plus simple :
    1. création d'une table temp représentant les SUM des valeurs HT, TVA, TTC, etc, venant de la table-fille des éléments du bon de livraison sélectionné.
    2. mise à jour du montant total des HT, TVA, TTC, etc dans la table des bons de livraison avec les montants de la table temp.


    Ma question maintenant est : pour MS SQL faut-il remplacer les DoCmd.RunSQL, et si oui, par quoi ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DoCmd.RunSQL "SELECT BLItems.Field1, BLItems.Field2, BLItems.Fields3 " & _
                                "INTO TblTemp " & _
                                "FROM BLItems " & _
                                "WHERE blablabla...;"
    Par ceci ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        Dim adoCMD As ADODB.Command, strSQL As String
            Set adoCMD = New ADODB.Command
            adoCMD.ActiveConnection = CurrentProject.Connection
            strSQL = "SELECT BLItems.Field1, BLItems.Field2, BLItems.Fields3 " & _
                                "INTO TblTemp " & _
                                "FROM BLItems " & _
                                "WHERE blablabla...;"
        adoCMD.CommandText = strSQL
        adoCMD.Execute
     
    Set adoCMD = Nothing
    Toute réponse m'évitera de faire des bêtises inutiles !

    Un grand merci à tous les deux !

    phil

  12. #32
    Rédacteur/Modérateur
    Avatar de argyronet
    Homme Profil pro
    Panseur de bobos en solutions ETL
    Inscrit en
    Mai 2004
    Messages
    5 123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Panseur de bobos en solutions ETL
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 5 123
    Points : 12 169
    Points
    12 169
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    Un Docmd.RunQSQL sur un SELECT ?

    Quel intérêt ?

    De manière générale, oubli l'objet DoCmd.

    ecris du vrai code ADO (ou DAO selon le cas) de façon générique avec instanciation de l'objet DB pour DAO et d'une connexion pour les autres mais dans la même fonction (ou procédure) VBA.
    Ainsi ton code n'aura pas de redondances et sera aussi souple que lisible.

    Argy
    Ce qui donne son sens à la communication, c´est la réponse que l´on obtient. Si vous n´obtenez pas la réponse voulue, communiquez différemment.

    Ils comptent sur vous...
    Web Site@Mail
    Tutoriels : Déployez vos applications Access 2010 à 2019 */* Réalisez un Assistant de présaisie...
    MDB Viewer : Visionneuse Access v4.0
    *** Je recherche des profils (2 ans min.) Java EE, Fullstack, Front, .Net, Mobile... pour CDI ***

  13. #33
    Membre habitué Avatar de harpyopsis
    Homme Profil pro
    Vétérinaire
    Inscrit en
    Octobre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : Indonésie

    Informations professionnelles :
    Activité : Vétérinaire
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 143
    Points : 187
    Points
    187
    Par défaut
    OK merci Argy !

    A. Donc mon deuxième code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        Dim adoCMD As ADODB.Command, strSQL As String
            Set adoCMD = New ADODB.Command
            adoCMD.ActiveConnection = CurrentProject.Connection
            strSQL = "SELECT BLItems.Field1, BLItems.Field2, BLItems.Fields3 " & _
                                "INTO TblTemp " & _
                                "FROM BLItems " & _
                                "WHERE blablabla...;"
        adoCMD.CommandText = strSQL
        adoCMD.Execute
    qui remplace DoCmd.runSQL est avalisé, c'est bon ?

    Pourquoi quelle raison dis-tu d'oublier DoCmd ? On le retrouve un peu partout ! (Docmd.Close, DoCmd.OpenForm, DoCmd.RunCommand acCmdSaveRecord, DoCmd.SetWarnings)... Il faut supprimer tout ça ?

    B. Finalement, dans quel cas peut-on laisser du DAO dans un code destiné à MS SQL ?

    Encore merci pour toutes ces lumières !

    phil

    PS : Voilà, je commence à remplacer les DoCmd.RunSQL par ADO. Il y en a 1.576 en tout ! Donnez-moi du courage SVP !

  14. #34
    Rédacteur/Modérateur
    Avatar de argyronet
    Homme Profil pro
    Panseur de bobos en solutions ETL
    Inscrit en
    Mai 2004
    Messages
    5 123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Panseur de bobos en solutions ETL
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 5 123
    Points : 12 169
    Points
    12 169
    Billets dans le blog
    5
    Par défaut
    Humm, non tu n'as pas compris, je pense...

    Une fonction générique est une fonction qui va pouvoir prendre de façon générique des paramètres et te retourner un résultat...
    Mais on ne met rien de figé relatif aux données dedans.

    Par exemple (toujours à adapter...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    #Const MODE_ADO = 0
     
    Sub test_EnregistrementsExistent()
    Const MSG_RESULT                                       As String = "Il y a # enregistrement(s) trouvé(s) dans votre requête."
    Const SQL                                              As String = "SELECT Field1, Field2, Fields3 FROM BLItems WHERE Field1='blablabla'...;"
    Dim strConnexionDBDorsale                              As String
    Dim lngEnr                                             As Long
    Dim strErreur                                          As String
     
    Dim strResult                                          As String
     
        #If MODE_ADO Then
            'On considère que la base est du SQL Server (idéalement, il faut que ce soit une propriété public dans une classe)
            strConnexionDBDorsale = "provider=SQLOLEDB.1;DataSource=MonServeur;Initial Catalog=MaBDDSQLServer;User ID=MonCompte;Password=MonMDP;"
        #Else
            'On considère que la base dorsale porte le même nom que le forontale avec le suffice Data
            strConnexionDBDorsale = Replace(CurrentDb.Name, ".accdb", "_Data.accdb")
        #End If
     
        If EnregistrementsExistent(strConnexionDBDorsale, SQL, lngEnr, strErreur) = False Then
            MsgBox strErreur, vbExclamation
        Else
            strResult = Replace(MSG_RESULT, "#", Trim(Str(lngEnr)))
            MsgBox strResult, vbInformation
        End If
     
    End Sub
     
     
    Public Function EnregistrementsExistent(ByVal ChaineConnexionOuChemin As String, ByVal SQL As String, ByRef NBEnregistrements As Long, Optional ByRef MsgErreur As String) As Boolean
    Dim I                                                  As Long
     
        On Error GoTo L_ErrEnregistrementsExistent
        NBEnregistrements = 0
        #If MODE_ADO Then
            Dim oDB                                        As ADODB.Connection
            Dim oRS                                        As ADODB.Recordset
     
            Set oDB = New ADODB.Connection
            With oDB
                .ConnectionString = ChaineConnexionOuChemin
                .Open
            End With
            oRS.Open SQL, ChaineConnexionOuChemin, adOpenDynamic, adLockBatchOptimistic, adCmdTable
        #Else
            Dim oDB                                        As DAO.Database
            Dim oRS                                        As DAO.Recordset
            Set oDB = DBEngine.OpenDatabase(ChaineConnexionOuChemin)
            Set oRS = oDB.OpenRecordset(SQL, dbOpenDynaset)
        #End If
     
     
        With oRS
            If Not .EOF Then
                Do While Not .EOF
                    I = I + 1
                    .MoveNext
                Loop
            Else
                Err.Raise 3021, "Aucun enregistrement trouvé", "Il n'existe actuellement aucun enregistremnet correspondant à la requête utilisée."
            End If
            .Close
        End With
     
        NBEnregistrements = I
        EnregistrementsExistent = (I > 0)
     
         #If MODE_ADO Then
            If oDB.State = adStateOpen Then
                oDB.Close
            End If
        #Else
            If Not oDB Is Nothing Then
                oDB.Close
            End If
        #End If
     
        On Error GoTo 0
    L_ExEnregistrementsExistent:
        Set oRS = Nothing
        Set oDB = Nothing
        Exit Function
     
    L_ErrEnregistrementsExistent:
        MsgErreur = Err.Description & " (" & Err.Number & ")"
        Resume L_ExEnregistrementsExistent
    End Function
    Argy
    Ce qui donne son sens à la communication, c´est la réponse que l´on obtient. Si vous n´obtenez pas la réponse voulue, communiquez différemment.

    Ils comptent sur vous...
    Web Site@Mail
    Tutoriels : Déployez vos applications Access 2010 à 2019 */* Réalisez un Assistant de présaisie...
    MDB Viewer : Visionneuse Access v4.0
    *** Je recherche des profils (2 ans min.) Java EE, Fullstack, Front, .Net, Mobile... pour CDI ***

Discussions similaires

  1. Migrer une base de données MySQL vers SQL Server
    Par Goupo dans le forum MS SQL Server
    Réponses: 17
    Dernier message: 04/06/2010, 09h58
  2. [AC-2003] Projet ADP/SQL Server Multi-utilisateurs
    Par hannii dans le forum VBA Access
    Réponses: 0
    Dernier message: 30/08/2009, 15h12
  3. Réponses: 2
    Dernier message: 29/04/2008, 13h59
  4. créer une base de données navec MS sql server 2005
    Par katyajea dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 12/04/2007, 23h02
  5. Projet ADP + SQL Server : tables en lecture seule
    Par hannii dans le forum Access
    Réponses: 8
    Dernier message: 09/03/2007, 14h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo