Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1178 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  vbs et manipulation de word

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

vbs et manipulation de word

n°1134851
jnauche
Posté le 29-06-2005 à 16:00:53  profilanswer
 

Bonjour, j'essai a partir d'un fichier vbs de manipuler word. j'arrive a ouvrir word sans probleme mais le probleme se situe au niveau du remplacement de text. j'ai trouver le script suivant sur msdn  
 
objWord.documents.Open(path)
  objWord.Visible = true
  With objWord.Selection.Find
   .ClearFormatting()
          .Text = "Document2"
          With .Replacement
           .ClearFormatting()
           .Text = "yessssssss"
          End With
   .Execute(Replace:=Word.WdReplace.wdReplaceAll)
                End With
 
j'ai defini mon objword au debut du programme :
 
Set objWord = CreateObject("Word.Application" )
 
 
Le probleme se situe a l'execution du vbs, il me genere une erreur sur la ligne  
.Execute(Replace:=Word.WdReplace.wdReplaceAll)
Apparement vbs n'aime pas le ":=" qui est spécifique au macro, il me dit qu'il manque une " )" lorsque je lance le vbs.
 
Si quelqu'un a une idée pour me sortir de se petrin merci par avance de la réponse.

mood
Publicité
Posté le 29-06-2005 à 16:00:53  profilanswer
 

n°1135229
pelw
Posté le 29-06-2005 à 21:41:22  profilanswer
 

Bonjour,
 
Essaye éventuellement ceci :
 
Const wdReplaceAll = 2
path = "C:\MonDocument.doc"
Set objWord = CreateObject("Word.Application" )  
objWord.Documents.Open(path)  
objWord.Visible = True  
With objWord.Selection.Find  
   .ClearFormatting
   .Text = "Document2"  
   With .Replacement  
      .ClearFormatting
      .Text = "yessssssss"  
   End With  
   .Execute , , , , , , , , , , wdReplaceAll
End With
 
 
pelw

n°1135566
jnauche
Posté le 30-06-2005 à 11:07:15  profilanswer
 

pelw a écrit :

Bonjour,
 
Essaye éventuellement ceci :
 
Const wdReplaceAll = 2
path = "C:\MonDocument.doc"
Set objWord = CreateObject("Word.Application" )  
objWord.Documents.Open(path)  
objWord.Visible = True  
With objWord.Selection.Find  
   .ClearFormatting
   .Text = "Document2"  
   With .Replacement  
      .ClearFormatting
      .Text = "yessssssss"  
   End With  
   .Execute , , , , , , , , , , wdReplaceAll
 
 
pelw


 
 
Donne moi ton adresse, il faut que je vienne chez toi te faire un bisou, tu m'as sauvé alors que j'etais au bord du gouffre, merci beaucouuuuuuuuuuuup!!!  
Honnetement quand jai vu ta réponse j'y ai pas cru en plus.
Poue etre un peu plus sérieux, pourrais tu m'expliquer cette ligne  
.Execute , , , , , , , , , , wdReplaceAll  
je ne comprends pas cette hidtoire de virgule!!!
Et aussi pourquoi tu remplaces wdreplaceall par 2???
 
En tous les cas merci beaucoup, j'aurais jamais trouvé seul!!
 

n°1136171
jnauche
Posté le 30-06-2005 à 16:37:33  profilanswer
 

pelw a écrit :

Bonjour,
 
Essaye éventuellement ceci :
 
Const wdReplaceAll = 2
path = "C:\MonDocument.doc"
Set objWord = CreateObject("Word.Application" )  
objWord.Documents.Open(path)  
objWord.Visible = True  
With objWord.Selection.Find  
   .ClearFormatting
   .Text = "Document2"  
   With .Replacement  
      .ClearFormatting
      .Text = "yessssssss"  
   End With  
   .Execute , , , , , , , , , , wdReplaceAll
End With
 
 
pelw


 
 
