Obtenir l'adresse d'une cellule passée en paramètre à une macro

Bonjour,

Je cherche à développer une macro qui a besoin de modifier des cellules
passées en paramètre à l'appel de la macro comme une fonction dans une
cellule : =mafonction(A1)

A chaque fois, j'obtiens la valeur de la cellule A1, pas moyen d'obtenir A1.

J'ai lu que c'était impossible :

https://wiki.openoffice.org/wiki/Documentation/OOo3_User_Guides/Calc_Guide/Passing_arguments_to_a_macro

Ce document date un peu, cela a peut être changé depuis, mais je n'arrive
pas à trouver.

Merci pour vos suggestions

Pierre

Bonjour,

-----Message d'origine-----
De : PierreM [mailto:mazeinp@free.fr]
Envoyé : dimanche 10 novembre 2013 21:29
À : users@fr.libreoffice.org
Objet : [fr-users] Obtenir l'adresse d'une cellule passée en paramètre à
une macro

Bonjour,

Je cherche à développer une macro qui a besoin de modifier des cellules
passées en paramètre à l'appel de la macro comme une fonction dans une
cellule : =mafonction(A1)

A chaque fois, j'obtiens la valeur de la cellule A1, pas moyen d'obtenir
A1.

J'ai lu que c'était impossible :

https://wiki.openoffice.org/wiki/Documentation/OOo3_User_Guides/Calc_Guide
/Passing_arguments_to_a_macro

Ce document date un peu, cela a peut être changé depuis, mais je n'arrive
pas à trouver.

Merci pour vos suggestions

C'est tout à fait possible, l'argument doit être passé comme String qui sera
ensuite utilisé dans la fonction pour définir l'objet Cellule qui a pour
adresse cette chaîne:

Par exemple:
Si l'argument est adCellule, la cellule visée est trouvée par:

Cellule=ThisComponent.Sheets.GetByName("Feuille1").GetCellRangeByName(adCell
ule)

C'est-à-dire si adCellule = "a1", Cellule sera bien la cellule
$Feuille1.$A$1

Bonne journée,
Michel

Bonjour

Pour préciser la réponse de Michel je voudrais insister sur plusieurs
points:

1. Une fonction ne peut pas modifier d'autre cellule que celle d'appel de
la fonction
et ce pour lui renvoyer une valeur ou un texte.

On peut passer en paramètre une chaîne identique à l'adresse d'une cellule
et "travailler" à partir de là (cf. réponse de Michel) mais le programme ne
devra de toute manière pas déroger au 1 ci-dessus.

Cette technique présente par ailleurs l'inconvénient de travailler "en
absolu" : les arguments de la fonction ne seront pas adaptés lors de la
copie de la cellule.

On peut s'affranchir de cette limite en passant en paramètres des formules
(feuille, cellule, colonne, ligner) renvoyant des informations relatives sur
des adresses. Je donne un exemple d'appel dans ce fil :
http://nabble.documentfoundation.org/Re-Fonction-Cellule-appelant-une-macro-tp4080631p4080719.html

2. Il existe un moyen (listener asynchrone particulier) de modifier
une autre cellule que celle appelée mais c'est complexe et sans doute
pénalisant pour des calculs importants.

On peut le plus souvent éviter ce type de traitement en gérant les
événements au niveau de la feuille...

Cordialement
Pierre-Yves

Bonsoir

Ou passée tout court...

Dans Main, on récupère l'objet cellule qui correspond à A1 (.getCellByPosition ou .getCellRangeByName) et on passe l'objet en paramètre :

Sub Main
Dim oCell As Object
    oCell = thisComponent.Sheets(0).getCellByPosition(0,0)
    LaMacro(oCell)
End Sub

Le sub (ou la fonction) appelé récupère l'objet cellule et on a accès aux propriétés/métodes/etc... classiques, entre autres .String ou .Value :

