IPB

Bienvenue invité ( Connexion | Inscription )

 
Reply to this topicStart new topic
> Script existant à "vitaminer", Mon script fonctionne mais est lent...
Options
Speed Moock
posté 21 Sep 2016, 07:08
Message #1


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Bonjour à tous,

J'ai fais un script pour aggréger des tableaux excels mais il fonctionne trop lentement.
Ce que fait le script :
- Il parcours un dossier dont les fichiers excels ont comme structure de nom : NOMSTUDIO numéro_incrément.xls
Tous les fichiers ont le même nombre de colonnes : de A à S mais un nombre de lignes variables. S'il y a des lignes vides, il ne faut pas les copier (en général je fais le ménage avant de lancer le script)
- A chaque fichier trouvé le script en copie le contenu et le colle dans un fichier listing.xls enregistré à l'extérieur du dossier.
- Il colle le contenu dans les colonnes B à T et rempli la colonne A avec NOMSTUDIO
- Ensuite il passe au fichier excel suivant et fait la même chose à la suite du bloc qu'il vient de coller.

Mes fichiers excels peuvent comporter jusqu'à 1000 lignes chacun et je peux avoir 15 fichiers maximum.
Au fur et à mesure de sa progression le script mouline. Parfois il n'arrive pas à terminer son travail...

Voici mon code :
set AppleScript's text item delimiters to {ASCII character (32)}
set vDossier to choose folder
set vFileDest to choose file
set vList to list folder of vDossier without invisibles
with timeout of 300 seconds
repeat with vFile in vList

set vFile to ((vDossier as string) & vFile) as alias
copierbloc(vFile, vFileDest)
end repeat
end timeout

on copierbloc(fichierSource, fichierDest)
set vNLG1 to Nbligne(fichierSource)
-- display dialog vNLG1 as string
set vNLG2 to Nbligne(fichierDest)
-- display dialog vNLG2 as string
set vSET to (text item 1 of (name of (info for fichierSource) as string))
tell application "Microsoft Excel"

set w1 to open workbook workbook file name (fichierSource as string)
set w2 to open workbook workbook file name (fichierDest as string)
set range1 to "A2:S" & ((vNLG1 + 1) as string)
set range2 to "B" & ((vNLG2 + 1) as string) & ":T" & ((vNLG1 + vNLG2) as string)
copy range range (range1) of sheet 1 of w1 destination range (range2) of sheet 2 of w2
set value of range (("A" & (vNLG2 + 1) as string) & ":A" & ((vNLG1 as integer) + ((vNLG2 as integer) - 1) as string)) of sheet 2 of w2 to vSET
close w1
close w2 saving yes
end tell
return
end copierbloc



on Nbligne(monfichier)
set last_line to 1
tell application "Microsoft Excel"
open monfichier as string
set vVal to get value of cell "B1"
repeat while vVal is not equal to ""
set last_line to (last_line + 1)
set vVal to get value of cell ("B" & last_line as string)
end repeat
end tell
close monfichier
set last_line to last_line - 1
return last_line as integer
end Nbligne


Voilà si vous savez vitaminer la bête ça serait top !

Merci
Go to the top of the page
 
+Quote Post
PBell
posté 21 Sep 2016, 13:06
Message #2


Adepte de Macbidouille
*

Groupe : Membres
Messages : 184
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Bonjour,
D'un point de vue AS, je dirai que tu perds du temps à chaque fichier car tu ouvres FichierDest, tu le modifies et tu l'enregistres à chaque fois.
Il semblerait plus judicieux de ne l'ouvrir qu'une seule fois et d'y coller successivement le contenu de chaque fichier.

Ensuite, à chaque itération, tu ouvres 2 fois les 2 fichiers : une fois pour la routine NbLigne, puis une seconde fois pour "set w1 to open workbook workbook file name..."
Ceci étant aussi vrai pour le fichier en cours, mais aussi pour FichierDest !

En corrigeant ces 2 points tu vas gagner beaucoup de temps :
1) Ouvre FichierDest une fois au début
2) A l'ouverture, tu comptes une seule fois le Nb de lignes et tu enregistres dans une variable POSITION la prochaine ligne vide (où sera le prochain "coller").
3) pour chaque fichier :
-- tu l'ouvres, tu comptes le nb de lignes, tu copies
-- tu te positionnes sur FichierDest à POSITION et tu colles
-- tu incrémentes POSITION du nombre de lignes que tu viens de copier/coller
-- tu fermes le fichier sans le sauver et tu passes au fichier suivant
4) Tu ferme une seule fois, à la fin du traitement de tous les fichiers, le fichier FichierDest en l'enregistrant.

