[{"data":1,"prerenderedAt":4898},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fcapabilities\u002Freports":3,"docs-nav":4686},{"id":4,"title":5,"body":6,"description":4677,"extension":4678,"meta":4679,"navigation":4681,"path":4682,"seo":4683,"stem":4684,"__hash__":4685},"docs\u002Fdocs\u002Fcapabilities\u002Freports.md","Pixel-perfect reports",{"type":7,"value":8,"toc":4643},"minimark",[9,13,34,53,60,71,76,226,230,266,271,291,294,349,352,356,362,494,514,520,560,564,576,583,589,616,620,633,743,784,809,815,826,837,958,961,965,968,1016,1030,1040,1063,1083,1087,1101,1251,1279,1288,1294,1307,1311,1319,1943,1950,1953,1970,2186,2307,2311,2314,2481,2494,2501,2504,2513,2541,2565,2571,2576,2580,2598,2761,2821,2843,2850,2854,2864,2870,2892,2938,2944,2956,2972,2976,2998,3004,3013,3033,3036,3047,3053,3069,3073,3135,3141,3146,3150,3153,3177,3180,3184,3191,3197,3202,3206,3209,3283,3295,3298,3304,3323,3405,3412,3419,3425,3432,3436,3439,3485,3495,3502,3505,3509,3532,3536,3542,3548,3690,3693,3697,3706,3712,3839,3854,3857,3861,3871,4463,4477,4481,4511,4534,4538,4581,4585,4639],[10,11,5],"h1",{"id":12},"pixel-perfect-reports",[14,15,16,17,21,22,25,26,29,30,33],"p",{},"A report is a page of fixed size, designed in the browser to the tenth of a millimetre:\na header and a footer on every page, tables that group and subtotal over as many pages\nas the data needs, charts, gauges and KPI cards, texts written with expressions. It is\nan object of a folder, with its versions, like a flow or a SQL script. Readers open it\non screen with its parameters and download it as ",[18,19,20],"strong",{},"PDF"," or ",[18,23,24],{},"Excel","; a flow group\n",[18,27,28],{},"sends it by email"," right after the data it shows is refreshed; a script downloads it\nthrough the ",[18,31,32],{},"API",".",[14,35,36,37,42,43,47,48,52],{},"Use the ",[38,39,41],"a",{"href":40},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis#the-viewer","Viewer"," to explore a datasource: filters,\npivots and charts that change as you ask. Use a report when the answer has to arrive as\na document: the same layout every month, page numbers and totals in their place, for\npeople who never open Tabularia and read it as a PDF or in their inbox. Use a\n",[38,44,46],{"href":45},"\u002Fdocs\u002Fcapabilities\u002Fdashboards","dashboard"," when the screen is the answer: tiles on a grid that adapt to the\nwindow and filter each other at a click. Every installation has reports, Docker Compose\nincluded, and the sample data comes with ",[38,49,51],{"href":50},"#the-sample-reports","two of them"," to open and study.",[14,54,55],{},[56,57],"img",{"alt":58,"src":59},"The report designer: the page in millimetres with its header, three KPI cards, a combo chart, a table grouped by category and a matrix; the elements on the left, the selected table's properties on the right","\u002Fmedia\u002Fguide\u002Freports\u002Fdesigner-monthly-margin.png",[14,61,62],{},[63,64,65,66,70],"em",{},"The designer with the report of the ",[38,67,69],{"href":68},"#example-a-monthly-margin-report","example below",": the table is selected, its rows labelled on the right of the page (header, group, rows, the group's total, the grand total), its properties in the panel.",[72,73,75],"h2",{"id":74},"at-a-glance","At a glance",[77,78,79,90],"table",{},[80,81,82],"thead",{},[83,84,85,88],"tr",{},[86,87],"th",{},[86,89],{},[91,92,93,114,126,139,151,167,180,203,211],"tbody",{},[83,94,95,99],{},[96,97,98],"td",{},"Where",[96,100,101,102,105,106,109,110,113],{},"Explore → ",[18,103,104],{},"New"," → ",[18,107,108],{},"Report",", in a folder; it opens in the designer. Readers open it in the viewer from Explore or from ",[18,111,112],{},"Analysis → Reports",", the most read first",[83,115,116,119],{},[96,117,118],{},"What it reads",[96,120,121,122,125],{},"up to 20 ",[18,123,124],{},"datasets",": SQL on the catalog or on a database connection, a datasource, a saved view, a saved SQL script",[83,127,128,131],{},[96,129,130],{},"What it shows",[96,132,133,134,138],{},"texts and expressions, images, lines, rectangles, tables and matrices with groups and totals, 14 kinds of chart, KPI cards, and an ",[38,135,137],{"href":136},"#ai-comments","AI comment"," on the numbers",[83,140,141,144],{},[96,142,143],{},"Parameters",[96,145,146,147],{},"text, number, date or yes\u002Fno, one value or several, fixed choices or choices from a dataset; in the SQL as ",[148,149,150],"code",{},"{name}",[83,152,153,156],{},[96,154,155],{},"Formats",[96,157,158,160,161,163,164],{},[18,159,20],{}," (the page as designed), ",[18,162,24],{}," (the tables with their groups and subtotals), the ",[18,165,166],{},"summary in an email",[83,168,169,172],{},[96,170,171],{},"Sending",[96,173,174,175,179],{},"from a flow group's ",[38,176,178],{"href":177},"\u002Fdocs\u002Fpushmail#reports","Pushmail"," cell, after the steps that refresh the data; a report has no schedule of its own",[83,181,182,185],{},[96,183,184],{},"From code",[96,186,187,190,191,194,195,198,199],{},[148,188,189],{},"GET \u002Freports\u002F{id}\u002Frender"," with an API token (",[38,192,32],{"href":193},"\u002Fdocs\u002Fapi#download-a-report","), ",[148,196,197],{},"tabularia.report()"," in a ",[38,200,202],{"href":201},"\u002Fdocs\u002Fcapabilities\u002Fnotebooks#reports","marimo notebook",[83,204,205,208],{},[96,206,207],{},"Rights",[96,209,210],{},"VIEW on the folder to open and download it, EDIT to design it; the data is read with the rights of whoever reads the report",[83,212,213,216],{},[96,214,215],{},"Limits",[96,217,218,219,225],{},"3,000,000 rows per dataset and 200 pages per render by default (",[38,220,222],{"href":221},"\u002Fdocs\u002Fconfiguration#reports-1",[148,223,224],{},"REPORTS__*",")",[72,227,229],{"id":228},"the-designer","The designer",[14,231,232,235,236,239,240,243,244,247,248,243,251,247,254,257,258,261,262,265],{},[18,233,234],{},"New → Report"," in a folder creates «New report» and opens it in the designer. The bar\nat the top holds the report's name (write over it to rename), its folder, whether it is\nsaved and its version, undo and redo, the zoom, ",[18,237,238],{},"Snap to the millimetre grid",",\n",[18,241,242],{},"Page setup",", ",[18,245,246],{},"Design"," and ",[18,249,250],{},"Preview",[18,252,253],{},"Save",[18,255,256],{},"Done"," (save and open the\nreport as readers see it). The page sits in the middle with its rulers in millimetres;\non the left, ",[18,259,260],{},"Insert"," holds the elements and ",[18,263,264],{},"Data"," the datasets and the parameters;\non the right, the properties of what is selected: an item, a band (a click on its name\nbeside the page) or, with nothing selected, the report.",[267,268,270],"h3",{"id":269},"the-page-and-its-bands","The page and its bands",[14,272,273,275,276,279,280,283,284,247,287,290],{},[18,274,242],{}," sets the paper (A4, A3, A5, Letter, Legal or a size of your own in\nmillimetres), the orientation and the four margins; the ",[18,277,278],{},"language"," of the report\n(English, Italian, German, Spanish, French: the separators of the numbers, the names of\nmonths and days, and the words the report writes by itself, «Page 1 of 3», «Total»); its\n",[18,281,282],{},"time zone"," (",[148,285,286],{},"{today}",[148,288,289],{},"NOW()"," are read in it); and the theme: the font (the PDF\nembeds IBM Plex Sans), its size, the text colour and the accent that colours the charts\nand the sparklines.",[14,292,293],{},"A page has three bands:",[77,295,296,306],{},[80,297,298],{},[83,299,300,303],{},[86,301,302],{},"Band",[86,304,305],{},"What it holds",[91,307,308,336],{},[83,309,310,318],{},[96,311,312,243,315],{},[18,313,314],{},"Page header",[18,316,317],{},"Page footer",[96,319,320,321,247,324,327,328,331,332,335],{},"a fixed height, printed on every page; ",[18,322,323],{},"Also on the first page",[18,325,326],{},"Also on the last page"," turned off leave them out there. Texts, images, lines and rectangles only: what is the same on every page (a title, a logo, the parameters chosen, ",[148,329,330],{},"\"Page \" & PAGE() & \" of \" & PAGES()","). A field of a dataset is refused here; an aggregate of a named dataset, ",[148,333,334],{},"SUM([amount], \"orders\")",", is not",[83,337,338,343],{},[96,339,340],{},[18,341,342],{},"Body",[96,344,345,346,348],{},"flows over the pages. Items whose heights overlap make a row and are placed side by side; a ",[18,347,77],{}," takes its row alone, grows with its data and pushes down what is under it (an item dropped beside a table goes under it)",[14,350,351],{},"Every position and size is in millimetres, to a tenth. Items snap to the millimetre grid\nwhile you drag them; the edges and centres of the other items always guide. Held near an\nedge of the page's area, a dragged item scrolls it. Where items overlap, the one drawn\nlast is on top: in the header and the footer the one added last, in the body the one\nlower on the page (then the one more to the right), in the designer as in the PDF: a\nrectangle meant as a background starts at or above the texts it frames.",[267,353,355],{"id":354},"elements","Elements",[14,357,358,359,361],{},"Drag an element from ",[18,360,260],{}," onto the page, or click it to add it under what the page\nholds already:",[77,363,364,374],{},[80,365,366],{},[83,367,368,371],{},[86,369,370],{},"Element",[86,372,373],{},"What it is",[91,375,376,401,421,434,448,458,472,482],{},[83,377,378,383],{},[96,379,380],{},[18,381,382],{},"Text",[96,384,385,386,389,390,393,394,397,398],{},"text as written, or an ",[18,387,388],{},"expression"," when it starts with ",[148,391,392],{},"=",": ",[148,395,396],{},"=\"Sales in \" & PARAM(\"region\")",". Size, weight, italic, colours, alignment, padding, border, a format, and ",[18,399,400],{},"Grows with a long text",[83,402,403,408],{},[96,404,405],{},[18,406,407],{},"Image",[96,409,410,411,243,414,21,417,420],{},"a PNG, JPEG or SVG of at most 512 KiB, kept inside the report (never a link): ",[18,412,413],{},"Whole",[18,415,416],{},"Fill",[18,418,419],{},"Stretch",". An SVG that links outside itself or runs scripts is refused when the report is saved",[83,422,423,431],{},[96,424,425,243,428],{},[18,426,427],{},"Line",[18,429,430],{},"Rectangle",[96,432,433],{},"a rule, a frame or a coloured band",[83,435,436,441],{},[96,437,438],{},[18,439,440],{},"Table",[96,442,443,444],{},"the rows of a dataset, with columns, groups, subtotals and totals: ",[38,445,447],{"href":446},"#tables-and-matrices","tables and matrices",[83,449,450,455],{},[96,451,452],{},[18,453,454],{},"Matrix",[96,456,457],{},"a table with one column per value of a field",[83,459,460,465],{},[96,461,462],{},[18,463,464],{},"Chart",[96,466,467,468],{},"14 kinds, chosen when it is placed: ",[38,469,471],{"href":470},"#charts-and-kpis","charts and KPIs",[83,473,474,479],{},[96,475,476],{},[18,477,478],{},"KPI",[96,480,481],{},"one value in large type, its change against another and a sparkline",[83,483,484,488],{},[96,485,486],{},[18,487,137],{},[96,489,490,491],{},"a short text the configured AI model writes on the numbers of the elements you pick: ",[38,492,493],{"href":136},"below",[14,495,496,499,500,243,503,243,506,509,510,513],{},[18,497,498],{},"Ready-made texts"," are texts written for you: ",[18,501,502],{},"Page number of total",[18,504,505],{},"Date and time\nof printing",[18,507,508],{},"The report's name",", and ",[18,511,512],{},"Value of …"," for each parameter.",[14,515,516,517,519],{},"In ",[18,518,264],{},", a field dragged onto a table becomes a new column, and anywhere else in the\nbody a text that shows it; a click on a field adds it as a column to the selected table.\nA table reads one dataset: a field of another is refused.",[14,521,522,523,526,527,247,530,533,534,194,537,540,541,247,544,547,548,551,552,555,556,559],{},"The keys: ",[18,524,525],{},"Ctrl+S"," saves, ",[18,528,529],{},"Ctrl+Z",[18,531,532],{},"Ctrl+Shift+Z"," undo and redo; on the page,\nthe arrows move the selected item by 1 mm (5 mm with ",[18,535,536],{},"Shift",[18,538,539],{},"Ctrl+D"," duplicates\nit, ",[18,542,543],{},"Ctrl+C",[18,545,546],{},"Ctrl+V"," copy and paste, ",[18,549,550],{},"Del"," removes it. A copy can be pasted\ninto another report, open in another tab too; if it read a dataset that report does not\nhave, it reads its only dataset, or waits for one to be chosen, and says so. ",[18,553,554],{},"Tab","\ngoes through the bands' names and the items; ",[18,557,558],{},"Enter"," on a band's name selects it.",[267,561,563],{"id":562},"saving-and-the-preview","Saving and the preview",[14,565,566,568,569,572,573,575],{},[18,567,253],{}," keeps the report as a new version. The server checks the whole definition at\nevery save: a field that does not exist, a function with the wrong arguments, a text\nadded to a number. A save it refuses lists the problems in the bar; the first item is\nselected and the message sits under its field, with the character where the mistake\nis. The expression fields check what they can while you type: an expression you are still\nwriting (",[148,570,571],{},"SUM([ric",") is not a mistake, and is said only if you leave the field that way; one\nthat is finished and wrong is said at once. After a pause the server checks the report as\na save would (the types, where a field may be used, the formats) and says what it finds\nunder the same fields. If someone else saved\nthe report since you opened it, ",[18,574,253],{}," says so and asks before your version becomes\nthe newest: theirs stays among the versions.",[14,577,578,580,581,33],{},[18,579,250],{}," renders the report as it is on screen, saved or not, with the values of its\nparameters you choose in the same form the viewer has (the lists read from a dataset\nincluded): the same renderer as the PDF, so what you see is what will print. A report with mistakes is not rendered: the preview lists them, and a click on one\ntakes you to its field in ",[18,582,246],{},[14,584,585],{},[56,586],{"alt":587,"src":588},"In the designer a table is dragged under the chart; the fields Month, ricavo, costo and margine are dragged into it one after the other; a group by categoria adds the group's row, with no total yet; Sum is chosen in the Total list of ricavo, costo and margine, and the group's total row appears; Preview renders the page with the parameters above it; Salami chosen in Category and View report render that category, down to its total","\u002Fmedia\u002Fguide\u002Freports\u002Fdesigner-table-group-preview.gif",[14,590,591],{},[63,592,593,594,597,598,601,602,605,606,608,609,612,613,33],{},"A table under the chart: four fields dragged into it, a group by ",[148,595,596],{},"[categoria]"," written in its properties. A new column has no total: ",[18,599,600],{},"Sum",", chosen in the ",[18,603,604],{},"Total"," of each amount, brings the group's total row. ",[18,607,250],{}," asks for the parameters as the viewer does, here ",[18,610,611],{},"Category"," ",[148,614,615],{},"Salami",[72,617,619],{"id":618},"datasets-and-parameters","Datasets and parameters",[14,621,622,623,626,627,243,629,632],{},"A ",[18,624,625],{},"dataset"," is a set of rows the report reads; the items of the report each read one.\nIn ",[18,628,264],{},[18,630,631],{},"+ Dataset",":",[77,634,635,644],{},[80,636,637],{},[83,638,639,642],{},[86,640,641],{},"Data from",[86,643,118],{},[91,645,646,678,716,731],{},[83,647,648,653],{},[96,649,650],{},[18,651,652],{},"SQL",[96,654,655,656,659,660,664,665,668,669,672,673,677],{},"a query on the ",[18,657,658],{},"catalog"," (the datasources you may read, by name, on the engine you choose, as in a ",[38,661,663],{"href":662},"\u002Fdocs\u002Fsql-scripts","SQL script",") or on a ",[18,666,667],{},"database connection"," (in the database's own dialect, with ",[18,670,671],{},"CONNECT"," on the connection's folder). Only a query runs, as in a SQL script; as there, the barrier is ",[38,674,676],{"href":675},"\u002Fdocs\u002Fsql-scripts#on-a-database-connection","a read-only database user"," on the connection",[83,679,680,685],{},[96,681,682],{},[18,683,684],{},"Datasource",[96,686,687,688,691,692,612,694,612,697,612,700,612,703,612,706,612,709,612,712,715],{},"a datasource as it is, with optional ",[18,689,690],{},"filters"," (a column, ",[148,693,392],{},[148,695,696],{},"\u003C>",[148,698,699],{},"\u003C",[148,701,702],{},"\u003C=",[148,704,705],{},">",[148,707,708],{},">=",[148,710,711],{},"in",[148,713,714],{},"contains",", a value or a parameter) applied before the rows are read",[83,717,718,723],{},[96,719,720],{},[18,721,722],{},"Saved view",[96,724,725,726,730],{},"a ",[38,727,729],{"href":728},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis#saved-views","saved view"," with its filters, computed fields and pivot, plus filters of its own",[83,732,733,737],{},[96,734,735],{},[18,736,663],{},[96,738,739,740,742],{},"a saved ",[38,741,663],{"href":662},", its current version, on its catalog or connection: whoever changes the script changes the report. Its parameters are the report's",[14,744,745,746,243,748,751,752,755,756,759,760,763,764,767,768,771,772,776,777,243,780,783],{},"A parameter goes in the SQL as ",[148,747,150],{},[18,749,750],{},"without quotes",": Tabularia writes its value\nas a literal of the dialect, never as text pasted into the query. A text is quoted and\nescaped, a number checked as a number, a date written ",[148,753,754],{},"DATE 'yyyy-mm-dd'",", a list\n",[148,757,758],{},"(a, b, c)"," for ",[148,761,762],{},"IN {regions}"," (an empty list stops the render and says so). A parameter\nwritten inside quotes, ",[148,765,766],{},"'{region}'",", is refused: «write ",[148,769,770],{},"{region}"," without quotes:\nTabularia quotes it». Tabularia's own ",[38,773,775],{"href":774},"\u002Fdocs\u002Fplaceholders","placeholders"," work too,\n",[148,778,779],{},"{today-30}",[148,781,782],{},"{start_of_month}",", read in the report's time zone.",[14,785,786,789,790,793,794,796,797,800,801,804,805,808],{},[18,787,788],{},"Fields"," are the columns the designer last read from the data (",[18,791,792],{},"Refresh fields","):\nthey feed the completion and the checks; the render uses what the data has.\n",[18,795,792],{}," also counts the dataset's rows with the parameters' defaults and shows\nthe number under the dataset: past 500,000 rows an orange warning gives the time a render\nwill take, past ",[148,798,799],{},"REPORTS__MAX_ROWS"," a red one says the report will not render. Aggregate\nin the SQL and format in the report: ",[148,802,803],{},"SELECT region, SUM(amount) AS amount FROM orders GROUP BY region"," gives the report one row per region, not one per order.\n",[18,806,807],{},"Calculated fields"," are expressions computed for every row, used as any other field.",[14,810,811],{},[56,812],{"alt":813,"src":814},"The dataset dialog: the dataset margins, SQL on the catalog with DuckDB, a query with category and since as parameters, two calculated fields Month and MarginPct, and the fields read","\u002Fmedia\u002Fguide\u002Freports\u002Fdataset-dialog-sql.png",[14,816,817],{},[63,818,819,820,247,823,33],{},"The dataset of the example: the SQL with its two parameters in braces (the chips under the editor insert them), the calculated fields ",[148,821,822],{},"Month",[148,824,825],{},"MarginPct",[14,827,622,828,831,832,243,834,632],{},[18,829,830],{},"parameter"," is a value the reader chooses. In ",[18,833,264],{},[18,835,836],{},"+ Parameter",[77,838,839,848],{},[80,840,841],{},[83,842,843,846],{},[86,844,845],{},"Field",[86,847],{},[91,849,850,877,887,912,922,937],{},[83,851,852,857],{},[96,853,854],{},[18,855,856],{},"Name",[96,858,859,860,863,864,243,867,870,871,873,874],{},"letters, digits and ",[148,861,862],{},"_","; not a name of Tabularia's placeholders (",[148,865,866],{},"today",[148,868,869],{},"now","…). In the SQL ",[148,872,150],{},", in an expression ",[148,875,876],{},"PARAM(\"name\")",[83,878,879,884],{},[96,880,881],{},[18,882,883],{},"Label in the form",[96,885,886],{},"what the reader sees",[83,888,889,894],{},[96,890,891],{},[18,892,893],{},"Type",[96,895,896,243,898,243,901,21,904,907,908,911],{},[18,897,382],{},[18,899,900],{},"Number",[18,902,903],{},"Date",[18,905,906],{},"Yes or no","; ",[18,909,910],{},"Several values"," makes it a list",[83,913,914,919],{},[96,915,916],{},[18,917,918],{},"Required",[96,920,921],{},"the report does not render without a value",[83,923,924,929],{},[96,925,926],{},[18,927,928],{},"Default",[96,930,931,932,243,934],{},"used when the reader gives none: a value, or for a date a placeholder resolved at every render, ",[148,933,779],{},[148,935,936],{},"{start_of_month-1m}",[83,938,939,944],{},[96,940,941],{},[18,942,943],{},"Choices",[96,945,946,949,950,953,954,957],{},[18,947,948],{},"Any value",", a ",[18,951,952],{},"Fixed list"," (one per line), or ",[18,955,956],{},"From a dataset"," (an expression for the value and one for the label shown)",[14,959,960],{},"Values arrive as text (the viewer's form, a flow group's cell, the query string of the\nAPI) and are converted and checked against the type and the choices before anything\nruns: a value that does not fit stops the render with the parameter's name.",[267,962,964],{"id":963},"a-parameter-that-filters-the-data","A parameter that filters the data",[14,966,967],{},"The usual parameter takes its choices from a field of a dataset, and filters that same\ndataset by what the reader chooses:",[969,970,971,991,1009],"ol",{},[972,973,974,976,977,243,980,983,984,987,988,33],"li",{},[18,975,836],{},": a name, ",[148,978,979],{},"regione",[18,981,982],{},"Choices → From a dataset",", the dataset and, as\n",[18,985,986],{},"Value",", the field: ",[148,989,990],{},"[area]",[972,992,993,994,997,998,1001,1002,1005,1006,1008],{},"With a datasource or a saved view, ",[18,995,996],{},"Filter this dataset by what is chosen"," is already\nticked: it adds the filter ",[148,999,1000],{},"area = {regione}"," to the dataset (",[148,1003,1004],{},"area in {regione}"," with\n",[18,1007,910],{},"), and takes it away when you untick it.",[972,1010,1011,1012,1015],{},"With a SQL or a SQL script the query stays as you wrote it: the dialog shows the line\nto add, ",[148,1013,1014],{},"WHERE {regione} IS NULL OR area = {regione}",", with a button that copies it.",[14,1017,1018,1019,1022,1023,1025,1026,1029],{},"That is all. The list always shows every value of the field, whatever is chosen: to read\nit Tabularia leaves out what depends on that parameter, while the report itself applies\nthe filter. If the parameter is not required, with nothing chosen (",[18,1020,1021],{},"Any",") every row stays.\nWith ",[18,1024,910],{}," a SQL needs at least one value (",[148,1027,1028],{},"IN {regione}","), and the report\nasks for it; a filter on a datasource or a view lets every row through with none.",[14,1031,1032,1033,1035,1036,1039],{},"Several parameters on one dataset work the same way, and follow the order of the form:\nadd ",[148,1034,979],{},", then ",[148,1037,1038],{},"agente",", and the agents follow the region while the regions stay all\nthere. To take the choices from somewhere else, a table of regions or a list you curate,\nchoose another dataset as their source: the filter on the data is then yours to add. Two\nlists that follow each other through two different datasets are refused, by name, because\nneither could be chosen first.",[14,1041,1042,1043,1046,1047,1050,1051,1054,1055,1058,1059,1062],{},"In a SQL, Tabularia recognises the conditions on the parameter in the ",[148,1044,1045],{},"WHERE",", the\n",[148,1048,1049],{},"HAVING"," and the ",[148,1052,1053],{},"ON"," of a join, in subqueries too, and takes them for true when it reads\nthe list. Written anywhere else, say in the columns or in a ",[148,1056,1057],{},"LIMIT",", the parameter reads\n",[148,1060,1061],{},"NULL"," for the list, as with no value; if that leaves the list empty, the form says so and\nwhat to do.",[14,1064,1065,1066,1069,1070,1072,1073,1075,1076,247,1079,1082],{},"The value of a filter on a datasource or a view is chosen in the dataset's dialog: ",[18,1067,1068],{},"A\nvalue written here",", or a parameter of the report, by its label and name. A parameter of\nseveral values sets the operator to ",[148,1071,711],{},", one of a single value takes it back to ",[148,1074,392],{},", and\nthe dialog says so. Written by hand, ",[148,1077,1078],{},"{regione}",[148,1080,1081],{},"PARAM(\"regione\")"," both become the\nparameter, and a name that does not exist is an error on the spot, with the name you\nprobably meant. Renaming a parameter carries its filters and its SQL with it (a saved SQL\nscript is its own text: the designer tells you to change it there); removing one takes its\nfilters away and tells you which SQL still writes it.",[72,1084,1086],{"id":1085},"expressions","Expressions",[14,1088,1089,1090,1092,1093,1096,1097,1100],{},"Expressions are a small language of Tabularia's own, close to spreadsheet formulas. The\nserver parses and evaluates them, never runs them as code. They go wherever a value is\ncomputed: a text that starts with ",[148,1091,392],{},", a column's value and total, a group's key and\nlabel, a rule's condition, a chart's axis and series, a KPI, a table's ",[18,1094,1095],{},"Rows where","\nand its sort keys, an item's ",[18,1098,1099],{},"Shown when",", a calculated field.",[77,1102,1103,1113],{},[80,1104,1105],{},[83,1106,1107,1110],{},[86,1108,1109],{},"Write",[86,1111,1112],{},"For",[91,1114,1115,1133,1158,1172,1191,1204,1226,1241],{},[83,1116,1117,1122],{},[96,1118,1119],{},[148,1120,1121],{},"[ricavo]",[96,1123,1124,1125,1128,1129,1132],{},"a field; ",[148,1126,1127],{},"]]"," for a ",[148,1130,1131],{},"]"," in its name",[83,1134,1135,1151],{},[96,1136,1137,243,1140,243,1143,243,1146,243,1149],{},[148,1138,1139],{},"\"text\"",[148,1141,1142],{},"12.5",[148,1144,1145],{},"TRUE",[148,1147,1148],{},"FALSE",[148,1150,1061],{},[96,1152,1153,1154,1157],{},"values; ",[148,1155,1156],{},"\"\""," for a quote inside a text",[83,1159,1160,1165],{},[96,1161,1162],{},[148,1163,1164],{},"{today-7}",[96,1166,1167,1168,1171],{},"a date ",[38,1169,1170],{"href":774},"placeholder",", in the report's time zone",[83,1173,1174,1188],{},[96,1175,1176,612,1179,612,1182,612,1185],{},[148,1177,1178],{},"+",[148,1180,1181],{},"-",[148,1183,1184],{},"*",[148,1186,1187],{},"\u002F",[96,1189,1190],{},"arithmetic; a date plus a number moves it by days, a date minus a date is days",[83,1192,1193,1198],{},[96,1194,1195],{},[148,1196,1197],{},"&",[96,1199,1200,1201],{},"joins texts: ",[148,1202,1203],{},"\"Total \" & [region]",[83,1205,1206,1220],{},[96,1207,1208,612,1210,612,1212,612,1214,612,1216,612,1218],{},[148,1209,392],{},[148,1211,696],{},[148,1213,699],{},[148,1215,705],{},[148,1217,702],{},[148,1219,708],{},[96,1221,1222,1223],{},"comparisons, one at a time: join two with ",[148,1224,1225],{},"AND",[83,1227,1228,1238],{},[96,1229,1230,612,1232,612,1235],{},[148,1231,1225],{},[148,1233,1234],{},"OR",[148,1236,1237],{},"NOT",[96,1239,1240],{},"conditions",[83,1242,1243,1248],{},[96,1244,1245],{},[148,1246,1247],{},"SUM(...)",[96,1249,1250],{},"functions, in capitals or not",[14,1252,1253,243,1256,243,1259,243,1262,243,1265,243,1268,1271,1272,1275,1276,1278],{},[148,1254,1255],{},"!=",[148,1257,1258],{},"==",[148,1260,1261],{},"&&",[148,1263,1264],{},"||",[148,1266,1267],{},"^",[148,1269,1270],{},"%"," and texts in single quotes are not part of the\nlanguage: the check says what to write instead. NULL goes through arithmetic and\ncomparisons (",[148,1273,1274],{},"NULL + 1"," is NULL), aggregates skip it, a division by zero is NULL, ",[148,1277,1197],{},"\nwrites it as nothing, and a condition that is NULL is false.",[14,1280,1281,1284,1285,1287],{},[18,1282,1283],{},"Where an aggregate counts."," An aggregate works on the rows of the place it sits in:\nin a group's total row, the group's rows; in the grand total, the table's; in a text, a\nKPI or a chart of the body, the rows of its dataset. A dataset named as the last\nargument, ",[148,1286,334],{},", reads that whole dataset instead, which is the only\nway to show data in the page header and footer. A field written outside a row (in a\ngroup's total row) is the value of the group's first row.",[14,1289,1290],{},[56,1291],{"alt":1292,"src":1293},"The properties of a KPI whose value divides the sum of margine by the sum of ricavo, with the completion open: the fields of the dataset with their types, then the functions, SUM highlighted with its signature and what it does","\u002Fmedia\u002Fguide\u002Freports\u002Fexpression-completion.png",[14,1295,1296],{},[63,1297,1298,1299,1302,1303,1306],{},"The completion (",[18,1300,1301],{},"Ctrl+Space",", or ",[148,1304,1305],{},"["," for the fields): the dataset's fields with their types, the calculated ones, then the functions with their arguments; the highlighted one says what it does.",[267,1308,1310],{"id":1309},"functions","Functions",[14,1312,1313,1314,1318],{},"Every function with its cases and an example on the sample data, with the result it\nprints, is in ",[38,1315,1317],{"href":1316},"\u002Fdocs\u002Fcapabilities\u002Freport-functions","Report functions",", with recipes for a real report:\nthe margin percentage, the growth on the month before, the share of a level you choose,\nthe year before, a value from a price list, the sum of a period, running totals,\nthresholds, dates in titles.",[77,1320,1321,1334],{},[80,1322,1323],{},[83,1324,1325,1328,1331],{},[86,1326,1327],{},"Function",[86,1329,1330],{},"Arguments",[86,1332,1333],{},"Gives",[91,1335,1336,1354,1371,1386,1400,1417,1435,1453,1471,1489,1507,1525,1537,1552,1567,1581,1596,1611,1632,1647,1671,1689,1704,1723,1741,1755,1769,1784,1805,1819,1850,1865,1880,1899,1916,1931],{},[83,1337,1338,1346,1351],{},[96,1339,1340,243,1343],{},[148,1341,1342],{},"SUM",[148,1344,1345],{},"AVG",[96,1347,1348],{},[148,1349,1350],{},"value, [dataset or group]",[96,1352,1353],{},"the sum, the average of the values, NULLs left out",[83,1355,1356,1364,1368],{},[96,1357,1358,243,1361],{},[148,1359,1360],{},"MIN",[148,1362,1363],{},"MAX",[96,1365,1366],{},[148,1367,1350],{},[96,1369,1370],{},"the smallest, the largest value",[83,1372,1373,1378,1383],{},[96,1374,1375],{},[148,1376,1377],{},"COUNT",[96,1379,1380],{},[148,1381,1382],{},"[value], [dataset or group]",[96,1384,1385],{},"how many rows; with a value, how many are not NULL",[83,1387,1388,1393,1397],{},[96,1389,1390],{},[148,1391,1392],{},"COUNTDISTINCT",[96,1394,1395],{},[148,1396,1350],{},[96,1398,1399],{},"how many different values",[83,1401,1402,1410,1414],{},[96,1403,1404,243,1407],{},[148,1405,1406],{},"FIRST",[148,1408,1409],{},"LAST",[96,1411,1412],{},[148,1413,1350],{},[96,1415,1416],{},"the value of the first, the last row",[83,1418,1419,1424,1429],{},[96,1420,1421],{},[148,1422,1423],{},"SUMIF",[96,1425,1426],{},[148,1427,1428],{},"condition, value, [dataset or group]",[96,1430,1431,1432],{},"the sum over the rows where the condition is true: ",[148,1433,1434],{},"SUMIF(YEAR([day]) = 2025, [amount])",[83,1436,1437,1442,1447],{},[96,1438,1439],{},[148,1440,1441],{},"COUNTIF",[96,1443,1444],{},[148,1445,1446],{},"condition, [dataset or group]",[96,1448,1449,1450],{},"how many rows have the condition true: ",[148,1451,1452],{},"COUNTIF([state] = \"open\")",[83,1454,1455,1460,1465],{},[96,1456,1457],{},[148,1458,1459],{},"PERCENT",[96,1461,1462],{},[148,1463,1464],{},"aggregate, [group]",[96,1466,1467,1468],{},"the aggregate as a share of the same one level up, a row of its group, a group of the whole, or of the group named: ",[148,1469,1470],{},"PERCENT(SUM([amount]), \"region\")",[83,1472,1473,1478,1483],{},[96,1474,1475],{},[148,1476,1477],{},"RUNNING",[96,1479,1480],{},[148,1481,1482],{},"aggregate",[96,1484,1485,1486],{},"the running total within the group, row after row: ",[148,1487,1488],{},"RUNNING(SUM([amount]))",[83,1490,1491,1496,1501],{},[96,1492,1493],{},[148,1494,1495],{},"PREVIOUS",[96,1497,1498],{},[148,1499,1500],{},"value",[96,1502,1503,1504],{},"the value on the row above in its group; in a total, on the group before: ",[148,1505,1506],{},"[amount] \u002F PREVIOUS([amount]) - 1",[83,1508,1509,1514,1519],{},[96,1510,1511],{},[148,1512,1513],{},"LOOKUP",[96,1515,1516],{},[148,1517,1518],{},"key, key field, result, [dataset]",[96,1520,1521,1522],{},"the result on the rows whose key field equals the key: a field of the first, an aggregate of them, NULL if there are none: ",[148,1523,1524],{},"LOOKUP([code], [sku], [price], \"prices\")",[83,1526,1527,1532,1534],{},[96,1528,1529],{},[148,1530,1531],{},"ROWNUMBER",[96,1533],{},[96,1535,1536],{},"the number of the row within its group, from 1",[83,1538,1539,1544,1549],{},[96,1540,1541],{},[148,1542,1543],{},"IF",[96,1545,1546],{},[148,1547,1548],{},"condition, value if true, [value if false]",[96,1550,1551],{},"one value or the other; without the third, NULL",[83,1553,1554,1559,1564],{},[96,1555,1556],{},[148,1557,1558],{},"IFS",[96,1560,1561],{},[148,1562,1563],{},"condition1, value1, condition2, value2, …, [else]",[96,1565,1566],{},"the value of the first true condition, else the last argument",[83,1568,1569,1574,1578],{},[96,1570,1571],{},[148,1572,1573],{},"ISNULL",[96,1575,1576],{},[148,1577,1500],{},[96,1579,1580],{},"true when the value is missing",[83,1582,1583,1588,1593],{},[96,1584,1585],{},[148,1586,1587],{},"COALESCE",[96,1589,1590],{},[148,1591,1592],{},"value1, value2, …",[96,1594,1595],{},"the first value that is not missing",[83,1597,1598,1603,1608],{},[96,1599,1600],{},[148,1601,1602],{},"ROUND",[96,1604,1605],{},[148,1606,1607],{},"number, [decimals]",[96,1609,1610],{},"rounded half away from zero, to 0 decimals by default",[83,1612,1613,1624,1629],{},[96,1614,1615,243,1618,243,1621],{},[148,1616,1617],{},"ABS",[148,1619,1620],{},"FLOOR",[148,1622,1623],{},"CEILING",[96,1625,1626],{},[148,1627,1628],{},"number",[96,1630,1631],{},"without its sign, rounded down, rounded up",[83,1633,1634,1639,1644],{},[96,1635,1636],{},[148,1637,1638],{},"POWER",[96,1640,1641],{},[148,1642,1643],{},"number, exponent",[96,1645,1646],{},"a number raised to the exponent",[83,1648,1649,1663,1668],{},[96,1650,1651,243,1654,243,1657,243,1660],{},[148,1652,1653],{},"UPPER",[148,1655,1656],{},"LOWER",[148,1658,1659],{},"TRIM",[148,1661,1662],{},"LEN",[96,1664,1665],{},[148,1666,1667],{},"text",[96,1669,1670],{},"in capitals, in lower case, without spaces at its ends, its length",[83,1672,1673,1681,1686],{},[96,1674,1675,243,1678],{},[148,1676,1677],{},"LEFT",[148,1679,1680],{},"RIGHT",[96,1682,1683],{},[148,1684,1685],{},"text, count",[96,1687,1688],{},"the first, the last characters",[83,1690,1691,1696,1701],{},[96,1692,1693],{},[148,1694,1695],{},"MID",[96,1697,1698],{},[148,1699,1700],{},"text, start, count",[96,1702,1703],{},"part of a text, from a position (1 is the first character)",[83,1705,1706,1711,1716],{},[96,1707,1708],{},[148,1709,1710],{},"REPLACE",[96,1712,1713],{},[148,1714,1715],{},"text, old, new",[96,1717,1718,1719,1722],{},"every occurrence of ",[148,1720,1721],{},"old"," replaced",[83,1724,1725,1733,1738],{},[96,1726,1727,243,1730],{},[148,1728,1729],{},"CONTAINS",[148,1731,1732],{},"STARTSWITH",[96,1734,1735],{},[148,1736,1737],{},"text, part",[96,1739,1740],{},"true when the text contains, starts with, the part",[83,1742,1743,1748,1752],{},[96,1744,1745],{},[148,1746,1747],{},"TEXT",[96,1749,1750],{},[148,1751,1500],{},[96,1753,1754],{},"the value as text, as the report would write it",[83,1756,1757,1762,1766],{},[96,1758,1759],{},[148,1760,1761],{},"CONCAT",[96,1763,1764],{},[148,1765,1592],{},[96,1767,1768],{},"the values joined as one text",[83,1770,1771,1776,1781],{},[96,1772,1773],{},[148,1774,1775],{},"DATE",[96,1777,1778],{},[148,1779,1780],{},"year, month, day",[96,1782,1783],{},"a date; an impossible one (30 February) is NULL",[83,1785,1786,1797,1802],{},[96,1787,1788,243,1791,243,1794],{},[148,1789,1790],{},"YEAR",[148,1792,1793],{},"MONTH",[148,1795,1796],{},"DAY",[96,1798,1799],{},[148,1800,1801],{},"date",[96,1803,1804],{},"the year, the month (1 to 12), the day of the month",[83,1806,1807,1812,1816],{},[96,1808,1809],{},[148,1810,1811],{},"WEEKDAY",[96,1813,1814],{},[148,1815,1801],{},[96,1817,1818],{},"the day of the week, 1 (Monday) to 7 (Sunday)",[83,1820,1821,1826,1831],{},[96,1822,1823],{},[148,1824,1825],{},"DATEADD",[96,1827,1828],{},[148,1829,1830],{},"unit, count, date",[96,1832,1833,1834,1837,1838,1841,1842,1845,1846,1849],{},"the date moved by ",[148,1835,1836],{},"\"d\""," days, ",[148,1839,1840],{},"\"w\""," weeks, ",[148,1843,1844],{},"\"m\""," months or ",[148,1847,1848],{},"\"y\""," years; 31 January plus a month is the last day of February",[83,1851,1852,1857,1862],{},[96,1853,1854],{},[148,1855,1856],{},"DATEDIFF",[96,1858,1859],{},[148,1860,1861],{},"unit, start, end",[96,1863,1864],{},"whole days, weeks, months or years from start to end",[83,1866,1867,1875,1877],{},[96,1868,1869,243,1872],{},[148,1870,1871],{},"TODAY",[148,1873,1874],{},"NOW",[96,1876],{},[96,1878,1879],{},"today's date, the date and time of the render, in the report's time zone",[83,1881,1882,1887,1892],{},[96,1883,1884],{},[148,1885,1886],{},"FORMAT",[96,1888,1889],{},[148,1890,1891],{},"value, pattern",[96,1893,1894,1895,1898],{},"a number or a date as text: ",[148,1896,1897],{},"FORMAT([day], \"d MMM yyyy\")"," (the patterns are below)",[83,1900,1901,1909,1911],{},[96,1902,1903,243,1906],{},[148,1904,1905],{},"PAGE",[148,1907,1908],{},"PAGES",[96,1910],{},[96,1912,1913,1914],{},"the page's number and how many pages there are; only in a text, joined with ",[148,1915,1197],{},[83,1917,1918,1923,1928],{},[96,1919,1920],{},[148,1921,1922],{},"PARAM",[96,1924,1925],{},[148,1926,1927],{},"\"name\"",[96,1929,1930],{},"the value of a parameter, the name in quotes",[83,1932,1933,1938,1940],{},[96,1934,1935],{},[148,1936,1937],{},"REPORT",[96,1939],{},[96,1941,1942],{},"the report's name",[14,1944,1945,1946,1949],{},"Arguments in brackets are optional. An aggregate takes one value at a time: write\n",[148,1947,1948],{},"SUM([a]) \u002F SUM([b])",", not an aggregate inside another.",[267,1951,155],{"id":1952},"formats",[14,1954,1955,1956,1959,1960,1963,1964,247,1967,1969],{},"The ",[18,1957,1958],{},"Format"," of a text, a column, a chart or a KPI, and the second argument of\n",[148,1961,1962],{},"FORMAT()",", is a pattern. ",[148,1965,1966],{},",",[148,1968,33],{}," mark where the separators go; the characters\nwritten are those of the report's language.",[77,1971,1972,1987],{},[80,1973,1974],{},[83,1975,1976,1979,1981,1984],{},[86,1977,1978],{},"Pattern",[86,1980,986],{},[86,1982,1983],{},"English",[86,1985,1986],{},"Italian",[91,1988,1989,2003,2019,2035,2051,2067,2083,2099,2112,2128,2143,2157,2172],{},[83,1990,1991,1996,1999,2001],{},[96,1992,1993],{},[148,1994,1995],{},"0",[96,1997,1998],{},"202401",[96,2000,1998],{},[96,2002,1998],{},[83,2004,2005,2010,2013,2016],{},[96,2006,2007],{},[148,2008,2009],{},"#,##0",[96,2011,2012],{},"10478825.4",[96,2014,2015],{},"10,478,825",[96,2017,2018],{},"10.478.825",[83,2020,2021,2026,2029,2032],{},[96,2022,2023],{},[148,2024,2025],{},"#,##0.00",[96,2027,2028],{},"1234.5",[96,2030,2031],{},"1,234.50",[96,2033,2034],{},"1.234,50",[83,2036,2037,2042,2045,2048],{},[96,2038,2039],{},[148,2040,2041],{},"0.0%",[96,2043,2044],{},"0.2453",[96,2046,2047],{},"24.5%",[96,2049,2050],{},"24,5%",[83,2052,2053,2058,2061,2064],{},[96,2054,2055],{},[148,2056,2057],{},"€ #,##0",[96,2059,2060],{},"2569181",[96,2062,2063],{},"€ 2,569,181",[96,2065,2066],{},"€ 2.569.181",[83,2068,2069,2074,2077,2080],{},[96,2070,2071],{},[148,2072,2073],{},"#,##0 pcs",[96,2075,2076],{},"1200",[96,2078,2079],{},"1,200 pcs",[96,2081,2082],{},"1.200 pcs",[83,2084,2085,2090,2093,2096],{},[96,2086,2087],{},[148,2088,2089],{},"#,##0;(#,##0)",[96,2091,2092],{},"-1500",[96,2094,2095],{},"(1,500)",[96,2097,2098],{},"(1.500)",[83,2100,2101,2106,2108,2110],{},[96,2102,2103],{},[148,2104,2105],{},"#,##0;-#,##0;-",[96,2107,1995],{},[96,2109,1181],{},[96,2111,1181],{},[83,2113,2114,2119,2122,2125],{},[96,2115,2116],{},[148,2117,2118],{},"d MMM yyyy",[96,2120,2121],{},"2026-03-05",[96,2123,2124],{},"5 Mar 2026",[96,2126,2127],{},"5 mar 2026",[83,2129,2130,2135,2137,2140],{},[96,2131,2132],{},[148,2133,2134],{},"MMMM yyyy",[96,2136,2121],{},[96,2138,2139],{},"March 2026",[96,2141,2142],{},"marzo 2026",[83,2144,2145,2150,2152,2155],{},[96,2146,2147],{},[148,2148,2149],{},"dd\u002FMM\u002Fyyyy",[96,2151,2121],{},[96,2153,2154],{},"05\u002F03\u002F2026",[96,2156,2154],{},[83,2158,2159,2164,2166,2169],{},[96,2160,2161],{},[148,2162,2163],{},"EEEE d MMMM",[96,2165,2121],{},[96,2167,2168],{},"Thursday 5 March",[96,2170,2171],{},"giovedì 5 marzo",[83,2173,2174,2179,2182,2184],{},[96,2175,2176],{},[148,2177,2178],{},"HH:mm",[96,2180,2181],{},"14:30",[96,2183,2181],{},[96,2185,2181],{},[2187,2188,2189,2215,2285,2301],"ul",{},[972,2190,2191,393,2194,2196,2197,2200,2201,2203,2204,243,2206,21,2208,2210,2211,2214],{},[18,2192,2193],{},"Numbers",[148,2195,1995],{}," a digit always written, ",[148,2198,2199],{},"#"," one written only when needed, ",[148,2202,1270],{},"\nmultiplies by 100; text before or after the digits as it is, in double quotes when it\nholds ",[148,2205,1995],{},[148,2207,2199],{},[148,2209,1270],{},". Up to three sections separated by ",[148,2212,2213],{},";",":\npositive, negative, zero. Rounding is half away from zero. French groups with a\nspace (1 234,50); Spanish starts grouping at five digits (1234, but 12.345).",[972,2216,2217,393,2220,612,2223,2226,2227,612,2230,612,2233,612,2236,2239,2240,612,2243,2246,2247,612,2250,2253,2254,612,2257,2260,2261,612,2264,2267,2268,612,2271,2274,2275,2277,2278,2280,2281,2284],{},[18,2218,2219],{},"Dates",[148,2221,2222],{},"yyyy",[148,2224,2225],{},"yy"," the year, ",[148,2228,2229],{},"MMMM",[148,2231,2232],{},"MMM",[148,2234,2235],{},"MM",[148,2237,2238],{},"M"," the month (name, short name,\ntwo digits, one or two), ",[148,2241,2242],{},"dd",[148,2244,2245],{},"d"," the day, ",[148,2248,2249],{},"EEEE",[148,2251,2252],{},"EEE"," the day of the week, ",[148,2255,2256],{},"HH",[148,2258,2259],{},"H","\nthe hour, ",[148,2262,2263],{},"mm",[148,2265,2266],{},"m"," the minutes, ",[148,2269,2270],{},"ss",[148,2272,2273],{},"s"," the seconds. ",[148,2276,2238],{}," is the month and ",[148,2279,2266],{}," the\nminute. Text goes in single quotes, ",[148,2282,2283],{},"''"," for an apostrophe.",[972,2286,2287,2290,2291,2293,2294,2296,2297,2300],{},[18,2288,2289],{},"Without a format"," a whole number is written as it is (a year or a month code is\nnever «2,026»), other numbers with separators and up to two decimals, a date in the\nlanguage's own way (",[148,2292,2118],{}," in English, ",[148,2295,2149],{}," in Italian, Spanish and\nFrench, ",[148,2298,2299],{},"dd.MM.yyyy"," in German), a yes\u002Fno as Yes or No.",[972,2302,2303,2306],{},[18,2304,2305],{},"In Excel"," a cell keeps the raw number or date, with the same pattern as its number\nformat, so it can still be summed; a pattern that does not say how to write negatives\nwrites them in red.",[72,2308,2310],{"id":2309},"tables-and-matrices","Tables and matrices",[14,2312,2313],{},"A table lists the rows of its dataset and grows over as many pages as they need, its\nheader repeated at the top of every page. Its properties:",[77,2315,2316,2325],{},[80,2317,2318],{},[83,2319,2320,2323],{},[86,2321,2322],{},"Section",[86,2324],{},[91,2326,2327,2343,2397,2433,2455,2465],{},[83,2328,2329,2333],{},[96,2330,2331],{},[18,2332,264],{},[96,2334,2335,2336,2338,2339,2342],{},"the dataset; ",[18,2337,1095],{},", a condition that keeps some rows; ",[18,2340,2341],{},"Order of the rows",", keys with their direction",[83,2344,2345,2350],{},[96,2346,2347],{},[18,2348,2349],{},"Columns",[96,2351,2352,2353,243,2356,2358,2359,2362,2363,243,2365,283,2367,2370,2371,243,2373,243,2376,243,2379,21,2382,2385,2386,2389,2390,2393,2394],{},"for each: ",[18,2354,2355],{},"Header",[18,2357,986],{}," (an expression), ",[18,2360,2361],{},"Width"," (millimetres, or automatic), alignment, ",[18,2364,1958],{},[18,2366,604],{},[18,2368,2369],{},"None"," until you choose one: ",[18,2372,600],{},[18,2374,2375],{},"Average",[18,2377,2378],{},"Minimum",[18,2380,2381],{},"Maximum",[18,2383,2384],{},"Count"," of the column's value, or an ",[18,2387,2388],{},"Expression…",", an aggregate of your own such as ",[148,2391,2392],{},"SUM([margine]) \u002F SUM([ricavo])","; printed in the groups' total rows and in the grand total), the style of its cells and its ",[18,2395,2396],{},"Conditional formatting",[83,2398,2399,2404],{},[96,2400,2401],{},[18,2402,2403],{},"Groups",[96,2405,2406,2407,2358,2410,2413,2414,243,2417,243,2420,2423,2424,243,2427,247,2430],{},"up to six levels, each with ",[18,2408,2409],{},"Group by",[18,2411,2412],{},"Name in expressions"," (how an aggregate names the group; a group by a field already has its name), ",[18,2415,2416],{},"Label",[18,2418,2419],{},"Order",[18,2421,2422],{},"Page break"," (none, between groups, after each group), ",[18,2425,2426],{},"Header row",[18,2428,2429],{},"Total row",[18,2431,2432],{},"Keep the last rows with their total",[83,2434,2435,2440],{},[96,2436,2437],{},[18,2438,2439],{},"Layout",[96,2441,2442,2445,2446,243,2449,243,2452],{},[18,2443,2444],{},"Show the rows"," (off: the groups' totals only), ",[18,2447,2448],{},"Grand total at the end",[18,2450,2451],{},"Header on every page",[18,2453,2454],{},"Alternate row shading",[83,2456,2457,2462],{},[96,2458,2459],{},[18,2460,2461],{},"Sheet name in Excel",[96,2463,2464],{},"the table's sheet when the report is downloaded as Excel",[83,2466,2467,2472],{},[96,2468,2469],{},[18,2470,2471],{},"On screen",[96,2473,2474,243,2477,2480],{},[18,2475,2476],{},"Sort by a column with a click on its header",[18,2478,2479],{},"Close and open the groups",": what the reader may do in the viewer",[14,2482,2483,2484,2487,2488,2490,2491,2493],{},"No column gets a total by itself: a field dragged onto a table, a column added and a new\ntable have none, because a price or a discount does not add up and only you know which\nvalues do. The table's first total, when no row is there to print it, turns on ",[18,2485,2486],{},"Grand\ntotal at the end","; turn it off if you want the groups' totals alone. A table where no column\nhas a total prints no total rows at all, not even empty ones, and the designer draws none\n(a group with its ",[18,2489,2426],{}," off keeps its ",[18,2492,2429],{},": it is all that names the group).",[14,2495,2496,2497,2500],{},"A group's total row reads «Total» and the group's label, across the columns before the\nfirst one that has a total; when the first column has a total too, the label takes a row\nof its own above the values. A group whose value is missing is named «(blank)». A group\nthat goes on over the next page repeats its label there. ",[18,2498,2499],{},"Keep the last rows with their\ntotal"," never leaves a total alone at the top of a page. A table with no rows says «No\ndata», with no total of nothing.",[14,2502,2503],{},"Columns whose widths add up to more than the table are narrowed to fit it, and a value\nwider than its column (a long number in a narrow column) would run into the next one:\nthe preview and the viewer say both, naming the table and the columns, so the design can\nbe fixed. So does an item that goes past the edge of the paper, and a KPI whose value is\nwider than its card.",[14,2505,2506,2508,2509,2512],{},[18,2507,2396],{}," gives a column's cells a style when a condition about their\nrow is true: ",[148,2510,2511],{},"[MarginPct] \u003C 0.3"," in red and bold. A column may have several rules; when\nmore than one holds, the later ones win where they differ. Rules colour the rows'\ncells, not the totals.",[14,2514,622,2515,2518,2519,2522,2523,2526,2527,2530,2531,194,2534,2537,2538,2540],{},[18,2516,2517],{},"matrix"," is a table with ",[18,2520,2521],{},"One column per value of"," an expression (at most 60\ncolumns): ",[148,2524,2525],{},"YEAR([Month])"," gives a column per year. Its groups make the rows, ",[18,2528,2529],{},"Value of\nthe cells"," is an aggregate of the rows that meet there (",[148,2532,2533],{},"SUM([margine])",[18,2535,2536],{},"Total\ncolumn",", which a new matrix leaves off, adds the row totals, and ",[18,2539,2448],{},"\nadds the column totals.",[14,2542,2543,2544,2546,2547,2549,2550,2553,2554,2557,2558,2561,2562,2564],{},"The columns come in the order of the data: each value where it first comes in the rows the\ntable reads, after its ",[18,2545,1095],{}," and its ",[18,2548,2341],{},", as a chart's categories\ndo with «In the data's order». With levels of columns, each one's values follow the same rule\ninside the value above them. So the ",[148,2551,2552],{},"ORDER BY"," of the dataset's SQL decides: with ",[148,2555,2556],{},"ORDER BY anno_mese",", a column per ",[148,2559,2560],{},"FORMAT([Month], \"MMM\")"," reads Jan, Feb, Mar. A value that the first rows\ndo not have comes where it first shows up, so sort by what makes the columns, before the\nrest. A query without ",[148,2563,2552],{}," has no order the database promises, and the columns may\nchange from one run to the next: order the dataset, or the table. A missing value is a\ncolumn too, «(blank)», in its place.",[14,2566,2567],{},[56,2568],{"alt":2569,"src":2570},"The last page of the example PDF: the group Salumi stagionati continued from the page before with its label repeated, the margin percentages under 30% in red, the group's total and the grand total, then the matrix of the margin by category and year with its totals","\u002Fmedia\u002Fguide\u002Freports\u002Fpdf-group-totals-and-matrix.png",[14,2572,2573],{},[63,2574,2575],{},"Page 3 of the example: the group carried over from page 2 repeats its label, the rule paints the margins under 30% red, the group's total and the grand total follow; then the matrix, one column per year.",[72,2577,2579],{"id":2578},"charts-and-kpis","Charts and KPIs",[14,2581,2582,2583,2586,2587,243,2590,2593,2594,2597],{},"A chart reads its dataset and aggregates it: ",[18,2584,2585],{},"Along the axis"," says what the bars,\npoints or slices are (",[148,2588,2589],{},"[region]",[148,2591,2592],{},"FORMAT([day], \"yyyy-MM\")","), and each ",[18,2595,2596],{},"Series"," is an\naggregate. The server draws the charts, the same in the PDF, on screen and (as images)\nin the email.",[77,2599,2600,2610],{},[80,2601,2602],{},[83,2603,2604,2607],{},[86,2605,2606],{},"Kind",[86,2608,2609],{},"Draws",[91,2611,2612,2625,2637,2650,2668,2678,2688,2702,2715,2725,2746],{},[83,2613,2614,2622],{},[96,2615,2616,243,2619],{},[18,2617,2618],{},"Bar",[18,2620,2621],{},"Column",[96,2623,2624],{},"horizontal bars, vertical columns; stacked if asked",[83,2626,2627,2634],{},[96,2628,2629,243,2631],{},[18,2630,427],{},[18,2632,2633],{},"Area",[96,2635,2636],{},"one line per series along the axis",[83,2638,2639,2647],{},[96,2640,2641,243,2644],{},[18,2642,2643],{},"Pie",[18,2645,2646],{},"Donut",[96,2648,2649],{},"each category's share; values below zero are left out",[83,2651,2652,2657],{},[96,2653,2654],{},[18,2655,2656],{},"Combo",[96,2658,2659,2660,2663,2664,2667],{},"bars and lines together, each series ",[18,2661,2662],{},"Drawn as"," bars or line, on the left or the right axis, with a ",[18,2665,2666],{},"Format of its values"," of its own (amounts in euros on the left, a percentage on the right); its axis writes its numbers the same way",[83,2669,2670,2675],{},[96,2671,2672],{},[18,2673,2674],{},"Waterfall",[96,2676,2677],{},"how each category adds to or takes from a total: rises in green, falls in red, the total last",[83,2679,2680,2685],{},[96,2681,2682],{},[18,2683,2684],{},"Funnel",[96,2686,2687],{},"stages from the largest to the smallest",[83,2689,2690,2695],{},[96,2691,2692],{},[18,2693,2694],{},"Treemap",[96,2696,2697,2698,2701],{},"each category as a rectangle sized by its value; with ",[18,2699,2700],{},"One series per value of",", nested",[83,2703,2704,2709],{},[96,2705,2706],{},[18,2707,2708],{},"Heatmap",[96,2710,2711,2712,2714],{},"a grid of the axis by ",[18,2713,2700],{},", the colour by the value",[83,2716,2717,2722],{},[96,2718,2719],{},[18,2720,2721],{},"Scatter",[96,2723,2724],{},"one point per category (X the category, Y the aggregate), or one per row with a value that is not an aggregate",[83,2726,2727,2732],{},[96,2728,2729],{},[18,2730,2731],{},"Gauge",[96,2733,2734,2735,243,2737,949,2739,2742,2743],{},"one value on an arc, with ",[18,2736,2378],{},[18,2738,2381],{},[18,2740,2741],{},"Target"," and coloured ",[18,2744,2745],{},"Bands",[83,2747,2748,2753],{},[96,2749,2750],{},[18,2751,2752],{},"Bullet",[96,2754,2755,2756,2758,2759],{},"a bar per category against its ",[18,2757,2741],{},", over its ",[18,2760,2745],{},[14,2762,2763,2764,2766,2767,243,2770,243,2773,243,2776,247,2778,2781,2782,239,2784,243,2786,2788,2789,2791,2792,2795,2796,2798,2799,2801,2802,2804,2805,2807,2808,2811,2812,2814,2815,2817,2818,2820],{},"The options: ",[18,2765,2700],{}," (the first series repeated for each value of a\nfield, up to 24), ",[18,2768,2769],{},"Stacked",[18,2771,2772],{},"Values on the chart",[18,2774,2775],{},"Legend",[18,2777,2419],{},[18,2779,2780],{},"Top","\n(the N largest values of the first series, the rest gathered as «Other»), ",[18,2783,2378],{},[18,2785,2381],{},[18,2787,2741],{}," (a number or an aggregate), ",[18,2790,2745],{}," (their limits, ",[148,2793,2794],{},"50, 80",")\nand a ",[18,2797,1958],{}," for the values. With ",[18,2800,2419],{}," «In the data's order» the categories come\nas they first appear in the dataset's rows, so the ",[148,2803,2552],{}," of its SQL decides: sort\nthe query by the axis (",[148,2806,2556],{},") and the months follow one another in time,\nwhatever they print as (",[148,2809,2810],{},"\"MMM yy\""," too); the series of ",[18,2813,2700],{}," and a\nKPI's trend follow the same order. «By value, smallest first» and «By value, largest\nfirst» sort the categories by the first series' value instead. With ",[18,2816,2780],{},", the N\nlargest are kept and shown in the order chosen. A chart draws at most 2,000 categories:\nset ",[18,2819,2780],{},", or aggregate.",[14,2822,622,2823,2825,2826,247,2828,2830,2831,2834,2835,2838,2839,2842],{},[18,2824,478],{}," card shows one aggregate in large type, with its ",[18,2827,2416],{},[18,2829,1958],{},";\n",[18,2832,2833],{},"Compared with",", another aggregate, adds the change in percent with an arrow and a\ncolour; ",[18,2836,2837],{},"Show the trend under the value"," draws a sparkline of an aggregate ",[18,2840,2841],{},"Along"," a\nfield.",[14,2844,2845,2846,33],{},"The new kinds (combo, waterfall, funnel, heatmap, gauge, bullet, the KPI card) are in\nthe Viewer's and the assistant's charts too: see\n",[38,2847,2849],{"href":2848},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis#more-chart-kinds","Preview and analysis",[72,2851,2853],{"id":2852},"the-viewer","The viewer",[14,2855,2856,2857,2859,2860,2863],{},"A click on a report in Explore opens it for reading. The bar at the top has one field\nper parameter, as the report defines it: a list for those with choices («Any» for an\noptional one), a date picker, Yes or No, several values for a list; ",[148,2858,1184],{}," marks a required\none. The fields open with the defaults. An optional field emptied has no value, whatever\nits default; a required one asks for a value. ",[18,2861,2862],{},"View report"," renders it.",[14,2865,2866],{},[56,2867],{"alt":2868,"src":2869},"The viewer of Monthly margin: the bar with the parameters Category (Prosciutti) and From (01\u002F01\u002F2025), View report, and the first page at 100% with the title Monthly margin — Prosciutti, three KPI cards and the chart","\u002Fmedia\u002Fguide\u002Freports\u002Fviewer-monthly-margin.png",[14,2871,2872],{},[63,2873,2874,2875,612,2877,2880,2881,243,2883,243,2885,2888,2889,33],{},"The example with ",[18,2876,611],{},[148,2878,2879],{},"Prosciutti",": the title says which category, and the KPIs and the chart count only its rows. Above, ",[18,2882,20],{},[18,2884,24],{},[18,2886,2887],{},"Copy API link",", the versions and ",[18,2890,2891],{},"Edit",[14,2893,2894,2895,2898,2899,243,2902,2905,2906,243,2908,243,2911,2913,2914,2917,2918,2923,2924,2927,2928,2930,2931,2933,2934,2937],{},"The pages are those of the PDF, drawn by the same renderer, with ",[18,2896,2897],{},"Page"," to move\nbetween them (",[18,2900,2901],{},"Page Up",[18,2903,2904],{},"Page Down","), the zoom (",[18,2907,1178],{},[18,2909,2910],{},"−",[18,2912,1995],{}," to fit the\nwidth) and ",[18,2915,2916],{},"Fit",". Where the designer allowed it, a click on a column's header sorts the\ntable by it (again for descending), unless its value depends on that order, as\n",[38,2919,2921],{"href":2920},"\u002Fdocs\u002Fcapabilities\u002Freport-functions#previous",[148,2922,1495],{}," does, and a click on a group's label closes or opens it;\n",[18,2925,2926],{},"Reset view"," goes back to the report's own order with every group open. ",[18,2929,20],{}," and\n",[18,2932,24],{}," download the report ",[18,2935,2936],{},"as shown",": with the values chosen, the sort and the\ngroups closed on screen. The API, the flow groups and the notebooks render it in its own\norder.",[14,2939,2940],{},[56,2941],{"alt":2942,"src":2943},"The viewer of Margin growth by month: the year of From is typed over, 2025 becomes 2026, View report renders one page; a click on the header vs month before sorts each category's months by their growth, the arrow beside the header; a click on the label of Insaccati cotti closes the group to its total row; Reset view appears in the bar","\u002Fmedia\u002Fguide\u002Freports\u002Fviewer-parameter-sort-group.gif",[14,2945,2946],{},[63,2947,2948,2949,2952,2953,2955],{},"«Margin growth by month» from January 2026: a click on the header ",[18,2950,2951],{},"vs month before","\nsorts every group by it (the running revenue follows the new order), a click on the\ngroup's label closes it to its total; ",[18,2954,2926],{}," puts the report back as designed.",[14,2957,2958,2959,2961,2962,2964,2965,2968,2969,2971],{},"The other buttons: ",[18,2960,2887],{}," (the address a script downloads the report from,\nwith the values on screen that are not the defaults, so a default such as\n",[148,2963,779],{}," keeps moving with the calendar, and the same as a Python or a curl\nexample), the ",[18,2966,2967],{},"versions"," (every save; who may\nedit restores an older one, which becomes the newest), and ",[18,2970,2891],{},", which opens the\ndesigner for who may edit. A report that cannot be rendered says why in words: a value\nthat does not fit, a dataset you may not read, too much data, too many pages, the time\nlimit.",[72,2973,2975],{"id":2974},"the-reports-tab","The Reports tab",[14,2977,2978,2980,2981,2984,2985,2987,2988,239,2991,2994,2995,2997],{},[18,2979,112],{}," in the top bar lists every report you may open, from every\nfolder, the most read first; ",[18,2982,2983],{},"Analysis"," also holds the\n",[38,2986,41],{"href":40},". Each row shows the report's name and\ndescription, how many datasets and parameters it has, its folder with the folders above\nit, its readers, when it was last opened, and when it was last changed, with its version\nand its author. A click on a row opens it in the viewer; on the right, ",[18,2989,2990],{},"Open",[18,2992,2993],{},"Edit in the designer"," (with EDIT on its folder) and ",[18,2996,2887],{},", the same as in\nthe viewer, with the report's defaults.",[14,2999,3000],{},[56,3001],{"alt":3002,"src":3003},"The Reports tab: five reports of the folder Sales reports and of its subfolder Channels, the most read first, each with its description, datasets and parameters, its folder, a bar with its readers in the last 30 days (5 people, 4, 3, 2, 1), when it was last opened, and when it was changed, with its version and author; on the right Open, Edit in the designer and Copy API link","\u002Fmedia\u002Fguide\u002Freports\u002Freports-tab.png",[14,3005,3006],{},[63,3007,3008,3009,3012],{},"The tab as an analyst with EDIT on ",[148,3010,3011],{},"Sales reports"," sees it: «Monthly margin», opened by\nfive people this month, comes first.",[14,3014,3015,3018,3019,3022,3023,3026,3027,247,3029,3032],{},[18,3016,3017],{},"Readers · 30 days"," is what the default order, ",[18,3020,3021],{},"Most read",", follows: the people who\nopened the report in the viewer in the last 30 days, with a short bar against the most\nread report of the page. Under it, the openings in those days and the openings ever. A\nperson counts once a day per report: reloading the page, choosing other values or opening\nit from three tabs is still one opening. The day is the installation's (",[148,3024,3025],{},"APP__TIMEZONE",").\nAt the same number of people the report opened more times comes first, then the one\nopened more times ever, then the one changed last. ",[18,3028,856],{},[18,3030,3031],{},"Recently changed"," order\nthe list the other ways.",[14,3034,3035],{},"Only the viewer counts: a download through the API, a flow group's email and a notebook\nrender the report without anyone reading it on screen, and the designer's preview is its\nauthor at work. Who opened a report is kept for 30 days and then removed every hour; the\nreport keeps its total and the moment it was last opened. The list never says who read a\nreport, only how many.",[14,3037,3038,3039,3042,3043,3046],{},"The search box looks in the names, the descriptions and the folders: ",[148,3040,3041],{},"finance"," finds the\nreports of a folder ",[63,3044,3045],{},"Finance"," and of every folder inside it. The list shows 50 reports a\npage. The order, the search and the page are in the address, so a link or a reload gives\nthe same list.",[14,3048,3049],{},[56,3050],{"alt":3051,"src":3052},"Analysis then Reports in the top bar: the list, the most read first; the order changed to Name and back to Most read; channels typed in the search finds the two reports of the folder Sales reports › Channels; margin finds three reports by their names and descriptions; a click on Margin growth by month opens it in the viewer","\u002Fmedia\u002Fguide\u002Freports\u002Freports-tab-trending-search.gif",[14,3054,3055],{},[63,3056,3057,3058,3060,3061,3064,3065,3068],{},"From the ",[18,3059,2983],{}," menu: the most read first, then by name; the search finds by\nfolder (",[148,3062,3063],{},"channels",") and by name or description (",[148,3066,3067],{},"margin","); a click on a row opens the\nreport.",[72,3070,3072],{"id":3071},"pdf-excel-and-the-email","PDF, Excel and the email",[77,3074,3075,3083],{},[80,3076,3077],{},[83,3078,3079,3081],{},[86,3080,1958],{},[86,3082,373],{},[91,3084,3085,3094,3118],{},[83,3086,3087,3091],{},[96,3088,3089],{},[18,3090,20],{},[96,3092,3093],{},"the page as designed: positions exact to a tenth of a millimetre, the font embedded, the header and footer on every page, «Page X of Y». The same data gives the same file",[83,3095,3096,3100],{},[96,3097,3098],{},[18,3099,24],{},[96,3101,3102,3103,3105,3106,3108,3109,247,3111,3113,3114,3117],{},"one sheet per table and matrix (an ",[38,3104,137],{"href":136}," has no place in it), named by ",[18,3107,2461],{},": the groups as outline levels (closed and opened with Excel's ",[18,3110,1178],{},[18,3112,2910],{},"), the subtotals and totals as ",[148,3115,3116],{},"SUBTOTAL"," formulas with their values, numbers that stay numbers in the report's formats (a whole number past 16 digits, an id, and a date before 1900 are written as text: a cell of Excel would change the first and cannot show the second), the header frozen and repeated on printed pages, a page break per group where the report has one; one more sheet lists the parameters' values. A text is never turned into a formula",[83,3119,3120,3125],{},[96,3121,3122],{},[18,3123,3124],{},"Email",[96,3126,3127,3128,3130,3131,3134],{},"the summary in the body of a ",[38,3129,178],{"href":177}," email, 640 pixels wide: the report's texts, its KPI cards, its charts as images and the totals of every table and matrix (",[38,3132,493],{"href":3133},"#the-summary-in-the-email","); the detail goes as the attached PDF or Excel",[14,3136,3137],{},[56,3138],{"alt":3139,"src":3140},"Page 1 of the example PDF: the title, the printing date, the line in the accent colour, three KPI cards with sparklines, the combo chart of revenue and margin by month, and the table grouped by category with the first group's total; the report's name and Page 1 of 3 in the footer","\u002Fmedia\u002Fguide\u002Freports\u002Fpdf-monthly-margin-page-1.png",[14,3142,3143],{},[63,3144,3145],{},"Page 1 of 3 of the example's PDF with every category, from January 2025.",[267,3147,3149],{"id":3148},"the-summary-in-the-email","The summary in the email",[14,3151,3152],{},"The summary follows the body of the report, in its order:",[2187,3154,3155,3162,3171],{},[972,3156,3157,3158,3161],{},"its texts, its KPI cards, its charts and its ",[38,3159,3160],{"href":136},"AI comments",", each with its line;",[972,3163,3164,3165,3167,3168,3170],{},"each ",[18,3166,77],{}," as its totals: the total row of each of its outermost groups and the\ngrand total, with the columns that have a total; a ",[18,3169,2517],{}," as its rows and its total\ncolumn. Five columns of values at most fit the width of an email: a wider matrix shows\nits total column alone, a wider table its first five, and says how many more are in the\nattached report;",[972,3172,3173,3174,3176],{},"a table with nothing to total (no group with a total row, no grand total) is left out,\nand so is the row of texts right above it that introduces it, its title; a table with no\ntext above it is introduced by its ",[18,3175,2461],{},", when it has one.",[14,3178,3179],{},"Gmail cuts a message longer than about 100 KB: a long summary shows fewer groups per table\n(«… and 40 more: the whole report is attached»), then leaves out the last tables («2 more\ntables are in the attached report»). The same summary goes as plain text, a line per\ntotal («Total Salami — Revenue 4,854,308 · Margin 1,299,924»), for a mail client that\nshows no HTML.",[72,3181,3183],{"id":3182},"sending-it-by-email","Sending it by email",[14,3185,3186,3187,3190],{},"A report is sent only by a flow group: a ",[38,3188,3189],{"href":177},"Pushmail cell"," attaches\nit (PDF or Excel, the values of its parameters, the file's name) and can put its summary\nin the email's body. The cell runs after the steps before it, so the email leaves right\nafter the data it shows has been refreshed, and not at all when a refresh failed.",[14,3192,3193],{},[56,3194],{"alt":3195,"src":3196},"The email in Mailpit: from Tabularia Reports to sales-team@example.com, subject Monthly margin 2026-10-30, the message, then the report's summary: the title, the three KPI cards, the combo chart, the totals of each category and the margin by category and year, with the PDF attached","\u002Fmedia\u002Fguide\u002Freports\u002Femail-summary-mailpit.png",[14,3198,3199],{},[63,3200,3201],{},"The example sent by a flow group to a test mail server: the cell's message, then the report's summary; the whole report is the attached PDF.",[72,3203,3205],{"id":3204},"from-scripts-the-api-and-notebooks","From scripts: the API and notebooks",[14,3207,3208],{},"Any script downloads a report with an API token that may read, with the values of its\nparameters in the query string:",[3210,3211,3216],"pre",{"className":3212,"code":3213,"language":3214,"meta":3215,"style":3215},"language-bash shiki shiki-themes github-dark-dimmed github-light","curl -fG -H \"Authorization: Bearer $TABULARIA_TOKEN\" -o monthly_margin.pdf \\\n  --data-urlencode format=pdf --data-urlencode category=Salami --data-urlencode \"since={start_of_year}\" \\\n  https:\u002F\u002Ftabularia.example.com\u002Fapi\u002Freports\u002F12\u002Frender\n","bash","",[148,3217,3218,3255,3277],{"__ignoreMap":3215},[3219,3220,3223,3227,3231,3234,3238,3242,3245,3248,3251],"span",{"class":3221,"line":3222},"line",1,[3219,3224,3226],{"class":3225},"sqRhv","curl",[3219,3228,3230],{"class":3229},"swcJU"," -fG",[3219,3232,3233],{"class":3229}," -H",[3219,3235,3237],{"class":3236},"sXfbr"," \"Authorization: Bearer ",[3219,3239,3241],{"class":3240},"ssh_m","$TABULARIA_TOKEN",[3219,3243,3244],{"class":3236},"\"",[3219,3246,3247],{"class":3229}," -o",[3219,3249,3250],{"class":3236}," monthly_margin.pdf",[3219,3252,3254],{"class":3253},"sxsTv"," \\\n",[3219,3256,3258,3261,3264,3267,3270,3272,3275],{"class":3221,"line":3257},2,[3219,3259,3260],{"class":3229},"  --data-urlencode",[3219,3262,3263],{"class":3236}," format=pdf",[3219,3265,3266],{"class":3229}," --data-urlencode",[3219,3268,3269],{"class":3236}," category=Salami",[3219,3271,3266],{"class":3229},[3219,3273,3274],{"class":3236}," \"since={start_of_year}\"",[3219,3276,3254],{"class":3253},[3219,3278,3280],{"class":3221,"line":3279},3,[3219,3281,3282],{"class":3236},"  https:\u002F\u002Ftabularia.example.com\u002Fapi\u002Freports\u002F12\u002Frender\n",[14,3284,3285,3286,3289,3290,3294],{},"The formats, the errors and a Python example are in the API's\n",[38,3287,3288],{"href":193},"Download a report","; in a marimo notebook,\n",[38,3291,3292],{"href":201},[148,3293,197],{}," does the same in one line.",[72,3296,3160],{"id":3297},"ai-comments",[14,3299,3300,3301,3303],{},"An ",[18,3302,137],{}," is a short text written by the configured AI model on the numbers of the\nKPIs, charts and tables you pick, such as what moved and what stands out. The numbers never\ndepend on it: a provider that is down, a budget that is spent or a mode that forbids it costs\nthe comment only, and the page says so.",[14,3305,3306,3309,3310,3312,3313,3315,3316,3319,3320,3322],{},[18,3307,3308],{},"To add one",", drag ",[18,3311,137],{}," from ",[18,3314,260],{}," onto the page, and in its panel write what\nyou ask of it (at most 1,000 characters; empty, it says what stands out) and tick what it\nreads, from 1 to 10 elements. Its place and size are in millimetres, as for any item, and it\nis at least 40 mm wide. A longer text makes the box grow and pushes down what is under it, and\na very long word breaks at the edge. ",[18,3317,3318],{},"Try it"," shows what it writes: it is the only moment the\ndesigner asks the model, and the preview shows what ",[18,3321,3318],{}," wrote and never asks.",[77,3324,3325,3333],{},[80,3326,3327],{},[83,3328,3329,3331],{},[86,3330],{},[86,3332],{},[91,3334,3335,3344,3354,3368,3382,3396],{},[83,3336,3337,3341],{},[96,3338,3339],{},[18,3340,118],{},[96,3342,3343],{},"the title and the numbers of the elements it reads, as the page writes them: a KPI's value and change, a chart's categories and series, a table's groups and totals, a matrix's rows, with your instruction, in the report's language",[83,3345,3346,3351],{},[96,3347,3348],{},[18,3349,3350],{},"What it never reads",[96,3352,3353],{},"a row. A table's detail rows and a scatter that is not aggregated stay out, though the page shows them. An element with only those is left out, and with nothing left no call is made: the panel says so. It has no tool to query with, and it reads nothing else",[83,3355,3356,3361],{},[96,3357,3358],{},[18,3359,3360],{},"When it writes",[96,3362,3363,3364,3367],{},"when the report is opened, or a PDF or a summary made, if those numbers have no comment. The same numbers make one call for everyone, for a day (",[148,3365,3366],{},"AI__COMMENT_KEEP_SECONDS","); other values of a parameter or data that changed make another",[83,3369,3370,3375],{},[96,3371,3372],{},[18,3373,3374],{},"How long it waits",[96,3376,3377,3378,3381],{},"at most ",[148,3379,3380],{},"AI__COMMENT_WAIT_SECONDS"," (30), with the render behind it. A report without the element waits for nothing, asks nothing, and is the file it always was",[83,3383,3384,3389],{},[96,3385,3386],{},[18,3387,3388],{},"Who pays",[96,3390,3391,3392,3395],{},"whoever causes the call, under the daily ceilings: who opens the report, the account of an API token that may write, the group's author for a ",[38,3393,3189],{"href":3394},"\u002Fdocs\u002Fpushmail#ai-comments",". A read-only API token, a notebook and an observer cause no call, and get what is kept",[83,3397,3398,3402],{},[96,3399,3400],{},[18,3401,24],{},[96,3403,3404],{},"it has no place in a workbook, so an Excel asks the model nothing, and the workbook is the same with or without one",[14,3406,3407,3408,3411],{},"On paper and on screen it is always marked: ",[18,3409,3410],{},"Written by AI · the model · numbers of the moment\nthey were read",", and that it may be wrong. No setting takes that away. The text is plain text,\nat most 1,500 characters, with no link: nothing in it is ever read as markup, in the PDF as\nin the email.",[14,3413,3414,3415,3418],{},"When it cannot write, the document goes out all the same, with one line in its place: that\nthe comment is not available, that the day's spending limit has been reached, that this\ninstallation sends no data to AI models (",[148,3416,3417],{},"AI__METADATA_ONLY",": nothing is sent and no number is\nread for it). Past the wait the text is kept for the next one who asks, and this document says\nit is not available: paper does not speak of what is on its way.",[14,3420,3421,3424],{},[18,3422,3423],{},"The numbers are those on the page."," The comment and the pages read the same rows, once from\nthe source for that document. A report also never lends its author's rights: a reader who may\nnot read a dataset gets no pages, as for any report, and so no text. The text kept for someone\nwho reads more is found only by whoever has just read the same numbers.",[14,3426,3427,3428,33],{},"What its model reads goes where the administrator said: ",[38,3429,3431],{"href":3430},"\u002Fdocs\u002Fintegrations\u002Fai","AI in Tabularia",[72,3433,3435],{"id":3434},"with-whose-rights","With whose rights",[14,3437,3438],{},"A report never lends its author's rights. What it reads is checked dataset by dataset\nwith the rights of whoever it is rendered for:",[77,3440,3441,3451],{},[80,3442,3443],{},[83,3444,3445,3448],{},[86,3446,3447],{},"Rendered",[86,3449,3450],{},"Reads with the rights of",[91,3452,3453,3461,3469,3477],{},[83,3454,3455,3458],{},[96,3456,3457],{},"in the viewer, in the designer's preview",[96,3459,3460],{},"whoever opens it",[83,3462,3463,3466],{},[96,3464,3465],{},"by a flow group",[96,3467,3468],{},"whoever runs the group: the author of its schedule, for a scheduled run, checked again at every send",[83,3470,3471,3474],{},[96,3472,3473],{},"through the API",[96,3475,3476],{},"the token's account",[83,3478,3479,3482],{},[96,3480,3481],{},"in a notebook",[96,3483,3484],{},"the notebook's session, as its reads",[14,3486,3487,3488,3491,3492,3494],{},"A dataset the reader may not read stops the render with its name, as one that does not\nexist (",[148,3489,3490],{},"The dataset «orders»: there is no datasource «Salaries» you can read","): two\npeople may open the same report and one of them gets an explanation instead of the\npages. SQL on a connection needs ",[18,3493,671],{}," on the connection's folder.",[14,3496,3497,3498,3501],{},"Because a scheduled group sends with its author's rights, someone else who changes what\na report ",[18,3499,3500],{},"reads"," switches off the schedules of the groups that send it: a dataset added,\nor one whose SQL, connection, datasource, view or filters changed; a new default of a\nparameter the group's cell does not set itself; a change to a SQL script or to the filters,\ncomputed fields or pivot of a saved view that the report reads; an AI comment added, or\none that reads something else or is asked something else, since it spends the author's budget. The audit log says why,\nand the author schedules the group again after looking. A change of layout, or one made\nby the schedule's own author, keeps them. A report that a flow group sends cannot be\ndeleted until it is taken out of the group's cells.",[14,3503,3504],{},"The other way round, what a report reads by reference (a saved view, a SQL script, a\ndatasource chosen as such, a connection) cannot be deleted while the report's current\nversion reads it: the refusal names the reports you may see and counts the others. A\ndatasource named in a SQL goes by its name, and is not looked for: the report then says\nit cannot find it.",[72,3506,3508],{"id":3507},"the-sample-reports","The sample reports",[14,3510,1955,3511,3515,3516,3519,3520,3522,3523,3525,3526,3529,3530,33],{},[38,3512,3514],{"href":3513},"\u002Fdocs\u002Fgetting-started-docker-compose#a-the-sample-data-already-there","sample data"," ends with\ntwo finished reports in the ",[148,3517,3518],{},"Sample"," folder, to open and to take apart: ",[18,3521,112],{},"\nlists them, and ",[18,3524,2891],{}," shows how each is made. Nothing in them is typed by hand: each number is read\nfrom the tables of ",[148,3527,3528],{},"Sample \u002F Private tables",", written by the sample flows. Whoever reads them needs\nVIEW on ",[148,3531,3518],{},[267,3533,3535],{"id":3534},"margin-review","Margin review",[14,3537,3538,3539,3541],{},"The document for the directors: where the revenue and the margin of a period stand, against the\nsame months a year earlier. It opens on 2025, in two pages; with one ",[18,3540,611],{},", in one.",[14,3543,3544],{},[56,3545],{"alt":3546,"src":3547},"Page 1 of Margin review: a sentence with the revenue and the margin against a year earlier, four cards with arrows and trends, a combo chart of revenue and margin percent by month, the margin percent by category, and the table by category and month with its totals","\u002Fmedia\u002Fguide\u002Freports\u002Fsample-margin-review.png",[77,3549,3550,3560],{},[80,3551,3552],{},[83,3553,3554,3557],{},[86,3555,3556],{},"Look at",[86,3558,3559],{},"To see",[91,3561,3562,3597,3608,3624,3640,3663,3679],{},[83,3563,3564,3574],{},[96,3565,3566,243,3568,243,3571],{},[18,3567,611],{},[18,3569,3570],{},"From",[18,3572,3573],{},"To",[96,3575,3576,3577,3580,3581,3583,3584,3587,3588,509,3591,3593,3594,3596],{},"three lists on one dataset, ",[148,3578,3579],{},"months",", each filtering it: ",[18,3582,3570],{}," shows months with the label ",[148,3585,3586],{},"FORMAT([Month], \"MMMM yyyy\")"," and the value ",[148,3589,3590],{},"[anno_mese]",[18,3592,3573],{}," starts where ",[18,3595,3570],{}," does, since a list follows those before it",[83,3598,3599,3605],{},[96,3600,3601,3602],{},"The dataset ",[148,3603,3604],{},"history",[96,3606,3607],{},"the same table with the category only, so that a year earlier is there to compare with. A second dataset is how a filter leaves out what a comparison still needs",[83,3609,3610,3615],{},[96,3611,3612,3613],{},"The cards' ",[18,3614,2833],{},[96,3616,3617,3620,3621,3623],{},[148,3618,3619],{},"SUMIF([anno_mese] >= PARAM(\"first_month\") - 100 AND [anno_mese] \u003C= PARAM(\"last_month\") - 100, [ricavo], \"history\")",": the same months a year earlier, and inside an ",[148,3622,1543],{}," nothing when the data does not go back that far, rather than half a period",[83,3625,3626,3629],{},[96,3627,3628],{},"The sentence on top",[96,3630,725,3631,3633,3634,3636,3637,3639],{},[18,3632,382],{}," that starts with ",[148,3635,392],{},", joining ",[148,3638,1962],{}," of aggregates of two datasets",[83,3641,3642,3648],{},[96,3643,3644,3645],{},"The table's ",[18,3646,3647],{},"Share",[96,3649,3650,3651,612,3653,3656,3657,612,3659,3662],{},"as ",[18,3652,986],{},[148,3654,3655],{},"PERCENT(SUM([ricavo]), \"categoria\")",", a month's part of its category; as ",[18,3658,604],{},[148,3660,3661],{},"PERCENT(SUM([ricavo]))",", the category's part of the whole",[83,3664,3665,3669],{},[96,3666,3667],{},[18,3668,2951],{},[96,3670,3671,3674,3675,3678],{},[148,3672,3673],{},"[ricavo] \u002F PREVIOUS([ricavo]) - 1",", with a ",[18,3676,3677],{},"Rule"," that writes the falls in red. A category's first month has none, and the column offers no sort: its value depends on the order",[83,3680,3681,3684],{},[96,3682,3683],{},"The header",[96,3685,3686,3689],{},[148,3687,3688],{},"=REPORT() & IF(ISNULL(PARAM(\"category\")), \"\", \" — \" & PARAM(\"category\"))",", and the months of the parameters turned into dates",[14,3691,3692],{},"The data stops on 15 July 2026, so July 2026 is half a month, in the chart and in a comparison.",[267,3694,3696],{"id":3695},"agent-scorecard","Agent scorecard",[14,3698,3699,3700,1050,3702,3705],{},"The document for a sales manager: how the agents of an area stand, on revenue and on the contacts\nof the CRM. Three pages for all of them; choose an ",[18,3701,2633],{},[18,3703,3704],{},"Agent"," list holds only its\nagents.",[14,3707,3708],{},[56,3709],{"alt":3710,"src":3711},"The viewer of Agent scorecard with Area Nord-Ovest: the lists Area and Agent above the page, four cards with revenue, orders, revenue per order and field visits, a scatter of revenue against visits and the contacts by kind","\u002Fmedia\u002Fguide\u002Freports\u002Fsample-agent-scorecard.png",[77,3713,3714,3722],{},[80,3715,3716],{},[83,3717,3718,3720],{},[86,3719,3556],{},[86,3721,3559],{},[91,3723,3724,3743,3762,3776,3792,3806,3825],{},[83,3725,3726,3732],{},[96,3727,3728,243,3730],{},[18,3729,2633],{},[18,3731,3704],{},[96,3733,3734,3738,3739,3742],{},[38,3735,3737],{"href":3736},"#a-parameter-that-filters-the-data","two lists that follow each other",": both read and filter the dataset ",[148,3740,3741],{},"agents",", in the order of the form",[83,3744,3745,3750],{},[96,3746,3747,3748],{},"The calculated fields of ",[148,3749,3741],{},[96,3751,3752,247,3755,393,3758,3761],{},[148,3753,3754],{},"Visits",[148,3756,3757],{},"Contacts",[148,3759,3760],{},"LOOKUP([area] & [agente], [area] & [agente], [visita], \"crm\")"," reads a second table, with the area in the key as two agents may share a name. Then they are fields like any other, in a card, a chart, a total",[83,3763,3764,3770],{},[96,3765,3766,3769],{},[18,3767,3768],{},"Size",", another calculated field",[96,3771,3772,3775],{},[148,3773,3774],{},"IFS([ricavo] >= 1.2 * AVG([ricavo]), \"Over 120%\", …)",": an aggregate in a calculated field is over the dataset, as chosen in the form",[83,3777,3778,3783],{},[96,3779,3644,3780],{},[18,3781,3782],{},"Of the area",[96,3784,3785,3788,3789,3791],{},[148,3786,3787],{},"[ricavo] \u002F SUM([ricavo], \"area\")",", a row's part of its group; the same in the ",[18,3790,604],{},", with the grand total left empty because it is in no group",[83,3793,3794,3799],{},[96,3795,3796],{},[18,3797,3798],{},"Of contacts",[96,3800,3801,3802,3805],{},"two ",[18,3803,3804],{},"Rules",", in red under 18% and in green from 22%",[83,3807,3808,3811],{},[96,3809,3810],{},"The matrix under the table",[96,3812,3813,612,3815,3818,3819,612,3821,3824],{},[18,3814,2521],{},[148,3816,3817],{},"[Size]",", the columns in the order of the rows, which the table sorts by revenue; ",[18,3820,1099],{},[148,3822,3823],{},"COUNT() > 1"," takes it away for one agent",[83,3826,3827,3832],{},[96,3828,3829],{},[18,3830,3831],{},"Contacts by area and kind",[96,3833,3834,3835,3838],{},"a stacked chart on ",[148,3836,3837],{},"crm",", a dataset with the same two filters: five series, one per field of the table",[14,3840,3841,3842,3845,3846,3849,3850,3853],{},"To ",[18,3843,3844],{},"add an AI comment"," to one of them, ",[38,3847,3848],{"href":136},"as above",", duplicate it first: ",[18,3851,3852],{},"Insert → AI comment",", then tick\nthe cards and the table it reads. They come without one because it needs a model: on an\ninstallation with none it would say only that it is not available.",[14,3855,3856],{},"A report you change stays as you left it, whatever runs later: the sample container looks it up by name and writes\nnothing over it. One you delete comes back as it was the next time the container runs.",[72,3858,3860],{"id":3859},"example-a-monthly-margin-report","Example: a monthly margin report",[14,3862,3863,3864,3867,3868,3870],{},"With the sample data (",[38,3865,3866],{"href":3513},"the «Sample» folder","):\na report on the datasource «Margin by Category and Month» (in ",[148,3869,3528],{},",\nwritten by the sample flow of the same name), with the revenue, cost and margin of each\ncategory month by month, a chart and three KPIs on top, and a choice of category and of\nthe first month.",[969,3872,3873,3896,3921,4040,4166,4202,4247,4279,4376,4409,4427,4440],{},[972,3874,3875,3878,3879,194,3881,3884,3885,3888,3889,3891,3892,3895],{},[18,3876,3877],{},"The report."," In Explore, in a folder of yours (here ",[148,3880,3011],{},[18,3882,3883],{},"New →\nReport",". In the designer, write ",[148,3886,3887],{},"Monthly margin"," over «New report». In ",[18,3890,242],{},"\nkeep A4 portrait with margins 15 · 12 · 15 · 12, set the language English, the time\nzone ",[148,3893,3894],{},"Europe\u002FRome"," and the font size 8.",[972,3897,3898,612,3901,3904,3905,3908,3909,3911,3912,239,3914,3916,3917,3920],{},[18,3899,3900],{},"The first month.",[18,3902,3903],{},"Data → + Parameter",": name ",[148,3906,3907],{},"since",", label ",[148,3910,3570],{},", type ",[18,3913,903],{},[18,3915,918],{},", default ",[148,3918,3919],{},"{start_of_year-1y}"," (the first of January of last year, at\nevery render).",[972,3922,3923,612,3926,3904,3928,243,3931,243,3933,3936,3937,4006,4009,4012,4013,4016,4017,4020,4021,393,4024,243,4026,4029,4030,243,4032,4035,4036,4039],{},[18,3924,3925],{},"The data.",[18,3927,631],{},[148,3929,3930],{},"margins",[18,3932,652],{},[18,3934,3935],{},"Runs on"," Datasources, engine\nDuckDB:",[3210,3938,3942],{"className":3939,"code":3940,"language":3941,"meta":3215,"style":3215},"language-sql shiki shiki-themes github-dark-dimmed github-light","SELECT categoria, anno_mese, ricavo, costo, margine\nFROM \"Margin by Category and Month\"\nWHERE anno_mese >= EXTRACT(YEAR FROM {since}) * 100 + EXTRACT(MONTH FROM {since})\nORDER BY categoria, anno_mese\n","sql",[148,3943,3944,3953,3961,3998],{"__ignoreMap":3215},[3219,3945,3946,3950],{"class":3221,"line":3222},[3219,3947,3949],{"class":3948},"s6PUj","SELECT",[3219,3951,3952],{"class":3240}," categoria, anno_mese, ricavo, costo, margine\n",[3219,3954,3955,3958],{"class":3221,"line":3257},[3219,3956,3957],{"class":3948},"FROM",[3219,3959,3960],{"class":3236}," \"Margin by Category and Month\"\n",[3219,3962,3963,3965,3968,3970,3973,3975,3978,3981,3983,3986,3989,3991,3993,3995],{"class":3221,"line":3279},[3219,3964,1045],{"class":3948},[3219,3966,3967],{"class":3240}," anno_mese ",[3219,3969,708],{"class":3948},[3219,3971,3972],{"class":3240}," EXTRACT(",[3219,3974,1790],{"class":3948},[3219,3976,3977],{"class":3948}," FROM",[3219,3979,3980],{"class":3240}," {since}) ",[3219,3982,1184],{"class":3948},[3219,3984,3985],{"class":3229}," 100",[3219,3987,3988],{"class":3948}," +",[3219,3990,3972],{"class":3240},[3219,3992,1793],{"class":3948},[3219,3994,3977],{"class":3948},[3219,3996,3997],{"class":3240}," {since})\n",[3219,3999,4001,4003],{"class":3221,"line":4000},4,[3219,4002,2552],{"class":3948},[3219,4004,4005],{"class":3240}," categoria, anno_mese\n",[4007,4008],"br",{},[148,4010,4011],{},"{since}"," becomes a date, and ",[148,4014,4015],{},"anno_mese"," holds months as ",[148,4018,4019],{},"202501",". Add two ",[18,4022,4023],{},"Calculated\nfields",[148,4025,822],{},[148,4027,4028],{},"DATE(FLOOR([anno_mese] \u002F 100), [anno_mese] - FLOOR([anno_mese] \u002F 100) * 100, 1)",",\nthe first day of the month as a date; and ",[148,4031,825],{},[148,4033,4034],{},"IF([ricavo] = 0, NULL, [margine] \u002F [ricavo])",".\n",[18,4037,4038],{},"Add",": the fields are read from the data.",[972,4041,4042,612,4045,3904,4047,3908,4050,3911,4052,4054,4055,393,4057,4059,4060,4062,4063,4065,4066,4068,4069,4071,4072,4074,4075,632,4077,4156,4158,4159,4162,4163,4165],{},[18,4043,4044],{},"The category.",[18,4046,836],{},[148,4048,4049],{},"category",[148,4051,611],{},[18,4053,382],{},", not\nrequired, no default, ",[18,4056,982],{},[148,4058,3930],{},", value and label\n",[148,4061,596],{},". ",[148,4064,3930],{}," is SQL, so the dialog shows the line that filters it by what\nis chosen: ",[18,4067,4038],{},", then open ",[148,4070,3930],{}," and put that line in its ",[148,4073,1045],{},", joined to the\nother condition with ",[148,4076,1225],{},[3210,4078,4080],{"className":3939,"code":4079,"language":3941,"meta":3215,"style":3215},"SELECT categoria, anno_mese, ricavo, costo, margine\nFROM \"Margin by Category and Month\"\nWHERE ({category} IS NULL OR categoria = {category})\n  AND anno_mese >= EXTRACT(YEAR FROM {since}) * 100 + EXTRACT(MONTH FROM {since})\nORDER BY categoria, anno_mese\n",[148,4081,4082,4088,4094,4118,4149],{"__ignoreMap":3215},[3219,4083,4084,4086],{"class":3221,"line":3222},[3219,4085,3949],{"class":3948},[3219,4087,3952],{"class":3240},[3219,4089,4090,4092],{"class":3221,"line":3257},[3219,4091,3957],{"class":3948},[3219,4093,3960],{"class":3236},[3219,4095,4096,4098,4101,4104,4107,4110,4113,4115],{"class":3221,"line":3279},[3219,4097,1045],{"class":3948},[3219,4099,4100],{"class":3240}," ({category} ",[3219,4102,4103],{"class":3948},"IS",[3219,4105,4106],{"class":3948}," NULL",[3219,4108,4109],{"class":3948}," OR",[3219,4111,4112],{"class":3240}," categoria ",[3219,4114,392],{"class":3948},[3219,4116,4117],{"class":3240}," {category})\n",[3219,4119,4120,4123,4125,4127,4129,4131,4133,4135,4137,4139,4141,4143,4145,4147],{"class":3221,"line":4000},[3219,4121,4122],{"class":3948},"  AND",[3219,4124,3967],{"class":3240},[3219,4126,708],{"class":3948},[3219,4128,3972],{"class":3240},[3219,4130,1790],{"class":3948},[3219,4132,3977],{"class":3948},[3219,4134,3980],{"class":3240},[3219,4136,1184],{"class":3948},[3219,4138,3985],{"class":3229},[3219,4140,3988],{"class":3948},[3219,4142,3972],{"class":3240},[3219,4144,1793],{"class":3948},[3219,4146,3977],{"class":3948},[3219,4148,3997],{"class":3240},[3219,4150,4152,4154],{"class":3221,"line":4151},5,[3219,4153,2552],{"class":3948},[3219,4155,4005],{"class":3240},[4007,4157],{},"With no category chosen ",[148,4160,4161],{},"{category}"," is ",[148,4164,1061],{}," and every category stays. The list of\ncategories reads the same query without that condition, so it always holds them all.",[972,4167,4168,4171,4172,4174,4175,4177,4178,4180,4181,243,4183,4186,4187,4190,4191,4194,4195,4198,4199,4201],{},[18,4169,4170],{},"The page header."," A new report starts with a title and a line here, and a page\nnumber in the footer. Click ",[18,4173,314],{}," beside the page, select the title and the\nline and press ",[18,4176,550],{},", then in ",[18,4179,260],{}," a ",[18,4182,382],{},[18,4184,4185],{},"Expression",":\n",[148,4188,4189],{},"=\"Monthly margin\" & IF(ISNULL(PARAM(\"category\")), \"\", \" — \" & PARAM(\"category\"))",",\nsize 14, bold. Under it a text\n",[148,4192,4193],{},"=\"From \" & FORMAT(PARAM(\"since\"), \"MMMM yyyy\") & \" · revenue, cost and margin of the sample orders\"",",\nsize 8, grey; on the right the ready-made ",[18,4196,4197],{},"Date and time of printing","; a ",[18,4200,427],{},"\nacross, 0.4 mm, in the accent colour. Header height 17 mm.",[972,4203,4204,4207,4208,4210,4211,4213,4214,393,4216,243,4219,4222,4223,907,4225,243,4228,239,4230,907,4232,243,4235,243,4237,4239,4240,4243,4244,4246],{},[18,4205,4206],{},"The KPIs."," Click ",[18,4209,342],{},", then three ",[18,4212,478],{}," cards side by side, 58 mm wide, on\n",[148,4215,3930],{},[148,4217,4218],{},"Revenue",[148,4220,4221],{},"SUM([ricavo])",", format ",[148,4224,2057],{},[148,4226,4227],{},"Margin",[148,4229,2533],{},[148,4231,2057],{},[148,4233,4234],{},"Margin %",[148,4236,2392],{},[148,4238,2041],{},". Each with ",[18,4241,4242],{},"Show the\ntrend under the value"," along ",[148,4245,3590],{},", the same value.",[972,4248,4249,4252,4253,4255,4256,4258,4259,4262,4263,4266,4267,243,4269,4271,4272,243,4274,4276,4277,33],{},[18,4250,4251],{},"The chart."," A ",[18,4254,464],{},", kind ",[18,4257,2656],{},", the full width under the cards, title\n",[148,4260,4261],{},"Revenue and margin by month",": along the axis ",[148,4264,4265],{},"FORMAT([Month], \"yyyy-MM\")",", series\n",[148,4268,4218],{},[148,4270,4221],{},", drawn as bars, and ",[148,4273,4227],{},[148,4275,2533],{},", as a line;\nformat ",[148,4278,2009],{},[972,4280,4281,4252,4284,4286,4287,3309,4289,243,4291,239,4294,243,4297,247,4300,4302,4303,243,4305,247,4307,4309,4310,4312,4313,4315,4316,243,4318,243,4320,243,4323,243,4325,4327,4328,4330,4331,4333,4334,907,4336,4338,4339,4341,4343,4344,4346,4347,4349,4350,4352,4353,393,4355,4035,4357,393,4360,4062,4362,4364,4365,4367,4368,4370,4371,4375],{},[18,4282,4283],{},"The table.",[18,4285,440],{}," under the chart. In ",[18,4288,264],{},[148,4290,822],{},[148,4292,4293],{},"ricavo",[148,4295,4296],{},"costo",[148,4298,4299],{},"margine",[148,4301,825],{}," onto it. Open ",[148,4304,4293],{},[148,4306,4296],{},[148,4308,4299],{}," and\nchoose ",[18,4311,600],{}," as their ",[18,4314,604],{},".\nName the headers ",[148,4317,822],{},[148,4319,4218],{},[148,4321,4322],{},"Cost",[148,4324,4227],{},[148,4326,4234],{},"; give ",[148,4329,822],{}," the\nformat ",[148,4332,2134],{}," and the amounts ",[148,4335,2009],{},[148,4337,4234],{}," the total ",[18,4340,2388],{},[148,4342,2392],{},", the format ",[148,4345,2041],{}," and a ",[18,4348,3677],{},": when\n",[148,4351,2511],{},", red and bold. ",[18,4354,2341],{},[148,4356,3590],{},[18,4358,4359],{},"+ Group",[148,4361,596],{},[18,4363,2448],{}," is already on, from the first\ntotal you chose; tick ",[18,4366,2454],{}," and both ",[18,4369,2471],{}," options. The ",[38,4372,4374],{"href":4373},"#saving-and-the-preview","GIF above","\nshows the drag and the group.",[972,4377,4378,4381,4382,4385,4386,4388,4389,243,4391,4393,243,4395,612,4398,4222,4400,4402,4403,4405,4406,4408],{},[18,4379,4380],{},"The matrix."," Under the table a text ",[148,4383,4384],{},"Margin by category and year"," (size 10, bold)\nand a ",[18,4387,454],{},": rows grouped by ",[148,4390,596],{},[18,4392,2521],{},[148,4394,2525],{},[18,4396,4397],{},"Value of the cells",[148,4399,2533],{},[148,4401,2009],{},"; tick ",[18,4404,2536],{},". The years come in the order of the rows, which the query sorts by ",[148,4407,4015],{},"\nwithin each category.",[972,4410,4411,4207,4414,4416,4417,4419,4420,4422,4423,4426],{},[18,4412,4413],{},"The footer.",[18,4415,317],{},", select the page number it started with and\npress ",[18,4418,550],{},", then add the ready-made ",[18,4421,508],{}," on the left and ",[18,4424,4425],{},"Page\nnumber of total"," on the right.",[972,4428,4429,4431,4432,4434,4435,612,4437,4439],{},[18,4430,250],{}," and look at it, then ",[18,4433,256],{},": the report is saved and opens in the\nviewer. It has three pages; with ",[18,4436,611],{},[148,4438,2879],{},", one.",[972,4441,4442,4444,4445,4447,4448,247,4451,4454,4455,4458,4459,4462],{},[18,4443,20],{}," downloads it. To send it every month, put it in a flow group after the\nrefresh of its data: step 1 the flow «Margin by Category and Month», step 2 a\n",[38,4446,3189],{"href":177}," with the report as PDF, the file name\n",[148,4449,4450],{},"monthly_margin_{today:yyyyMM}",[18,4452,4453],{},"Summary in the email body","; then\n",[18,4456,4457],{},"Schedule"," the group, for example ",[148,4460,4461],{},"0 7 1 * *",", at seven on the first of every\nmonth.",[14,4464,4465,4466,4468,4469,4471,4472,4476],{},"Who reads it needs VIEW on ",[148,4467,3011],{}," and on ",[148,4470,3528],{},", where the\ndatasource is; who sends it from a flow group needs, besides, what the\n",[38,4473,4475],{"href":4474},"\u002Fdocs\u002Fpushmail#what-is-checked-and-when","group and the Pushmail cell"," need.",[72,4478,4480],{"id":4479},"permissions","Permissions",[77,4482,4483,4493],{},[80,4484,4485],{},[83,4486,4487,4490],{},[86,4488,4489],{},"On the report's folder",[86,4491,4492],{},"You can",[91,4494,4495,4503],{},[83,4496,4497,4500],{},[96,4498,4499],{},"VIEW",[96,4501,4502],{},"open it, choose its values, read it on screen, download it as PDF or Excel, copy its API link, read its versions",[83,4504,4505,4508],{},[96,4506,4507],{},"EDIT",[96,4509,4510],{},"create it, design and save it, rename, move, duplicate and delete it, restore a version",[14,4512,4513,4514,4518,4519,283,4523,239,4526,4529,4530,4533],{},"Whoever has VIEW only is taken to the viewer when they open the designer's address.\nAdministrators see every report. Reports show in Explore, with their own icon, in the\nsearch and in the ",[38,4515,4517],{"href":4516},"#the-reports-tab","Reports tab",". Every save, rename, move, duplicate,\ndelete and restore is in the ",[38,4520,4522],{"href":4521},"\u002Fdocs\u002Fgovernance\u002Faudit-log","audit log",[148,4524,4525],{},"report.create",[148,4527,4528],{},"report.update","…), and so is every render (",[148,4531,4532],{},"report.render","), with its format, the values of its parameters, the\noutcome and where it came from: the interface, the API, a notebook or a flow group.",[72,4535,4537],{"id":4536},"limits-and-good-to-know","Limits and good to know",[2187,4539,4540,4565,4572,4575,4578],{},[972,4541,4542,4543,4545,4546,4549,4550,4553,4554,4557,4558,4561,4562,33],{},"A dataset reads at most ",[148,4544,799],{}," rows (3,000,000 by default): one more stops\nthe render and names the dataset. The query is cut at the source, so a ",[148,4547,4548],{},"SELECT *"," on a\nbig table costs no more than that many rows. A report is a document, not an export:\naggregate in the SQL where you can. The report works out its groups, totals, charts and\nKPIs over the rows in columns, with DuckDB: a million rows grouped with their totals\ntake a second or two and some 500 MB of the worker's memory, a thousand totals almost\nnothing. Shown row by row they would not fit the pages: a table with more rows to show\nthan its pages can hold stops at once and says so. A render makes at most ",[148,4551,4552],{},"REPORTS__MAX_PAGES"," pages (200); its\nlayout runs in a process of its own with ",[148,4555,4556],{},"REPORTS__RENDER_MEMORY_MB"," of memory\n(1024: some 200 pages of tables) and ",[148,4559,4560],{},"REPORTS__RENDER_SECONDS"," of time (120). See the\n",[38,4563,4564],{"href":221},"configuration",[972,4566,4567,4568,4571],{},"Charts are drawn by a chart service: the ",[148,4569,4570],{},"chart-renderer"," service on Docker Compose, a\nsidecar of the worker pods on Kubernetes. When it does not answer, a report with charts\nfails and says so; the others still render.",[972,4573,4574],{},"At most 20 datasets and 50 parameters per report, six levels of groups per table, 60\ncolumns per table or matrix, 2,000 categories per chart, an expression of 4,000\ncharacters, an image of 512 KiB.",[972,4576,4577],{},"The screen is drawn from the same pages as the PDF; sorting and closing groups render\nit again, which takes as long as a render.",[972,4579,4580],{},"No subreports and no Word output. A report has no lineage of its own: it writes no\ndataset. Its schedule is that of the flow group that sends it.",[72,4582,4584],{"id":4583},"related","Related",[2187,4586,4587,4592,4598,4603,4613,4621,4629,4634],{},[972,4588,4589,4591],{},[38,4590,1317],{"href":1316},": every function with examples on the sample data",[972,4593,4594,4597],{},[38,4595,4596],{"href":45},"Dashboards",": the same datasets and parameters, on a screen that answers clicks",[972,4599,4600,4602],{},[38,4601,178],{"href":177},": sending a report from a flow group",[972,4604,4605,247,4609],{},[38,4606,4608],{"href":4607},"\u002Fdocs\u002Fcapabilities\u002Fflow-groups","Flow groups",[38,4610,4612],{"href":4611},"\u002Fdocs\u002Fcapabilities\u002Fscheduling","Scheduling",[972,4614,4615,239,4618],{},[38,4616,4617],{"href":193},"API: download a report",[38,4619,4620],{"href":201},"marimo notebooks",[972,4622,4623,243,4626],{},[38,4624,4625],{"href":662},"SQL scripts",[38,4627,2849],{"href":4628},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis",[972,4630,4631],{},[38,4632,4633],{"href":774},"Date placeholders",[972,4635,4636],{},[38,4637,4638],{"href":221},"Configuration: reports",[4640,4641,4642],"style",{},"html pre.shiki code .sqRhv, html code.shiki .sqRhv{--shiki-default:#F69D50;--shiki-light:#6F42C1}html pre.shiki code .swcJU, html code.shiki .swcJU{--shiki-default:#6CB6FF;--shiki-light:#005CC5}html pre.shiki code .sXfbr, html code.shiki .sXfbr{--shiki-default:#96D0FF;--shiki-light:#032F62}html pre.shiki code .ssh_m, html code.shiki .ssh_m{--shiki-default:#ADBAC7;--shiki-light:#24292E}html pre.shiki code .sxsTv, html code.shiki .sxsTv{--shiki-default:#F47067;--shiki-light:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .s6PUj, html code.shiki .s6PUj{--shiki-default:#F47067;--shiki-light:#D73A49}",{"title":3215,"searchDepth":3257,"depth":3279,"links":4644},[4645,4646,4651,4654,4658,4659,4660,4661,4662,4665,4666,4667,4668,4669,4673,4674,4675,4676],{"id":74,"depth":3257,"text":75},{"id":228,"depth":3257,"text":229,"children":4647},[4648,4649,4650],{"id":269,"depth":3279,"text":270},{"id":354,"depth":3279,"text":355},{"id":562,"depth":3279,"text":563},{"id":618,"depth":3257,"text":619,"children":4652},[4653],{"id":963,"depth":3279,"text":964},{"id":1085,"depth":3257,"text":1086,"children":4655},[4656,4657],{"id":1309,"depth":3279,"text":1310},{"id":1952,"depth":3279,"text":155},{"id":2309,"depth":3257,"text":2310},{"id":2578,"depth":3257,"text":2579},{"id":2852,"depth":3257,"text":2853},{"id":2974,"depth":3257,"text":2975},{"id":3071,"depth":3257,"text":3072,"children":4663},[4664],{"id":3148,"depth":3279,"text":3149},{"id":3182,"depth":3257,"text":3183},{"id":3204,"depth":3257,"text":3205},{"id":3297,"depth":3257,"text":3160},{"id":3434,"depth":3257,"text":3435},{"id":3507,"depth":3257,"text":3508,"children":4670},[4671,4672],{"id":3534,"depth":3279,"text":3535},{"id":3695,"depth":3279,"text":3696},{"id":3859,"depth":3257,"text":3860},{"id":4479,"depth":3257,"text":4480},{"id":4536,"depth":3257,"text":4537},{"id":4583,"depth":3257,"text":4584},"A report is a page of fixed size, designed in the browser to the tenth of a millimetre:\na header and a footer on every page, tables that group and subtotal over as many pages\nas the data needs, charts, gauges and KPI cards, texts written with expressions. It is\nan object of a folder, with its versions, like a flow or a SQL script. Readers open it\non screen with its parameters and download it as PDF or Excel; a flow group\nsends it by email right after the data it shows is refreshed; a script downloads it\nthrough the API.","md",{"source":4680},"docs\u002Fcapabilities\u002Freports.md",true,"\u002Fdocs\u002Fcapabilities\u002Freports",{"title":5,"description":4677},"docs\u002Fcapabilities\u002Freports","Ij-nmG-y0dn7JCgLjSUiyplXRAIZSpzSrSzDcOcNo9g",[4687,4706,4748,4780,4812,4840,4864,4890],{"title":4688,"icon":4689,"intro":4690,"items":4691},"Getting started","start","Install it on one machine, learn the few ideas everything else is built on, and run a first flow.",[4692,4694,4697,4700,4703],{"path":4693,"title":4688},"\u002Fdocs\u002Fgetting-started",{"path":4695,"title":4696},"\u002Fdocs\u002Fgetting-started-docker-compose","Walkthrough with Docker Compose",{"path":4698,"title":4699},"\u002Fdocs\u002Fdeploy\u002Fminikube","Try it on your computer (minikube)",{"path":4701,"title":4702},"\u002Fdocs\u002Fconcepts","Concepts",{"path":4704,"title":4705},"\u002Fdocs\u002Foverview","Overview (README)",{"title":4707,"icon":4708,"intro":4709,"items":4710},"Capabilities","capabilities","What you can build: visual flows, analysis on any step, AI questions, pixel-perfect reports, dashboards, Python, R and SQL scripts, containers and the orchestration that ties them together.",[4711,4714,4717,4718,4721,4722,4723,4724,4727,4728,4731,4734,4736,4737,4740,4742,4745],{"path":4712,"title":4713},"\u002Fdocs\u002Fcapabilities","All capabilities",{"path":4715,"title":4716},"\u002Fdocs\u002Fcapabilities\u002Fflows","Low-code flows",{"path":4628,"title":2849},{"path":4719,"title":4720},"\u002Fdocs\u002Fcapabilities\u002Fask-your-data","Ask your data with AI",{"path":4682,"title":5},{"path":1316,"title":1317},{"path":45,"title":4596},{"path":4725,"title":4726},"\u002Fdocs\u002Fscripting","Python and R",{"path":662,"title":4625},{"path":4729,"title":4730},"\u002Fdocs\u002Fcapabilities\u002Fnotebooks","marimo notebooks as apps",{"path":4732,"title":4733},"\u002Fdocs\u002Fcontainer-node","Docker images in flows",{"path":4607,"title":4735},"Flow groups: orchestration",{"path":4611,"title":4612},{"path":4738,"title":4739},"\u002Fdocs\u002Fpushmail","Pushmail: datasources, reports and dashboards by email",{"path":774,"title":4741},"Dynamic dates",{"path":4743,"title":4744},"\u002Fdocs\u002Fcapabilities\u002Fengines","Engines",{"path":4746,"title":4747},"\u002Fdocs\u002Fengines\u002Fengine-differences","Engine differences",{"title":4749,"icon":4750,"intro":4751,"items":4752},"Sources","sources","Every way data comes in: files, databases, buckets, SFTP folders, HTTP APIs, SharePoint, Google Sheets, and the results of your own flows.",[4753,4756,4759,4762,4765,4768,4771,4774,4777],{"path":4754,"title":4755},"\u002Fdocs\u002Fsources","All sources",{"path":4757,"title":4758},"\u002Fdocs\u002Fsources\u002Ffiles","Uploaded files",{"path":4760,"title":4761},"\u002Fdocs\u002Fsources\u002Fdatabases","Database tables and queries",{"path":4763,"title":4764},"\u002Fdocs\u002Fs3-datasource","S3 buckets",{"path":4766,"title":4767},"\u002Fdocs\u002Fsftp","SFTP folders",{"path":4769,"title":4770},"\u002Fdocs\u002Fapi-datasource","HTTP APIs",{"path":4772,"title":4773},"\u002Fdocs\u002Fsources\u002Fsharepoint","Excel on SharePoint",{"path":4775,"title":4776},"\u002Fdocs\u002Fsources\u002Fgoogle-sheets","Google Sheets",{"path":4778,"title":4779},"\u002Fdocs\u002Fsources\u002Fflow-outputs","Results of flows and scripts",{"title":4781,"icon":4782,"intro":4783,"items":4784},"Connections","connections","The systems Tabularia reads from and writes to, how each connection is set up, and who may use it.",[4785,4788,4791,4794,4797,4799,4800,4802,4803,4806,4809],{"path":4786,"title":4787},"\u002Fdocs\u002Fconnections","All connections",{"path":4789,"title":4790},"\u002Fdocs\u002Fconnections\u002Fdatabases","Databases",{"path":4792,"title":4793},"\u002Fdocs\u002Fsqlserver","Microsoft SQL Server driver",{"path":4795,"title":4796},"\u002Fdocs\u002Fconnections\u002Fs3","S3 and compatible storage",{"path":4766,"title":4798},"SFTP servers",{"path":4769,"title":4770},{"path":4772,"title":4801},"SharePoint",{"path":4775,"title":4776},{"path":4804,"title":4805},"\u002Fdocs\u002Fconnections\u002Fsmtp","SMTP email",{"path":4807,"title":4808},"\u002Fdocs\u002Fcontainer-registries","Container registries",{"path":4810,"title":4811},"\u002Fdocs\u002Fconnections\u002Fdestinations","Writing data out",{"title":4813,"icon":4814,"intro":4815,"items":4816},"Integrations","integrations","How Tabularia fits your stack: AI providers, the REST API and webhooks, dbt, OpenLineage, single sign-on, SIEM and monitoring.",[4817,4820,4822,4825,4828,4831,4834,4837],{"path":4818,"title":4819},"\u002Fdocs\u002Fintegrations","All integrations",{"path":3430,"title":4821},"AI: where it is used",{"path":4823,"title":4824},"\u002Fdocs\u002Fapi","API, tokens and webhooks",{"path":4826,"title":4827},"\u002Fdocs\u002Fdbt-export","Export to dbt",{"path":4829,"title":4830},"\u002Fdocs\u002Fopenlineage","OpenLineage",{"path":4832,"title":4833},"\u002Fdocs\u002Fsso-keycloak","Single sign-on with Keycloak",{"path":4835,"title":4836},"\u002Fdocs\u002Fsiem-splunk","Audit log to Splunk",{"path":4838,"title":4839},"\u002Fdocs\u002Fintegrations\u002Fmonitoring","Monitoring",{"title":4841,"icon":4842,"intro":4843,"items":4844},"Security & governance","governance","Who may see and do what, what is recorded, and how data quality and personal data are kept in check.",[4845,4848,4850,4852,4855,4858,4861],{"path":4846,"title":4847},"\u002Fdocs\u002Fgovernance","Overview",{"path":4849,"title":4480},"\u002Fdocs\u002Fgovernance\u002Fpermissions",{"path":4521,"title":4851},"Audit log",{"path":4853,"title":4854},"\u002Fdocs\u002Fgovernance\u002Fdata-contracts","Data contracts",{"path":4856,"title":4857},"\u002Fdocs\u002Fdesign\u002Fsso-group-mapping","SSO and group mapping",{"path":4859,"title":4860},"\u002Fdocs\u002Fexamples\u002Fkeycloak","Keycloak example on a laptop",{"path":4862,"title":4863},"\u002Fdocs\u002Fengines\u002Fclickhouse-ai-user","A ClickHouse user for the AI assistant",{"title":4865,"icon":4866,"intro":4867,"items":4868},"Install & operate","operate","Run it in production on Kubernetes, configure it, upgrade it and keep it healthy.",[4869,4872,4875,4878,4881,4884,4887],{"path":4870,"title":4871},"\u002Fdocs\u002Fdeploy\u002Fkubernetes","Kubernetes and Helm",{"path":4873,"title":4874},"\u002Fdocs\u002Fdeploy\u002Fkind","A company-like cluster on one computer (kind)",{"path":4876,"title":4877},"\u002Fdocs\u002Fdeploy\u002Fupgrading","Upgrading, backups and restore",{"path":4879,"title":4880},"\u002Fdocs\u002Fdeploy\u002Frelease-checklist","Install and upgrade checklist",{"path":4882,"title":4883},"\u002Fdocs\u002Fconfiguration","Configuration reference",{"path":4885,"title":4886},"\u002Fdocs\u002Fengine-settings","Settings from the panel",{"path":4888,"title":4889},"\u002Fdocs\u002Fdatabase-migrations","Database migrations",{"title":4891,"icon":4892,"intro":4893,"items":4894},"Reference","reference","Release process and the remaining reference pages.",[4895],{"path":4896,"title":4897},"\u002Fdocs\u002Frelease-process","Release process",1793656371554]