[Macro-Basic] génération de cours eleve à partir de fichier cours enseignant

Bonjour,

je veux reproduire ce que je faisais avec find en shell en fait pour que
tout soit dans la macro et surtout que pour que cela puisse servir à
d'autres. Je m'explique: si je fais la recherche le filtrage et le renomage
des fichiers avec le shell j'aurais une macro qui ne peux pas faire tout le
travail à elle seule, elle perd donc de son intérêt (je parle pour
l'interet commun dans l'optique d'être réutilisé).

Avant de me lancer dans cette macro je faisais un:

<https://forum.openoffice.org/fr/forum/viewtopic.php?f=8&t=47475#>find
/home/cemoi/Documents/cible -type f -mtime -1 -iname "*eleve*.odt" -execdir
libreoffice --headless --convert-to pdf '{}' \;

Ca veut dire: cherche et trouve dans toute l'arborescence de
/home/cemoi/Documents/cible tous les fichiers modifié il y a 24h ou moins
de 24h ayant les caractéres (sans prendre en compte la casse) eleve dans
leur nom et ayant comme extension odt puis ça passe les resultats à
libreoffice qui est exécuté en -headless pour convertir en pdf tous les
fichiers trouvé.

Attention ici chaque pdf est mis au même endroit que le fichier source avec
lequel il est généré.

Comme on a des problèmes pour tenir à jour tous les fichiers eleves (et ça
prend aussi pas mal de temps) je me suis dis qu'il serai bon que cela soit
automatiser... en remplaçant le styleprof par des ___ comme cela il ne
resterai plus qu'à générer le pdf pour que cela sorte le document eleve.

pour le moment je fais la recherche de tous les fichiers odt contenant le
mot cours puis j'y ajoute le suffix _eleve puis je le copie comme ça je
conserve ma source voila le code:

#! /bin/bash
IFS=

find /home/cemoi/Documents/bactma/seconde/ \
    -type f \
    -iname '*cours*.odt' \
    -not -iname '*_eleve.odt' \
    -print0 |
    while read -rd '' name
    do
        new_name=$(echo $name|sed 's/\.odt$/_eleve.odt/')
        if [ "$name" -nt "$new_name" ]
        then
            cp "$name" "$new_name"
        fi
    done

la macro que je veux faire doit faire en premier ce script (si dessus) puis
remplacer les caractéres des styles text prof par des_____à tous les
*eleve.odt puis enregistrer ces midifications et enfin générer un pdf de ce
fichier.

Attention la macro parcours une arborecense elle est recursive.

Quand la macro sera terminé elle sera exploité sur un serveur de fichiers
sur lequel des enseignants travail chaque jour. les cours enseignants
seront traité par la macro ce qui sortira tous les
cours_calculs_flexion_eleve.odt (ici je parle du fichier déja modifié par
la macro) et cours_calculs_flexion_eleve.pdf à partir du fichier
cours_calculs_flexion.odt (qui est le document complet sur lequel les
enseignants travail). Sur le serveur de fichiers il y a une branche de
l'arborecsence pour la "fabrication des cours" et une branche "cours
terminé et /ou en production.

Voila la macro mais elle n'est pas terminé:

Option Explicit
'LG Global monTab() as String
dim monTab() as String

Sub CopierFichier
Dim Chemin as String, NomFichier as String, Fichier(), NewName as String
Dim X as Integer

' LG initialise
Redim monTab(0)

   Chemin = ConvertToURL("/home/cemoi/Documents/bac/seconde/")'le chemin
est à adapter à l'emplacement des fichiers
   NomFichier = Dir(Chemin & "Cours*.odt")
   X = 0
   Do While NomFichier <> ""
      Fichier = Split(NomFichier,".")
      NewName = Fichier(0) & "_eleve.odt"
     'LG
     X = X +1
' reDim Preserve monTab(X)
        redim Preserve monTab(1 to X)
      monTab(X) = ConvertToURL(Chemin & NewName)
      Filecopy ConvertToURL(Chemin & NomFichier), monTab(X)
      NomFichier = Dir()
     ' LG inutile X = X + 1
   Loop
   RemplacerStyle
End Sub

Sub RemplacerStyle()
Dim oDocument as Object, searchDescriptor As Object
Dim Args(0) as New com.sun.star.beans.PropertyValue
Dim i as Integer
   Args(0).Name = "Hidden"
   Args(0).Value = True 'LG essaye dejà avec false

FOR i=1 to UBound(monTab)
'LG For i = 0 to UBound(monTab)
      oDocument = StarDesktop.loadComponentFromURL(monTab(i),"_blank",0,Args
())
      searchDescriptor = oDocument.createReplaceDescriptor
      With searchDescriptor
         .SearchString = "Texte prof"
         .ReplaceString = "Blanc"
         .SearchStyles = True
      End With
      oDocument.replaceAll(searchDescriptor)
      oDocument.Store()
      ExportPDF(oDocument,monTab(i))
   Next i
End Sub

Sub ExportPDF(oDoc as Object,monFichier as String)
Dim oURL as String
Dim Args(0) as New com.sun.star.beans.PropertyValue
   oURL = Left(monFichier,CInt(Len(monFichier))-3) & "pdf"
   Args(0).Name = "FilterName"
   Args(0).Value = "writer_pdf_Export"
   oDoc.storeToURL(oUrl,args())
   oDoc.Close(True)
   Kill(monFichier)
   MsgBox("Le fichier " & ConvertFromURL(oURL) & " à été créé")
End Sub

à la ligne oURL = Left(monFichier,CInt(Len(monFichier))-3) & "pdf" ça
retourne l'agument n'est pas facultatif
Je ne comprends pas ce que contient la variable momFichier on dirait
qu'elle est vide! Et je ne comprends pas pourquoi...

Merci pour votre aide!

Bonjour,

Dans le batch il y

'*cours*.odt' \

dans la macro

"Cours*.odt"

Si les noms des fichiers ne commencent pas par "cours" cela ne fonctionne pas.

J'ai fait un test de ta macro et elle fonctionne (sous windows). Sous Linux n'y-a-t-il pas aussi le problème de la casse sur les noms de fichiers ?)

