March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount! Early bird discount ends December 31.
Register NowBe one of the first to start using Fabric Databases. View on-demand sessions with database experts and the Microsoft product team to learn just how easy it is to get started. Watch now
Is there a power bi custom visual based on seat allocation? for example:
or is there anything similar custom visual to the screenshot above?
All the colours are allocated seat in a company annual meeting.
Solved! Go to Solution.
I got this to work in the attached file by just modifying the Vega spec you posted slightly. Note that I needed to add a "person" field in my example to effectively generate a row per seat
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 550,
"height": 300,
"signals": [
{
"name": "dataLength",
"update": "length(data('dataset'))"
},
{
"name": "row0Radius",
"value": 280
},
{
"name": "row1Radius",
"value": 260
},
{
"name": "row2Radius",
"value": 240
},
{
"name": "row3Radius",
"value": 220
},
{
"name": "row4Radius",
"value": 200
},
{
"name": "row5Radius",
"value": 180
},
{
"name": "row6Radius",
"value": 160
},
{
"name": "row0Circ",
"update": "PI*row0Radius"
},
{
"name": "row1Circ",
"update": "PI*row1Radius"
},
{
"name": "row2Circ",
"update": "PI*row2Radius"
},
{
"name": "row3Circ",
"update": "PI*row3Radius"
},
{
"name": "row4Circ",
"update": "PI*row4Radius"
},
{
"name": "row5Circ",
"update": "PI*row5Radius"
},
{
"name": "row6Circ",
"update": "PI*row6Radius"
},
{
"name": "totalLength",
"update": "row0Circ+row1Circ+row2Circ+row3Circ+row4Circ+row5Circ+row6Circ "
}
],
"data": [
{
"name": "dataset",
"transform": [
{
"type": "project",
"fields": ["Person", "Party"]
},
{
"type": "window",
"ops": ["row_number"],
"fields": [null],
"as": ["index"],
"sort": {
"field": "Party",
"order": "descending"
}
}
]
},
{
"name": "placement",
"transform": [
{
"type": "sequence",
"start": 1,
"stop": {
"signal": "dataLength+1"
},
"as": "index"
},
{
"type": "formula",
"as": "wholeCirc",
"expr": "totalLength/dataLength"
},
{
"type": "window",
"ops": ["sum"],
"fields": ["wholeCirc"],
"as": ["cumWholeCirc"]
},
{
"type": "formula",
"as": "row",
"expr": "datum.cumWholeCirc <row0Circ?0:datum.cumWholeCirc <row0Circ+row1Circ?1:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ?2:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ?3:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ+row4Circ?4:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ+row4Circ+row5Circ?5:6 "
},
{
"type": "joinaggregate",
"fields": ["Person"],
"ops": ["count"],
"groupby": ["row"],
"as": ["rowCount"]
},
{
"type": "formula",
"as": "rowCirc",
"expr": "datum.row==0?(row0Circ/(datum.rowCount-1)):datum.row==1?(row1Circ/(datum.rowCount-1)):datum.row==2?(row2Circ/(datum.rowCount-1)):datum.row==3?(row3Circ/(datum.rowCount-1)):datum.row==4?(row4Circ/(datum.rowCount-1)):datum.row==5?(row5Circ/(datum.rowCount-1)):datum.row==6?(row6Circ/(datum.rowCount-1)):0"
},
{
"type": "window",
"ops": ["sum"],
"fields": ["rowCirc"],
"groupby": ["row"],
"sort": {
"field": "index",
"order": "descending"
},
"as": ["cumRowCirc"]
},
{
"type": "formula",
"as": "cumRowCircAct",
"expr": "datum.cumRowCirc - datum.rowCirc "
},
{
"type": "formula",
"as": "theta",
"expr": "datum.cumRowCircAct==0?0:datum.row==0?(datum.cumRowCircAct/row0Radius):datum.row==1?(datum.cumRowCircAct/row1Radius):datum.row==2?datum.cumRowCircAct/row2Radius:datum.row==3?datum.cumRowCircAct/row3Radius:datum.row==4?datum.cumRowCircAct/row4Radius:datum.row==5?datum.cumRowCircAct/row5Radius:datum.row==6?datum.cumRowCircAct/row6Radius:0"
},
{
"type": "formula",
"as": "x",
"expr": "datum.row==0?row0Radius*cos(datum.theta):datum.row==1?row1Radius*cos(datum.theta):datum.row==2?row2Radius*cos(datum.theta):datum.row==3?row3Radius*cos(datum.theta):datum.row==4?row4Radius*cos(datum.theta):datum.row==5?row5Radius*cos(datum.theta):datum.row==6?row6Radius*cos(datum.theta):0"
},
{
"type": "formula",
"as": "y",
"expr": "datum.row==0?row0Radius*sin(datum.theta):datum.row==1?row1Radius*sin(datum.theta):datum.row==2?row2Radius*sin(datum.theta):datum.row==3?row3Radius*sin(datum.theta):datum.row==4?row4Radius*sin(datum.theta):datum.row==5?row5Radius*sin(datum.theta):datum.row==6?row6Radius*sin(datum.theta):0"
},
{
"type": "window",
"sort": {
"field": "theta",
"order": "ascending"
},
"ops": ["row_number"],
"fields": ["row_number"],
"as": ["lookup"]
},
{
"type": "lookup",
"from": "dataset",
"key": "index",
"fields": ["lookup"],
"values": ["Party"],
"as": ["finalParty"]
}
]
}
],
"scales": [
{
"name": "x",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {
"field": "x",
"data": "placement"
},
"range": "width"
},
{
"name": "y",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {
"field": "y",
"data": "placement"
},
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "placement",
"field": "finalParty"
},
"range": {"scheme": "pbiColorNominal"}
}
],
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "placement"},
"encode": {
"update": {
"x": {
"scale": "x",
"field": "x"
},
"y": {
"scale": "y",
"field": "y"
},
"shape": {"value": "circle"},
"size": {"value": 130},
"stroke": {
"value": "#4682b4"
},
"tooltip": {
"signal": "datum"
},
"fill": {
"scale": "color",
"field": "finalParty"
}
}
}
}
]
}
This is the updated Vega specification (note you need to change the setting in the Deneb visual to use the "Vega" provider instead of the default "Vega-Lite" provider)
I got this to work in the attached file by just modifying the Vega spec you posted slightly. Note that I needed to add a "person" field in my example to effectively generate a row per seat
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 550,
"height": 300,
"signals": [
{
"name": "dataLength",
"update": "length(data('dataset'))"
},
{
"name": "row0Radius",
"value": 280
},
{
"name": "row1Radius",
"value": 260
},
{
"name": "row2Radius",
"value": 240
},
{
"name": "row3Radius",
"value": 220
},
{
"name": "row4Radius",
"value": 200
},
{
"name": "row5Radius",
"value": 180
},
{
"name": "row6Radius",
"value": 160
},
{
"name": "row0Circ",
"update": "PI*row0Radius"
},
{
"name": "row1Circ",
"update": "PI*row1Radius"
},
{
"name": "row2Circ",
"update": "PI*row2Radius"
},
{
"name": "row3Circ",
"update": "PI*row3Radius"
},
{
"name": "row4Circ",
"update": "PI*row4Radius"
},
{
"name": "row5Circ",
"update": "PI*row5Radius"
},
{
"name": "row6Circ",
"update": "PI*row6Radius"
},
{
"name": "totalLength",
"update": "row0Circ+row1Circ+row2Circ+row3Circ+row4Circ+row5Circ+row6Circ "
}
],
"data": [
{
"name": "dataset",
"transform": [
{
"type": "project",
"fields": ["Person", "Party"]
},
{
"type": "window",
"ops": ["row_number"],
"fields": [null],
"as": ["index"],
"sort": {
"field": "Party",
"order": "descending"
}
}
]
},
{
"name": "placement",
"transform": [
{
"type": "sequence",
"start": 1,
"stop": {
"signal": "dataLength+1"
},
"as": "index"
},
{
"type": "formula",
"as": "wholeCirc",
"expr": "totalLength/dataLength"
},
{
"type": "window",
"ops": ["sum"],
"fields": ["wholeCirc"],
"as": ["cumWholeCirc"]
},
{
"type": "formula",
"as": "row",
"expr": "datum.cumWholeCirc <row0Circ?0:datum.cumWholeCirc <row0Circ+row1Circ?1:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ?2:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ?3:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ+row4Circ?4:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ+row4Circ+row5Circ?5:6 "
},
{
"type": "joinaggregate",
"fields": ["Person"],
"ops": ["count"],
"groupby": ["row"],
"as": ["rowCount"]
},
{
"type": "formula",
"as": "rowCirc",
"expr": "datum.row==0?(row0Circ/(datum.rowCount-1)):datum.row==1?(row1Circ/(datum.rowCount-1)):datum.row==2?(row2Circ/(datum.rowCount-1)):datum.row==3?(row3Circ/(datum.rowCount-1)):datum.row==4?(row4Circ/(datum.rowCount-1)):datum.row==5?(row5Circ/(datum.rowCount-1)):datum.row==6?(row6Circ/(datum.rowCount-1)):0"
},
{
"type": "window",
"ops": ["sum"],
"fields": ["rowCirc"],
"groupby": ["row"],
"sort": {
"field": "index",
"order": "descending"
},
"as": ["cumRowCirc"]
},
{
"type": "formula",
"as": "cumRowCircAct",
"expr": "datum.cumRowCirc - datum.rowCirc "
},
{
"type": "formula",
"as": "theta",
"expr": "datum.cumRowCircAct==0?0:datum.row==0?(datum.cumRowCircAct/row0Radius):datum.row==1?(datum.cumRowCircAct/row1Radius):datum.row==2?datum.cumRowCircAct/row2Radius:datum.row==3?datum.cumRowCircAct/row3Radius:datum.row==4?datum.cumRowCircAct/row4Radius:datum.row==5?datum.cumRowCircAct/row5Radius:datum.row==6?datum.cumRowCircAct/row6Radius:0"
},
{
"type": "formula",
"as": "x",
"expr": "datum.row==0?row0Radius*cos(datum.theta):datum.row==1?row1Radius*cos(datum.theta):datum.row==2?row2Radius*cos(datum.theta):datum.row==3?row3Radius*cos(datum.theta):datum.row==4?row4Radius*cos(datum.theta):datum.row==5?row5Radius*cos(datum.theta):datum.row==6?row6Radius*cos(datum.theta):0"
},
{
"type": "formula",
"as": "y",
"expr": "datum.row==0?row0Radius*sin(datum.theta):datum.row==1?row1Radius*sin(datum.theta):datum.row==2?row2Radius*sin(datum.theta):datum.row==3?row3Radius*sin(datum.theta):datum.row==4?row4Radius*sin(datum.theta):datum.row==5?row5Radius*sin(datum.theta):datum.row==6?row6Radius*sin(datum.theta):0"
},
{
"type": "window",
"sort": {
"field": "theta",
"order": "ascending"
},
"ops": ["row_number"],
"fields": ["row_number"],
"as": ["lookup"]
},
{
"type": "lookup",
"from": "dataset",
"key": "index",
"fields": ["lookup"],
"values": ["Party"],
"as": ["finalParty"]
}
]
}
],
"scales": [
{
"name": "x",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {
"field": "x",
"data": "placement"
},
"range": "width"
},
{
"name": "y",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {
"field": "y",
"data": "placement"
},
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "placement",
"field": "finalParty"
},
"range": {"scheme": "pbiColorNominal"}
}
],
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "placement"},
"encode": {
"update": {
"x": {
"scale": "x",
"field": "x"
},
"y": {
"scale": "y",
"field": "y"
},
"shape": {"value": "circle"},
"size": {"value": 130},
"stroke": {
"value": "#4682b4"
},
"tooltip": {
"signal": "datum"
},
"fill": {
"scale": "color",
"field": "finalParty"
}
}
}
}
]
}
This is the updated Vega specification (note you need to change the setting in the Deneb visual to use the "Vega" provider instead of the default "Vega-Lite" provider)
Hi there, Does the visual need to be curved? There may be a waffle template that will be easier to use. If there are always the same amount of seats, there might be a lower code solution, such as using Synoptic Panel, Pureviz or Visio diagram
Proud to be a Super User!
@KerKol @v-henryk-mstf I wanted it to be curve but if there is other alternative visual please share with me. It is same number of seat every time.
Hi @Anonymous ,
There does not seem to be a similar visual object in powerbi. What are your specific needs and maybe there is some other visual object that can replace it.
Looking forward to your reply.
Best Regards,
Henry
I want researching and I found that Deneb declarative custom visual can be use to achieve this.
However, I have tried to use it but didn't work.
I found some code in JSON but I don't know anything regarding Deneb and JSON. see below
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 550,
"height": 300,
"signals": [
{"name": "dataLength", "update": "length(data('penguins'))"},
{"name": "row0Radius", "value": 280},
{"name": "row1Radius", "value": 260},
{"name": "row2Radius", "value": 240},
{"name": "row3Radius", "value": 220},
{"name": "row4Radius", "value": 200},
{"name": "row5Radius", "value": 180},
{"name": "row6Radius", "value": 160},
{"name": "row0Circ", "update": "PI*row0Radius"},
{"name": "row1Circ", "update": "PI*row1Radius"},
{"name": "row2Circ", "update": "PI*row2Radius"},
{"name": "row3Circ", "update": "PI*row3Radius"},
{"name": "row4Circ", "update": "PI*row4Radius"},
{"name": "row5Circ", "update": "PI*row5Radius"},
{"name": "row6Circ", "update": "PI*row6Radius"},
{
"name": "totalLength",
"update": "row0Circ+row1Circ+row2Circ+row3Circ+row4Circ+row5Circ+row6Circ "
}
],
"data": [
{
"name": "penguins",
"url": "data/penguins.json",
"transform": [
{"type": "project", "fields": ["Species", "Island"]},
{
"type": "window",
"ops": ["row_number"],
"fields": [null],
"as": ["index"],
"sort": {"field": "Island", "order": "ascending"}
}
]
},
{
"name": "placement",
"transform": [
{
"type": "sequence",
"start": 1,
"stop": {"signal": "dataLength+1"},
"as": "index"
},
{
"type": "formula",
"as": "wholeCirc",
"expr": "totalLength/dataLength"
},
{
"type": "window",
"ops": ["sum"],
"fields": ["wholeCirc"],
"as": ["cumWholeCirc"]
},
{
"type": "formula",
"as": "row",
"expr": "datum.cumWholeCirc <row0Circ?0:datum.cumWholeCirc <row0Circ+row1Circ?1:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ?2:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ?3:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ+row4Circ?4:datum.cumWholeCirc <row0Circ+row1Circ+row2Circ+row3Circ+row4Circ+row5Circ?5:6 "
},
{
"type": "joinaggregate",
"fields": ["Species"],
"ops": ["count"],
"groupby": ["row"],
"as": ["rowCount"]
},
{
"type": "formula",
"as": "rowCirc",
"expr": "datum.row==0?(row0Circ/(datum.rowCount-1)):datum.row==1?(row1Circ/(datum.rowCount-1)):datum.row==2?(row2Circ/(datum.rowCount-1)):datum.row==3?(row3Circ/(datum.rowCount-1)):datum.row==4?(row4Circ/(datum.rowCount-1)):datum.row==5?(row5Circ/(datum.rowCount-1)):datum.row==6?(row6Circ/(datum.rowCount-1)):0"
},
{
"type": "window",
"ops": ["sum"],
"fields": ["rowCirc"],
"groupby": ["row"],
"sort": {"field": "index", "order": "descending"},
"as": ["cumRowCirc"]
},
{
"type": "formula",
"as": "cumRowCircAct",
"expr": "datum.cumRowCirc - datum.rowCirc "
},
{
"type": "formula",
"as": "theta",
"expr": "datum.cumRowCircAct==0?0:datum.row==0?(datum.cumRowCircAct/row0Radius):datum.row==1?(datum.cumRowCircAct/row1Radius):datum.row==2?datum.cumRowCircAct/row2Radius:datum.row==3?datum.cumRowCircAct/row3Radius:datum.row==4?datum.cumRowCircAct/row4Radius:datum.row==5?datum.cumRowCircAct/row5Radius:datum.row==6?datum.cumRowCircAct/row6Radius:0"
},
{
"type": "formula",
"as": "x",
"expr": "datum.row==0?row0Radius*cos(datum.theta):datum.row==1?row1Radius*cos(datum.theta):datum.row==2?row2Radius*cos(datum.theta):datum.row==3?row3Radius*cos(datum.theta):datum.row==4?row4Radius*cos(datum.theta):datum.row==5?row5Radius*cos(datum.theta):datum.row==6?row6Radius*cos(datum.theta):0"
},
{
"type": "formula",
"as": "y",
"expr": "datum.row==0?row0Radius*sin(datum.theta):datum.row==1?row1Radius*sin(datum.theta):datum.row==2?row2Radius*sin(datum.theta):datum.row==3?row3Radius*sin(datum.theta):datum.row==4?row4Radius*sin(datum.theta):datum.row==5?row5Radius*sin(datum.theta):datum.row==6?row6Radius*sin(datum.theta):0"
},
{
"type": "window",
"sort": {"field": "theta", "order": "ascending"},
"ops": ["row_number"],
"fields": ["row_number"],
"as": ["lookup"]
},
{
"type": "lookup",
"from": "penguins",
"key": "index",
"fields": ["lookup"],
"values": ["Island"],
"as": ["finalIsland"]
}
]
}
],
"scales": [
{
"name": "x",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {"field": "x", "data": "placement"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {"field": "y", "data": "placement"},
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {"data": "placement", "field": "finalIsland"},
"range": {"scheme": "category10"}
}
],
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "placement"},
"encode": {
"update": {
"x": {"scale": "x", "field": "x"},
"y": {"scale": "y", "field": "y"},
"shape": {"value": "circle"},
"size": {"value": 130},
"stroke": {"value": "#4682b4"},
"tooltip": {"signal": "datum"},
"fill": {"scale": "color", "field": "finalIsland"}
}
}
}
]
}
This code was shared but I don't know how to reference my data and the column and measure I'm using.
My data is Poll and the field (Party ) and measure (Seat Allocated).
Please can someone help me out with the Deneb and code above to reference dataset and column and measure.
March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount!
Arun Ulag shares exciting details about the Microsoft Fabric Conference 2025, which will be held in Las Vegas, NV.
User | Count |
---|---|
125 | |
85 | |
69 | |
54 | |
45 |
User | Count |
---|---|
204 | |
106 | |
98 | |
65 | |
54 |