Sub LaMacro(oCellParam)
    oCellParam.String = "Voili, voilou"
' ou oCellParam.Value = 10
End Sub

Cordialement

Ok, je suis coincé pour faire quelque chose de propre. l'appel de
mafonction("A1") c'est pas super pratique. En tout cas pas autant que
mafonction(A1). Pas de décalage automatique par sélection ... Il faut tout
modifier à la mano ensuite. Si je veux utiliser 100 fois mafonction, il faut
que je tappe 100 lignes. C'est un peu lourd.

J'ai besoin que ma fonction modifie une valeur à un endroit de la feuille,
et récupère une autre valeur ailleurs pour la retourner au lieu de l'appel
de la fonction.

En fait, je veux utiliser une partie d'une feuille comme une fonction.

Je trouve étonnant qu'on ne puisse pas faire ça. Ca vaut peut être une
feature request ?

Il est aussi très étonnant que byrange n'existe pas. Ca existe sous excel
il me semble. Le fait de manipuler des pointeurs donne des possibilités
énormes.

Du coup j'ai téléchargé le code source, et je cherche un exemple simple.
Pour l' instant, j'ai 2 pistes : me baser sur la recherche de valeur cible,
ou sur une fonction plus simple Vlookup par exemple. Ca n'est pas gagné.

Merci d'avoir pris du temps pour me répondre.

Pierre

Bonjour Patrice

VEDEL Patrice wrote

Dans Main, on récupère l'objet cellule...

Je crains que tu n'aies pas lu attentivement la demande :

PierreM wrote

modifier des cellules passées en paramètre à l'appel de la macro
comme une fonction dans une cellule : =mafonction(A1)
A chaque fois, j'obtiens la valeur de la cellule A1, pas moyen d'obtenir
A1.

Cordialement
Pierre-Yves

Yeap

En lisant la réponse de PYS, j'ai pigé que j'avais lu en diagonale, son message me le confirme :dizzy_face:

Donc pour une réponse plus juste : l'option du listener asynchrone (servica AsynCallBack) a été abordée par bm (Bernard Marcelly) ici :
https://forum.openoffice.org/fr/forum/viewtopic.php?f=15&t=23700

Cordialement

Bonjour

PierreM wrote

Pas de décalage automatique par sélection ... Il faut tout modifier à la
mano ensuite. Si je veux utiliser 100 fois mafonction, il faut que je
tappe 100 lignes

Comme je le disais dans ma réponse précédente tu as d'autres
possibilités, notamment pour gérer la mise à jour des
références lors de la copie (utilisation de fonctions
tableur retournant des références).

PierreM wrote

J'ai besoin que ma fonction modifie une valeur à un endroit de la feuille,
et récupère une autre valeur ailleurs pour la retourner au lieu de l'appel
de la fonction.

S'il s'agit de modifier une ou plusieurs cellules *autres*
que celle "appelante" j'indiquais la méthode "événement
feuille" (par exemple "sur contenu modifié").

Le classeur joint illustre cela: si la colonne B est
modifiée et si la modification porte sur une cellule
le programme vérifie le type des données. S'il s'agit
d'un texte ou d'un nombre négatif le texte de la cellule de même
ligne dans la colonne C devient "incorrect" et la couleur est modifiée.

EvenementFeuille.ods
<http://nabble.documentfoundation.org/file/n4082918/EvenementFeuille.ods>

J'indiquais que le listener "asynchrone" (lien sur le forum donné par
Patrice) était une autre solution, plus complexe. Je n'ai pas fait
d'essais récents mais cette technique atteint sa limite si beaucoup
de cellules sont impactées.

Je te joins néanmoins un autre classeur exemple dans lequel je montre
comment passer en deuxième argument la référence de la cellule à
modifier (ici sous forme de texte mais il suffit d'adapter si on veut
passer une référence par fonction tableur).

