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

VBA Access Discussion :

Sauvegarde d'informations d'impression [Toutes versions]


Sujet :

VBA Access

  1. #1
    Membre confirmé Avatar de morobaboumar
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2009
    Messages
    1 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 114
    Points : 491
    Points
    491
    Par défaut Sauvegarde d'informations d'impression
    Salut.
    Comment sauvegarder les informations (ID,nombre de tirages, etc.) du tirage (impressions) des états dans une table Access ?
    Je ne Suis Pas un Expert en Programmation
    Le savoir est la lumière de l'esprit
    Le chemin de la réussite

    Les savants sont les héritiers de la science
    Qui cherche positivement trouve
    Tout ce qui brille n'est pas l'or ou diamant
    Mais l'or et le diamant se trouvent avec sagesse, intelligence et effort

  2. #2
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 183
    Points : 5 515
    Points
    5 515
    Par défaut Pistes ?
    Un moyen approché est d'inclure un suivi dans l'événement "Sur impression" (OnPrint) dans l'entête de l'état. Cela ne permet pas de vérifier le nombre de tirages demandés.

    Un autre moyen est d'ajouter un bouton "Imprimer" sur le rapport (bouton dont la propriété 'Afficher' = 'A l'écran' pour qu'il ne soit pas imprimé), lequel demande le nombre de copies à faire, qui ensuite lance l'impression en utilisant la commande
    Docmd.PrintOut PrintRange, PageFrom, PageTo, PrintQuality, Copies, CollateCopies

    mais cela n'est pas sur à 100%, cela pouvant éventuellement être contourné par un Ctrl-P.

  3. #3
    Membre confirmé Avatar de morobaboumar
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2009
    Messages
    1 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 114
    Points : 491
    Points
    491
    Par défaut
    Bonsoir EricDgn,

    Voici mon modèle:

    Nom : CaptureInfoRecuPayement_2.PNG
Affichages : 239
Taille : 25,4 Ko
    Nom : CaptureInfoRecuPayement_3.PNG
Affichages : 228
Taille : 80,4 Ko
    Nom : CaptureInfoRecuPayement_1.PNG
Affichages : 248
Taille : 88,8 Ko
    Nom : CaptureInfoRecuPayement_5.PNG
Affichages : 227
Taille : 19,3 Ko
    Nom : CaptureInfoRecuPayement_4.PNG
Affichages : 220
Taille : 21,4 Ko
    Nom : CaptureInfoRecuPayement_6.PNG
