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

Word Discussion :

Combobox sous word 2003


Sujet :

Word

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut Combobox sous word 2003
    Bonjour à tous,

    Je souhaite creer une liste deroulante contenant des noms.
    Lorsque je choisis un des noms de la liste, je souhaiterais que les coordonnées completes liées à se nom s'inscrivent dans un document word.

    J'ai testé plusieurs methode mais je n'ai rien trouvé de concluant jusque là.

    L'ideal serait de creer une base de donnée (publipostage word - ça je sais faire) contenant les coordonnées completes.

    Inserer des champs de fusion et fusionner (ça je sais faire aussi)

    L'ennui est qu'a chaque fois, je suis obligé de choisir la base de donnée (puisque j'en utilise une autre pour autre chose) puis de choisir dans cette base la ligne du contact a inserer puis de fusionner.

    Serait il possible de creer une liste deroulante, qui se connecte directement à la bonne base de donnée (publipostage word) et renvoi les coordonnées automatiquement dans des champs mis en forme prealablement?

    Aujourd'hui j'ai testé une methode qui m'eclaire un peu :

    une combobox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Private Sub UserForm_Initialize()
      ComboBox1.ColumnCount = 1
      'Load data into ComboBox
      ComboBox1.List() = Array("Zero", "One", "Two", "Three")
    End Sub
    puis un signet (Text1):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub ComboBox1_Change()
       ActiveDocument.FormFields("Text1").Result = ComboBox1.Value
    End Sub
    puis un bouton FERMER :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub Cmdclose_Click()
      Unload Me
    End Sub
    puis une macro :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Sub gocombobox()
       frmcombo.Show
    End Sub
    et enfin un champ text form qui apelle la macro, donc la combobox.

    L'ennui : c'est la valeur de la liste deroulante qui est renvoyée dans le champ "formtext", et puis il n'y a pas de mise en forme possible (preformaté) ... mais le principe est pas mal...

    En gros ,

    A l'aide )

    Merci a tous
    Thomas

  2. #2
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut
    Salut,

    On peut faire de différentes façon.
    On peut comme tu le suggères utiliser une base de données pour y stocker les données.
    Ensuite, on va puiser les données dans une des tables.

    L'idéal, ce serait d'extraire les noms de cette table pour être certain de ne pas avoir d'erreur !

    Pour ce faire, nous allons utiliser du DAO.

    Un tuto sur le DAO : http://warin.developpez.com/access/dao/

    Dans la procédure d'initialisation du UserForm, on va aller chercher les noms.
    Tu dois ajouter la référence au DAO dans ton projet.

    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 UserForm_Initialize()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim SQL As String
     
    SQL = "Select * From maTable"
     
     
    Set db = OpenDatabase("Le chemin de ma base")
    Set rs = db.OpenRecordset(SQL)
    While Not rs.EOF
        Me.Combo1.AddItem rs.Fields("Nom")
        rs.MoveNext
    Wend
    rs.Close
    Set rs = Nothing
    Set db = Nothing
    End Sub
    Pour la récupération des données et les injecter dans le combo.

    Après mise à jour du combo, on peut faire la même chose pour obtenir les données correspondantes au nom choisi.

    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
    Private Sub ComboBox1_Change()
        Dim db As DAO.Database
        Dim rs As DAO.Recordset
        Dim SQL As String
       Dim stTemp as String
     
    SQL = "Select * From maTable Where nom = '" & Me.Combo.Value & "'"
     
    Set db = Opendatabase("Le chemin de ma DB")
    Set rs = db.OpenRecordset(SQL)
    stTemp = rs.Fields("Nom")
    stTemp = stTemp & " " & rs.fields("Prenom")
    stTemp = stTemp & vbCrLf & rs.Fields("Adresse")
    rs.close
     
       ActiveDocument.Bookmarks("Text1").Range.Text = stTemp
     
    set rs = Nothing
    set db = nothing
    End Sub
    Voilà la récupération des données et leur envoi vers un signet.
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  3. #3
    Membre émérite
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Points : 2 793
    Points
    2 793
    Par défaut
    Pour l'initialisation,pourquoi passer par une requête SQL?
    Autant faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Set db = OpenDatabase("Le chemin de ma base")
    Set rs = db.OpenRecordset("matable")
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SQL = "Select * From maTable"
     
     
    Set db = OpenDatabase("Le chemin de ma base")
    Set rs = db.OpenRecordset(SQL)
    c'est la même chose et c'est plus court
    Toute question technique envoyée en MP ira directement à la poubelle

    Un code ne marchera jamais, il n'a jamais reçu la capacité de se déplacer.
    Inutile donc de dire "ça marche pas", donnez plutôt des informations précises afin de mieux pouvoir vous aider.


    Grand gourou de la -attitude

  4. #4
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut
    Tu as raison ,c'est une habitude.
    Comme j'ai écrit le code à la volée
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  5. #5
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    merci les amis de vos reponses.

    Serait il possible d'utiliser à la place du DAO, l'utilitaire de word :
    lettre et publipostage - saisie d'une nouvelle liste - creer la liste ?
    et recuperer les données a partir d'une liste de choix?

    Ca m'arrangerai car DAO, je comprend pas

    je suis novice et j'ai besoin d'explications pas a pas

    Merci de votre aide.
    Thomas

    ou un exemple serait le bien venu sinon...
    Merci
    Thomas

  6. #6
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut BASE EXEMPLE
    Voilà le type de base que j'utilise :
    voir fichier joint dans l'archive ZIP

    Merci encore
    Thomas
    Fichiers attachés Fichiers attachés

  7. #7
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut
    Pour répondre à ta question, il est possible d'utiliser l'utilitaire de publipostage, mais ce sera de la même manière qu'avec le DAO, avant d'aller chercher les données, il faudra les sélectionner.

    Pour ce qui est de l'exemple, il suffit de remplacer les données génériques par tes variables.

    Le Chemin de ma base de données fera par exemple C:\Data\Adresses.mdb
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  8. #8
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut
    Voilà,

    Tu mets ta db dans le répertoire c:\Temp

    Et tu ouvres le document
    Fichiers attachés Fichiers attachés
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  9. #9
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut nE VOUS MOQUEZ PAS SVP;

    Voili, Voilà mon arrangement, qui, évidement ne fonctionne pas puisque je n'utilise pas la table DAO mais MDB (en piece jointe ci-dessus :

    Y a t il beaucoup de chosees à modifier?

    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
    Private Sub UserForm_Initialize()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim SQL As String
     
    SQL = "Select * From `Office Address List`"  
     
    Set db = Opendatabase("E:\Documents and Settings\Thom@s\Bureau\BASE ADRESSE.mdb")
    Set rs = db.OpenRecordset(SQL)
    While Not rs.EOF
        Me.Combo1.AddItem rs.Fields("Nom")
        rs.MoveNext
    Wend
    rs.Close
    Set rs = Nothing
    Set db = Nothing
    End Sub
    Private Sub ComboBox1_Change()
        Dim db As DAO.Database
        Dim rs As DAO.Recordset
        Dim SQL As String
       Dim stTemp As String
     
    SQL = "Select * From BASE ADRESSE Where nom = '" & Me.Combo.Value & "'"
     
    Set db = Opendatabase("E:\Documents and Settings\Thom@s\Bureau\BASE ADRESSE.mdb")
    Set rs = db.OpenRecordset(SQL)
    stTemp = rs.Fields("Nom")
    stTemp = stTemp & " " & rs.Fields("Prénom")
    stTemp = stTemp & vbCrLf & rs.Fields("Adresse ligne 1")
    stTemp = stTemp & vbCrLf & rs.Fields("Adresse ligne 2")
    stTemp = stTemp & vbCrLf & rs.Fields("Code postal - Ville")
    rs.Close
     
       ActiveDocument.Bookmarks("Text1").Range.Text = stTemp
     
    Set rs = Nothing
    Set db = Nothing
    End Sub
    Private Sub Cmdclose_Click()
     
      Unload Me
     
    End Sub
    merci
    Thomas

  10. #10
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut
    Excuse moi, mais je ne pige pas pourquoi tu as tout refait n'importe comment !

    Il ne fallait changer que le chemin de la DB dans les deux codes.

    En plus, tu ouvre une DB à la place d'une table
    On ne trouve jamais de nom de DB dans une clause SQL

    Conseil, si tu reçois un code qui fonctionne, modifie ligne par ligne et regarde ce que ça fait, si ça ne marche pas, annule la modification pour voir ce qui coince.

    Si tu veux des info sur le DAO, j'avais mis un lien en début de discussion.

    Et le DAO est une bibliothèque qui te donne accès aux objets contenus dans une base de données Access.

    De plus, dans le nom de la table qui contient les données, il n'y a pas d'espace mais des underscore _ Office_Address_List.

    Corriger ton code reviendrait à remettre exactement le code que je t'ai donné !
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  11. #11
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut re
    Je te remercie enormement de prendre du temps pour m'expliquer.
    C'est vrai je ne suis vraiment pas doué et je bidouille à l'aveugle.

    J'essai de télécharger ton fichier joint mais le forum me bloque l'accés.
    Je n'ai pas les autorisation semble t il.

    Merci beaucoup.
    Thomas

  12. #12
    Membre émérite
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Points : 2 793
    Points
    2 793
    Par défaut
    bizarre j'arrive très bien à l'ouvrir
    Toute question technique envoyée en MP ira directement à la poubelle

    Un code ne marchera jamais, il n'a jamais reçu la capacité de se déplacer.
    Inutile donc de dire "ça marche pas", donnez plutôt des informations précises afin de mieux pouvoir vous aider.


    Grand gourou de la -attitude

  13. #13
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut WAOUUUUUU!!!
    MERCI !!

    Grâce à vous, non seulement j'ai exactement le fichier que je souhaitais, mais surtout je comprend exactement comment ça marche grâce aux explications de tous et à la démo de Heureux-oli.

    Juste une petite chose, comment serait-il possible de lancer l'userform à demande au lieu qu'il se lance automatiquement à l'ouverture du fichier?

    Je pensais enlever du code "Sub Document_Open()", créer une macro et un bouton.

    Quen pensez vous?

    A propos un bouton de commande peut il se trouver dans une page word ou doit il obligatoirement se situer dans les barres d outils?

    Merci à tous.
    Thomas

    PS : je doit vous souler avec mes mercis mais je suis trop content.

  14. #14
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut
    Sub Document_Open est la détection d'un évènement.

    Rien ne t'empêche de le faire sur un bouton.
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  15. #15
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut erreur de compilation

    Encore moi,

    Lorsque j'essaie d'intégrer l'userform (glisser déplacer dans la console visual basic) j'obtient l'erreur suivante :
    erreur de compilation
    type defini par l'utilisateur non defini
    le script bloque ici :
    Private Sub UserForm_Initialize()
    Dim db As DAO.Database

    Je ne comprend vraiment pas d'ou cela vient, que j'essai d'intégrer l'userform dans une feuille vierge ou normal.dot ou autre, j'ai toujours la même erreur.
    Pourtant la feuille d'origine, créee par Heureux-oli fonctionne parfaitement.

    Merci.
    Thomas

  16. #16
    Membre éprouvé
    Avatar de JackOuYA
    Inscrit en
    Juin 2008
    Messages
    1 040
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 1 040
    Points : 1 191
    Points
    1 191
    Par défaut
    bonsoir,

    jette un coup d'oeil aux références de ton projet et de celui à oli .. menu projet référence
    JacqueS.

    Ps: je ne télécharge les piéces jointes qu'en dernier recours .(et encore...)

    Pour devenir mon ami laissez moi un message

  17. #17
    Rédacteur/Modérateur

    Avatar de Heureux-oli
    Homme Profil pro
    Contrôleur d'industrie
    Inscrit en
    Février 2006
    Messages
    21 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Contrôleur d'industrie
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 21 087
    Points : 42 926
    Points
    42 926
    Par défaut


    J'ai écrit dans mon premier message qu'il faut ajouter la référence DAO au projet !!
    J'ai pas encore de décodeur, alors, postez en clair ! Comment mettre une balise de code ?
    Débutez en VBA

    Mes articles


    Dans un MP, vous pouvez me dire que je suis beau, ... mais si c'est une question technique je ne la lis pas ! Vous êtes prévenus !

  18. #18
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut Perfectionnisme...
    re re re
    Je constate un tout petit defaut :

    Lorsque je choisis un nom de la liste déroulante, les coordonnées complétes s'affiche dans la feuille.

    Mais si jamais je me trompe de nom et en choisi un nouveau, celui-ci s'inscrit dans la feuille sans effacer le premier...
    C'est pas très grave car je me trompe rarement de nom
    Mais bon si cela arrive, ça me fait faire une manipulation de plus pour effacer les mauvaises coordonnées.

    Modifications possibles?

    Merci.
    Thomas

  19. #19
    Membre à l'essai
    Inscrit en
    Juin 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 27
    Points : 11
    Points
    11
    Par défaut On avance...
    Oula, il faut encore la trouver l'option :
    Microsoft DAO 3.6 Object Library

    En fait elle est dans le menu Outils Référence sous Word 2003...
    Enfin c'est nikel, ça marche.

    Reste que ce petit problême d'adresse qui s'ajoute au lieu de se remplacer.
    Mais là, si vous en avez assez de moi , je me contenterais de ce que j'ai et qui me va très bien déjà.

    Merci beaucoup les gars, mais comment vous rendre la pareil?
    Thomas

  20. #20
    Membre émérite
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Points : 2 793
    Points
    2 793
    Par défaut
    bah en cliquant sur le bouton
    Toute question technique envoyée en MP ira directement à la poubelle

    Un code ne marchera jamais, il n'a jamais reçu la capacité de se déplacer.
    Inutile donc de dire "ça marche pas", donnez plutôt des informations précises afin de mieux pouvoir vous aider.


    Grand gourou de la -attitude

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Pb impression doc avec renvoi sous WORD 2003
    Par Mygush dans le forum Word
    Réponses: 7
    Dernier message: 19/12/2008, 09h32
  2. Problème de publipostage sous word 2003
    Par Jipé70 dans le forum Word
    Réponses: 0
    Dernier message: 19/12/2007, 16h10
  3. Problème - Impression sous Word 2003
    Par kip dans le forum Word
    Réponses: 6
    Dernier message: 29/11/2007, 13h43
  4. clavier américain et non français sous word 2003
    Par cyrano_de_bergerac dans le forum Word
    Réponses: 1
    Dernier message: 09/10/2007, 18h40
  5. SQL sous Word 2003
    Par Stef.web dans le forum Langage SQL
    Réponses: 3
    Dernier message: 01/12/2005, 13h54

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