Extraire les données des lignes; les séparer en colonnes
Bonjour,
En effet, les données de temps offert sont indépendantes au tableau de l'activité.
Ce 2e tableau comprendra donc :
Colonne A : Date
Colonne B: Chirurgien
Colonne C: Temps Offert
Les données de colonne C sont à collées à la fin du 1e tableau (ou associées d'une certaine façon) en respectant les conditions citées, à savoir :
jour férié, samedi et dimanche : pour tout le monde : TOffert : 0
Pour un seul chirurgien qui a plusieurs activités durant le même jour : donc plusieurs lignes,
TOffert sera, disons 10 heures sur une seule ligne et toutes les autres lignes de la même date seront = 0...
car imaginons qu'il a 2 intervention le vendredi 07/07/2017, donc deux lignes de données ...
disons qu'il dispose de 10 heures de bloc pour cette date,
donc le TOffert sera de 10 heures sur une seule ligne et non sur les 2 lignes ...
sinon le tableau lui renverra 20 heures de bloc si les deux lignes sont remplies
J'ai re re re lu les explications ... j'apprécie la pédagogie ... au moins je commence à comprendre !
Merci, Amitiés
A bientôt
Bonjour,
Je poursuis sur les données...
Recueil des données : la salle
Avec la salle, on se trouve dans des conditions analogues à la date, sans problème particulier d'identification de la ligne : elle débute par 'salle', on aura éliminé les lignes débutant par 'salle externe', donc on trouvera le numéro de salle après la mention 'salle', lequel permettra de composer l'indication de salle devant figurer au tableau final.
Pour les mêmes raisons que précédemment, on externalisera cette composition dans une fonction qu'il suffira de faire appeler par procédure principale.
Function SalleInterv(salle As String) As String
Dim s$
s = Replace(LCase(salle), "salle", "")
SalleInterv = "S" & Val(s)
End FunctionOn fournit à la fonction le texte de la ligne détectée. Cette dernière en supprime la mention 'salle' initiale, récupère le numéro de salle en utilisant la fonction VBA Val, qu'elle accole à un "S", et renvoie ce résultat.
[nb- La fonction Val s'avère bien utile dans nombre de situations pour récupérer une valeur numérique, elle transforme en valeur numérique les caractères situés au début d'un texte correspondant à des chiffres. S'il n'y en a pas, elle renvoie 0. Et elle ignore les espaces (ce qui justement peut s'avérer particulièrement pratique !) Cela n'est pas le cas ici mais elle peut renvoyer une valeur décimale, toutefois il faut savoir qu'elle ne reconnaît que le point comme séparateur décimal, on lui soumet donc dans ce cas une chaîne dans laquelle on transforme les virgules en points...]
l'heure
L'heure nous sert à détecter les lignes correspondant à une intervention est l'on a déjà vu le modèle de texte permettant de la détecter (en utilisant l'opérateur Like) : ##:##*. [Les modèles de texte utilisent des caractères génériques : # est un chiffre (0 à 9), ? est un seul caractère quelconque, * indique la présence possible d'un ou plusieurs caractères ou d'aucun.]
La détection d'une ligne heure nous indique que l'on va servir une ligne de notre tableau final d'interventions. On pourra donc commencer par incrémenter le tableau et lui affecter cet élément heure (de même que les éléments date et salle dont logiquement on dispose dans des variables).
Aucune manipulation particulière pour l'heure : on n'a qu'à prélever les 5 premiers caractères de la ligne détectée (après élimination des espaces à gauche) et affecter cette chaîne au tableau. Il s'agit d'un texte représentant une donnée horaire, mais l'on sait que ce texte affecté à une cellule sera automatiquement reconnu par Excel et transformé en valeur horaire.
le service
Tu avais initié une méthode consistant à relever sa présence dans la ligne de texte, sachant que le nombre de service est limité et que la liste peut en être prédéfinie pour le rechercher.
On va suivre cette voie et externaliser cette recherche dans une fonction qui renverra le service.
Function ServiceInterv(interv As String) As String
Dim sce, i%, svc$
sce = Split("Orthopédie Viscéral Gynécologie Gastro")
For i = 0 To UBound(sce)
If InStr(1, interv, sce(i), vbTextCompare) > 0 Then
svc = sce(i): Exit For
End If
Next i
ServiceInterv = svc
End FunctionOn forme un tableau des services susceptibles d'apparaître. La fonction Split est utilisée à cette fin.
[NB- Split transforme une chaîne en tableau d'éléments (tableau de base 0) en utilisant un séparateur inclus dans la chaîne. Le séparateur par défaut (qu'on peut alors omettre d'indiquer) est l'espace. Un autre séparateur (qui peut être un seul caractère, plusieurs, un mot, une expression...) sera indiqué en second argument de la fonction. L'intérêt indéniable de cette fonction permettant de transformer n'importe quel texte en tableau se trouve encore accru si l'on considère la fonction Join (dont on n'aura pas d'utilisation ici...) avec laquelle elle forme en quelque sorte un couple : Join fait l'opération inverse, tranformer un tableau en texte en introduisant un élément séparateur entre chaque élément du tableau...]
On boucle sur ce tableau des services. Et on recherche si le service indiqué se trouve dans la ligne de texte, au moyen de la fonction InStr, qui recherche la présence d'une sous-chaîne dans une chaîne et renvoie sa position (d'où le test consistant à vérifier que le renvoi de la fonction est >0).
[A noter que l'on ne s'est pas préoccupé de réduire la ligne de texte en caractères minuscules, la fonction disposant d'un paramètre permettant d'indiquer que l'on opère une comparaison de type Texte (ignorant la casse). La comparaison type Binaire, qui distingue majuscules et minuscules est le mode de comparaison par défaut de VBA...]
Quand on l'a trouvé, on l'extrait, on sort de la boucle et on le renvoie...
Je marque une pause (café) pour éviter les posts trop longs...
Hello,
Je fais vite avant que tu continues !
Tu écris :
Tu avais initié une méthode consistant à relever sa présence dans la ligne de texte, sachant que le nombre de service est limité et que la liste peut en être prédéfinie pour le rechercher.
et plus loin:
sce = Split("Orthopédie Viscéral Gynécologie Gastro")
NON. Au début vu ma méthodologie visuelle pas à pas, je me suis contenté de 4 services afin dé vérifier mon programme. Mais par la suite j'ai changé puisqu'il y a au moins 8 ou 9 services et je voulais une façon de travailler qui prend en considération même un service futur. Donc j'ai re-utilisé ma fonction SPLIT.
Voyons une ligne de ma base de données :
07:40 BRUNIER Jean louis 18/09/1934 BR - Orthopédie - Epaule prothèse totale Traumatique 3h27 C: ANTOINE JEAN-PAUL / AG + ALR/ droit/
Le service se trouve après BR -
Merci d'en tenir compte.
et merci pour le conseil ... c'est corrigé
amitiés
Salut vespéral !
J'ai pris une pause sur un autre sujet qui s'est avéré un peu plus long à traiter que prévu... Le débogage s'est prolongé en raison de 3 points de blocage dont les 2 premiers tenaient à des particularités du fichiers, le 3e à une erreur de ma part, de celles que j'ai qualifié d'erreurs simples (utilisation d'un tableau en oubliant de mentionner l'indice !). Mais il m'a fallu avancer pas à pas pour détecter chacun des 3 points de décrochage, en trouver la raison, et trouver le moyen de rectifier...
Je prends en note ta précision concernant le service, et je mets tout de suite une fonction pour le renvoyer, qui se substituera à la précédente établie.
Function ServiceInterv(interv As String) As String
Dim sce, i%
sce = Split(interv, "BR")(1)
sce = Trim(Replace(sce, "-", "", 1, 1))
ServiceInterv = Split(sce)(0)
End FunctionJe te laisse le soin de l'analyser si besoin est... Vais m'occuper de mon repas !
hello,
Ça m'a l'air d'être bien. Je commence à comprendre ... et à améliorer mes codes.
Le repas : il n'est que 18H40 !
Amitiés
Ça dépend où on se trouve !
Pour moi : UTC +4, soit actuellement 2 heures de plsu qu'en France métropolitaine...
Hello,
Ah oui! En effet je vois où tu es. Ça c'est une surprise ! Figures-toi que sommes (étions) voisins ... de 250 km. Je suis du côte de Nantes depuis plus de 37 ans maintenant ! Ça fait vieux
Maintenant je comprends mieux tes horaires ... je croyais que tu étais insomniaque !
En tout cas, c'est un plaisir d'échanger avec toi!
Ici il fait très chaud et lourd. OK pour ceux qui sont en vacances, ce qui n'est pas mon cas
Amitiés
Je dors très bien quand je dors, mais souvent pas aux heures habituelles !
Bon je vais essayer de m'y remettre !
hello,
oui ... tu chipotes
il est 00H52 demain chez toi!
bonne nuit
a bientôt
Je poursuis donc sur le recueil des données restantes...
le chirurgien
Comme le service, on le trouve dans la ligne d'intervention après l'indication 'C:'. Suivant toujours la même méthode, une fonction pourra également nous renvoyer le nom du chirurgien...
Function ChirurgInterv(interv As String) As String
Dim nchrg
nchrg = Split(interv, "C:")
nchrg = Split(Trim(nchrg(1)))
ChirurgInterv = nchrg(0)
End FunctionTu commences à être parfaitement à l'aise avec Split, il n'est donc guère utile que j'ajoute quelque explication...
la durée
Elle figure sur la ligne avant la mention 'C:'déjà utilisée pour localiser le nom du chirurgien. Elle peut apparaître sous diverses formes : la forme générale est un nombre d'heures suivi de 'h' suivi d'un nombre de minutes, mais le nombre de minutes peut faire défaut, ou bien le nombre d'heures et le 'h' peuvent faire défaut.
Il faudra donc récupérer l'indication représentative de l'heure et la remettre en forme sous un format horaire.
Function DuréeInterv(interv As String) As String
Dim h, m%
h = Split(interv, "C:")
h = Right(Trim(h(0)), 5)
If InStr(1, h, "h") > 0 Then
h = Split(h, "h"): m = Val(h(1)): h = Val(h(0))
Else
m = Val(h): h = 0
End If
DuréeInterv = h & ":" & m
End FunctionAprès récupération de la mention de durée, on en extrait nombre d'heures et nombre de minutes pour les réassembler. L'extraction se fait différemment selon que le 'h' est présent ou non.
[NB- On ne se préoccupe pas plus du format de la chaîne renvoyée : que la partie heures ou la partie minutes de part et d'autre des deux-points ait un chiffre ou deux, Excel opèrera une conversion horaire et mettra la cellule au format hh:mm. Pour respecter les règles typographiques en matière d'indication de durée, il conviendra d'ailleurs de modifier ce format en h:mm...]
On a omis au passage le type d'intervention, Urgence ou Programmée. On le détecte lors de la reconnaissance d'une mention horaire en début de ligne de texte, en testant la ligne suivante de façon à ajuster la ligne sur laquelle trouver les données propres à l'intervention, ce qui nous indique en même temps le type. Il suffira donc alors de l'indiquer dans notre tableau final.
Tout ayant été examiné, il ne nous reste donc plus qu'à écrire le code de la procédure principale, ce qui s'évèrera facilité par le fait qu'elle pourra faire appel aux 6 fonctions que nous avons établies lors de l'examen des conditions dans lesquelles les données pourront être recueillies.
OK !
hello
une autre époque ...
bon c'est vrai que je ne me rappelle de rien
bye
Attaquons le code de la procédure principale : (je vais procéder pas à pas, de la façon dont je procède en écrivant une procédure)
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
For ln = 1 To dln
Next ln
End With
End SubLa cadre est posé ! Déclaration des variables, mise sous bloc With de la feuille contenant le texte à traiter [NB- c'est toujours un élément des plus important de la rapidité d'exécution du code...], détection de la dernière ligne de texte en A, initialisation d'une boucle allant de la ligne 1 à cette dernière.
NB- En prenant l'habitude en ce qui concerne les instructions composites, comportant une instruction d'initilisation et une instruction de fin (comme ici With... End With ou For... Next) d'écrire le début et la fin simultanément (en veillant naturellement que l'indentation des deux morceaux soit la même), on élimine de fait une source potentielle d'erreurs...
On poursuit en plaçant dans la boucle initiée le recueil de la ligne de texte, et les tests à appliquer à cette ligne.
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
For ln = 1 To dln
lgn = LTrim(.Cells(ln, 1))
If lgn <> "" Then
If LCase(lgn) Like "remise*" Or LCase(lgn) Like "saisie*" Or _
LCase(lgn) Like "salle externe*" Then
ElseIf lgn Like "##:##*" Then
ElseIf LCase(lgn) Like "salle*" Then
ElseIf EstDateInterv(lgn) Then
End If
End If
Next ln
End With
End SubJe surligne le code ajouté à chque étape... On a donc récupéré la ligne de texte dans une variable, en en supprimant les espaces à gauche, puis posé les instructions décisionnelles telles qu'on les a préalablement définies. On a le cadre de tests à effectuer pour détecter les lignes utiles et les identifier : on ignore les lignes vides, on teste si le début du texte doit également nous conduire à ignorer la ligne, puis viennent 3 tests successifs pour identifier si l'on sur une ligne intervention, une ligne salle ou une ligne date.
On va tour à tour remplir pour ces 3 tests, ce qu'il y a lieu de faire s'il sont positifs.
NB- Le cas se produisant ci-dessus, il n'est peut-être pas inutile de noter en matière d'écriture de code que : une ligne se terminant par espace suivie de underscore indique que la ligne de code se poursuit à la ligne physique suivante. A l'inverse le caractère deux-points (hormis s'il est intégré à l'instruction) est un séparateur permettant d'écrire deux lignes de code ou plus sur la même ligne physique.
A noter que le test de détection d'une ligne date utilise la fonction établie à cette fin.
A suivre...
Pour suivre l'ordre logique en termes de raisonnement, on s'occupera d'abord de la détection d'une ligne date.
Dans ce cas on doit simplement stocker la date dans une variable, et nous avons établi une fonction pour ce faire.
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
For ln = 1 To dln
lgn = LTrim(.Cells(ln, 1))
If lgn <> "" Then
If LCase(lgn) Like "remise*" Or LCase(lgn) Like "saisie*" Or _
LCase(lgn) Like "salle externe*" Then
ElseIf lgn Like "##:##*" Then
ElseIf LCase(lgn) Like "salle*" Then
ElseIf EstDateInterv(lgn) Then
d = DateInterv(lgn)
End If
End If
Next ln
End With
End SubOn continue avec la détection d'une ligne salle. Comme pour les dates, on doit stocker l'information dans une variable et nous avons établi une fonction à cette fin.
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
For ln = 1 To dln
lgn = LTrim(.Cells(ln, 1))
If lgn <> "" Then
If LCase(lgn) Like "remise*" Or LCase(lgn) Like "saisie*" Or _
LCase(lgn) Like "salle externe*" Then
ElseIf lgn Like "##:##*" Then
ElseIf LCase(lgn) Like "salle*" Then
s = SalleInterv(lgn)
ElseIf EstDateInterv(lgn) Then
d = DateInterv(lgn)
End If
End If
Next ln
End With
End SubNe reste plus que le cas des lignes interventions à la détection d'un texte débutant par une heure : dans ce cas nous avons une ligne de notre tableau à servir. On commence donc par incrémenter la variable dédiée à cet effet et redimensionner le tableau pour lui ajouter une nouvelle ligne (en préservant les données déjà affectées).
On peut déjà alimenter cette nouvelle ligne par les éléments dont on dispose déjà : l'heure (que l'on vient de trouver), mais également la date et la salle (stockées à partir de lignes antérieures), en plaçant ces infos dans les bonnes colonnes.
Il nous faudra tester sur quel type d'intervention on est (test sur la ligne immédiatement suivante) de façon à définir sur quelle ligne de texte trouver les autres informations pour notre ligne de tableau. On initie l'instruction décisionnelle.
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
For ln = 1 To dln
lgn = LTrim(.Cells(ln, 1))
If lgn <> "" Then
If LCase(lgn) Like "remise*" Or LCase(lgn) Like "saisie*" Or _
LCase(lgn) Like "salle externe*" Then
ElseIf lgn Like "##:##*" Then
i = i + 1: ReDim Preserve Itv(6, i)
Itv(5, i) = Left(lgn, 5): Itv(0, i) = d: Itv(1, i) = s
If LCase(.Cells(ln + 1, 1)) Like "*urgence*" Then
Else
End If
ElseIf LCase(lgn) Like "salle*" Then
s = SalleInterv(lgn)
ElseIf EstDateInterv(lgn) Then
d = DateInterv(lgn)
End If
End If
Next ln
End With
End SubSi l'on est dans le type Urgence, il y a lieu de le noter à son emplacement dans la ligne du tableau, et il nous faut également incrémenter la boucle sur les lignes de texte pour substituer dans notre variable texte de la ligne celui de la ligne suivante (et la boucle générale se poursuivra alors sur la ligne suivant cette dernière, sans repasser sur celle-ci...)
Si l'on n'est pas dans le type Urgence, c'est qu'on est dans le type Programmée, et il n'y a alors qu'à noter cette indication à son emplacement dans la ligne du tableau.
Dans les deux cas la variable ligne de texte contient le texte de la bonne ligne et l'on pourra y prélever les informations encore manquantes : service, chirurgien et durée (pour lesquelles on dispose de fonctions).
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
For ln = 1 To dln
lgn = LTrim(.Cells(ln, 1))
If lgn <> "" Then
If LCase(lgn) Like "remise*" Or LCase(lgn) Like "saisie*" Or _
LCase(lgn) Like "salle externe*" Then
ElseIf lgn Like "##:##*" Then
i = i + 1: ReDim Preserve Itv(6, i)
Itv(5, i) = Left(lgn, 5): Itv(0, i) = d: Itv(1, i) = s
If LCase(.Cells(ln + 1, 1)) Like "*urgence*" Then
Itv(3, i) = "Urgence"
ln = ln + 1: lgn = LTrim(.Cells(ln, 1))
Else
Itv(3, i) = "Programmée"
End If
Itv(2, i) = ServiceInterv(lgn)
Itv(4, i) = ChirurgInterv(lgn)
Itv(6, i) = DuréeInterv(lgn)
ElseIf LCase(lgn) Like "salle*" Then
s = SalleInterv(lgn)
ElseIf EstDateInterv(lgn) Then
d = DateInterv(lgn)
End If
End If
Next ln
End With
End SubA ce stade on a parcouru toutes les lignes de la feuille, on peut en sortir, il ne nous restera plus qu'à finaliser le tableau et l'affecter...
A suivre...
Bonjour,
La première partie de la procédure est terminée : nous avons parcouru le texte, extrait les informations voulues pour constituer un tableau des interventions tel qu'on l'avait projeté.
Ce que l'on peut constater, c'est que cette opération a été réalisée avec un volume de code somme toute assez réduit ! Et il est clair que ce résultat est dû à l'externalisation de diverses opérations d'extraction sur des fonctions dédiées qui, intégrées à la procédure principale auraient pour le moins doublé le volume de code écrit...
On peut certes dire que si du code a été basculé dans diverses autres procédures au lieu d'être concentré dans une procédure unique, globalement il n'y en a pas moins... Certainement ! Le gain n'est pas à ce niveau, les opérations qu'il convenait de faire pour parvenir au résultat demeurent, il fallait bien en écrire le code... mais en procédure ainsi, on obtient une procédure principale épurée dont la structure apparaît plus simple et plus claire et dont il sera plus facile d'assurer le bon fonctionnement.
Qu'une erreur survienne, et on saura immédiatement sans avoir à le chercher si l'erreur se situe dans le code de la procédure principale ou concerne l'une ou l'autre des opérations externalisées, et l'on sera à même de passer immédiatement à la recherche d'une solution au bon endroit en faisant l'économie d'une localisation exacte de l'erreur qui n'apparaît pas toujours avec évidence.
Et ce découpage permet de même de modifier plus facilement le code si des modifications doivent être apportées...
Mais reprenons le fil pour poursuivre la procédure jusqu'à son terme. Cette première partie étant bouclée, il nous reste, nous l'avons dit à finaliser le tableau des interventions.
Le tableau constitué est de base 0, il comporte une ligne d'indice 0 que nous avons laissé de côté pour y placer les en-têtes, ce que nous allons faire afin de finaliser le tableau.
Ensuite il conviendra de l'affecter à une feuille de calcul, sans quoi son utilité resterait purement virtuelle car présent en mémoire il ne serait pas pour autant visible !
On connaît la taille du tableau, 7 colonnes (indices 0 à 6), la dernière ligne au fil de la construction a été incrémentée avec la variable i, qui contient donc toujours l'indice de cette dernière ligne (donc indices lignes de 0 à i), le nombre de lignes s'établit donc à i+1.
Le tableau étant sous la forme (colonnes, lignes), pour l'avoir sur la feuille en [lignes, colonnes] il faudra le transposer...
La méthode est simple et rapide, de celles dont on ne dispose pas en travaillant manuellement dans Excel, mais que VBA nous permet d'utiliser : on dimensionne la plage nécessaire pour accueillir le tableau et on y affecte le tableau transposé, de cette façon chaque cellule de la plage prendra la valeur d'un élément du tableau.
Sub RecueilInterventions()
'[...]
Itv(0, 0) = "Date": Itv(1, 0) = "Salle": Itv(2, 0) = "Service": Itv(3, 0) = "Urg./Progr."
Itv(4, 0) = "Chirurgien": Itv(5, 0) = "Heure": Itv(6, 0) = "Durée"
Application.ScreenUpdating = False
With Worksheets.Add(after:=Worksheets("Feuil1")).Range("A1").Resize(i + 1, 7)
.Value = WorksheetFunction.Transpose(Itv)
End With
End SubInutile de reprendre la première partie qui était désormais complète, l'introduction des libellés d'en-têtes complète le tableau.
Ensuite, nous avons fait le choix d'affecter le tableau sur une nouvelle feuille, ajoutée pour l'occasion. On pourrait faire de même sur une feuille existante, ce qui n'entraîne que des modifications mineures...
Ce qui est plus important à constater, c'est que nous dimensionnons la plage d'affectation sur la feuille ajoutée (à partir de A1, i+1 lignes et 7 colonnes) en la mettant sous bloc With, de façon à s'y référer pour toutes les opérations suivantes, à commencer par la première qui est l'affectation du tableau transposé.
Il faut noter également que tout ce que nous avions fait antérieurement n'avait aucun effet sur l'affichage à l'écran, on ne s'en est donc pas préoccupé. Par contre ajoutant une feuille, Excel en fait automatiquement la feuille active, et on écrit sur cette feuille, ce qui aura alors un effet sur l'affichage. D'où l'instruction d'inhibition de la mise à jour de l'affichage pour éviter que cela ralentisse l'exécution de la procédure...
A noter aussi, on l'a déjà souligné mais on n'insistera jamais trop là-dessus, si le code permettant de dimensionner la plage cible et d'y affecter le tableau occupe peu de place (moins qu pour toute autre méthode), son exécution en est aussi plus rapide. La méthode n'est pas seulement utilisable pour affecter un tableau à une plage, on peut de la même façon affecter une plage à une autre plage de même taille (plage2.Value = plage1.Value), ou en écraser les formules pour ne conserver que les valeurs (plage.Value = plage.Value). Plus simple et plus rapide que tout copier-coller vers lequel on a tendance à se tourner en pareil cas. Méthode à privilégier dès lors que ce que l'on transfère ou reproduit sont des valeurs.
Il va encore nous rester un aspect à programmer, à l'intérieur de notre bloc With, la mise en forme du tableau...
Pour en terminer avec cette procédure, il nous reste à la compléter par la mise en forme du tableau une fois ce dernier affecté.
Deux éléments de mise en forme sont impliqués par l'affichage voulu de certaines données : la colonne date à mettre au format jjjj jj/mm/aaaa et la colonne durée à h:mm. Il s'agit donc de définir le format de cellule adéquat dans ces deux colonnes (on n'a pas besoin de se préoccuper de ne pas l'appliquer à la ligne 1 contenant du texte, car si le format défini ne peut être appliqué à la valeur, il ne le sera tout simplement pas !)
En ce qui concerne la première ligne on va suivre le modèle que tu as établi... : augmenter la hauteur de ligne, centrer les libellés verticalement et horizontalement, colorer les cellules en jaune.
Egalement mettre des bordures sur l'ensemble du tableau.
Enfin, les mentions étant susceptibles de ne pas tenir dans des colonnes de largeur standard, on provoquera un ajustement automatique (quite à revenir par la suite à une définition plus individuelle de la largeur de chaque colonne si l'on estime que l'automatisme n'est pas satisfaisant du point de vue esthétique).
En la matière, les choix pouvant être très divers et subjectifs, il conviendra de procéder à des essais, voir les résultats, et modifier jusqu'à atteindre la présentation correspondant le mieux à ce que l'on souhaite...
Du point de vue méthodologique, il faut noter que l'on va opérer le codage, à la suite de l'affectation, dans un bloc With dont l'objet de référence est la plage affecté dans sa totalité. On se trouve donc en adressage relatif par rapport à cette plage, mais du fait que la plage débute en A1, l'adressage des cellules par rapport à la plage demeure identique à celui fait par rapport à la feuille entière.
Toutefois lorsqu'on désignera des lignes (.Rows(1)) ou des colonnes (.Columns(1)), leur extension sera limitée à la plage et ne s'étendra pas à toute la feuille...
Sub RecueilInterventions()
'[...]
Itv(0, 0) = "Date": Itv(1, 0) = "Salle": Itv(2, 0) = "Service": Itv(3, 0) = "Urg./Progr."
Itv(4, 0) = "Chirurgien": Itv(5, 0) = "Heure": Itv(6, 0) = "Durée"
Application.ScreenUpdating = False
With Worksheets.Add(after:=Worksheets("Feuil1")).Range("A1").Resize(i + 1, 7)
.Value = WorksheetFunction.Transpose(Itv)
.Borders.Weight = xlThin
With .Rows(1)
.RowHeight = 40
.Interior.Color = vbYellow
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
.Columns(1).NumberFormat = "dddd dd/mm/yyyy"
.Columns(7).NumberFormat = "h:mm"
.Columns.AutoFit
End With
End SubVoilà !
Reste ensuite selon les choix que l'on fera pour lancer cette opération à affecter éventuellement cette procédure à un bouton.
(Je l'ai fait dans le fichier modèle fourni avec un bouton sur Feuil2.)
Je rappelle aussi mes préconisations visant à rendre son utilisation plus souple et sans avoir à y apporter la moindre modification liée au contexte d'utilisation, en lui adjoignant une procédure de lancement, qui la lancera en lui passant la feuille sur laquelle intervenir (ce qui implique que la procédure soit doté d'un argument de type Worksheet, repris comme objet sur lequel elle intervient dans la procédure, modification très minime et rapide...)
Autre considération pour le cas où l'on souhaite mesurer l'efficacité de la procédure ainsi établie, notamment si l'on veut comparer avec d'autres procédures alternatives, on mesure alors la durée d'exécution, plusieurs fois car des variations sont toujours susceptibles d'intervenir... Pour ce faire, on ajoute une variable (de type Single de préférence, l'accès aux variables typées étant plus rapides qu'aux variables de type Variant) que l'on initialise avec la fonction Timer, qui renvoie le temps système en secondes compté à partir de minuit (00:00:00), ce en tout début de macro, et en fin de macro on affiche un MsgBox : (Timer - t) * 1000, t étant la variable initialisée au départ. On obtient ainsi la durée d'exécution en millisecondes.
La procédure qui vient d'être construite s'exécute donc entre 47 et 62 millisecondes, la moyenne s'établissant donc autour de 56 millisecondes. Ce qui paraît relativement satisfaisant
Cordialement.
NB- On peut envisager quelques modifications pour obtenir un tableau plus étoffé selon les utilisations ultérieures que l'on souhaite en faire, ou bien s'agissant de deux aspects disjoints s'en tenir là pour le tableau issu de l'extraction et le reprendre dans le cadre de son utilisation avec d'autres procédures... Tous les choix demeurent ouverts.
hello
merci, infiniment
ceci dit, il y a un problème :
dans ma base de données il y a 41885 lignes
et ton programme coince ici :
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%, t!
t = Timer
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Row
et quand je diminue à 25000 lignes
il bloque à:
Function ChirurgInterv(interv As String) As String
Dim nchrg
nchrg = Split(interv, "C:")
nchrg = Split(Trim(nchrg(1)))
désolé ... j'ai testé plusieurs fois
ne t'en fait pas
ce n'est pas urgent
merci
amitiés
Bonjour,
De façon générale quand tu as une erreur d'exécution, il faut indiquer : le numéro de l'erreur, la ligne de code sur laquelle elle apparaît (surlignée en jaune lorsque tu cliques sur Débogage), et selon les cas, les valeurs des variables au moment de l'erreur (il suffit tant que tu es en mode Arrêt de survoler les noms des variables à la souris pour que leur valeur s'affiche dans une info-bulle).
Ceci dit si tu m'annonces 41885 lignes ! il n'y a pas à chercher !! C'est une erreur 6 et tu vas remplacer dans les déclarations de variables : ... i%, ln%, dln%... par i&, ln&, dln&
c'est à dire qu'on les passe de type Integer à type Long (le type Integer couvre les nombre entiers de -32768 à 32767, la raison de l'erreur est donc là tout à fait évidente).
J'en profite pour t'indiquer que dans les déclarations de variables :
i% équivaut à : i As Integer
i& équivaut à : i As Long
s$ équivaut à : s As String
t! équivaut à : t As Single
%, &, !, $ sont ce que l'on nomme des caractères de déclarations de type, cela permet de réduire de façon assez conséquente l'écriture des déclarations...
(il existe encore # pour As Double et @ pour As Currency).
[t! tu peux le supprimer, oubli après mes mesures de temps d'exécution... Remarque que pour 40000 je suis intéressé à savoir en combien de temps on réalise l'opération ! mais une fois qu'il n'y aura plus d'erreur !
On était resté à un nombre de lignes réduit, sans quoi dès quelques milliers j'aurais passé les variables à Long (divers essais ayant montré que contrairement à ce qu'à pu dire Microsoft sur le sujet l'exécution est plus rapide avec des variables Long qu'avec des Integer, même en restant dans une plage couverte par le type Integer...)
Pour la 2e erreur par contre, il faut indiquer le numéro de l'erreur, qui peut être une erreur 9 (si le C: manque) mais il y d'autre possiblité et essayer de récupérer la valeur de ln au moment de l'erreur (l'erreur se produit dans la fonction mais la procédure appelante est en cours et on devrait pouvoir récupérer cette valeur de la façon que j'ai indiquée).
Ce qui fournira la ligne de texte sur laquelle cette erreur est provoquée, car c'est là que l'on trouvera la raison de l'erreur : variante non prise en compte, qu'il faudra donc essayer d'intégrer, ou élément atypique non rencontré jusqu'ici et pour lequel il faudra éliminer la prise en considération de la ligne ou surmonter l'erreur pour qu'elle ne bloque pas le déroulement...
Mais il faut savoir ce qu'il en est !
Ta feuille texte est une source de données, mais je ne saurais l'appeler base ! Par contre le tableau constitué à partir de cette source est lui susceptible de constituer une base de données...
Réglons d'abord cette erreur... et je te proposerai d'examiner la suite : savoir s'il est plus rationnel d'ajouter une colonne ou introduire autrement l'élément temps imparti au chirurgien (ce qui dépend de sa signification au regard de chaque intervention considérée individuellement, telles qu'elles sont listées dans le tableau constitué, et de l'utilisation que tu entends en faire...)
Cordialement.
hello,
au début :
Sub RecueilInterventions()
Dim Itv(), lgn$, s$, d, i%, ln%, dln%, t!
t = Timer
With Worksheets("Feuil1")
dln = .Cells(.Rows.Count, 1).End(xlUp).Rowça n'a pas marché : erreur '6' dépassement de capacité
j'ai apporté la modification :
Dim Itv(), lgn$, s$, d, i&, ln%, dln%, t!même erreur
re modification
Dim Itv(), lgn$, s$, d, i&, ln&, dln%, t!même erreur
re re modification
Dim Itv(), lgn$, s$, d, i&, ln&, dln&, t!erreur '9'
Function ChirurgInterv(interv As String) As String
Dim nchrg
nchrg = Split(interv, "C:")
nchrg = Split(Trim(nchrg(1)))
ChirurgInterv = nchrg(0)
End Function2e: tu m'as demandé de vérifier le temps ... quand ça marche. Comment tu fais pour vérifier ce temps?
3e : pour le temps offert au chirurgien, ce ne sera pas nécessaire, je ferai un tableau séparé.
Merci et bonne nuit
(un peu épuisé ce soir, car j'ai opéré non stop depuis mardi dernier, samedi et dimanche compris, et ça continue demain !
Pas la peine de t'y reprendre à 3 fois pour ajuster les types de variables...
Pour l'erreur suivante : erreur 9, ce qui était la principale possibilité, ce qui signifie a-priori que l'élément 1 de nchrg(1) n'existe pas, et s'il n'existe pas c'est que le Split sur "C:" n'a pas eu l'effet normal prévu.
Donc pendant que ta ligne est surligné en jaune, un petit coup de roulette pour descendre plus bas dans le code, à la proc. principale: RecueilInterventions, et tu positionnes le curseur sur le premier ln que tu vois, soit dans la ligne de déclaration des variable, et une info-bulle t'affichera : ln&= suivi d'un nombre, qui est la valeur de ln au moment de l'erreur, et qui est en même temps la ligne du texte sur laquelle on a buté.
Il ne reste plus alors qu'à se rendre sur la feuille texte, trouver la ligne en question, et y chercher ce qui a pu provoquer la non détection du nom du chirurgien.
La probabilité serait qu'il manque le "C:" ou les deux-points, mais il faut s'en assurer...
Cordialement.
hello,
En effet tu as raison.
Ma liste de 2016 comprend 85321 lignes. Je l'ai passée dans mon système et après 45 minutes (!) la liste s'est bloquée quelque part vers le 27/03/2016.
Je n'ai fait que supprimer la période du 26/03/2016 au 31/03/2016 et j'ai inséré la même période sans vérifier le contenu , et j'ai repassé la liste dans ton système .... et ça a marché! A mon avis c'était un problème de copier-coller (erreur de frappe de ma part). Désolé. En, tout cas ça marche. Merci +++
Pour le temps mis = 85321 lignes = 1937,5 (je suppose millisec)
Amitiés