Ceci étant, compte tenu de ce que tu fais, un script VB (macro Excel) serait encore plus simple et surtout bien plus performant qu'un AppleScript.
J'ai des scripts de ce type sur PC, avec des temps de traitement très courts pour quelques centaines de milliers de lignes (1 000 000 max!).

Cordialement


--------------------
iMac 27 i7 2,8GHz 8Go/1To 10.6.8 /10.10 / 10.11
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Speed Moock
posté 21 Sep 2016, 19:32
Message #3


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Salut,

Encore une fois merci PBell d'avoir pris le temps de décortiquer ma demande.

Je modifie mon script et te dis quoi (comme on dit dans le Nord).

Quant à VB oui j'imagine que ce serait idéal vu que je serais dans Excel lui même mais je ne connais pas - ou très peu - ce langage.

Merci
Go to the top of the page
 
+Quote Post
Speed Moock
posté 26 Sep 2016, 11:01
Message #4


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Bonjour,

Voici donc mon code allégé :

set AppleScript's text item delimiters to {ASCII character (32)}
set vDossier to choose folder
set vFileDest to choose file

set vList to list folder of vDossier without invisibles
tell application "Microsoft Excel"
open vFileDest
set vNLG2 to 0
set w2 to open workbook workbook file name (vFileDest as string)
with timeout of 300 seconds
repeat with vFile in vList
open vFile
set vFile to ((vDossier as string) & vFile) as alias
set vSET to (text item 1 of (name of (info for vFile) as string))
set vNLG1 to Nbligne(vFile)
set w1 to open workbook workbook file name (vFile as string)
set range1 to "A2:S" & ((vNLG1 + 1) as string)
set range2 to "B" & ((vNLG2 + 1) as string) & ":T" & ((vNLG1 + vNLG2) as string)
copy range range (range1) of sheet 1 of w1 destination range (range2) of sheet 2 of w2
set value of range (("A" & (vNLG2 + 1) as string) & ":A" & ((vNLG1 as integer) + ((vNLG2 as integer) - 1) as string)) of sheet 2 of w2 to vSET
set vNLG2 to vNGL2 + vNLG1
close w1
close vFile
end repeat
close w2 saving yes

display dialog "Traitement Terminé"
end timeout
end tell




on Nbligne(monfichier)
set last_line to 1
tell application "Microsoft Excel"
open monfichier as string
set vVal to get value of cell "B1"
repeat while vVal is not equal to ""
set last_line to (last_line + 1)
set vVal to get value of cell ("B" & last_line as string)
end repeat
end tell
close monfichier
set last_line to last_line - 1
return last_line as integer
end Nbligne


mais le script bloque sur la première commande NBligne avec le message d'erreur suivant "error "Erreur dans Microsoft Excel : Il est impossible de poursuivre Nbligne." number -1708"

Je ne trouve pas la raison.

Une idée ?

Merci
Go to the top of the page
 
+Quote Post
Speed Moock
posté 26 Sep 2016, 11:32
Message #5


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



En complément j'ai re-testé ma fonction NBligne avec le code suivant et ça fonctionne :

set vFileDest to choose file


set valeur to Nbligne(vFileDest)

display dialog valeur as integer





on Nbligne(monfichier)
set last_line to 1
tell application "Microsoft Excel"
set vFichierCourant to open workbook workbook file name (monfichier as string)
set vVal to get value of cell "B1"
repeat while vVal is not equal to ""
set last_line to (last_line + 1)
set vVal to get value of cell ("B" & last_line as string)
end repeat
set last_line to last_line - 1
close vFichierCourant
end tell
return last_line as integer
end Nbligne

Pourquoi ça na passe pas du coup quand je l'appelle dans mon code ?

Merci
Go to the top of the page
 
+Quote Post
PBell
posté 26 Sep 2016, 20:27
Message #6


Adepte de Macbidouille
*

Groupe : Membres
Messages : 184
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Bonsoir,
Je me suis penché plus à fond sur ton code. Outre les améliorations suggérées la dernière fois, que tu as mis en place, j'ai aussi regardé la méthode que tu utilises pour trouver le nombre de lignes du fichier destination et de chacun des fichiers à copier. Il y a beaucoup plus simple en utilisant les instructions Excel Applescript "count of rows" et "used range".