J'ai fini par comprendre tout seul qu'en fait les "," definissent des champs vide et que wdReplaceAll est le dernier parametres et qu'en vbs il faut mettre "2" pour "replace all"
Bon alors maintenant j'ai avancé grace a toi mais je bute sur exactement le meme probleme, sauf que la c'est avec la boite de dialogue "enregistrer sous" que je veux afficher a l'ouverture de mon word
j'ai trouver ce script :
Dim dlg As Word.Dialog
    dlg = ThisApplication.Dialogs.Item( _
        Word.WdWordDialog.wdDialogFileNew)
    dlg.Show()
 
Mais encore une fois ca bloque sur les parametres de Item que vbs ne reconnait pas, j'imgine qu'il faut le remplacer par un autre parametre (adapté au langage vbs), mais je ne le trouve pas sur le web, tu aurais un lien pour que j'arrete de t'embeter, ou juste une solution pour passer ce nouveau probleme?
ps : ceci est censé affiché la boite de dialogue nouveau document mais bon j'imagine que c'est la meme chose pour "SaveAs"

n°1136651
pelw
Posté le 30-06-2005 à 23:43:13  profilanswer
 

Bonjour,
 
Essaye ceci :
 
Const wdDialogFileSaveAs = 84
path = "C:\MonDocument.doc"  
Set objWord = CreateObject("Word.Application" )  
objWord.Documents.Open(path)  
objWord.Visible = True
objWord.Dialogs(wdDialogFileSaveAs).Show
 
 
pelw

n°1136946
jnauche
Posté le 01-07-2005 à 11:08:46  profilanswer
 

pelw a écrit :

Bonjour,
 
Essaye ceci :
 
Const wdDialogFileSaveAs = 84
path = "C:\MonDocument.doc"  
Set objWord = CreateObject("Word.Application" )  
objWord.Documents.Open(path)  
objWord.Visible = True
objWord.Dialogs(wdDialogFileSaveAs).Show
 
 
pelw


 
J'applaudis encore des deux mains ca marche impecable.
J'ai encore pas mal de chose a faire avec word et je ne voudrais pas trop te deranger, j'imagine que le "84" n'etais pas inscrit au fin fond de ta memoire, donc si tes sources ne sont pas confidentiels j'aimerais bien les voir, surtout le tableau qui convertit les commandes macro en vbscript.
En tous les cas merci beaucoup pour les aides que tu m'as apporté jusqu'ici

n°1139743
pelw
Posté le 04-07-2005 à 20:26:34  profilanswer
 

Bonsoir,
 
Tu pourras trouver toutes les constantes Word dans... Word. Pour cela, procéder comme suit :
 
. Ouvrir Word
. Faire Alt+F11 pour aller dans l'éditeur VBA
. Faire F2 pour afficher l'explorateur d'objets
. Dans la liste de droite (celle intitulée Membres de '<globales>') tu trouveras, entre autres choses, toutes les constantes Word
. En sélectionnant p.ex. la constante wdDialogFileSaveAs, sa valeur (84) apparaîtra dans la zone de texte, sous la liste
 
Si tu as d'autres questions, n'hésite pas.
 
 
pelw

n°1140998
jnauche
Posté le 05-07-2005 à 17:03:15  profilanswer
 

Tu m'as dit de ne pas hesiter alors je vais oser te demander encore quelque chose du meme type :
 
Il faut que maintenant j'arrive a ouvrir entete et pied page (pour y remplacer du text ensuite)
 
Mais ce coup si j'ai pas trouver de script model qui est pres de matcher, je sais juste qu'il faut simuler les actions "view" puis "header and footer" mais je ne vois pas comment faire.  
 
Comme je commence a connaitre tes capacités, je te remercie par avance de ta reponse :)
 
Cordialement julien

n°1141173
pelw
Posté le 05-07-2005 à 19:04:07  profilanswer
 

Bonjour,
 
Peut-être comme ceci :
 

