Fermer

mars 12, 2021

Explication du moteur de rapport Telerik


Un regard sous le capot sur les processus complexes de notre moteur de reporting.

Dans ce billet de blog, je continuerai la série d'articles consacrés à l'ensemble d'outils Telerik Reporting. Le but de la série est de fournir une vue plus technique sur les spécificités de notre produit. Ces connaissances approfondies profiteront aux créateurs de rapports qui souhaitent s’assurer d’utiliser tout le potentiel du moteur de création de rapports, d’obtenir des performances élevées et une intégration sans problème de Telerik Reporting dans leurs applications.

Présentation

Ce L'article suppose que vous avez déjà une certaine expérience avec Telerik Reporting, mais au cas où vous seriez un utilisateur pour la première fois ou que vous voudriez revenir sur les points principaux, je peux vous recommander quelques articles avant de continuer avec celui-ci. Pour un rapide exercice pratique sur la façon de créer un rapport en quelques étapes, je suggère la section QuickStart dans notre documentation . Mais pour un aperçu plus détaillé, vous pouvez continuer avec l'excellente série d'articles d'Eric Rohler, consacrée aux Desktop et Web Report Designers et avec le précédent blog de notre série intitulé « Meilleures pratiques pour l'extraction de données dans Telerik Reporting », où je parle de la bonne façon de préparer et de transmettre des données à un rapport Telerik.

Si vous avez déjà parcouru les lectures suggérées, vous avez peut-être remarqué qu'elles suivez les premières étapes du cycle de vie du rapport, comme indiqué sur l'image ci-dessous: création de la définition de rapport et alimentation des données.

 Un organigramme montre la définition de rapport: flèche bidirectionnelle de Visual Studio Designer avec classe de rapport, et Flèche bidirectionnelle du concepteur autonome avec fichier XML. La définition de rapport et la source de données alimentent le moteur de rapport. Le moteur de rapport est composé du processeur de rapport qui coule vers l'extension de rendu. Enfin, il existe un document de rapport.

Mais comment exactement cette définition de rapport, créée sous la forme d'un ensemble de contrôles statiques et de certaines règles dans le concepteur de rapports, est-elle mise en ligne et produit des milliers de pages dans un fichier PDF ou DOCX? ? Comment les données de la base de données sont-elles divisées en groupes et agrégées pour calculer les expressions SUM ou COUNT? Quand les liaisons sont-elles appliquées? On répondra à ces questions et à d'autres ci-dessous.

Définition et données

Pour mieux illustrer le flux de travail de traitement, j'utiliserai une définition de rapport très simple qui affichera tous les pays du monde, regroupés par la première lettre de leur Nom. Le rapport utilise un WebServiceDataSource pour récupérer les données d'un service REST à l'aide de l'URL https://restcountries.eu/rest/v2/all?fields=name . Comme l'URL le suggère, les données JSON, renvoyées par le service REST distant, ne contiendront que le nom du pays. Afin de classer les données par ordre alphabétique, j'ai ajouté une règle de tri au rapport. En termes de performances, il aurait été préférable que je puisse obtenir les données commandées auprès du service REST, mais comme il ne dispose pas d'une telle option, j'ai décidé d'ajouter la règle de tri dans le rapport.

Le rapport comporte également un groupe de rapports avec une expression de regroupement définie sur:

 = Substr (Fields.name, 0, 1) 

Le pied de page du groupe contient une zone de texte avec une expression agrégée:

 = Count : {Count (Fields.name)} 

qui affichera le décompte des pays de chaque groupe. L'aspect général du rapport sur la surface du concepteur est illustré ci-dessous:

 Le fichier countries.trdx montre la section d'en-tête de groupe, la section de détail, la section de pied de page de groupe. de pays, regroupés par leur première lettre:</p data-recalc-dims=

 Liste des pays commençant par A et le nombre est 15.

Vous pouvez télécharger la définition du rapport ici: Countries.trdp