Claude

Cemoi Cemoi a écrit :

il y a peut eter un problème de casse effectivement mais ce que je aperçois
c'est que la première partie n'est pas recursive et le but de la macro
c'est de traiter toute une arborescense. Il faudrait boucler sur les
dossiers et faire l'appel moi même?

Merci pour votre aide.

voici la dernière versio nde la macro mais je n'arrive pas à bien
comprendre comment gérer la recursivité dans la première partie.

l'etat de dir() est global, c'est a dire que l'on peut pas utiliser une
boucle dir() dans une boucle dir() la parade, serai de faire une passe en
stockant dans un tableau tous les chemins de repertoires avec un dir()
puis ensuite boucler sur ce tableau, et ainsi le dir() sur les odt passera
en récursif
mais je n'arrive pas à comprendre comment appliquer ça dans la macro...

Option Explicit
'LG Global monTab() as String
dim monTab() as String

Sub CopierFichier
Dim Chemin as String, NomFichier as String, Fichier(), NewName as String
Dim X as Integer

' LG initialise
Redim monTab(0)

   Chemin = ConvertToURL("/home/cemoi/Documents/bac/seconde/")'le chemin
est à adapter à l'emplacement des fichiers
   NomFichier = Dir(Chemin & "Cours*.odt")
   X = 0
   Do While NomFichier <> ""
      Fichier = Split(NomFichier,".")
      NewName = Fichier(0) & "_eleve.odt"
     'LG
     X = X +1
' reDim Preserve monTab(X)
   redim Preserve monTab(1 to X)
      monTab(X) = ConvertToURL(Chemin & NewName)
      Filecopy ConvertToURL(Chemin & NomFichier), monTab(X)
      NomFichier = Dir()
     ' LG inutile X = X + 1
   Loop
   RemplacerStyle
End Sub

Sub RemplacerStyle()
Dim oDocument as Object, searchDescriptor As Object
Dim Args(0) as New com.sun.star.beans.PropertyValue
Dim i as Integer
   Args(0).Name = "Hidden"
   Args(0).Value = True 'LG essaye dejà avec false

FOR i=1 to UBound(monTab)
'LG For i = 0 to UBound(monTab)
      oDocument =