Code :
  1. Const wdSeekMainDocument = 0
  2. Const wdReplaceAll = 2
  3. Const wdPrintView = 3
  4. Const wdSeekCurrentPageHeader = 9
  5. Const wdSeekCurrentPageFooter = 10
  6. path = "C:\MonDocument.doc"
  7. Set objWord = CreateObject("Word.Application" )
  8. objWord.Documents.Open(path)
  9. With objWord.ActiveWindow.ActivePane.View
  10.    'Passer en mode d'affichage "Page"
  11.    .Type = wdPrintView
  12.    'Ouvrir l'en-tête de page
  13.    .SeekView = wdSeekCurrentPageHeader
  14.    'Remplacer toutes les occurrences de "titi" en "toto"
  15.    objword.Selection.Find.Execute "titi", , , , , , , , , "toto", wdReplaceAll
  16.    'Basculer vers le pied de page
  17.    .SeekView = wdSeekCurrentPageFooter
  18.    'Remplacer toutes les occurrences de "titi" en "toto"
  19.    objword.Selection.Find.Execute "titi", , , , , , , , , "toto", wdReplaceAll
  20.    'Fermer le pied de page
  21.    .SeekView = wdSeekMainDocument
  22. End With
  23. objWord.Visible = True


 
pelw

n°1141857
jnauche
Posté le 06-07-2005 à 11:55:33  profilanswer
 

pelw a écrit :

Bonjour,
 
Peut-être comme ceci :
 

Code :
  1. Const wdSeekMainDocument = 0
  2. Const wdReplaceAll = 2
  3. Const wdPrintView = 3
  4. Const wdSeekCurrentPageHeader = 9
  5. Const wdSeekCurrentPageFooter = 10
  6. path = "C:\MonDocument.doc"
  7. Set objWord = CreateObject("Word.Application" )
  8. objWord.Documents.Open(path)
  9. With objWord.ActiveWindow.ActivePane.View
  10.    'Passer en mode d'affichage "Page"
  11.    .Type = wdPrintView
  12.    'Ouvrir l'en-tête de page
  13.    .SeekView = wdSeekCurrentPageHeader
  14.    'Remplacer toutes les occurrences de "titi" en "toto"
  15.    objword.Selection.Find.Execute "titi", , , , , , , , , "toto", wdReplaceAll
  16.    'Basculer vers le pied de page
  17.    .SeekView = wdSeekCurrentPageFooter
  18.    'Remplacer toutes les occurrences de "titi" en "toto"
  19.    objword.Selection.Find.Execute "titi", , , , , , , , , "toto", wdReplaceAll
  20.    'Fermer le pied de page
  21.    .SeekView = wdSeekMainDocument
  22. End With
  23. objWord.Visible = True


 
pelw


 
 
Salut merci encore ca marche bien, j'ai fait legerement autrement car je devais modifier plusieurs champ qui sont dans un tableau. Voici comment j'ai fait, ca tourne nikel :
 

pelw a écrit :


For i=0 to UBound(tableau)
    Execute "tempo=" & tableau(i,2)
    tempo = modiftextdoc(tempo)
    With objWord.ActiveWindow.ActivePane.View  
       .Type = wdPrintView  
       .SeekView = wdSeekCurrentPageHeader  
       With objword.Selection.Find
     .ClearFormatting()
     .Text = "@" & tableau(i,0) & "@"
     With .Replacement
             .ClearFormatting()
             .Text = tempo
            End With
            .Execute , , , , , , , , , , wdReplaceAll  
       End With  
       .SeekView = wdSeekCurrentPageFooter
       With objword.Selection.Find
     .ClearFormatting()
     .Text = "@" & tableau(i,0) & "@"
     With .Replacement
             .ClearFormatting()
             .Text = tempo
            End With
            .Execute , , , , , , , , , , wdReplaceAll
       End With
       .SeekView = wdSeekMainDocument  
     End With
   Next
   objWord.Visible = True
   fiche_a_generer = fso.GetBaseName(fiche_a_generer)
   doc.SaveAs path_fiche & "\" & document_a_sauvegarder & ".doc"
   doc.Close
   objWord.Quit
 


 
A bientot pour d'autres questions :)

mood
Publicité
Posté le 06-07-2005 à 11:55:33  profilanswer
 

n°1147971
jnauche
Posté le 12-07-2005 à 15:14:58  profilanswer
 

bonjour il y avait longtemps car j'ai du bosser sur autre chose mais la je regalere sur la meme chose...
J'ai essayer de suivre tes instructions mais je me perds tellement c vaste!!!
 
Je cherche a changr toujorus du texte plus dans les entetes mais dans les "text box". Ce sont les box que tu as dans la barre d'outils "dessin" que tu peux deplacer n'importe ou dans la page...
 