Traitement du rapport

Les éléments de rapport dans la définition de rapport sont décrits dans une arborescence hiérarchique, où le nœud racine est le rapport et ses descendants de premier niveau sont les sections du rapport. Les sections de rapport contiennent des éléments qui peuvent avoir d'autres descendants (comme Panel) ou qui représentent des nœuds feuilles (TextBox, Shape, PictureBox, etc.). La structure hiérarchique contient également les règles supplémentaires telles que le style, la mise en forme conditionnelle ou les liaisons qui peuvent être appliquées à chaque élément.

Une fois que nous avons configuré la définition du rapport, il est temps de traiter le rapport. En fait, l'étape de traitement et l'étape de rendu ultérieure sont étroitement liées et du point de vue de l'utilisateur, elles sont représentées par une opération commune. Par exemple, lors du rendu d'un rapport par programme à l'aide du ReportProcessor, nous appelons la méthode RenderReport (), qui lance l'opération en deux étapes de traitement et de rendu dans le format de document sélectionné. Les visualiseurs de rapports appellent également la même méthode en interne pour déclencher le processus de création de pages et de les montrer à l'utilisateur. Néanmoins, nous examinerons les étapes de traitement et de rendu séparément afin que vous ayez une meilleure idée de ce qui se passe sous le capot.

Aperçu du traitement

Le type de chaque nœud dans la définition de rapport est représenté par une classe de la Espace de noms Telerik.Reporting, par exemple Telerik.Reporting.Report, Telerik.Reporting.TextBox, etc. Chaque classe «définition» a une classe correspondante de l'espace de noms Telerik.Reporting.Processing. Ces classes de «traitement» contiennent des informations d'exécution utilisées lors des étapes de traitement et de rendu. Une seule instance d'une classe de définition (par exemple, une Telerik.Reporting.TextBox) peut être représentée par plusieurs instances de traitement de Telerik.Reporting.Processing.TextBox.

Je comprends que cela peut sembler un peu déroutant, alors voyons comment cela fonctionne par l’exemple. Nous allons suivre le traitement de notre exemple de rapport étape par étape.

L'étape de traitement commence par la lecture de la hiérarchie des définitions de rapport et en parcourant consécutivement ses nœuds descendants. Étant donné que la racine de la hiérarchie est le nœud Report, le moteur commence à le traiter en créant une instance de la classe Telerik.Reporting.Processing.Report – l'instance dite de «traitement» ou l'élément de traitement.

À l'étape suivante, le moteur déclenche l'événement ItemDataBinding, qui peut être utile si nous voulons accéder aux éléments de rapport par programme.

Après cela, le moteur passe par les règles de formatage conditionnel et les liaisons (dans cet ordre) et les applique, le cas échéant. Ces règles sont utilisées pour modifier l'instance de «traitement» avant de la lier aux données et d'effectuer les opérations suivantes.

Modification de l'instance de traitement actuelle

Dans les versions antérieures de Telerik Reporting, le gestionnaire de l'événement ItemDataBinding était l'endroit approprié pour mettre du code qui modifie l'élément de traitement actuel Mais dans les éditions récentes de notre produit, nous déconseillons fortement la modification programmatique et suggérons d'utiliser le formatage conditionnel et / ou les liaisons.

L'utilisation de code pour modifier l'élément de traitement peut être source d'erreurs et il n'est pas garanti de fonctionner dans aucun scénario. L'une des erreurs les plus courantes consiste à utiliser cet événement pour modifier l'instance de «définition» à l'origine de l'élément de traitement actuel. Cette approche, bien que désapprouvée, a fonctionné dans le passé, mais les récentes optimisations du moteur ne permettent pas d'appliquer de telles modifications et ce comportement est toujours source de confusion chez les utilisateurs qui mettent à niveau leurs projets vers une version récente de notre produit. La déclaration de toutes les règles de modification dans la définition de rapport conviendra à la plupart des scénarios utilisateur et constitue un moyen fiable de modifier les éléments du rapport lors de l'exécution.