StarDesktop.loadComponentFromURL(monTab(i),"_blank",0,Args())
      searchDescriptor = oDocument.createReplaceDescriptor
      With searchDescriptor
         .SearchString = "Texte prof"
         .ReplaceString = "Blanc"
         .SearchStyles = True
      End With
      oDocument.replaceAll(searchDescriptor)
      oDocument.Store()
      ExportPDF(oDocument,monTab(i))
   Next i
End Sub

Sub ExportPDF(oDoc as Object,monFichier as String)
Dim oURL as String
Dim Args(0) as New com.sun.star.beans.PropertyValue
   oURL = Left(monFichier,CInt(Len(monFichier))-3) & "pdf"
   Args(0).Name = "FilterName"
   Args(0).Value = "writer_pdf_Export"
   oDoc.storeToURL(oUrl,args())
   oDoc.Close(True)
   Kill(monFichier)
'la MsgBox ne sert à rien
  ' MsgBox("Le fichier " & ConvertFromURL(oURL) & " à été créé")
End Su

une tentative d'integration mais je m'y perds...

'on construit un tableau dynamique de tous les sous repertoires et ensuite
on boucle sur tous les repertoires ainsi trouvés,
'l'astuce est que la premiere boucle for continuera toujours tant que l'on
ajouteras des repertoires dans la liste pour
'justement aller voir leur sous repertoires car le ubound() evolue
'!Penser à adapter l'appel de copieFichier, le reprtoire n'est plus en dur
dans cette sub mais passée desormais en argument!

sub general

dim listeDirs()
redim listeDirs(0)
indexDir = 0

dirBase="/home/cemoi/Docments/bactma/seconde/"
listeDir(0) = dirBase

for r = 0 to ubound(listeDir)
   curDir = listeDir(r)
   chaine = dir(curDir+"*",16) ' le 16 ce n'est que pour les repertoires
   while chaine<>""
      if chaine <>"." and chaine<>".." then
         indexDir = indexDir + 1
         redim preserve listeDir(0 to indexDir)
         listeDir(indexDir) = curDir+chaine+"/"
      endif
      chaine = dir()
   wend
next r

for r = 0 to ubound(listeDir)
    chemin = listeDir(r)
    call CopierFichier(chemin)
next r
  end sub

'ancien code qui ne traite que dans le repertoire spécifié et non en
recursif

   ' Option Explicit
   ' public monTab() as String

   ' Sub CopierFichier
   ' Dim Chemin as String, NomFichier as String, Fichier(), NewName as
String
   ' Dim X as Integer
'
   ' Chemin =
ConvertToURL("/home/cemoi/Documents/bactma/seconde/Projet_01/Seq_terminologie_piece/")'le
chemin est à adapter à l'emplacement des fichiers
   ' NomFichier = Dir(Chemin & "*Cours.odt")
   ' X = 0
      ' Do While NomFichier <> ""
          'Fichier = Split(NomFichier,".")
         'NewName = Fichier(0) & "_eleve.odt"
         ' redim Preserve monTab(X)
         ' monTab(X) = ConvertToURL(Chemin & NewName)
         ' Filecopy ConvertToURL(Chemin & NomFichier), monTab(X)
         ' NomFichier = Dir()
         ' X = X + 1
      ' Loop
      ' RemplacerStyle
   ' End Sub

    Sub RemplacerStyle()
    Dim oDocument as Object, searchDescriptor As Object
    Dim Args(0) as New com.sun.star.beans.PropertyValue
    Dim i as Integer
    Args(0).Name = "Hidden"
    Args(0).Value = True 'LG essaye dejà avec false

       FOR i = 0 to UBound(monTab)
          oDocument =
StarDesktop.loadComponentFromURL(monTab(i),"_blank",0,Args())
          searchDescriptor = oDocument.createReplaceDescriptor
             With searchDescriptor
                .SearchString = "Texte prof"
                .ReplaceString = "Blanc"
                .SearchStyles = True
             End With
          oDocument.replaceAll(searchDescriptor)
          oDocument.Store()
          ExportPDF(oDocument,monTab(i))
       Next i
    End Sub

    Sub ExportPDF(oDoc as Object,monFichier as String)
    Dim oURL as String
    Dim Args(0) as New com.sun.star.beans.PropertyValue
        ' Cemoi: que contient monFichier? à première vue c'est vide!
       oURL = Left(monFichier,CInt(Len(monFichier))-3) & "pdf"
       Args(0).Name = "FilterName"
       Args(0).Value = "writer_pdf_Export"
       oDoc.storeToURL(oUrl,args())
       oDoc.Close(True)
       Kill(monFichier)
    End Sub