Affichages : 225
Taille : 23,4 Ko

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Private Sub Détail_Print(cancel As Integer, PrintCount As Integer)
    majTableInfosRecus
    End Sub
     
    Sub majTableInfosRecus()
    On Error Resume Next
    Dim sql As String
    Dim nbTirage As Integer
    nbTirage = NbreRecuDejaEdite(Me.numpayementScol, Me.ID_EtablissFreq) + 1
    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
     
    Public Function NbreRecuDejaEdite(intRecu As Long, idEcol As Long) As Integer
    On Error GoTo OUMAR
    Dim BD As Database
    Dim rs As Recordset
    Set BD = CurrentDb
    Set rs = BD.OpenRecordset("select * from [INFO_TIRAGE_RECU_PAY_FS] where NumRECU = " & intRecu & "and  IdEcole = " & idEcol & " order by Date_Tirage desc;")
     
    If rs.EOF Then
       NbreRecuDejaEdite = 0
    Else
        NbreRecuDejaEdite = rs.Fields("Nombre_Tirage")
    End If
    Exit Function
    OUMAR:
    MsgBox err.Description, vbExclamation, err.Number
    End Function
    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
     
    Public Function fNumeroTirage() As Long
    On Error GoTo OUMAR
    Dim BD As Database
    Dim rs As Recordset
    Set BD = CurrentDb
    Set rs = BD.OpenRecordset("select * from [INFO_TIRAGE_RECU_PAY_FS] order by identifiantTirage desc;")
    If rs.EOF Then
       fNumeroTirage = 0
    Else
        fNumeroTirage = rs.Fields("identifiantTirage")
    End If
    Exit Function
    OUMAR:
    MsgBox err.Description, vbExclamation, err.Number
    End Function
    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
     
    Public Function AnneeTirageRecu(intRecu As Long) As String
    On Error GoTo OUMAR
    Dim BD As Database
    Dim rs As Recordset
    Set BD = CurrentDb
    Set rs = BD.OpenRecordset("select * from [PAYEMENTS_Scolairite] where numpayementScol = " & intRecu & " ;")
     
    If rs.EOF Then
       AnneeTirageRecu = ""
    Else
        AnneeTirageRecu = rs.Fields("AnneeScolairePay")
    End If
    Exit Function
    OUMAR:
    MsgBox err.Description, vbExclamation, err.Number
    End Function
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub Report_Close()
    SupprInfosRecus (Me.numpayementScol)
    End Sub
    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
    Sub SupprInfosRecus(idX As Long)
    Dim BD As Database
    Dim enr As Recordset
    Dim sql As String
     
    Set BD = CurrentDb
     
    sql = "select * from [INFO_TIRAGE_RECU_PAY_FS] where NumRECU = " & idX & " order by Date_Tirage desc ;"
    Set enr = BD.OpenRecordset(sql)
     
    With enr
        If Not .EOF Then
            .MoveFirst
            .Edit
            .Delete
        End If
    End With
    End Sub
    Voici le sql du formulaire "INFO_TIRAGE_RECU_PAYEMENT_Frais_Scolaire"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT INFO_TIRAGE_RECU_PAY_FS.identifiantTirage, INFO_TIRAGE_RECU_PAY_FS.NumRECU, INFO_TIRAGE_RECU_PAY_FS.Date_Tirage, INFO_TIRAGE_RECU_PAY_FS.Nombre_Tirage, INFO_TIRAGE_RECU_PAY_FS.TypedeRecu, INFO_TIRAGE_RECU_PAY_FS.MontantVerse, INFO_TIRAGE_RECU_PAY_FS.mlePa, AnneeTirageRecu([INFO_TIRAGE_RECU_PAY_FS]![NumRECU]) AS ANNEE_SCOLdeTirage, INFO_TIRAGE_RECU_PAY_FS.IdEcole
    FROM INFO_TIRAGE_RECU_PAY_FS;
    Maintenant, aidez moi à écrire code permettant d'enregistrer les données d'impression à chaque nouveau tirage de d'un même
    parent, et aussi à la demande d'un duplicata.

    la fonction supprimer les infos entrées en double.
    Elle supprime aussi les anciennes données d'un parent par erreur. Exemple: lorsque j'annule le tirage du duplicata d'un ancien reçu.

    Cordialement.
    Je ne Suis Pas un Expert en Programmation
    Le savoir est la lumière de l'esprit
    Le chemin de la réussite

    Les savants sont les héritiers de la science
    Qui cherche positivement trouve
    Tout ce qui brille n'est pas l'or ou diamant
    Mais l'or et le diamant se trouvent avec sagesse, intelligence et effort

  4. #4
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 183
    Points : 5 515
    Points
    5 515
    Par défaut
    Bonjour,

    Je dois dire que je ne comprends pas vraiment ce que vous voulez faire, mais voici toujours un élément qui pourra vous aider pour les calculs de NbreRecuDejaEdite et AnneeTirageRecu
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Public Function NbreRecuDejaEdite(intRecu As Long, idEcol As Long) As Integer
        NbreRecuDejaEdite = Nz(DLookup("*", "INFO_TIRAGE_RECU_PAY_FS]", "NumRECU=" & intRecu & " AND  IdEcole=" & idEcol), 0)
    End Function
     
    Public Function AnneeTirageRecu(intRecu As Long) As String
        AnneeTirageRecu = Nz(DLookup("AnneeScolairePay", "PAYEMENTS_Scolairite", "numpayementScol=" & intRecu), "Non trouvée")
    End Function
    ... à vérifier, vu mon manque de compréhension de votre base de données. Cela peut donner de mauvaises réponses s'il y a des doublons (qui pourraient être détectées à l'aide d'instructions DCount()).

    Pour ce qui est de fNumeroTirage, aucune idée de ce vous voulez en faire.

    Pour ce qui est de la mise à jour, vous pourriez sans doute utiliser une requête sql "UPDATE ..." (voir dans l'aide d'Access la rubrique RunSQL).

    Cordialement.

  5. #5
    Membre confirmé Avatar de morobaboumar
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2009
    Messages
    1 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 114
    Points : 491
    Points
    491
    Par défaut
    Citation Envoyé par EricDgn Voir le message
    ... à vérifier, vu mon manque de compréhension de votre base de données. Cela peut donner de mauvaises réponses s'il y a des doublons (qui pourraient être détectées à l'aide d'instructions DCount()).
    Pour ce qui est de fNumeroTirage, aucune idée de ce vous voulez en faire.
    Pour ce qui est de la mise à jour, vous pourriez sans doute utiliser une requête sql "UPDATE ..." (voir dans l'aide d'Access la rubrique RunSQL)
    Bonjour EricDgn,
    Toujours très heureux de vous retrouver !
    Permettez moi de vous envoyer une copie de mon application afin que vous pussiez mieux me comprendre.
    Cordialement.
    Fichiers attachés Fichiers attachés
    Je ne Suis Pas un Expert en Programmation
    Le savoir est la lumière de l'esprit
    Le chemin de la réussite

    Les savants sont les héritiers de la science
    Qui cherche positivement trouve
    Tout ce qui brille n'est pas l'or ou diamant
    Mais l'or et le diamant se trouvent avec sagesse, intelligence et effort

  6. #6
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 183
    Points : 5 515
    Points
    5 515
    Par défaut
    Bonjour,

    Si je comprends bien:
    dans le formulaire Tbl_Eleve_InserserPhoto / sous-formualre Quittance_Scolarite_SF
    un clic sur RECU VERSEMENT ----> Aperçu avant impression du Reçu

    cas 1) c'est un nouveau reçu (n'ayant jamais été imprimé)
    --- 1a) lancer l'impression ----> que faire ?
    --- 1b) fermer l'aperçu sans imprimer ----> que faire ?

    cas 2) c'est un duplicata (reçu a déjà été imprimé une ou plusieurs fois)
    --- 2a) lancer l'impression ----> que faire ?
    --- 2b) fermer l'aperçu sans imprimer ----> que faire ?

    Cordialement.

  7. #7
    Membre confirmé Avatar de morobaboumar
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2009
    Messages
    1 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 114
    Points : 491
    Points
    491
    Par défaut
    Citation Envoyé par EricDgn Voir le message
    Bonjour,
    Si je comprends bien:
    dans le formulaire Tbl_Eleve_InserserPhoto / sous-formualre Quittance_Scolarite_SF
    un clic sur RECU VERSEMENT ----> Aperçu avant impression du Reçu
    cas 1) c'est un nouveau reçu (n'ayant jamais été imprimé)
    --- 1a) lancer l'impression ----> que faire ?
    --- 1b) fermer l'aperçu sans imprimer ----> que faire ?

    cas 2) c'est un duplicata (reçu a déjà été imprimé une ou plusieurs fois)
    --- 2a) lancer l'impression ----> que faire ?
    --- 2b) fermer l'aperçu sans imprimer ----> que faire ?

    Cordialement.
    Bonsoir EricDgn,
    Voici ce qu'il faut faire:
    cas 1) c'est un nouveau reçu (n'ayant jamais été imprimé)
    --- 1a) lancer l'impression ----> que faire ?
    --- 1b) fermer l'aperçu sans imprimer ----> que faire ?
    Nom : CaptureInfoRecuPayement_7.PNG