Encore plus vicieux je vient d'aprendre que tu pouvais faire des textbox dans les pied ou en tete de page qui ne sont pas accessible sans entrer dans ceux ci... Enfin maintenant que j'arrive a ouvrir les entete ca devrait pas poser de probleme.

n°1148016
jnauche
Posté le 12-07-2005 à 15:33:24  profilanswer
 

pelw a écrit :

Bonjour,
 
Peut-être comme ceci :
 

Code :
  1. Const wdSeekMainDocument = 0
  2. Const wdReplaceAll = 2
  3. Const wdPrintView = 3
  4. Const wdSeekCurrentPageHeader = 9
  5. Const wdSeekCurrentPageFooter = 10
  6. path = "C:\MonDocument.doc"
  7. Set objWord = CreateObject("Word.Application" )
  8. objWord.Documents.Open(path)
  9. With objWord.ActiveWindow.ActivePane.View
  10.    'Passer en mode d'affichage "Page"
  11.    .Type = wdPrintView
  12.    'Ouvrir l'en-tête de page
  13.    .SeekView = wdSeekCurrentPageHeader
  14.    'Remplacer toutes les occurrences de "titi" en "toto"
  15.    objword.Selection.Find.Execute "titi", , , , , , , , , "toto", wdReplaceAll
  16.    'Basculer vers le pied de page
  17.    .SeekView = wdSeekCurrentPageFooter
  18.    'Remplacer toutes les occurrences de "titi" en "toto"
  19.    objword.Selection.Find.Execute "titi", , , , , , , , , "toto", wdReplaceAll
  20.    'Fermer le pied de page
  21.    .SeekView = wdSeekMainDocument
  22. End With
  23. objWord.Visible = True


 
pelw


 
 
apparement ca serai celui la
Const wdDialogFormatDrawingObjectTabTextbox = 1200005 (&H124F85)
    Member of Word.WdWordDialogTab
 
mais comment ca marche???  :??:

n°1149531
pelw
Posté le 13-07-2005 à 21:48:39  profilanswer
 

Bonjour,
 
Apparemment la méthode traditionnelle de "rechercher/remplacer" ne fonctionne pas pour les "text box", lorsqu'elle est lancée depuis VBS. Voici donc une autre façon de faire :
 

Code :
  1. Const msoCanvas = 20
  2. Const msoTextBox = 17
  3. Const wdHeaderFooterPrimary = 1
  4. path = "C:\MonDocument.doc"
  5. Set objWord = CreateObject("Word.Application" )
  6. objWord.Documents.Open(path)
  7. 'Parcourir les formes du corps du document (sans l'en-tête et le pied de page)
  8. For Each objShape In objWord.ActiveDocument.Shapes
  9.    Call FindAndReplace()
  10. Next
  11. 'Parcourir les formes de l'en-tête et du pied de page
  12. For Each objShape In objWord.ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes
  13.    Call FindAndReplace()
  14. Next
  15. objWord.Visible = True
  16. Sub FindAndReplace()
  17. Select Case objShape.Type
  18. 'S'il s'agit d'une zone de dessin => rechercher les zones de texte et les traiter
  19. Case msoCanvas
  20.    For Each objShItm In objShape.CanvasItems
  21.       If objShItm.Type = msoTextBox Then
  22.          With objShItm.TextFrame.TextRange
  23.             .Text = Replace(.Text, "titi", "toto" )
  24.          End With
  25.       End If
  26.    Next
  27. 'S'il s'agit d'une zone de texte indépendante => la traiter directement
  28. Case msoTextBox
  29.    With objShape.TextFrame.TextRange
  30.       .Text = Replace(.Text, "titi", "toto" )
  31.    End With
  32. End Select
  33. End Sub


 
pelw

n°1150559
jnauche
Posté le 15-07-2005 à 11:46:27  profilanswer
 

pelw a écrit :

Bonjour,
 
Apparemment la méthode traditionnelle de "rechercher/remplacer" ne fonctionne pas pour les "text box", lorsqu'elle est lancée depuis VBS. Voici donc une autre façon de faire :
 

