Comparer et remplacer
Bonjour à toutes et tous !
Il est un moment où il faut bien se rendre à l'évidence ; nos petites compétences sont dépassées et, humblement, il nous faut requérir l'assistance d'autrui.
Je vous tends donc la main et vous détaille la démarche entreprise jusqu'ici (bah oui, j'y ai quand même consacré quelques heures de recherches/essais avant de venir vous embêter).
Je possède un fichier caisse au format Excel dans lequel sont répertoriés des articles. Il se constitue d'environ une 10aine de colonnes et un peu plus de 7000 lignes, où chaque ligne est un article.
De temps en temps, il faut bien remplir la boutique et les gentils fournisseurs (au nombre de deux) m'envoient le contenu de ma commande sous la forme d'un fichier Excel. On reste sur du classique : 1 article = 1 ligne, un petit paquet de colonnes.
Je précise que le nombre et le contenu des colonnes est bien évidemment différent entre mes trois fichiers (un Bon de Livraison par fournisseur et mon fichier caisse). Bah oui, sinon ça serait trop simple.
Exemples au hasard :
Fichier 1 - col A désignation, B prix HT, C quantité, D EAN, ...
Fichier 2 - col A quantité, B désignation, C EAN, D prix TTC, ...
Bref, vous avez compris.
Mon besoin : j'aimerais mettre à jour les prix dans mon fichier caisse, en sachant que je ne commande pas les 7000 articles à chaque fois, captain obvious.
Mon idée est de scanner chaque EAN du fichier caisse et tenter de le trouver dans les BL. Il y est ? Wunderbar, on compare le prix dans la colonne idoine. S'il est différent, on écrase. S'il est identique, on ne fait rien. Paf, EAN suivant. Et tout ça tant qu'il y a des EAN.
Notez que comme le nombre de cycles est quand même faible (un peu plus de 7000) on pourrait envisager d'écraser dès qu'on trouve l'EAN, sans s'embêter à comparer. En terme de nombre de cycles/puissance nécessaire, c'est un peu risible dans un cas comme l'autre. Mais je me trompe peut-être...
Comment je m'y suis pris jusqu'à présent ?
N'ayant pas les compétences requises pour des macros ou du VBA, j'essaie de gérer ça via des formules.
Étape 1
Dans le fichier de caisse, j'ai créé une feuille2 où j'effectue une recherchev en prenant comme critère l'EAN présent dans la feuille1 colonne F et qui renvoie le prix d'achat HT issu de la matrice du BL. La colonne A de la feuille 2 du fichier caisse reçoit les résultats du BL n°1, la colonne B ceux du BL n°2.
Voici la formule :
=SIERREUR(RECHERCHEV('feuille1'!F2; '[BL1.xlsx]BL 509595'!$C$2:$G$500;5;FAUX);""Et ça marche bien. Mes colonnes A et B comportent donc beaucoup de cellules sans résultat apparent ("" dans la formule ci-dessus pour ne pas avoir des #N/A partout) et quelques chiffres épars (en €, monétaire 2 décimales).Étape 2
Ensuite je pensais tout fusionner dans une troisième colonne, la C. Je n'ai pas encore mis cela en place, je voulais d'abord me consacrer à l'étape 3.
Étape 3
Là où je bloque, c'est pour intégrer ces résultats sur ma première feuille du fichier caisse.
J'avais dans l'idée d'utiliser cette formule
=SI(feuille2!C2="";C2;feuille2!C2)En somme, si la cellule dans la feuille 2 n'affiche rien, je laisse la valeur actuelle en place. Dans le cas contraire, on écrase avec la valeur trouvée à l'étape 1.
Et là, vous riez déjà tous. Bah oui, j'envisageais "C2" comme un résultat et non comme une cellule. Du coup, en y incorporant une formule la mentionnant, paf, une belle boucle !
Auriez-vous, chers amis, une idée pour solutionner tout cela ?
Je suis ouvert à tout : un fichier Excel intermédiaire, un CMD, batch ou même EXE externe, des boutons exécutant des macros dans le fichier caisse, ...
Je vous joins le fichier caisse et un BL. Les données qui m'importent sont en rouge. j'ai masqué certaines colonnes dans les deux fichiers, pour faciliter la lisibilité. J'ai aussi supprimé la moitié des lignes et colonnes dans le fichier caisse pour qu'il soit plus léger.
Au plaisir de vous lire,
Jonathan
PS : Vous l'aurez compris, je suis quelqu'un de littéraire et non "matheux". J'espère ne pas vous avoir perdu ni ennuyé avec mon post fleuve.
- Messages
- 3'678
- Excel
- 365, 2019
- Inscrit
- 11/04/2020
- Emploi
- Formateur bureautique, dvpt de fichiers
Bonjour,
Ce que tu pourrais essayer de faire, qui resterait facile d'utilisation en l'état actuel de tes connaissances, c'est peut-être ceci. Tu mets cette formule à la place de l'autre :
=SIERREUR(RECHERCHEV('feuille caisse'!F2; 'C:\Users\Nickname\Desktop\[BL1.xlsx]BL 509595'!$C$2:$G$500;5;FAUX);'feuille caisse'!C2)Ainsi, s'il trouve une correspondance, il met le nouveau prix, sinon l'ancien.
Tu as donc tous tes prix actualisés. Tu copies ces cellules, et tu les colles dans la colonne C de ta feuille de caisse. Mais tu colles uniquement les valeurs. Tu n'auras ainsi que les résultats et plus les formules. Et normalement le tour est joué.
Bonjour,
Merci infiniment pour ta réponse rapide et efficace. Pas de doute, tu portes bien ton pseudo. ;)
Connaitrais tu un moyen "'d'automatiser" la copie et le collage des valeurs depuis la feuille de résultats vers la feuille de caisse ? Du style appui sur un bouton ?
- Messages
- 3'678
- Excel
- 365, 2019
- Inscrit
- 11/04/2020
- Emploi
- Formateur bureautique, dvpt de fichiers
C'est effectivement possible.
Mais ça amènerait à une certaine rigueur. Pour le moment, vu que tu bidouilles entre plusieurs feuilles de plusieurs fichiers, que tes données ne sont pas dans des tableaux structurés, etc ... Je ne suis pas sûr que ça soit une super idée, surtout que tu ne fais pas ça plusieurs fois par jour.
De fait. Je comprends ton point de vue.
Cela dit, comme une jeune collègue devra manipuler aussi ce fichier et que je suis un rien opiniâtre, j'ai commencé à chercher des solutions.
Voilà où j'en suis
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
Dim F1 As Worksheet
Dim F2 As Worksheet
Dim i As Long
Dim j As Long
Set F1 = Sheets("feuille caisse")
Set F2 = Sheets("Resultat")
xSheet.Range(Columns("A").Select).Copy
xSheet.Range(Columns("C").Select).PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Application.ScreenUpdating = True
End SubBon, c'est sûrement truffé de bugs, je ne l'ai pas encore exécuté. J'en suis à comprendre la formule de base que j'ai trouvé et à l'adapter.
Après, je comprendrais que tu te tiennes à ton avis exprimé ci-dessus et me laisses me débattre avec mon obstination. ;)
- Messages
- 3'678
- Excel
- 365, 2019
- Inscrit
- 11/04/2020
- Emploi
- Formateur bureautique, dvpt de fichiers
Alors essaie plutôt ainsi :
Private Sub CommandButton1_Click()
Dim F1 As Worksheet, F2 As Worksheet
Set F1 = Sheets("feuille caisse")
Set F2 = Sheets("Resultat")
F1.Range("C:C").Value = F2.Range("A:A").Value
End SubM'enfin tu n'as pas les mêmes en-têtes, et d'autres problèmes peuvent surgir. Mais c'est en forgeant qu'on devient forgeron paraît-il :)
Je vois ce que tu veux dire pour les entêtes.
Mieux vaut définir alors une plage ce cellules du genre "C2:C20000" plutôt que la colonne entière. Et ça économisera surement du temps processeur.
Bien sûr, le défaut ici est que je dois prévoir une plage qui ne va pas laisser sur le carreau des données quand mon fichier sera obèse dans 10 ans et que j'aurai oublié comment faire ! J'imagine qu'il serait possible d'ajouter un marqueur qui scrollerait le document (genre une boucle tant qu'il y a du texte en A, le marqueur prend +1) et inclure cette valeur dans la plage "C2:Cxxxxx".
Je verrai si mes pérégrinations sur le web me permettent de mettre un point cette boucle et si oui, je viendrai la poster ici.
Pour le moment, en prévoyant 20000 lignes je pense être large. Merci encore pour toute ton aide !!!!
Je termine le fichier cette aprem' avant de passer le sujet en résolu. :)
Bon, je tombe une fois de plus sur un os.
Si je suis parvenu à rapidement obtenir ma dernière ligne via la formule
derniereLigne = F1.Range("A" & Rows.Count).End(xlUp).Row + 1Je ne trouve aucune méthode pour insérer la valeur de "derniereLigne" dans les deux Range ci dessous à la place de CXXXXXX et AXXXXXX.
F1.Range("C2:CXXXXXX").Value = F2.Range("A1:AXXXXXX").ValueEst-ce même possible ?!
- Messages
- 3'678
- Excel
- 365, 2019
- Inscrit
- 11/04/2020
- Emploi
- Formateur bureautique, dvpt de fichiers
Quelque chose comme ceci ?
F1.Range("C2:C" & derniereligne).Value = F2.Range("A1:A" & derniereligne).ValueSplendide, merci beaucoup. Tout fonctionne à merveille.
Je marque le sujet comme résolu.
Merci à JoyeuxNoel et à tous les détenteurs d'un savoir qui prennent sur leur temps libre, souvent très précieux car rare, pour aider leurs semblables de manière désintéressée.
Jonathan
- Messages
- 3'678
- Excel
- 365, 2019
- Inscrit
- 11/04/2020
- Emploi
- Formateur bureautique, dvpt de fichiers
Merci pour le retour :)
En fait,
derniereLigne = F1.Range("A" & Rows.Count).End(xlUp).Row + 1cette ligne de code te donne un nombre. Le numéro de la 1ère ligne vide.
Et comme tu l'as remarqué, range("A1:A200") est la structure pour faire référence à la plage allant de A1 jusqu'à A200.
Le symbole esperluette (ça fait toujours bien de placer son nom) "&", te permet d'ajouter des choses les unes après les autres dans des fonctions Excel, mais aussi en VBA.
Donc range("A1:A" & derniereligne) te donnera A1:A200 si derniereligne vaut 200.