C’est possible :s
Mon besoin est : je veux qu’un des mes tableaux croisés soit envoyé par mail toutes les semaines.
J’ai donc créé une action qui lance une alerte. J’ai défini le contenu de l’alerte avec un message contenant le mot [CROSSTAB] et je souhaite remplacer ce texte par le contenu du crosstab.
J’avoue ne pas savoir si les APIs d’export du tableau croisé sont facilement utilisables dans votre contexte. Je vais regarder.
En tout cas le HTML issu de toHTML est volontairement minimaliste (<table><tr><td>) car sa raison d’être était de pouvoir être récupéré par les Excel legacy comme source de données externe (ce qui est deprecated avec les versions modernes d’Excel qui savent appeler des services REST).
Bref ajouter des styles issus de la UI à ce HTML n’a donc aucun de sens, ça n’améliorera en rien la présentation de ce HTML brut.
Si vous voulez vraiment intégrer (inliner) ce HTML dans le corps HTML d’un mail (i.e. pas en pièce jointe) mieux vaut mettre vos propres styles (et faire attention de n’intégrer que le contenu du <body> de ce HTML dans le HTML de votre mail, pour ne pas avoir 2 tags body).
Votre besoin c’est d’inliner le tableau croisé dans le corps de votre mail ou de le mettre dans un format X ou Y en pièce jointe de ce mail ?
OK dans ce cas qques styles ad hoc dans le corps de votre mail + un coup de JSoup (lib intégrée à Simplicité) pour extraire le body (ex: https://jsoup.org/cookbook/input/parse-body-fragment) et ou l’enrichir et ça devrait le faire.
Autre approche on peut ajouter une variante de la méthode toHTML qui ne générerait que le contenu du body, j’ai regardé c’est facile à faire, ça peut être fait aujourd’hui.
PS: Pour une pièce jointe la bonne approche aurait effectivement été plutôt de taper sur les APIs d’export standard du tableau croisé, je ne creuse pas ce sujet donc.
public String preAlert(Alert a) {
if (a!=null && "myAlert".equals(a.getName()) {
String lang = getGrant().getLang();
String body = a.getContent(lang);
body = body.replace("[CROSSTAB]", "...");
a.setContent(lang, body);
}
return null; // no error
}
Cela dit mon point sur le contenu du body reste valable. Il ne faut pas remettre un <html>, <head> ou <body> dans un body. Donc avoir un toHTML avec un argument embedded = true/false ne serait pas inutile.
Est-ce normal que les colonnes “Total” ne soient pas dans le HTML ?
Dans le HTML, serais-ce possible d’avoir au minima les classes ctrow et ctcell ?
Est-ce possible de builder le cross tab dans une autre langue ?
Dans mon cas, j’ai une alerte envoyée à un groupe d’utilisateurs. Certains sont anglais d’autres non. Dans ma méthode preAlert, je substitue le texte “[CROSSTAB]” par le HTML fourni par toHtml. Problème : je ne peux pas spécifier la langue. (Désolée de ne pas avoir vu ce point plus tôt) --> mon utilisateur qui lance l’alerte est en français, j’ai essayé de récupérer le HTML en utilisant le grant Grant.getSystemAdmin() qui lui est en anglais mais cela m’a retourné le HTML en français également.
comme expliqué cette table “raw HTML” est à la base destinée à un import de donnée dans Excel, on n’y met donc que les données brutes du tableau croisé, pas ce qui peut être recalculé dans Excel
Non pour la même raison que ci-dessus => cela doit impérativement rester du raw HTML, mais avec du CSS un peu malin vous devez pouvoir faire ce qu’il faut, ex:
Je souhaiterai avoir la possibilité de générer le tableau dans une autre langue d’après votre point 3 ce n’est pas possible.
Comment puis-je gérer mon besoin fonctionnel d’envoyer un alerte à groupe de personnes ?
Ma compréhension du système d’alerting pour un groupe était que chaque utilisateur recevait l’alerte dans la langue configurée dans son profil.
Si je fais une substitution de mon “[CROSSTAB]” par le code HTML, je vais me retrouver avec un tableau en français dans un mail en anglais.
Comment pourrais-je gérer ce cas ?
Je ne connait pas bien la mécanique interne des alertes…
@Francois si nous mettons en place ce tag de substitution dans le corps des alertes (genre [CROSSTAB:myCrosstab]) est-ce que celui-ci sera bien instancié depuis un objet du user qui reçoit l’alerte (et donc avec les éventuels filtres propres à ce user) ?
Ce n’est pas conçu pour ce genre d’usage multi-langues. Une alerte = 1 email ayant plusieurs destinataires to/cc/bcc, donc chacun ne reçoit pas le sien dans sa langue.
Bref le pre/postAlert est appelé une seule fois pour tous les destinataires (emails distincts) et dans la langue de la session qui l’émet. Il faudrait changer la logique interne, pour grouper les users par langue, ou ce qui se fait en général de concaténer toutes les langues dans l’email si les destinataires ont plusieurs langues.
Donc une solution simple serait de paramétrer une alerte dont le body contient toutes les langues à la suite / et de substituer plusieurs fois le tableau ([CROSTAB_FRA] [CROSTAB_ENU]) généré plusieurs fois (en changeant temporairement la langue getGrant().setLang("ENU" | "FRA") et en la remettant à sa valeur d’origine à la fin).
Ensuite si le besoin est trop spécifique il est toujours possible par code :
de faire un ‘select group by’ maison qui devient un HTML comme souhaité
d’envoyer des Alertes ou des Emails en boucle en changeant les destinataires et le body
Il y a toutes les helpers dans Simplicité pour envoyer des emails simplement.
PS : le sujet initial du post est loin derrière nous, il aurait fallu en faire un autre.
Oui, je pense qu’on peut aller dans ce sens, le mail sortant devrait concaténer toutes les langues des destinataires une fois connus (donc après preAlert qui permet d’en changer par code).
A la différences des objects/fields instanciés par langue, une alerte contient toutes ses langues en mémoire, donc c’est plus simple de le faire comme suit :
public String preAlert(Alert a) {
if (a!=null && "myAlert".equals(a.getName()) {
Crosstab ct = getCrosstab("CT1");
String lang = getGrant().getLang();
getGrant().setLang("FRA");
ct.build(this);
String t = ct.toHTML(getGrant(), false);
a.setContent("FRA", a.getContent("FRA").replace("[CROSSTAB]", t));
getGrant().setLang("ENU");
ct.build(this);
t = ct.toHTML(getGrant(), false);
a.setContent("ENU", a.getContent("ENU").replace("[CROSSTAB]", t));
getGrant().setLang(lang); // restore user's language
}
return null; // no error
}
Je regarde pour que Simplicité concatène les langues des destinataires, ça devrait pas être compliqué.