Cela fonctionne parfaitement, avec l'hypothèse (que tu as confirmée) que tu n'a pas de lignes vides dans tes fichiers !

Par ailleurs, tu sembles séparer le nom de tes fichiers avec un espace (code 32) soit "racine numéro" alors que ta demande initiale était sur des nom de la forme "racine_numéro".
J'ai donc utilisé "_" comme séparateur et non l'espace.

Enfin, j'ai ajouté, par sécurité, un filtre sur les fichiers du dossier via leur extension. J'ai fait aussi le test avec un dossier qui contient des fichiers non Excel: Comme prévus, ils ne sont pas traités. A toi de voir si tu veux changer ce filtre sur les "xlsx".

Voici donc mon code (proche du tiens), qui est testé et fonctionne chez moi. Comme d'habitude, avec beaucoup de commentaires :

CODE
set vFileDest to choose file -- fichier résultat
set vDossier to choose folder -- dossier contenant les fichiers Excel
tell application "Finder" to set ListeNoms to name of every file of vDossier whose name extension is "xlsx"
set AppleScript's text item delimiters to {"_"} -- separateur du nom de fichier

tell application "Microsoft Excel"
    -- ouvre le fichier destination et compte son nombre actuel de lignes
    set WDest to open workbook workbook file name (vFileDest as string)
    set DerLigne to count of rows of used range of active sheet --  tu n'a pas de lignes vides !
    set DerLigne to DerLigne + 1 -- la prochaine position de "coller"

    repeat with F in ListeNoms -- pour chaque fichier du dossier choisi
        set Racine to text item 1 of F
        set WSource to open workbook workbook file name (vDossier as string) & F
        set SourceL to count of rows of used range of active sheet
        set RangeSource to range ("A1:S" & SourceL) of sheet 1 of WSource -- le range à copier col A à S sur le nb de lignes
        set RangeDest to range ("B" & DerLigne & ":T" & (DerLigne + SourceL - 1)) of sheet 1 of WDest -- le range à coller B à T à partir de DerLigne
        copy range RangeSource destination RangeDest
        set value of range ("A" & DerLigne & ":A" & (DerLigne + SourceL - 1)) of sheet 1 of WDest to Racine
        set DerLigne to DerLigne + SourceL -- positionne la prochaine place du "coller"
        close WSource without saving
    end repeat -- fichier suivant
    close WDest saving yes -- fermeture finale avec sauvegarde
end tell


Cordialement

Ce message a été modifié par PBell - 26 Sep 2016, 20:28.


--------------------
iMac 27 i7 2,8GHz 8Go/1To 10.6.8 /10.10 / 10.11
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Speed Moock
posté 26 Sep 2016, 21:42
Message #7


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Bonsoir,

ça fonctionne génialement bien !

Pour que je puisse progresser pourquoi dans ma tentative de correction avais-je une erreur 1708 ?

Je ne fais pas bien la différence entre "open monfichier" et set WDest to open workbook workbook file name (monfichier as string)

Mon soucis vient peut-être de là ?

En tout cas merci pour le coup de main !
Go to the top of the page
 
+Quote Post
PBell
posté 27 Sep 2016, 06:06
Message #8


Adepte de Macbidouille
*

Groupe : Membres
Messages : 184
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Bonjour,
Ces 2 instructions me semblent effectivement faire doublons.
Cependant, lors de mes tests, je me suis aperçu que Excel est plutôt accomodant sur l'ouverture des fichiers.
En effect un "open workbook workbook file name xxx" ne perturbe pas Excel si le fichier est déjà ouvert: cela ne renvoie pas d'erreur alors que cela devrait indiquer une erreur "fichier déjà ouvert".

Donc ton problème vient peut être de là, mais je n'en suis pas sûr.

Cordialement


--------------------
iMac 27 i7 2,8GHz 8Go/1To 10.6.8 /10.10 / 10.11
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Lionel
posté 27 Sep 2016, 09:09
Message #9


BIDOUILLE Guru
*****

Groupe : Admin
Messages : 52 105
Inscrit : 14 Jan 2001
Lieu : Paris
Membre no 3



Souvent, quand je dois faire des scripts puis ensuite les optimiser, je fais appel à des commandes Shell qui sont incroyablement rapides pour manipuler des fichiers ou des contenus de fichiers.
Désolé, je n'ai pas le temps de me pencher dessus.


--------------------
C'est parce que la vitesse de la lumière est plus grande que celle du son que tant de gens paraissent brillants avant d'avoir l'air con
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 19th October 2018 - 17:00