Il est également important de connaître la différence entre les règles de mise en forme conditionnelle et les liaisons, bien qu'elles puissent semblent servir le même objectif. Les règles de mise en forme conditionnelle appliquent les modifications uniquement sur les propriétés de style de l'élément de traitement, tandis que les liaisons permettent d'appliquer des modifications sur presque toutes les propriétés de l'élément de traitement.

Par exemple, ayons une zone de texte dont le style de police doit être changé en gras dans certaines circonstances. En fait, cela signifie que certaines des instances de traitement de TextBox auront leur Font.Style.Bold défini sur True. Nous pouvons le faire avec une liaison qui a Property Path défini sur Font.Style.Bold et Expression défini sur True et il le serait travailler. Cependant, ce serait loin d’être optimal, car les parties du chemin de propriété seront résolues en utilisant la réflexion sur les propriétés de l’élément de traitement. En outre, la valeur Expression sera convertie à l'aide du convertisseur de type, déduite du type de propriété cible. Toutes ces opérations sont coûteuses et peuvent nuire gravement aux performances. Il serait préférable d'utiliser les règles de mise en forme conditionnelle qui créeront un nouvel objet Style où Font.Bold est défini sur True et l'ajouteront à la chaîne de résolution de style actuelle de TextBox avec une priorité plus élevée.

Liaison aux données

Revenons au traitement de notre rapport. Après avoir vérifié les modifications à appliquer, le rapport peut être lié aux données. Dans notre exemple, le rapport a sa source de données définie sur WebServiceDataSource, qui pointe vers un service REST distant. Le moteur appelle la routine qui télécharge les données sous la forme d'une collection d'objets de données simples.

Lors de l'itération de cette collection, le moteur alimente l'ensemble de résultats multidimensionnel qui sera conservé en tant qu'ensemble de données du rapport. Cet ensemble de résultats multidimensionnel est une structure hiérarchique qui organise les données brutes en groupes, suivant le modèle des groupes de rapports dans notre définition de rapport. L'expression de regroupement est exécutée sur chaque objet de données et le résultat détermine dans quel groupe l'objet ira.

 Les données brutes contiennent l'Afghanistan ... le Zimbabwe. Les sous-ensembles incluent le groupe

Après avoir rempli le jeu de résultats multidimensionnel, le rapport commence le traitement récursif de ses propres enfants. Le sous-programme de traitement commence à parcourir les membres de données des données groupées et affecte chaque partie de ces données groupées en tant que contexte de données de l'instance de groupe actuelle. Cela signifie que le groupe et ses enfants n'auront accès qu'à cette partie des données brutes. Les expressions, utilisées dans la portée du groupe, ne fonctionneront que sur ce sous-ensemble de données – les pays commençant par «A». Après avoir affecté le contexte de données, le moteur continue le traitement récursif des enfants du groupe de rapports, qui dans ce scénario se composent de trois sections: en-tête de groupe, détails et pied de page de groupe.

Le traitement de l'en-tête de groupe de rapports est effectué de la même manière que traitement de tout autre élément – dans un premier temps, le moteur vérifie s'il y a des modifications définies dans Mise en forme conditionnelle et liaisons. Puisque l'en-tête de groupe n'est pas un DataItem, c'est-à-dire qu'il n'a pas sa propre DataSource, le moteur continue le traitement récursif avec ses enfants. Ici, l'en-tête de groupe n'a qu'un seul enfant: une zone de texte qui affiche la première lettre du premier membre du groupe.

