deneb
31 Topicsadvanced cross filtering with deneb and vega - brushed area disappearing when doing cross filter
My report has a deneb vega line chart and a table. I want to filter the table by brushing the chart and then clicking on the brushed area. The idea is to only apply cross filtering when required. PBIX file The filter works partially: (1) brushing on the area works as expected: (2) Then clicking on the brushed area filters the table: However the brushed area disappears. I'd like to keep the brushed area after the click. I've tried different debounce, throttle and consume values for the event - not sure what is causing the brushed area to disappear. { "data": [ { "name": "dataset" } ], "width": 200, "height": 200, "signals": [ { "name": "colour", "value": "blue" }, // brush { "name": "brush", "value": 0, "on": [ { "events": "@main:pointerdown", "update": "[x(), x()]" }, { "events": "[@main:pointerdown, window:pointerup] > window:pointermove!", "update": "[brush[0], clamp(round(x()-brush[0])+brush[0], 0, width)]" }, { "events": { "signal": "delta" }, "update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)" } ] }, // anchor { "name": "anchor", "value": null, "on": [ { "events": "@brush:pointerdown", "update": "slice(brush)" } ] }, // xdown { "name": "xdown", "value": 0, "on": [ { "events": "@brush:pointerdown", "update": "x()" } ] }, // delta { "name": "delta", "value": 0, "on": [ { "events": "[@brush:pointerdown, window:pointerup] > window:pointermove!", "update": "x() - xdown" } ] }, // main_brush { "name": "main_brush", // "push": "outer", "on": [ { "events": { "signal": "brush" }, "update": "span(brush) ? invert('x_scale', brush) : null" } ] }, // cross filter start ------------------------------------------ { "name": "pbiCrossFilterSelection", "value": [], "on": [ // when mark is brushed apply cross filter { "events": { "markname": "brush", "type": "click", "consume": true, "debounce": 100, "throttle": 100 }, "update": "pbiCrossFilterApply(event, \"datum['x'] >= main_brush[0] & datum['x'] <= main_brush[1]\" )" } ] } // cross filter end ------------------------------------------ ], "scales": [ { "name": "x_scale", "range": "width", "padding": 10, "domain": { "data": "dataset", "field": "x" } }, { "name": "y_scale", "range": "height", "padding": 10, "domain": { "data": "dataset", "field": "y" } } ], "axes": [ { "orient": "bottom", "scale": "x_scale" }, { "orient": "left", "scale": "y_scale" } ], "marks": [ { "name": "main", "type": "group", "encode": { "enter": { "x": { "value": 0 }, "y": { "value": 0 }, "height": { "value": 200 }, "width": { "value": 200 }, "fill": { "value": "transparent" } } }, "marks": [ // main line chart { "name": "main_line", "type": "line", "from": { "data": "dataset" }, "encode": { "enter": { "x": { "scale": "x_scale", "field": "x" }, "y": { "scale": "y_scale", "field": "y" } }, "update": { "stroke": { "signal": "colour" } } } }, // brush area mark { "type": "rect", "name": "brush", "encode": { "enter": { "y": { "value": 0 }, "height": { "value": 200 }, "fill": { "value": "#333" }, "fillOpacity": { "value": 0.2 } }, "update": { "x": { "signal": "brush[0]" }, "x2": { "signal": "brush[1]" } } } } ] } ] }SolvedDeneb data label help
I haven't been able to clear a hurdle with the labels on a Deneb bar chart. By default, as you can see in the GIF, the labels are on. I want the labels to be off by default. I only want to see a label when the user clicks on a row in the table. I'm unable to share a workbook due to restrictive workplace security measures. I will paste in some dummy data and my spec below: { "data": {"name": "dataset"}, "layer": [ { "mark": { "type": "bar", "opacity": 0.3, "tooltip": true }, "encoding": { "x": { "field": "ModelKey", "type": "nominal", "sort": { "field": "Min of MAPEVl", "order": "ascending" } }, "y": { "field": "Min of MAPEVl", "type": "quantitative" }, "color": {"value": "lightgrey"} } }, { "mark": { "type": "bar", "tooltip": true }, "encoding": { "x": { "field": "ModelKey", "type": "nominal", "sort": { "field": "Min of MAPEVl", "order": "ascending" } }, "y": { "field": "Min of MAPEVl__highlight", "type": "quantitative" }, "color": { "condition": { "test": "datum['Min of MAPEVl__highlight'] !== null", "value": "steelblue" }, "value": "lightgrey" } } }, { "mark": { "type": "text", "align": "center", "baseline": "bottom", "dy": -5 }, "encoding": { "x": { "field": "ModelKey", "type": "nominal", "sort": { "field": "Min of MAPEVl", "order": "ascending" } }, "y": { "field": "Min of MAPEVl__highlight", "type": "quantitative" }, "text": { "field": "Min of MAPEVl__highlight", "type": "quantitative", "format": ".2f" }, "color": {"value": "black"}, "opacity": { "condition": { "test": "datum['Min of MAPEVl__highlight'] !== null", "value": 1 }, "value": 0 } } } ], "encoding": { "x": { "field": "ModelKey", "type": "nominal", "sort": { "field": "Min of MAPEVl", "order": "ascending" }, "axis": null }, "y": { "type": "quantitative", "axis": { "title": null, "grid": false } } } } ModelKey MAPEVl 362609410_61 5.08 362619010_61 3.99 362706010_61 5.09 362715610_61 5.04 362968800_61 4.47 362978400_61 4.92 362978410_61 5.04 363134910_61 4.83 363242600_61 8.28 363289400_61 7.13 363664400_61 4.94 363854000_61 3.85 363961500_61 5.71 363961510_61 5.79 364201100_61 5.78 364344500_61 5.23 364380810_61 5.49 364404000_61 4.92 364622800_61 5.12 Anyone have a solution to share? giammariam , maybe? Thanks.SolvedHelp coloring Deneb heatmap
I’m new to Deneb and haven’t been able to figure out how to color this heatmap so that it is colored by row, or category, rather than as a whole: I want the rows to be color independently of one another, like this: This is my first forum post and I don't see a way to post a .pbix. Here is the Deneb specification using Vega Lite: { "data": {"name": "dataset"}, "mark": { "type": "rect", "stroke": "white", "tooltip": true }, "encoding": { "y": { "field": "Category", "type": "nominal", "title": "", "axis": { "domain": false, "ticks": false, "labels": true, "labelAngle": 0, "labelPadding": 5 } }, "x": { "field": "Date", "type": "ordinal", "title": "", "timeUnit": "yearmonth", "axis": { "domain": false, "ticks": false, "labels": true, "labelAngle": -90, "orient": "top" } }, "tooltip": [ { "field": "Category", "type": "nominal" }, { "field": "Date", "type": "ordinal" }, { "field": "Growth (MoYaM)", "type": "quantitative", "format": ".1%" }, { "field": "Growth (WDC)", "type": "quantitative", "format": ".1%" } ], "color": { "aggregate": "max", "field": "Growth (WDC)", "type": "quantitative", "title": "Growth (WDC)", "scale": { "scheme": "pbiColorDivergent" }, "legend": { "direction": "vertical", "gradientLength": 120, "format": ".1%" } } } } Any help is greatly appreciated. Thanks.Solved6.8KViews0likes24CommentsDeneb - How to add measures on another dataset
Hi, I want to replicate the sunburst example from Vega on my PBI here: https://vega.github.io/vega/examples/sunburst/ But, my values are not in a table, they are measures. So, I need to combine them on a hard-coded table and I'm getting this situation: Deneb is importing all measures as a table, like this: But, I need to create a dataset on Deneb like this: Any ideas on how I can do this "merge"? I think that he is not getting the values because they are on another table, but I also tried methods to do a lookup or transform it in a signal but I was unsuccessful in both cases.SolvedDened - Custom Matrix with double headers
Hi dm-p, I hope you can help me here to deliver a matrix view in Deneb to look like this: I aim to show the Category and Sub-category at the top of the matrix and colour the cells based on the values. So far, here is my code: { "data": {"name": "dataset"}, "encoding": { "y": { "field": "Product", "title": null }, "x": { "field": "Sub Cat", "axis": { "orient": "top" } } }, "layer": [ { "mark": {"type": "rect"}, "encoding": { "color": { "field": "Value", "scale": { "scheme": "lightgreyred" }, "legend": null } } }, { "mark": { "type": "text", "tooltip": true, "fontsize": 14 }, "encoding": { "text": { "field": "Value", "type": "quantitative", "format": ",.0f" }, "color": {"value": "black"} } } ] } And below is the output I got so far: I was hoping that when defining the "x" "field", I could add multiple fields ... but I am unsure how to do it. Many thanks Sample fileSolvedDeneb: Line Chart Tooltips that don't require you to hover directly over line
Hi all, I'm new to developing Custom Visuals and have decided to try using Deneb (from AppSource) to try and create a custom line chart that I want. Deneb seems to have adequate features, but I'm having trouble with tooltips. In my line chart, I used: "mark" : {"type": "line","tooltip": true} to create my line marking on the chart layer. The issue is that I can only get tooltips to show if I hover my cursor directly over the line. This is unlike the default PBI line chart, where I can hover anywhere on the line chart, and I will still see the tooltip for the value that is at that x-axis point. The functionality in this image is what I'm talking about: Does anyone know if this is possible in Deneb? So far, I've been using Vega-Lite. Thank you!Solved5.7KViews0likes3CommentsDeneb heatmap color tweak
Apologies but workplace security policies and practices prevent me from uploading a pbix, etc. I have a Deneb spec that I am reusing that, thanks to earlier contributions from giammariam , is almost exactly what I need: Until it's filtered (using a slicer) and an extreme outlier (in dark blue) dominates the color scale: Stakeholders are asking whether each row --across the fiscal years--can be colored independently. In other words, every row would have its own "blueorange" scale (in reverse). I have tried many approaches that have not worked. Here is my spec. Thanks for any help offered. { "transform": [ { "calculate": "(month(datum['Date'])+1)", "as": "monthNum" }, { "calculate": "datum['monthNum'] + (datum['monthNum'] < 7 ? 6 : -6)", "as": "monthSort" }, { "calculate": "'FY ' + toString(year(datum['Date']) + (datum['monthSort'] <= 6 ? +1 : 0))", "as": "FY" } ], "facet": { "column": { "field": "FY", "title": null, "header": {"labelFontSize": 13} } }, "resolve": { "scale": {"x": "independent"} }, "spacing": {"column": 5}, "spec": { "width": {"step": 35}, "mark": { "type": "rect", "stroke": "white", "tooltip": true }, "encoding": { "x": { "field": "Date", "type": "ordinal", "title": null, "timeUnit": "month", "axis": { "domain": false, "ticks": false, "labels": true, "labelOpacity": 0.65, "orient": "top" }, "sort": {"field": "monthSort"} }, "y": { "field": "Category", "type": "nominal", "title": "", "axis": { "domain": false, "ticks": false, "labels": true, "labelOpacity": 0.65, "labelAngle": 0, "labelPadding": 5 } }, "tooltip": [ { "field": "Category", "type": "nominal" }, { "field": "Date ", "type": "nominal" }, { "field": "Metric", "type": "quantitative", "format": ".1%" } ], "color": { "aggregate": "max", "field": "Metric", "type": "quantitative", "title": "Metric", "scale": { "reverse": true, "scheme": "blueorange" }, "legend": { "title": "", "titleAnchor": "middle", "titleBaseline": "top", "direction": "horizontal", "format": "%", "orient": "bottom-right", "offset": 14 } } } }, "data": {"name": "dataset"} }3.7KViews0likes13CommentsPower BI - Deneb visual - Read a JSON to create the visuals
Hi everyone, I have a graphic which work correctly. I use at the moment a table in power BI dedicated for this visual. It seems possible for deneb to read JSON data because when I provide the original table with the JSON column, I can see the data but when I try to use JSON.parse(), I have lot of errors Please find my current code which work perfectly from my Power BI. { "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "Final trusted version with a correctly implemented 'No Schedule Data' message.", "width": 372, "height": 48, "signals": [ { "name": "pbi_time_offset_seconds", "init": "isValid(data('pbi_summarize')[0]) ? data('pbi_summarize')[0].DST_ClockDiffBtwLocationAndLocalOffset : 0" }, { "name": "utc_now", "init": "now()", "on": [ { "events": {"type": "timer", "throttle": 10000}, "update": "now()" } ] }, { "name": "remote_now", "update": "utc_now + (pbi_time_offset_seconds * 1000)" }, { "name": "remote_day", "update": "day(remote_now)" }, { "name": "remote_hour_decimal", "update": "hours(remote_now) + (minutes(remote_now) / 60) + (seconds(remote_now) / 3600)" }, { "name": "remote_time_label", "update": "timeFormat(remote_now, '%H:%M')" }, { "name": "has_data_for_today", "update": "data('daily_schedule').length > 0" } ], "data": [ { "name": "dataset" }, { "name": "pbi_summarize" }, { "name": "daily_schedule", "source": "dataset", "transform": [ {"type": "filter", "expr": "datum.day_num != null && datum.day_num == remote_day"} ] }, { "name": "schedule_bands", "source": "daily_schedule", "transform": [ { "type": "filter", "expr": "datum.ScheduleType == 'Production' || datum.ScheduleType == 'ITSupport'" }, { "type": "formula", "as": "display_type", "expr": "datum.type == 'Normal' ? (datum.ScheduleType == 'Production' ? 'Working hours' : 'Support hours') : datum.type == 'Flexible' ? 'Flexible hours' : 'No Working hours'" } ] }, { "name": "site_opening_start", "source": "daily_schedule", "transform": [ {"type": "filter", "expr": "datum.ScheduleType == 'SiteOpening'"}, {"type": "project", "fields": ["startTime"], "as": ["time_value"]} ] }, { "name": "site_opening_end", "source": "daily_schedule", "transform": [ {"type": "filter", "expr": "datum.ScheduleType == 'SiteOpening'"}, {"type": "project", "fields": ["endTime"], "as": ["time_value"]} ] } ], "scales": [ { "name": "xscale", "type": "linear", "range": "width", "domain": [0, 24] }, { "name": "yscale", "type": "band", "range": [1, 50], "domain": ["ITSupport", "Production"], "padding": 0.1 }, { "name": "color", "type": "ordinal", "domain": ["Working hours", "Support hours", "Flexible hours", "No Working hours"], "range": ["#a6cee3", "#b2df8a", "#1f78b4", "#d3d3d3"] } ], "axes": [ { "orient": "bottom", "scale": "xscale", "tickCount": 25, "title": { "signal": "timeFormat(remote_now, 'Time & Day (%Y-%m-%d)')" }, "labelFontSize": 9, "titleFontSize": 9 } ], "marks": [ { "type": "group", "name": "custom_legend", "encode": {"enter": {"x": {"value": 0}, "y": {"value": -40}}}, "marks": [ {"type": "rect", "encode": {"enter": {"x": {"value": 0}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#a6cee3"}}}}, {"type": "text", "encode": {"enter": {"x": {"value": 15}, "y": {"value": 9}, "text": {"value": "Working hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}}, {"type": "rect", "encode": {"enter": {"x": {"value": 120}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#1f78b4"}}}}, {"type": "text", "encode": {"enter": {"x": {"value": 135}, "y": {"value": 9}, "text": {"value": "Flexible hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}}, {"type": "rect", "encode": {"enter": {"x": {"value": 240}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#d3d3d3"}}}}, {"type": "text", "encode": {"enter": {"x": {"value": 255}, "y": {"value": 9}, "text": {"value": "No Working hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}}, {"type": "rect", "encode": {"enter": {"x": {"value": 0}, "y": {"value": 15}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#b2df8a"}}}}, {"type": "text", "encode": {"enter": {"x": {"value": 15}, "y": {"value": 24}, "text": {"value": "Support hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}}, {"type": "rule", "encode": {"enter": {"x": {"value": 122}, "y": {"value": 13}, "x2": {"value": 122}, "y2": {"value": 23}, "stroke": {"value": "black"}}}}, {"type": "symbol", "encode": {"enter": {"x": {"value": 122}, "y": {"value": 22}, "shape": {"value": "triangle-up"}, "size": {"value": 25}, "fill": {"value": "black"}}}}, {"type": "rule", "encode": {"enter": {"x": {"value": 128}, "y": {"value": 15}, "x2": {"value": 128}, "y2": {"value": 24}, "stroke": {"value": "black"}}}}, {"type": "symbol", "encode": {"enter": {"x": {"value": 128}, "y": {"value": 15}, "shape": {"value": "triangle-down"}, "size": {"value": 25}, "fill": {"value": "black"}}}}, {"type": "text", "encode": {"enter": {"x": {"value": 135}, "y": {"value": 24}, "text": {"value": "Site Opening"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}} ] }, { "type": "text", "interactive": false, "encode": { "enter": { "x": {"field": {"group": "width"}, "mult": 0.5}, "y": {"field": {"group": "height"}, "mult": 0.5}, "text": {"value": "No Schedule Data for Today"}, "fontSize": {"value": 12}, "fontWeight": {"value": "bold"}, "fill": {"value": "gray"}, "align": {"value": "center"} }, "update": { "opacity": [{"test": "has_data_for_today", "value": 0}, {"value": 1}] } } }, { "type": "rect", "from": {"data": "schedule_bands"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "x2": {"scale": "xscale", "field": "endTime"}, "y": {"scale": "yscale", "field": "ScheduleType"}, "height": {"scale": "yscale", "band": 1}, "fill": {"scale": "color", "field": "display_type"} }, "update": { "opacity": [{"test": "has_data_for_today", "value": 1}, {"value": 0}] } } }, { "type": "rule", "from": {"data": "site_opening_start"}, "encode": { "enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 0}, "y2": {"value": 50}, "stroke": {"value": "black"}, "strokeWidth": {"value": 2}}, "update": {"opacity": [{"test": "has_data_for_today", "value": 1}, {"value": 0}]} } }, { "type": "symbol", "from": {"data": "site_opening_start"}, "encode": { "enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 50}, "shape": {"value": "triangle-up"}, "size": {"value": 50}, "fill": {"value": "black"}}, "update": {"opacity": [{"test": "has_data_for_today", "value": 1}, {"value": 0}]} } }, { "type": "rule", "from": {"data": "site_opening_end"}, "encode": { "enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 0}, "y2": {"value": 50}, "stroke": {"value": "black"}, "strokeWidth": {"value": 2}}, "update": {"opacity": [{"test": "has_data_for_today", "value": 1}, {"value": 0}]} } }, { "type": "symbol", "from": {"data": "site_opening_end"}, "encode": { "enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 3}, "shape": {"value": "triangle-down"}, "size": {"value": 50}, "fill": {"value": "black"}}, "update": {"opacity": [{"test": "has_data_for_today", "value": 1}, {"value": 0}]} } }, { "type": "rule", "encode": { "update": { "x": {"scale": "xscale", "signal": "remote_hour_decimal"}, "y": {"value": 2}, "y2": {"value": 50}, "stroke": {"value": "red"}, "strokeWidth": {"value": 2} } } }, { "type": "text", "encode": { "update": { "x": {"scale": "xscale", "signal": "remote_hour_decimal"}, "y": {"value": 3}, "text": {"signal": "remote_time_label"}, "baseline": {"value": "bottom"}, "align": {"value": "center"}, "fill": {"value": "red"} } } } ] } Please find an example of my JSON file stored in Sharepoint (Text multi-lines) {"schedule_rules":[{"day_num":"0","segments":[{"approval_needed":null,"communication_needed":"Mandatory","end_time":"23:59","start_time":"00:00","type":"No Production"}]},{"day_num":"1","segments":[{"approval_needed":"Yes","communication_needed":null,"end_time":"12:30","start_time":"08:30","type":"Normal"},{"approval_needed":"Yes","communication_needed":null,"end_time":"16:30","start_time":"13:30","type":"Normal"}]},{"day_num":"2","segments":[{"approval_needed":"Yes","communication_needed":null,"end_time":"12:30","start_time":"08:30","type":"Normal"},{"approval_needed":"Yes","communication_needed":null,"end_time":"16:30","start_time":"13:30","type":"Normal"}]},{"day_num":"3","segments":[{"approval_needed":"Yes","communication_needed":null,"end_time":"12:30","start_time":"08:30","type":"Normal"},{"approval_needed":"Yes","communication_needed":null,"end_time":"16:30","start_time":"13:30","type":"Normal"}]},{"day_num":"4","segments":[{"approval_needed":"Yes","communication_needed":null,"end_time":"12:30","start_time":"08:30","type":"Normal"},{"approval_needed":"Yes","communication_needed":null,"end_time":"16:30","start_time":"13:30","type":"Normal"}]},{"day_num":"5","segments":[{"approval_needed":"Yes","communication_needed":null,"end_time":"12:30","start_time":"08:30","type":"Normal"},{"approval_needed":"Yes","communication_needed":null,"end_time":"16:30","start_time":"13:30","type":"Normal"}]},{"day_num":"6","segments":[{"approval_needed":null,"communication_needed":"Mandatory","end_time":"23:59","start_time":"00:00","type":"No Production"}]}]} How to import this JSON in Deneb ? I tried with JSON.parse but fails each time Thank you for your supportSolvedAnother Deneb query - 2 data fields on one bar chart
I have cause to render two different data fields on to the same bars in the same chart. so for instance the x axis will be date y axis should have field 'A' and field 'B' stacked on top of each other for the given date. Also both fields are grouped by another field, 'Z'. Groupings for A should be shown separately from Groupings for B in the legend, Getting A to work is simple: { "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": { "values":[ {"A":10, "B":20, "Z":"poop", "created":"2022/01/01"}, {"A":10, "B":10, "Z":"moop", "created":"2022/01/01"}, {"A":10, "B":5, "Z":"doop", "created":"2022/01/01"}, {"A":13, "B":12, "Z":"poop", "created":"2022/02/01"}, {"A":33, "B":10, "Z":"moop", "created":"2022/02/01"}, {"A":0, "B":5, "Z":"doop", "created":"2022/02/01"}, {"A":13, "B":5, "Z":"poop", "created":"2022/03/01"}, {"A":3, "B":2, "Z":"moop", "created":"2022/03/01"}, {"A":20, "B":7, "Z":"doop", "created":"2022/03/01"} ] }, "mark": "bar", "encoding": { "x": { "timeUnit": "month", "field": "created", "type": "ordinal" }, "y": { "field":"A", "type": "quantitative" }, "color": { "field": "Z", "type": "nominal" } } } how would i go about adding the figures from 'B' onto each bar, in different colours and presented on the legend on separate rows?SolvedHelp - Building a 'Table' with Deneb that Mimics Power BI's Sort Function"
Hi Folks, Ever since I discovered Deneb a few months ago, I've been over the moon with how it broadens Power BI's capacity and amplifies its visual prowess so impressively. It's truly a game-changer 🙂 Yet, as I explore further, I've stumbled upon a challenge that I am confident can be addressed by the minds here 😉 . I'm attempting to build a Power BI "table like" in Deneb, and I confess, it's becoming a bit of an undertaking! To be specific, I'm looking to craft an hconcat that lines up 3-4 "columns" side by side. One column could be a bar, another a heatmap, and so on. Of course, the y-axis is shared among these "columns". But here's the twist, I need to mimic the functionality of clicking on a header to sort it - a feature that's strikingly akin to a Power BI table, a function our users are quite accustomed to and wouldn't want to let go. I've thoroughly combed through Vega's website and unearthed numerous cool features, but none seem to answer this exact question. Maybe it's right there and I'm overlooking it… Could anyone lend a hand or steer me in the right direction? Any help, suggestions, or guidance would be immensely appreciated. Why? - Native tables in Power BI are unfortunately still quite limited in customization, tooltips, etc. - Yet, users love tables, especially being able to create on-the-fly rankings by "sorting". - Keeping in mind what's achievable in Tableau, we believe that when used with discretion, Deneb could offer a super elegant and scalable alternative. PS: Maybe hconcat isn't the best approach, so I'm open to suggestions! I created this on vega editor as a first step:2.9KViews0likes2Comments