Je precise que le bout de code que j'ai fourni à l'arrache n'est absolument pas garanti sur la syntaxe mais l'esprit y est

qu'est ce que tu ne comprends pas ?
je suis toujours sur irc si tu veux poser des questions :wink:

laurent

Bonjour

Désolé, je n'ai pas le temps de développer tout ton sujet mais si c'est
uniquement
sur le parcours de ton arborescence tu peux faire comme ci-dessous (le
code affiche à l'écran le nom de tous les docs comprenant "cours" dans le
nom).

Il utilise le service SimpleFileAccess que je présentais ici:
https://wiki.documentfoundation.org/Macros/General/005/fr
et où tu verras comment ajouter la gestion des dates.
Le reste, si j'ai bien compris (remplacer par des _) tu n'as pas de
problème.

Option Explicit

Sub Main
Dim sUrl As String
sUrl = ConvertToURL("C:\Tests\")

Parcourir(sUrl)

MsgBox "Terminé"
End Sub

Sub Parcourir(sUrl)
Dim sNomFic As String
Dim oSFA as Object
Dim ListeFichiers As Variant

oSFA = createUnoService("com.sun.star.ucb.SimpleFileAccess")

ListeFichiers = oSFA.getFolderContents(sUrl, True)

for each sNomFic in ListeFichiers
  if oSFA.IsFolder(sNomFic) then
    Parcourir(sNomFic)
  else
    if instr(sNomFic, "cours") > 0 then
      print sNomFic
    end if
  end if
next sNomFic

End Sub
    
Cordialement
Pierre-Yves

Bonsoir Pierre Yves

Merci pour cet exemple "récursif"
Je n'en en avait pas sous la main et il est tres pedagogique

Je pense que "Cemoi" en tirera parti et je suis dispo pour l'y aider sur IRC

Encore merci

Laurent

Bonjour Laurent

Surtout merci à toi de qui j'ai tant appris même si tu ne le sais pas
(projet ancien...), et l'occasion de remercier aussi Andrew Pitonyak &
Bernard Marcelly (livre et Xray).

Pierre-Yves

Bonjour,
je m'excuse si je ne suis pas trop en ligne en ce moment... merci beaucoup
à vous deux, il y a peu de monde capable ou prenant le temps d'étudier une
telle demande qui est quand même un poil complexe...

Un exemple de l'utilisation de SimpleFileAccessqui se trouve à la page 155
du livre programmer avec openoffice.org 2, il compte les repertoires et le
fichiers:

Option Explicit

' exemple : compter le nombre de sous-répertoires et le nombre total de
fichiers
Private d as long, f as long

Sub Main
Dim depart As String
d= 0
f = 0
depart = ConvertToURL("C:\Docs OpenOffice\") 'adapter le chemin en fonction
du besoin
explorerDossier(depart)
MsgBox(d & " répertoires, " & f & " fichiers")
End Sub

Sub explorerDossier(ByVal repEnCours As String)
Dim item As String
Dim ucb As Object, dc As Variant

ucb = createUnoService("com.sun.star.ucb.SimpleFileAccess")
On Error GoTo accesInterdit
dc = ucb.getFolderContents(repEnCours, True)
' ici on obtient un tableau des url complètes
' de chaque fichier et chaque répertoire du répertoire en cours
' mais dans le désordre !
for each item in dc
  if ucb.IsFolder(item) then ' traitement pour chaque sous-répertoire
    d = d+1 ' exemple : compter les sous-répertoires
    explorerDossier(item) ' récursion
  else ' traitement pour chaque fichier
    f = f+1 ' exemple : compter les fichiers
  end if
next
GoTo Exit1

accesInterdit:
Resume Exit1
Exit1:
On Error GoTo 0
End Sub
J'espére pouvoir travailler dessus cette semaine et vous faire un retour.
Je documenterai un peu la macro quand elle sera fonctionnelle dans
l'optique qu'elle puisse être utilisable par le plus grand nombre.

Best regard :slight_smile:

Bonjour,
voila une version qui s'approche fortement de la version finale:

REM ***** BASIC *****

Sub Main

    repBase="/home/cemoi/Documents/bactma/Projet_01/" 'chemin à adapter

    ' boucle sur les repertoires et sous repertoires et traitement des
fichiers
    call boucleRepertoire(convertToUrl(repBase))

     msgBox "Fin du traitement"

End Sub

sub boucleRepertoire(sUrl)

    oSFA = createUnoService("com.sun.star.ucb.SimpleFileAccess")

    ListeFichiers = oSFA.getFolderContents(sUrl, True)

    for each sNom in ListeFichiers
         if oSFA.IsFolder(sNom) then
             call boucleRepertoire(sNom) ' appel recursif
         else
            if endWith(sNom, ".odt") then
                if not endWith(sNom,"_eleve.odt") then
                       if instr(sNom, "cours") > 0 then
                           call traiteFichier(sNom) ' on traite ce fichier
                       end if
                end if
            endif
        endif
    next sNom

end sub

function endWith(chaine, cherche)

    endWith = ( right(chaine, len(cherche)) = cherche)

end function

sub traiteFichier(urlFichier)

    ' ouverture
    doc = starDesktop.loadComponentFromUrl(urlFichier,"_blank",0, array())

    ' traitement des styles
    call RemplacerStylePartout2(doc)

    ' nom de fichier de sortie
    spliter = split(doc.url, ".") ' decoupe la chaine avec les points
    nb = ubound(spliter)
    spliter(nb-1) = spliter(nb-1)+"_eleve"

    spliter(nb)="pdf"
    newUrlPdf = join(spliter,".")

    spliter(nb)="odt"
    newUrlOdt = join(spliter,".")

    'enregistrement nouveau odt
    doc.storeAsUrl(newUrlOdt, array()) ' aucune option, array vide

    ' options de l'export pdf
    dim propsFiltre(0 to 0) as new com.sun.star.beans.PropertyValue
    propsFiltre(0).name = "IsSkipEmptyPages"
    propsFiltre(0).value = False

    dim prop(0 to 1) as new com.sun.star.beans.PropertyValue
    prop(0).name="FilterName"
    prop(0).value = "writer_pdf_Export"
    prop(1).name="FilterData"
    prop(1).value = propsFiltre()

    ' export pdf
    doc.storeToUrl(newUrlPdf, prop() )

    ' on ferme le fichier initial sans modification
    doc.close(false)

end sub

Sub RemplacerStylePartout2(MonDocument)

    Dim JeCherche As Object

    JeCherche = MonDocument.createReplaceDescriptor

    with JeCherche
      .SearchString = "Texte eleve visible"
      .ReplaceString = "Texte eleve invisible"
      .SearchStyles = true
    end with

    MonDocument.replaceAll(JeCherche)

End Sub

Un grand merci à Laurent G qui m'a fortement aidé!! Même si il a trouvé que
j'avais fait quasi toutes les routines plus ou moins fonctionnelles ça du
lui prendre 5min chrono en main pour terminer la macro...

Cette macro fonctionne il me faut ajouter la fonctionnalité de ne traiter
que les fichiers qui ont étaient modifié le X dernières heures cela dans le
but de ne pas traiter tous les fichiers de l'arborescense à chaque
traitement.
Il me faut l'adapter pour pouvoir l'executer sur un serveur (sans interface
graphique sous linux)
Âpres ça je documenterai un peu plus la macro avec des commentaires dedans
pour qu'elle puisse être réutilisés.

Merci beaucoup à tous ceux qui m'ont aidé!

Bonjour,
quelques nouvelles de la macro qui a encore un peu avancé grâce à votre
aide!

J'ai un ajouter la gestion du temps pour arriver à ne traiter que les
fichiers qui ont étaient édité les 24 dernières heures mais il me faut le
tester. Grâce à LG j'ai pu définir le filtrage par le mot cours sans
respecter la casse.
Mais j'ai un problème qui m'a donné mal à la tête cette après midi... le
filtrage ne se fait plus autrement dit tous les fichiers odt sont traité
alors qu'il ne devrai traiter que les fichiers qui contiennent le mot cours
(sans prendre en compte la casse).
Le problème étant que ça ne retourne aucun message d’erreur...du coup je
sèche un peu.

La macro complète via pastbin: http://pastebin.com/s9RMjp4H

Merci pour vos lumières.