CrossTab Impossible d'obtenir le HTML toHTML

C’est bon c’est corrigé. C’est poussé donc ce sera disponible chez vous dès demain.

J’ai fait un test (affichage du HTML du tableau croisé en texte via une action):

	public String action2() {
		try {
			Crosstab ct = getCrosstab(getName() + "-T1");
			ct.build(this);
			String t = ct.toHTML(getGrant(), false);
			return Message.formatSimpleText(t);
		} catch (Exception e) {
			return Message.formatSimpleError(e);
		}
	}

Ca marche:

Merci cela marche nickel.

Savez-vous s’il y a un moyen rapide de récupérer le CSS du thème admin pour l’intégrer dans le HTML généré ?

N’êtes vous pas en train de réinventer l’export du tableau croisé ?

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.

Y a t’il une meilleure façon de faire ?

Cordialement

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 ?

inliner le tableau.
Merci pour votre réponse et vos explications.

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.

Il suffit de faire un replace dans le preAlert.

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
}

Merci @david pour tes retours.

@Francois c’est effectivement ce que j’ai déjà implémenté. ^^

Ah ben je passe pour quoi avec mes approches compliquées maintenant… ;-)

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.

Done: https://docs.simplicite.io/4.0/javadoc-beta/com/simplicite/util/Crosstab.html#toHTML(com.simplicite.util.Grant,boolean,boolean)

Il faut mettre embedded = true pour n’avoir que la table.

C’est en train d’être poussé sur toutes les branches

1 Like

Merci @david pour ta célérité.

Nouvelles questions :

  1. Est-ce normal que les colonnes “Total” ne soient pas dans le HTML ?
  2. Dans le HTML, serais-ce possible d’avoir au minima les classes ctrow et ctcell ?
  3. 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.
  1. 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

  2. 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:

table { margin: 10px; border-collapse: collapse; }
tr:first-child, td:first-child { font-weight: bold; }
tr:nth-child(even) { background: #EEE; }
tr:nth-child(odd) { background: #DDD; }
td { padding: 5px; border: dotted 1px #CCC; }

Qui donne:
image

  1. Le tableau est généré dans la langue du user qui a instancié l’objet à partir duquel le tableau croisé est généré

Merci pour tes retours.

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 ?

Cordialement

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.

Bonjour François,
oui en effet, la pratique consistant à concaténer dans le corps du mail le contenu traduit dans plusieurs langues est couramment rencontrée (+1). C’est en lien avec un autre post sur le sujet (Permettre l'accès aux traductions d'un objet, d'un field dans une langue autre que celle de l'user).

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é.

En fait si, car une alerte peut être un SMS, une carte Trello… donc à étudier plus en détail.