Code :
  1. Const msoCanvas = 20
  2. Const msoTextBox = 17
  3. Const wdHeaderFooterPrimary = 1
  4. path = "C:\MonDocument.doc"
  5. Set objWord = CreateObject("Word.Application" )
  6. objWord.Documents.Open(path)
  7. 'Parcourir les formes du corps du document (sans l'en-tête et le pied de page)
  8. For Each objShape In objWord.ActiveDocument.Shapes
  9.    Call FindAndReplace()
  10. Next
  11. 'Parcourir les formes de l'en-tête et du pied de page
  12. For Each objShape In objWord.ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes
  13.    Call FindAndReplace()
  14. Next
  15. objWord.Visible = True
  16. Sub FindAndReplace()
  17. Select Case objShape.Type
  18. 'S'il s'agit d'une zone de dessin => rechercher les zones de texte et les traiter
  19. Case msoCanvas
  20.    For Each objShItm In objShape.CanvasItems
  21.       If objShItm.Type = msoTextBox Then
  22.          With objShItm.TextFrame.TextRange
  23.             .Text = Replace(.Text, "titi", "toto" )
  24.          End With
  25.       End If
  26.    Next
  27. 'S'il s'agit d'une zone de texte indépendante => la traiter directement
  28. Case msoTextBox
  29.    With objShape.TextFrame.TextRange
  30.       .Text = Replace(.Text, "titi", "toto" )
  31.    End With
  32. End Select
  33. End Sub


 
pelw


 
 
J'ai fait des testes avec des "titi" un peu partout dans mon word.  
Dans le document meme il ne remplace pas le "tit" mais c'est normal au vu de ton code et c pas grave vu que tu m'a deja dit comment faire.
Pareil pour les entetes et pied de page mais ca aussi ca m'a l'air d'etre normal.
En fait il devrait uniquement remplacer le text dans les textbox qui appartiennent ou pas a des entetes et pied de page.
Je constate que le text est bien remplacer lorsqu'il appartient a une entete ou pied de page, mais pas lorsque la zone de texte est independante. Etonnant!!!
Au vu du code je dirais que le probleme se situe dans ce case :
Case msoTextBox
 
   With objShape.TextFrame.TextRange  
      .Text = Replace(.Text, "titi", "toto" )  
   End With  
 
J'avoue etre un peu semer par ton niveau et je ne comprends pas trop ce qu'est "objshape" vu que tu ne le defini pas...
 
Je vais chercher de mon coté, essayé de trouver une solution mais j'espere que tes lumieres reviendront bientot vers ce forum.
 
Merci pelw

n°1150618
jnauche
Posté le 15-07-2005 à 13:30:01  profilanswer
 

Voici mon code complet qui permet d'ouvrir word et remplacer tous les champs comptenu dans un tableau pour d'aurte champs comptenu dans une autre colonne de ce meme tableau :
 
Set objWord = CreateObject("Word.Application" )
  Const wdSeekMainDocument = 0  
  Const wdPrintView = 3  
  Const wdSeekCurrentPageHeader = 9  
  Const wdSeekCurrentPageFooter = 10  
  Const wdDialogFileSaveAs = 84  
  Const wdReplaceAll = 2
  Const msoCanvas = 20  
  Const msoTextBox = 17  
  Const wdHeaderFooterPrimary = 1  
''''''''''''''''''''''''''traitement des documents un par un
  For j=0 to compteur -1
   document_a_sauvegarder = tab_a_sauvegarder(j)