FonctionModifAutreCellulePys.ods
<http://nabble.documentfoundation.org/file/n4082918/FonctionModifAutreCellulePys.ods>
Cordialement
Pierre-Yves

Je viens de regarder FonctionModifAutreCellulePys.ods qui a le même problème
que celui que j'ai actuellement.

Quand à EvenementFeuille.ods, je ne comprend pas comment elle fonctionne.
Apparemment, il y a une surveillance de toute la colonne, mais comment cette
surveillance est-elle mise en place ?

Sinon, comme cuisine, j'ai aussi pensé à mafonction(ligne(A1), colonne(A1)).
Mais je trouve triste de devoir en arriver là. Et pourtant, j'ai pas peur de
bitouiller.

Pas vous ?

Au final la fonction serait approximativement :

Option Explicit

function CellAsFunc(CellInput as range, CellValue as variant, CellOutput as
range)as variant

thiscomponent.currentcontroller.activesheet.CellInput.value = CellValue

CellAsFunc= thiscomponent.currentcontroller.activesheet.CellOutput.value

End Function

Pierre

PierreM wrote

Je viens de regarder FonctionModifAutreCellulePys.ods qui a le même
problème que celui que j'ai actuellement.
...
Sinon, comme cuisine, j'ai aussi pensé à mafonction(ligne(A1),
colonne(A1)).

S'il s'agit du fait que la cible est passée en texte je te l'avais indiqué,
ainsi
que *dès ma première réponse*, la solution que tu sembles redécouvrir:
utiliser les fonctions tableur pour obtenir les références à traiter.

PierreM wrote

Quand à EvenementFeuille.ods, je ne comprend pas comment elle fonctionne.

Comme déjà dit la procédure est un exemple de gestion des "événements
feuille" : clic droit sur l'onglet puis... même chose.

En l'occurrence la procédure est lancée "sur contenu modifié".

L'événement reçu en paramètre permet de vérifier si la modification
ayant déclenché la procédure porte sur une cellule (et non, par
exemple, la modification d'un graphique).
S'il s'agit d'une cellule, on obtient ses références ce qui permet le
traitement. Ici, pour l'exemple on travaille sur la colonne B.

Ce n'est qu'un exemple rapidement mis en place pour te montrer
le principe.

PierreM wrote

je trouve triste de devoir en arriver là. Et pourtant, j'ai pas peur de
bitouiller.
Pas vous ?

Chaque logiciel est différent. Si tu veux programmer avec LibreOffice il te
faut
investir un minimum dans le langage, l'Api, etc. justement pour éviter de
bidouiller, ce que *personnellement* je trouverais triste et ce qui me
ferait peur.

Pierre-Yves

Pierre yves,

Merci de prendre à nouveau le temps de me rappeler ce que j'ai lu un peu
vite. On ne trouve que ce que l'on cherche, et je ne cherchais pas encore ce
que tu me proposais.

J'ai implémenté le callback, et comme prévu cela fonctionne.

Par contre lorsque des cellules dont dépend le callback sont mises à jour,
le callback n'est pas rappelé. Du coup je suis en train de travailler avec
le callback qui signale les évenements de calculs de formules.

Je pense finir ça dans le we. Si ça tient la route, je posterai le résultat.

Pierre

Ca y est, j'ai un peu avancé. C'est fonctionnel, mais un peu bancal encore.

J'espère que ça vous donnera une idée de ce que je cherche à faire.

Fonctionnement :
l'appel de la fonction sert en fait de simple balise. Les arguments sont
analysés et utilisés dans les gestionnaires d'événements. La valeur de la
cellule qui contient la fonction n'a strictement aucun intérêt.

Les gestionnaires d'événements analysent la chaine d'appel de la fonction
pour agir :
les deux premiers arguments sont la cellule variable et la cellule qui
contient la valeur à y placer.
les deux derniers sont la cellule où trouver le résultat du calcul et la
cellule où le placer.

J'ai dû utiliser un autre événement de feuille : celui sur le recalcul de
formule, car l'événement sur une cellule ne suffisait pas. En effet, si la
formule changeait, il n'y avait pas de recalcul.

Il y a deux exemples : l'un est trivial d'une fonction linéaire (y=a*x+b)
En changeant a ou b, ou n'importe quoi en fait toute la courbe est retracée.

L'autre l'est moins et met mieux en valeur le côté pratique de cette
fonction. Les variables sont le revenu et le nombre de part, ainsi que tous
ce que le tableau IRPP 2013 contient.

De la cuisine, qu'en pensez vous ?

J'espère encore passer pour une buse qui n'a pas trouvé la bonne fonction
qui existe déjà, mais je n'y crois pas.

Pierre

La feuille :
CellFonction.ods
<http://nabble.documentfoundation.org/file/n4085122/CellFonction.ods>

Bonjour

-----Message d'origine-----
De : PierreM [mailto:mazeinp@free.fr]
Envoyé : mardi 26 novembre 2013 23:33
À : users@fr.libreoffice.org
Objet : [fr-users] RE: Obtenir l'adresse d'une cellule passée en paramètre
à une macro

Ca y est, j'ai un peu avancé. C'est fonctionnel, mais un peu bancal
encore.

J'espère que ça vous donnera une idée de ce que je cherche à faire.

Fonctionnement :
l'appel de la fonction sert en fait de simple balise. Les arguments sont
analysés et utilisés dans les gestionnaires d'événements. La valeur de la
cellule qui contient la fonction n'a strictement aucun intérêt.

Les gestionnaires d'événements analysent la chaine d'appel de la fonction
pour agir :
les deux premiers arguments sont la cellule variable et la cellule qui
contient la valeur à y placer.
les deux derniers sont la cellule où trouver le résultat du calcul et la
cellule où le placer.

J'ai dû utiliser un autre événement de feuille : celui sur le recalcul de
formule, car l'événement sur une cellule ne suffisait pas. En effet, si la
formule changeait, il n'y avait pas de recalcul.

Il y a deux exemples : l'un est trivial d'une fonction linéaire (y=a*x+b)
En changeant a ou b, ou n'importe quoi en fait toute la courbe est
retracée.

L'autre l'est moins et met mieux en valeur le côté pratique de cette
fonction. Les variables sont le revenu et le nombre de part, ainsi que
tous
ce que le tableau IRPP 2013 contient.

De la cuisine, qu'en pensez vous ?

J'espère encore passer pour une buse qui n'a pas trouvé la bonne fonction
qui existe déjà, mais je n'y crois pas.

Pierre

La feuille :
CellFonction.ods
<http://nabble.documentfoundation.org/file/n4085122/CellFonction.ods>

Il y a une chose que tu ne dis pas (ou que je n'ai pas su comprendre par
manque de temps pour me plonger dans le détail), quel est l'intérêt de faire
aussi compliqué, alors que l'on peut réaliser la même chose sans macro ?

Bonne journée,
Michel

Yeap

"quel est l'intérêt de faire aussi compliqué, alors que l'on peut réaliser la même chose sans macro "
Respecter l'axiome "pourquoi faire simple quand on peut faire compliqué" et la réutilisation de quelques codes dont on se plait à ignorer la complexité...
Cela dit le click droit qui gère un menu contextuel (merci PYS ;)) est plus facile à recaser qu'un listerner asynchrone...

AMHA

J'aimerai bien savoir comment faire ça sans macro. Mais vu qu'une fonction
n'affecte que la valeur dans laquelle elle se trouve, il y a peu de chance
qu'une fonction ...fonctionne.

Quelle fonction fait ça ?

Ce que permet mon code, c'est d'utiliser une partie d'une feuille comme une
fonction.

La complexité de la cuisine que je propose est une conséquence directe de la
première ligne de ce message.

Pierre