Affichages : 223
Taille : 13,8 Ko

    1°) Cliquer sur "Non" pour ne pas envoyer d'infos dans la table "INFO_TIRAGE_RECU_PAY_FS" au moment
    de l'aperçu du reçu avant l'impression.

    1a) Quand lance l'impression, voici ce qui se passe: - une boite de dialogue apparaît:

    Nom : CaptureInfoRecuPayement_8.PNG
Affichages : 199
Taille : 21,3 Ko

    - si vous cliquez sur "Oui" alors l'info d'impression au est envoyée dans la table "INFO_TIRAGE_RECU_PAY_FS" montrant
    qu'un 1er reçu N°.... est imprimé.

    1b) - si vous fermez l'aperçu sans imprimer, alors il y a la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub Report_Close()
    SupprInfosRecus (Me.numpayementScol)
    End Sub
    supprime les infos de ce reçu N°.... non imprimé.

    - Maintenant s'il se trouve que ce reçu N°.... était imprimé auparavant, la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub Report_Close()
    SupprInfosRecus (Me.numpayementScol)
    End Sub
    supprime les infos de ce reçu N°.... auparavant imprimé .

    Ce que je voudrais éviter.

    cas 2) c'est un duplicata (reçu a déjà été imprimé une ou plusieurs fois)
    --- 2a) lancer l'impression ----> que faire ?
    --- 2b) fermer l'aperçu sans imprimer ----> que faire ?
    - Suivre les mêmes instructions qui sont au niveau du 1a) et 2a).

    - Les infos des duplicatas des reçus anciennement imprimés doivent être enregistrées dans la table "INFO_TIRAGE_RECU_PAY_FS" dans le cas où l'impression de ces duplicatas est nécessaire.

    Cordialement.
    Je ne Suis Pas un Expert en Programmation
    Le savoir est la lumière de l'esprit
    Le chemin de la réussite

    Les savants sont les héritiers de la science
    Qui cherche positivement trouve
    Tout ce qui brille n'est pas l'or ou diamant
    Mais l'or et le diamant se trouvent avec sagesse, intelligence et effort

  8. #8
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 183
    Points : 5 515
    Points
    5 515
    Par défaut
    Bonjour,

    Une façon de faire est de rajouter un "En-tête de rapport" (ou En-tête d'état) dans le rapport "RECU DE VERSEMENT FRAIS ECOLAGE" et placer le code suivant:
    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
    Option Compare Database
    Option Explicit
     
    Dim kPrinted As Integer
     
    Private Sub Détail_Format(Cancel As Integer, FormatCount As Integer)
        If MontantFraisEcolageAnnuelParent(Me.ID_EtablissFreq, Me.AnneeScolairePay, Me.NumEnregistreParResponsable) - MontantFraisEcolageAnnuelPaye_Parent(Me.AnneeScolairePay, Me.ID_EtablissFreq, Me.NumEnregistreParResponsable) > 0 Then
            Me.txtSolde = "RESTE UN MONTANT A PAYER !"
            Me.txtSolde.ForeColor = 255
        Else
            Me.txtSolde = "SCOLARITE SOLDEE."
            Me.txtSolde.ForeColor = 6723891
        End If
    End Sub
     
    Private Sub EntêteÉtat_Print(Cancel As Integer, PrintCount As Integer)
        kPrinted = kPrinted + 1
        '--- ainsi au moment de l'aperçu kPrinted = 1
        '--- ensuite à chaque impression kPrinted est incrémenté de 1
        If kPrinted = 2 Then
            EnregistrerRecu
        End If
    End Sub
     
    Private Sub EnregistrerRecu()
        Dim sql As String
        Dim idTirage As Long
        Dim n°Tirage As Integer
        idTirage = DMax("identifiantTirage", "INFO_TIRAGE_RECU_PAY_FS") + 1
        n°Tirage = Nz(DMax("Nombre_Tirage", "INFO_TIRAGE_RECU_PAY_FS", "NumRECU = " & Me.numpayementScol & " And  IdEcole = " & Me.ID_EtablissFreq))
        sql = "INSERT INTO INFO_TIRAGE_RECU_PAY_FS(identifiantTirage, NumRECU, Date_Tirage, Nombre_Tirage, TypedeRecu, MontantVerse, mlePa, IdEcole)" & _
             " VALUES (" & idTirage & ", " & Me.numpayementScol & ",'" & Now() & "', " & n°Tirage + 1 & ",'ORIGINAL'," & Me.montantFS_Verse & ", " & Me.mlepa_Enreg_ParResp & ", " & Me.ID_EtablissFreq & " );"
        If n°Tirage > 0 Then
            sql = Replace(sql, "ORIGINAL", "DUPLICATA")
        End If
        CurrentDb.Execute sql, dbFailOnError
    End Sub
    Bonne continuation.

  9. #9
    Membre confirmé Avatar de morobaboumar
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2009
    Messages
    1 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 114
    Points : 491
    Points
    491
    Par défaut Codes parfaits
    Bonsoir EricDgn,
    Merci infiniment. Tous les codes sont parfaits.

    J'ai ajouté cette ligne de code à votre procédure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    If MsgBox("Voulez vous imprimer un reçu ?", vbQuestion + vbOKCancel, "Impression de Reçu de Payement") = vbCancel Then Exit Sub
    '_______________________________________________________________________________________
    Je demande s'en votre avis ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Private Sub EntêteÉtat_Print(Cancel As Integer, PrintCount As Integer)
    '__________________________________________________________________________________________
    If MsgBox("Voulez vous imprimer un reçu ?", vbQuestion + vbOKCancel, "Impression de Reçu de Payement") = vbCancel Then Exit Sub
    '__________________________________________________________________________________________
     
        kPrinted = kPrinted + 1
        '--- ainsi au moment de l'aperçu kPrinted = 1
        '--- ensuite à chaque impression kPrinted est incrémenté de 1
        If kPrinted = 2 Then
            EnregistrerRecu
        End If
    End Sub

    Je vous souhaite beaucoup de bonheurs !
    Cordialement.
    Je ne Suis Pas un Expert en Programmation
    Le savoir est la lumière de l'esprit
    Le chemin de la réussite

    Les savants sont les héritiers de la science
    Qui cherche positivement trouve
    Tout ce qui brille n'est pas l'or ou diamant
    Mais l'or et le diamant se trouvent avec sagesse, intelligence et effort

  10. #10
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 183
    Points : 5 515
    Points
    5 515
    Par défaut
    Bonjour,
    Surtout ne pas rajouter le message "Voulez-vous imprimer un reçu ?": cela faussera le fonctionnement du dispositif. En fait cette demande de confirmation est déjà posée au moment où l'on clique sur le bouton RECU VERSEMENT.

    Cordialement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. comment sauvegarder l'information dans le "Select"
    Par hadjiphp dans le forum Langage
    Réponses: 1
    Dernier message: 31/05/2009, 14h03
  2. Comment sauvegarder mes informations rentrées?
    Par Hellgast dans le forum Autres éditeurs
    Réponses: 6
    Dernier message: 02/04/2009, 21h51
  3. Sauvegarder des information dans un fichier XML
    Par doudoubens dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 08/03/2009, 13h45
  4. Réponses: 2
    Dernier message: 09/12/2008, 11h36
  5. Sauvegarder les informations d'une Listbox
    Par theobrendel dans le forum Windows Forms
    Réponses: 3
    Dernier message: 19/01/2007, 19h49

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