Pendant le traitement de la zone de texte, l'expression de sa propriété Value est évaluée par rapport à son contexte de données. Étant donné que la zone de texte fait partie du champ d'application du groupe de rapports et que le contexte de données du groupe de rapports est actuellement défini sur Groupe «A» le résultat sera un seul « A » et cette valeur sera stocké dans la propriété Value de la zone de texte de traitement. Avec cela, le traitement de la zone de texte se termine, l'exécution sort de l'algorithme récursif et revient au traitement de l'en-tête de groupe. Puisque l'en-tête de groupe n'a plus d'enfants, l'algorithme de traitement continue avec la section détail et ses enfants: dans notre scénario – une seule zone de texte affichant le nom du pays actuel.

Les opérations de traitement de la section détail et de sa zone de texte répéter pour tous les 15 membres dans le contexte de données actuel, donc lorsque le Groupe «A» aura terminé son traitement, le moteur aura créé 34 nouveaux éléments de traitement – section d'en-tête de rapport et sa zone de texte, 15 sections de détail et leurs TextBoxes correspondantes, et enfin une section de pied de page de groupe, contenant une seule TextBox qui montre le nombre de membres de ce groupe.

Après avoir terminé chaque cycle de traitement, le moteur déclenche l'événement ItemDataBound. De même que l'événement ItemDataBinding, celui-ci peut être utilisé pour observer l'état actuel de l'élément de traitement (par exemple, la valeur déjà calculée d'un TextBox de traitement), mais sa modification n'est pas recommandée. Le cycle de traitement se répète pour chaque instance de groupe dans les données groupées jusqu'à ce que tous les groupes soient traités.

Performances de traitement

Une fois l'étape de traitement terminée, le moteur écrit le temps écoulé dans le flux de sortie Trace et commence l'étape suivante —Rendering.

 Rendu de la sortie, Afficher la sortie de: Debug. Affiche les temps nécessaires pour terminer le traitement du rapport

Mais avant de l'examiner, laissez-moi vous expliquer comment utiliser le temps de traitement mesuré comme indicateur de performance.

Comme vous pouvez le voir, l'étape de traitement n'inclut pas de beaucoup d'opérations gourmandes en ressources processeur, comme le dessin de bitmaps ou la mesure de texte à l'aide du sous-système graphique. L'opération la plus «coûteuse» ici devrait être le processus de récupération des données et la construction de l'ensemble de résultats multidimensionnel. Ainsi, si vous remarquez que l’étape de traitement prend beaucoup de temps à s’achever, cela indique clairement que le rapport doit être optimisé.

Une raison possible d'une mauvaise performance peut être l'utilisation d'un trop grand nombre de liaisons sur un élément placé dans la section détail – dans ce cas, le code de réflexion sera exécuté pour chaque instance d'élément de traitement créée pour chaque objet de l'ensemble de données. Une autre cause de performances médiocres peut être des expressions extrêmement volumineuses ou des fonctions utilisateur qui sont appelées pour chaque enregistrement de données et contiennent du code non optimisé. Cependant, il devrait avoir une consommation de mémoire importante pendant l'étape de traitement, car toute la hiérarchie avec les éléments de traitement créés – le soi-disant «arbre de traitement» – est conservée en mémoire.

Rendu du rapport

Pendant le opération de rendu, le moteur calcule les positions de tous les éléments de rapport déjà traités et écrit leur représentation graphique (texte, image, ensemble de primitives graphiques, etc.) dans le flux de sortie en fonction de l'extension de rendu sélectionnée. En fonction de cette extension, le moteur choisira également quel algorithme de pagination sera utilisé. Certaines extensions de rendu comme HTML5Interactive ou IMAGEInteractive utilisent des pages logiques, d'autres comme PDF et IMAGEPrintPreview – physiques – et certaines comme XLSX n'utilisent aucune pagination. La principale différence est que la pagination logique (également appelée interactive ) produit des pages qui peuvent avoir une hauteur supérieure à la hauteur de page sélectionnée lors de la conception du rapport. La pagination logique utilise les soi-disant «sauts de page souples» où le contenu du rapport est optimisé pour la prévisualisation à l'écran. La pagination physique divise le contenu du rapport, de sorte qu'il s'adapte exactement à la taille de page conçue.

Configuration des conditions préalables

Trouvons le processus de rendu de notre rapport dans un fichier PDF. La première chose importante que le moteur déterminera est si les expressions du document contiennent ou non une expression PageCount. Si l'une des sections de page ou des filigranes contient cette expression, le moteur lance un rendu de rapport de pré-vol dont le seul objectif est de compter les pages du rapport. Cela peut sembler étrangement compliqué, mais voici pourquoi cela a tout à fait du sens. Lorsque vous ajoutez une expression telle que:

 Page {PageNumber} / {PageCount} 

à une section de page, le moteur a besoin de connaître le nombre total de pages afin de l'évaluer correctement. La seule façon de déterminer le nombre de pages consiste à effectuer un rendu «léger» qui calcule les positions de tous les éléments du rapport et détermine le nombre de pages que le contenu du rapport couvrira. C'est un rendu «léger», car il n'implique que la logique de mesure et n'écrit aucun contenu dans le flux de sortie.

Measurement and Arrangement

J'ai mentionné à plusieurs reprises les termes «mesures» et « calculs de position »sans les expliquer, mais comme c'est l'une des routines les plus importantes dans le rendu du rapport, je voudrais entrer dans quelques détails.

La mesure et l'organisation sont différentes pour les différentes classes de traitement, mais le résultat est commun – pour déterminer les limites exactes de l'élément en coordonnées logiques de page. Le calcul de la position des éléments en coordonnées logiques signifie que la taille de la page du rapport n’est pas prise en compte, car la pagination n’a pas encore eu lieu. Au lieu de cela, tous les éléments sont considérés comme placés sur un canevas sans fin avec des coordonnées en haut à gauche définies sur 0, 0. Pour plus de simplicité, la plupart des calculs sont effectués en coordonnées relatives (par rapport à leur élément parent), mais à un stade ultérieur, ils seront converti en coordonnées absolues.

La logique de mesure varie entre les différents éléments de traitement. Lors de la mesure d'une zone de texte, nous utilisons les méthodes GDI + pour calculer l'espace que son texte occupera. Lors de la mesure d'une PictureBox, nous transformons son image en fonction de la définition du rapport et déterminons la taille physique (cm, mm, pouces, etc.) qu'elle aurait. La mesure est effectuée de manière récursive dans l'arborescence de traitement et chaque élément de conteneur mesure les limites de ses enfants. De cette façon, chaque conteneur «sait» s'il a besoin de grandir pour accueillir tous ses enfants, ou de rétrécir pour conserver de l'espace.

Alors que les mesures déterminent la taille des articles, leur emplacement est calculé par une routine distincte appelée «arrangement». Cette logique prend soin de conserver la mise en page du rapport telle que définie dans le concepteur. Un exemple très courant est montré sur l'image ci-dessous:

 La mise en page conçue a deux cases: [=Fields.LoremIpsum] et [=Fields.Translation]. Le document rendu a deux boîtes similaires avec du texte qui contient un paragraphe complet, la première en latin, la seconde en anglais.

Ici, nous avons deux TextBoxes empilées les unes sur les autres. Le texte du haut doit être affiché sur quelques lignes lors du rendu. Si leurs positions restent les mêmes, leur contenu se chevaucherait. La logique de disposition «pousse» la deuxième zone de texte vers le bas pour qu’elle reste telle qu’elle a été conçue. La même logique est appliquée lorsqu'un élément, c'est-à-dire CrossTab, grandit horizontalement et que les éléments de son côté droit doivent être poussés latéralement.

Paging

Une fois tous les éléments mesurés et arrangés, il est temps de les placer sur le pages. Comme je l'ai expliqué ci-dessus, certains formats de rendu rendent leur contenu en utilisant la pagination logique sur une seule page logique, et d'autres, sur de vraies pages physiques. Voyons à quoi cela ressemblerait si notre exemple était rendu au format PDF, qui est un format de rendu de page physique.

 L'algorithme de traitement de l'arbre / de pagination pointe vers la page 2 ... page 1, pointe vers la file d'attente de redéfinition, pointe vers Extension de rendu PDF, pointe vers PDF 2 ... PDF 1.

Le moteur génère une seule page – une structure de données qui contiendra un ou plusieurs éléments de l'arborescence de traitement. La logique commence à énumérer les éléments de traitement dans la hiérarchie, crée leurs représentations de pagination légères appelées «éléments de pagination» et les ajoute à la collection d'éléments de la page. Le processus continue jusqu'à ce qu'il trouve un élément dont les coordonnées dépassent les coordonnées de la page. Cela signifie que la page actuelle est déjà remplie et doit être envoyée pour le rendu.

Dans les versions précédentes de Telerik Reporting, la logique de préparation de page et la logique de rendu de page étaient exécutées de manière synchrone. Lorsqu'une page était préparée, le moteur commençait son rendu et attendait que la routine de rendu ait terminé son travail. Nous avons reconnu cela comme un domaine à améliorer, car la préparation de la page est généralement effectuée plus rapidement que le rendu réel.Ainsi, à partir de R3 2020, la logique de rendu est exécutée de manière asynchrone en utilisant le modèle classique producteur-consommateur. Ainsi, au lieu d'attendre la fin du rendu, la logique de pagination commence à préparer une nouvelle page une fois que la précédente est déclarée terminée. C'est ici que la logique complexe de conservation des éléments entre en jeu: lorsqu'un élément est positionné sur plus d'une page, le moteur passe par sa définition et décide s'il faut déplacer tout l'élément sur la page suivante ou en laisser une partie sur

Une fois qu'une page est terminée et ajoutée à la file d'attente du producteur pour le rendu, l'algorithme de pagination crée une nouvelle page. Il peut s'agir d'une nouvelle page horizontale, si le rapport contient des éléments qui s'étendent horizontalement sur plusieurs pages, ou il peut s'agir d'une nouvelle page verticale. Le moteur continue son énumération de la hiérarchie de traitement, ajoutant les éléments de pagination à la nouvelle page jusqu'à ce qu'elle soit remplie, l'envoie pour le rendu et la routine se répète jusqu'à ce que tous les éléments de traitement soient énumérés. À ce stade, le processus de rendu aurait certainement dû commencer – voyons comment cela se passe.

Rendu natif

Jusqu'à présent, le flux de travail suit un modèle commun – depuis la création de l'arbre de traitement, en passant par les mesures et les arrangements et plus à la routine de pagination – c'est presque le même quelle que soit l'extension de rendu. Cependant, les algorithmes de rendu réels diffèrent considérablement les uns des autres. Ils ont une entrée commune – les pages, ajoutées à la file d'attente de rendu par l'algorithme de pagination – mais leur sortie peut être un fichier graphique, une page HTML ou un rédacteur XAML.

Quelle que soit la sortie sélectionnée, le moteur essaiera toujours d’utiliser les primitives natives du format lors du rendu. Par exemple, lors du rendu d'un rapport contenant un graphique, à l'aide de l'extension de rendu HTML, le graphique sera rendu comme un élément de balisage SVG, plutôt que de le rendre comme une seule image bitmap. Cela permet une meilleure interactivité et un rendu de haute qualité par le navigateur à n'importe quel niveau de zoom. Cependant, le rendu natif signifie que chaque extension de rendu a des limitations différentes imposées par l'API que nous utilisons. Une telle limitation est, par exemple, le rendu des info-bulles. Certains des formats de rendu comme les info-bulles de support HTML de manière native; d'autres, comme le PDF, via des annotations de texte, et certains, comme les formats de rendu d'image, ne prennent pas du tout en charge les info-bulles. Les limitations de chaque extension de rendu sont répertoriées dans un article sur les «considérations de conception» de notre documentation et doivent être examinées avant de sélectionner un format de rendu cible pour notre rapport.

Voyons comment le rendu PDF réel de notre rapport est effectué. Lorsque le processus de rendu est lancé, l'extension de rendu crée une instance d'une classe appelée PdfDocument et définit ses attributs obligatoires tels que la structure racine, les dictionnaires internes, etc. Lorsque l'algorithme de pagination envoie une page pour le rendu, la routine de rendu la sélectionne et commence à parcourir les éléments placés sur cette page. Chaque élément a déjà ses coordonnées de page calculées et son texte ou d'autres données visuelles évaluées.

L'extension de rendu conserve une collection de classes d'écriture spécifiques qui sont spécialisées dans le rendu d'un type d'élément particulier. Ainsi, lorsqu'un élément doit être écrit sur la page PDF, le moteur choisit le rédacteur approprié en fonction du type d'élément et appelle sa méthode qui écrira le contenu de l'élément sur la page. Par exemple, le rédacteur TextBox démarrera le processus d'écriture en configurant la matrice de transformation de texte et en ouvrant un nouvel objet texte. Ensuite, il obtiendra la police actuelle utilisée par la zone de texte et s'assurera qu'elle existe dans le dictionnaire de polices du PDF. Après cela, le rédacteur recalculera les coordonnées pour s'adapter à la page actuelle, définira la position du texte et affichera les glyphes de texte. Si nécessaire, le rédacteur TextBox ajoutera également des décorations de texte comme le soulignement et le barré. Enfin, il fermera l'objet texte et restaurera la matrice de transformation de texte. La procédure se répète pour chaque élément de pagination de la page jusqu'à ce qu'il soit complètement rendu à l'aide des primitives PDF natives.

Contrôle de l'extension de rendu

Chaque extension de rendu a des paramètres qui peuvent être configurés via une classe appelée paramètres d'informations de périphérique . Ces paramètres peuvent être définis par programme ou via le fichier de configuration de l'application: app.config pour les applications .NET Framework ou appsettings.json pour les applications .NET Core.

Lors du rendu d'un rapport par programme avec la classe ReportProcessor, les paramètres des informations de périphérique sont représentés par une instance Hashtable . Les clés de cette table de hachage sont les noms des paramètres répertoriés dans l'article de documentation correspondant. La valeur de chaque clé doit être conforme aux valeurs disponibles pour cette clé ou correspondre au type de valeur attendu. Toutes les clés prises en charge et leurs valeurs sont répertoriées dans les articles de documentation pour chaque extension de rendu.

Par exemple, si nous voulons que tous les rapports soient rendus au format PDF pour se conformer à la norme PDF / A-1b, nous devons ajouter une section de configuration dans notre fichier app.config comme celle-ci ci-dessous:

< Telerik.Reporting >

< extensions >

< render >

< extension nom = "PDF" >

< paramètres >

<[19659077] paramètre nom = "ComplianceLevel" valeur = [1 9659089] "PDF / A-1b" />

</ paramètres >

</ extension >

</ render >

</ extensions >

</ Telerik.Reporting >

Si nous devons le faire par programmation, nous pouvons initialiser les paramètres des informations de l'appareil tout en les passant au processeur de rapports:

var reportSource = new Telerik.Reporting.UriReportSource ()

{

[1 9459039] Uri = "Pays.trdx"

};

var deviceInfo = new Hashtable ()

{

{ "ComplianceLevel" "PDF / A-1b" }

} ;

var result = new Telerik.Reporting.Processing.ReportProcessor (). RenderReport ( "PDF" reportSource, deviceInfo);

Les paramètres d'informations sur l'appareil transmis

Rendering Performance

Le temps qu'il faudra au moteur pour terminer l'étape de rendu dépend principalement de la structure du rapport. Naturellement, plus le moteur doit rendre d'éléments, plus il avance lentement. Dans de nombreux cas, le nombre d'éléments dans le rapport peut être réduit sans affecter la mise en page, et je donnerai ci-dessous quelques exemples à ce sujet.

Une erreur courante consiste à utiliser des éléments TextBox séparés pour former une phrase ou juste un ligne de texte. Considérez la conception suivante:

 Dans quatre cases distinctes: Destinataire:, M., [=Field.FirstName][=Fields.SecondName]

Ici, nous avons quatre TextBoxes qui forment le titre et les noms du destinataire. Tous peuvent être remplacés par un seul TextBox avec l'expression suivante:

 Recipient: Mr. {Fields.FirstName} {Fields.SecondName} 

En plus de réduire le nombre de TextBox à traiter et rendre, cette approche permettra également améliorer l'apparence du document rendu, car la conception d'origine laisserait des espaces entre les premier et deuxième noms.

Un autre exemple d'utilisation d'éléments de rapport redondants est un scénario dans lequel des éléments de forme ont été utilisés pour dessiner des bordures entre des zones de texte dans une tentative de créer une disposition en forme de grille. Étant donné que les éléments de forme ont été placés dans la section des détails, l'arborescence de traitement était surchargée par une quantité énorme d'éléments de traitement de forme qui devaient être mesurés, arrangés et rendus dans le document de sortie. Tout cela pourrait être évité en utilisant simplement la propriété Borders des éléments TextBox – et cela fournirait même un meilleur résultat.

Hormis l'optimisation de la quantité d'éléments de rapport, leur positionnement est également très important et peut entraîner des problèmes de performances s'il n'est pas effectué correctement. L'erreur la plus courante est de permettre à un élément de rapport de se développer latéralement, provoquant ainsi la création d'une page horizontale supplémentaire. Le moteur de pagination conservera cette mise en page et continuera à générer des pages vierges, bien qu'il n'y ait aucun élément de rapport dessus. Dans notre dernière version, R1 2021, nous avons introduit une amélioration qui, par défaut, ignore les pages vierges, mais elles seront toujours générées, il est donc préférable de s'assurer que les éléments du rapport ne sortent pas de la taille de page conçue.

étape de traitement, le moteur garde une trace du temps écoulé pendant l'étape de rendu et le sort dans le flux Trace une fois que c'est fait. Cette mesure du temps peut être utile pour affiner un rapport et rechercher les meilleures performances.

Conclusion

Le moteur de rendu de Telerik Reporting est un ensemble élaboré de règles et de procédures. Bien qu'assez mature, il est constamment amélioré et optimisé afin de fournir un ensemble riche de fonctionnalités et les meilleures performances sans sacrifier la convivialité. Due to its complexity, it is not always straightforward to achieve the desired results even for experienced users. With this article I believe I managed to describe in details the main stages in the report lifecycle and answer the questions you were having. I hope you enjoyed reading the article at least as much as I enjoyed writing it. In case I failed to explain well enough some of the concepts, or just skipped a particularly interesting subject, I would appreciate it if you'd drop a line or two in the comments below.

Learn More and Try for Yourself

Want to try it out for yourself? You can learn more about Telerik Reporting and Telerik Report Server and start free trials at the links below.

Try Telerik Reporting

Also Available in Telerik DevCraft

Both Telerik Reporting and Telerik Report Server are also available as part of Telerik DevCraft.

DevCraft is the most powerful collection of Telerik .NET and Kendo UI JavaScript developer tools, which includes modern, feature-rich and professionally designed UI components for web, desktop and mobile applications, reporting and report management solutions, document processing libraries, automated testing and mocking tools. DevCraft will arm you with everything you need to deliver outstanding applications in less time and with less effort. With award-winning technical support delivered by the developers who built the products and a ton of resources and trainings, you can rest assured that you have a stable provider to rely on for your everyday challenges along your software development journey. Learn more about Telerik DevCraft.

Try Telerik DevCraft




Source link