''''''''''''''''''en fait ici j'ouvre un doc vbs qui stocks des varaibles, je l'execute pour remplir ses variables (mais pas utile pour notre cas)
   r = path_ville & "\" & fiche_a_generer & ".vbs"
   Set f=fso.OpenTextFile(r,1)
   Do while f.AtEndOfStream = false
    lecture_vbs = lecture_vbs & f.ReadLine & vbcrlf
   loop
   lecture_vbs = modiftextdoc(lecture_vbs)
   Execute lecture_vbs
   Set f= Nothing
   Set doc = objWord.Documents.Add(path_doc & "\" & tab_a_generer(j) & ".doc" )
   objWord.Visible = true
   For i=0 to UBound(tableau)
''''''''''''''''''''les varibles cotenues dans le tableau sont mise dans tempo
    Execute "tempo=" & tableau(i,2)
    tempo = modiftextdoc(tempo)
''''''''''''''''''ici rempacement dans le text word (ca amrche)
    With objWord.Selection.Find
     .ClearFormatting()
            .Text = "@" & tableau(i,0) & "@"
            With .Replacement
             .ClearFormatting()
             .Text = tempo
            End With
     .Execute , , , , , , , , , , wdReplaceAll  
    End With
   Next
 ''''''''''''''''''remplacement du text dans les entetes et pied de pages (ca marche)
   With objWord.ActiveWindow.ActivePane.View  
   .Type = wdPrintView  
   .SeekView = wdSeekCurrentPageHeader  
   For i=0 to UBound(tableau)
    Execute "tempo=" & tableau(i,2)
    tempo = modiftextdoc(tempo)
    With objword.Selection.Find
     .ClearFormatting()
     .Text = "@" & tableau(i,0) & "@"
     With .Replacement
             .ClearFormatting()
             .Text = tempo
            End With
            .Execute , , , , , , , , , , wdReplaceAll  
    End With  
   Next
   .SeekView = wdSeekCurrentPageFooter
   For i=0 to UBound(tableau)
    Execute "tempo=" & tableau(i,2)
    tempo = modiftextdoc(tempo)
    With objword.Selection.Find
     .ClearFormatting()
     .Text = "@" & tableau(i,0) & "@"
     With .Replacement
             .ClearFormatting()
             .Text = tempo
            End With
            .Execute , , , , , , , , , , wdReplaceAll
    End With
   Next
   .SeekView = wdSeekMainDocument  
   End With
   For i=0 to UBound(tableau)
    Execute "tempo=" & tableau(i,2)
    tempo = modiftextdoc(tempo)
   Next
'''''''''''''''remplacement du text dans les textbox cotenu dans les entetes et pied (ca marche que pour les entetes)
   For Each objShape In objWord.ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes
    For i=0 to UBound(tableau)
     Execute "tempo=" & tableau(i,2)
     tempo = modiftextdoc(tempo)
     Select Case objShape.Type  
     Case msoCanvas  
     MsgBox "canvas"
      For Each objShItm In objShape.CanvasItems  
       If objShItm.Type = msoTextBox Then  
        With objShItm.TextFrame.TextRange  
           .Text = Replace(.Text,"@" & tableau(i,0) & "@", tempo)  
        End With  
       End If  
      Next
     Case msoTextBox  
     MsgBox "textbox"
      With objShape.TextFrame.TextRange  
       .Text = Replace(.Text,"@" & tableau(i,0) & "@", tempo)  
      End With  
     End Select
    Next
   Next
   fiche_a_generer = fso.GetBaseName(fiche_a_generer)
   doc.SaveAs choix_dossier & "\" & document_a_sauvegarder & ".doc"
   doc.Close
  Next
  objword.visible=true
  objWord.Quit
  Set objWord = Nothing
 
 
Alors, j'ai pas mis le remplacement dans les textbox directement car ca marche pas.
J'ai laissé msocanvas meme si je ne sais pas quel option woes il s'agit... :p
J'espere que tu pourras m'aider parce que je bloque pour le spied de page -> textbox
et textbox direct...
Merci

n°1152440
jnauche
Posté le 18-07-2005 à 12:40:27  profilanswer
 

je suis contient que ca demande du temps mais j'aurai vraiment besoin de tes lumieres pelw.
J'arrive pas a avancer


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  vbs et manipulation de word

 

Sujets relatifs
[.net] Générer doc WORDenregistrer document word par VBA sous excel [résolu]
[VBS] [WORD] Expressions régulières - Rechercher toutes les lignes...[vba] un peu de word sous excel?
Copier/coller des colonnes d'excel vers wordWord-VB Problème avec des modèles de document
Taille du texte dans document word[vb.net] Génération et mise en page document WORD
Inserer un tableau dans WORD sous PHP via objet COMAssocier de l'XML à un document WORD
Plus de sujets relatifs à : vbs et manipulation de word


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR