<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Adding a Second Measure to Custom Visual in Developer</title>
    <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916844#M22161</link>
    <description>&lt;P&gt;Hi &lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/175974"&gt;@cogsie&lt;/a&gt;&amp;nbsp;- just getting your code set up and I'm getting some compilation errors due to my &lt;FONT face="courier new,courier"&gt;settings.ts&lt;/FONT&gt; not being in sync with the code in your &lt;FONT face="courier new,courier"&gt;visual.ts&lt;/FONT&gt;. Are you able to provide that too (sorry, I should have thought to ask for it orginally)?&lt;/P&gt;&lt;P&gt;One other question - is your visual intending to only display a maximum of two measures, and is the second measure performing a specific role (e.g. as a target vs the other measure)? This is important as it'll have an effect on how we build your view model and &lt;FONT face="courier new,courier"&gt;capabilties.json&lt;/FONT&gt; to suit.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Daniel&lt;/P&gt;</description>
    <pubDate>Thu, 30 Jan 2020 18:50:10 GMT</pubDate>
    <dc:creator>dm-p</dc:creator>
    <dc:date>2020-01-30T18:50:10Z</dc:date>
    <item>
      <title>Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916586#M22155</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I am new to programming and not even really sure how to ask this question.&amp;nbsp; Please let me know if anyhting is unclear or you need more information, but here it goes:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I am creating my first custom visual in Power BI.&amp;nbsp; I want to have overlapping bar charts.&amp;nbsp; I found an example/tutorial online showing how to create a simple bar chart.&amp;nbsp; I was able to modify the visual to get the two overlapping bar charts, and the custom visual is looking exactly how I want it (see below).&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Capture.JPG" style="width: 200px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/230555i372E689E0122A710/image-size/small?v=v2&amp;amp;px=200" role="button" title="Capture.JPG" alt="Capture.JPG" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The problem is that the example I modified restricted the visual to only using one measure (that is why in the screenshot the thin yellow and fat green bars are exactly the same height - they are both based on the same set of values).&amp;nbsp; I was able to change the capabilities file to allow for 2 measures.&amp;nbsp; However, I can't figure out how to make it so the second set of bars (yellow bars) uses the second measure.&amp;nbsp; Can someone help point me in the right direction?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Below is the visual.ts file.&amp;nbsp; Please let me know if you need any additional information or if anything is unclear.&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;import "./../style/visual.less";

import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;

import DataView = powerbi.DataView;
import DataViewValueColumn = powerbi.DataViewValueColumn;
import DataViewCategorical = powerbi.DataViewCategorical;
import DataViewCategoricalColumn = powerbi.DataViewCategoricalColumn;
import DataViewCategoryColumn = powerbi.DataViewCategoryColumn;
import PrimitiveValue = powerbi.PrimitiveValue;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;

import IColorPalette = powerbi.extensibility.IColorPalette;
import VisualObjectInstance = powerbi.VisualObjectInstance;
import VisualObjectInstanceEnumeration = powerbi.VisualObjectInstanceEnumeration;
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import Fill = powerbi.Fill;
import VisualTooltipDataItem = powerbi.extensibility.VisualTooltipDataItem;
import ISelectionManager = powerbi.extensibility.ISelectionManager;

import { valueFormatter as vf, textMeasurementService as tms } from "powerbi-visuals-utils-formattingutils";
import IValueFormatter = vf.IValueFormatter;

import { VisualSettings,BarchartProperties } from "./settings";

import * as d3 from "d3";
type Selection&amp;lt;T extends d3.BaseType&amp;gt; = d3.Selection&amp;lt;T, any, any, any&amp;gt;;
type DataSelection&amp;lt;T&amp;gt; = d3.Selection&amp;lt;d3.BaseType, T, any, any&amp;gt;;

export interface BarchartDataPoint{
    Category: string;
    Value: number;
}

export interface BarchartViewModel{
    IsNotValid: boolean;
    DataPoints?:BarchartDataPoint[];
    Format?: string,
    SortBySize?: boolean;
    XAxisFontSize?: number;
    YAxisFontSize?: number;
    BarColor?: string
    ColumnName?: string;
    MeasureName?: string;
}

export class Barchart implements IVisual {
    private svg: Selection&amp;lt;SVGElement&amp;gt;;
    private barContainer: Selection&amp;lt;SVGGElement&amp;gt;;
    private plotBackground: Selection&amp;lt;SVGRectElement&amp;gt;;
    private barSelection: DataSelection&amp;lt;BarchartDataPoint&amp;gt;;
    private xAxisContainer: Selection&amp;lt;SVGGElement&amp;gt;;
    private yAxisContainer: Selection&amp;lt;SVGGElement&amp;gt;;

    private barContainer2: Selection&amp;lt;SVGGElement&amp;gt;;
    private plotBackground2: Selection&amp;lt;SVGRectElement&amp;gt;;
    private barSelection2: DataSelection&amp;lt;BarchartDataPoint&amp;gt;;
    private xAxisContainer2: Selection&amp;lt;SVGGElement&amp;gt;;
    private yAxisContainer2: Selection&amp;lt;SVGGElement&amp;gt;;


    private hostService: IVisualHost;

    private settings: VisualSettings;

    private viewModel: BarchartViewModel;

    private static margin = {
        top:20,
        right: 20,
        bottom: 20,
        left: 50,
    };




    constructor(options: VisualConstructorOptions) {
        console.log('Constructor executing', options);

        this.hostService = options.host;

        this.svg = d3.select(options.element)
            .append('svg')
            .classed('Barchart',true);
        
        this.barContainer = this.svg
            .append('g')
            .classed('barContainer', true);
        
        this.plotBackground = this.barContainer
            .append('rect')
            .classed('plotBackground', true);
            
        this.xAxisContainer = this.svg
            .append('g')
            .classed('xAxis', true);

        this.yAxisContainer = this.svg
            .append('g')
            .classed('yAxis', true);

        this.barContainer2 = this.svg
            .append('g')
            .classed('barContainer2', true);

        this.plotBackground2 = this.barContainer2
            .append('rect')
            .classed('plotBackground2', true);

        this.xAxisContainer2 = this.svg
            .append('g')
            .classed('xAxis2', true);

        this.yAxisContainer2 = this.svg
            .append('g')
            .classed('yAxis2', true);


        this.settings = VisualSettings.getDefault() as VisualSettings;

    }

    public update(options: VisualUpdateOptions) {

        var viewModel: BarchartViewModel = this.createViewModel(options.dataViews[0]);
        if (viewModel.IsNotValid){
            return;
        }

        //set height and width of root SVG element using viewport passed by Power BI host
        this.svg.attr("height",options.viewport.height);
        this.svg.attr("width", options.viewport.width);

        let marginLeft = Barchart.margin.left * (viewModel.YAxisFontSize / 10);
        let marginBottom = Barchart.margin.bottom * (viewModel.XAxisFontSize / 10);
        let marginTop = Barchart.margin.top;
        let marginRight = Barchart.margin.right;

        let plotArea = {
            x: marginLeft,
            y:marginTop,
            width: (options.viewport.width - (marginLeft + Barchart.margin.right))/2,
            height: (options.viewport.height - (marginTop + marginBottom)),
        };

        let plotArea2 = {
            x: plotArea.x + plotArea.width + 0.3,
            y: marginTop,
        };

        this.barContainer
            .attr("transform","translate(" + plotArea.x + "," + plotArea.y + ")")
            .attr("width",options.viewport.width)
            .attr("height", options.viewport.height);
        
        
        this.plotBackground
            .attr("width", plotArea.width)
            .attr("height", plotArea.height)
            .style("fill","blue");

        this.barContainer2
            .attr("transform", "translate(" + plotArea.x + "," + plotArea.y + ")")
            .attr("width", options.viewport.width)
            .attr("height", options.viewport.height);

        this.plotBackground2
            .attr("width", plotArea.width)
            .attr("height", plotArea.height)
            .style("fill", "none");


        var xScale = d3.scaleBand()
            .rangeRound([0, plotArea.width])
            .padding(0.1)
            .domain(viewModel.DataPoints.map((dataPoint:BarchartDataPoint) =&amp;gt; dataPoint.Category));

        this.xAxisContainer
            .attr("class", "xAxis")
            .attr("transform","translate(" + plotArea.x + "," + (plotArea.height + plotArea.y)+")")
            .call(d3.axisBottom(xScale));

        this.xAxisContainer2
            .attr("class", "xAxis2")
            .attr("transform", "translate(" + plotArea.x + "," + (plotArea.height + plotArea.y) + ")")
            .call(d3.axisBottom(xScale));


        d3.select(".xAxis").selectAll("text").style("font-size",viewModel.XAxisFontSize);

        d3.select(".xAxis2").selectAll("text").style("font-size", viewModel.XAxisFontSize);

        let maxValueY: number = d3.max(viewModel.DataPoints,(dataPoint:BarchartDataPoint) =&amp;gt; +(dataPoint.Value));

        var valueFormatter = vf.create({
            format: viewModel.Format,
            value: maxValueY/100,
            cultureSelector: this.hostService.locale
        });

        var yScale = d3.scaleLinear()
            .rangeRound([plotArea.height,0])
            .domain([0,maxValueY * 1.02]);

            
        var yAxis = d3.axisLeft(yScale)
            .tickFormat((d) =&amp;gt; valueFormatter.format(d));
        //        .tickPadding(12).ticks(5);


        this.yAxisContainer
            .attr("class","yAxis")
            .attr("transform", "translate(" + plotArea.x + "," + plotArea.y + ")")
            .call(yAxis);
/*
        this.yAxisContainer2
            .attr("class", "yAxis2")
            .attr("transform", "translate(" + plotArea2.x + "," + plotArea.y + ")")
            .call(yAxis);
*/

        d3.select(".yAxis").selectAll("text").style("font-size",viewModel.YAxisFontSize);
//        d3.select(".yAxis2").selectAll("text").style("font-size", viewModel.YAxisFontSize);

        this.barSelection2 = this.barContainer2
            .selectAll('.bar')
            .data(viewModel.DataPoints);


        this.barSelection = this.barContainer
            .selectAll('.bar')
            .data(viewModel.DataPoints);

    
        
        const barSelectionMerged = this.barSelection
            .enter()
            .append('rect')
            .merge(&amp;lt;any&amp;gt;this.barSelection)
            .classed('bar',true);

        const barSelectionMerged2 = this.barSelection2
            .enter()
            .append('rect')
            .merge(&amp;lt;any&amp;gt;this.barSelection2)
            .classed('bar', true);


        barSelectionMerged
            .attr("x", (dataPoint: BarchartDataPoint) =&amp;gt; xScale(dataPoint.Category))
            .attr("y", (dataPoint: BarchartDataPoint) =&amp;gt; yScale(Number(dataPoint.Value)))
            .attr("width", xScale.bandwidth())
            .attr("height", (dataPoint: BarchartDataPoint) =&amp;gt; (plotArea.height - yScale(Number(dataPoint.Value))))
            .style("fill",(dataPoint:BarchartDataPoint) =&amp;gt; viewModel.BarColor);

        barSelectionMerged2
            .attr("x", (dataPoint: BarchartDataPoint) =&amp;gt; xScale(dataPoint.Category) + xScale.bandwidth() / 4)
            .attr("y", (dataPoint: BarchartDataPoint) =&amp;gt; yScale(Number(dataPoint.Value)))
            .attr("width", xScale.bandwidth() / 2)
            .attr("height", (dataPoint: BarchartDataPoint) =&amp;gt; (plotArea.height - yScale(Number(dataPoint.Value))))
            .style("fill", (dataPoint: BarchartDataPoint) =&amp;gt; 'yellow')
            .style("fill-opacity", (dataPoint: BarchartDataPoint) =&amp;gt; 1);


        this.barSelection
            .exit()
            .remove();

    }

    public createViewModel(dataView: DataView): BarchartViewModel{

        //handle case where categorical DataView is not valid
        if(typeof dataView === "undefined" ||
            typeof dataView.categorical === "undefined" ||
            typeof dataView.categorical.categories === "undefined" ||
            typeof dataView.categorical.values === "undefined"){
            return {IsNotValid: true};
        }

        this.settings=VisualSettings.parse(dataView) as VisualSettings;

        var categoricalDataView: DataViewCategorical = dataView.categorical;
        var categoryColumn: DataViewCategoricalColumn = categoricalDataView.categories[0];
        var categoryNames: PrimitiveValue[] = categoricalDataView.categories[0].values;
        var categoryValues: PrimitiveValue[] = categoricalDataView.values[0].values;

        var BarchartDataPoints: BarchartDataPoint[] = [];

        for(var i=0; i &amp;lt; categoryValues.length; i++){
            //get category name and category value
            var category : string = &amp;lt;string&amp;gt;categoryNames[i];
            var categoryValue: number = &amp;lt;number&amp;gt;categoryValues[i];
            //add new data point to barchartDataPoints collection
            BarchartDataPoints.push({
                Category: category,
                Value: categoryValue
            });
        }

        //get formatting code for the field that is the measure
        var format: string = categoricalDataView.values[0].source.format

        //get persistent property values
        var SortBySize: boolean = this.settings.barchartProperties.sortBySize;
        var xAxisFontSize: number = this.settings.barchartProperties.xAxisFontSize;
        var yAxisFontSize: number = this.settings.barchartProperties.yAxisFontSize;
        var barColor: string = typeof (this.settings.barchartProperties.barColor) == "string"?
            this.settings.barchartProperties.barColor:
            this.settings.barchartProperties.barColor.solid.color;
        
        //sort dataset rows by measure value instead of cateogry value
        if(SortBySize){
            BarchartDataPoints.sort((x,y) =&amp;gt;{return y.Value - x.Value})
        }

        //return view model to upate method
        return{
            IsNotValid: false,
            DataPoints: BarchartDataPoints,
            Format: format,
            SortBySize: SortBySize,
            BarColor: barColor,
            XAxisFontSize: xAxisFontSize,
            YAxisFontSize: yAxisFontSize,
            ColumnName: dataView.metadata.columns[1].displayName,
            MeasureName:dataView.metadata.columns[0].displayName
        };

    }

    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {

        var visualObjects: VisualObjectInstanceEnumerationObject = &amp;lt;VisualObjectInstanceEnumerationObject&amp;gt;VisualSettings.enumerateObjectInstances(this.settings, options);
        
        visualObjects.instances[0].validValues = {
            xAxisFontSize:{numberRange:{min: 10, max:36}},
            yAxisFontSize: { numberRange: { min: 10, max: 36 } },
        };

        return visualObjects
    }

}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 14:40:32 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916586#M22155</guid>
      <dc:creator>cogsie</dc:creator>
      <dc:date>2020-01-30T14:40:32Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916817#M22158</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/175974"&gt;@cogsie&lt;/a&gt;,&lt;/P&gt;&lt;P&gt;I can help you with this one - can you please attach your &lt;FONT face="courier new,courier"&gt;capabilities.json&lt;/FONT&gt; as well? This will specify how the second measure is getting added to the data view and I can make sure I provide you with the correct code.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Daniel&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 18:24:00 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916817#M22158</guid>
      <dc:creator>dm-p</dc:creator>
      <dc:date>2020-01-30T18:24:00Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916831#M22159</link>
      <description>&lt;P&gt;Thanks so much.&amp;nbsp; I was doing some more research on this and I think it has something to do with using for...in instead of bind...to.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Below is the capabilities JSON&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;{
    "dataRoles": [
        {
            "displayName": "Bar Grouping",
            "name": "myCategory",
            "kind": "Grouping"
        },
        {
            "displayName": "Bar Measurement",
            "name": "myMeasure",
            "kind": "Measure"
        }
    ],
    "dataViewMappings": [
        {
            "conditions": [
                {
                    "myCategory": {
                        "max": 1
                    },
                    "myMeasure": {
                        "max": 2
                    }
                }
            ],
            "categorical": {
                "categories": {
                    "for": {
                        "in": "myCategory"
                    },
                    "dataReductionAlgorithm": {
                        "top": {}
                    }
                },
                "values": {
                    "select": [
                        {
                            "bind": {
                                "to": "myMeasure"
                            }
                        }
                    ]
                }
            }
        }
    ],
    "objects": {
        "barchartProperties": {
            "displayName": "Barchart Properties",
            "properties": {
                "sortBySize": {
                    "displayName": "Sort by Size",
                    "type": {
                        "bool": true
                    }
                },
                "barColor": {
                    "displayName": "Bar Color",
                    "type": {
                        "fill": {
                            "solid": {
                                "color": true
                            }
                        }
                    }
                },
                "xAxisFontSize": {
                    "displayName": "X Axis Font Size",
                    "type": {
                        "integer": true
                    }
                },
                "yAxisFontSize": {
                    "displayName": "Y Axis Font Size",
                    "type": {
                        "integer": true
                    }
                }
            }
        }
    }
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 18:38:56 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916831#M22159</guid>
      <dc:creator>cogsie</dc:creator>
      <dc:date>2020-01-30T18:38:56Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916844#M22161</link>
      <description>&lt;P&gt;Hi &lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/175974"&gt;@cogsie&lt;/a&gt;&amp;nbsp;- just getting your code set up and I'm getting some compilation errors due to my &lt;FONT face="courier new,courier"&gt;settings.ts&lt;/FONT&gt; not being in sync with the code in your &lt;FONT face="courier new,courier"&gt;visual.ts&lt;/FONT&gt;. Are you able to provide that too (sorry, I should have thought to ask for it orginally)?&lt;/P&gt;&lt;P&gt;One other question - is your visual intending to only display a maximum of two measures, and is the second measure performing a specific role (e.g. as a target vs the other measure)? This is important as it'll have an effect on how we build your view model and &lt;FONT face="courier new,courier"&gt;capabilties.json&lt;/FONT&gt; to suit.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Daniel&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 18:50:10 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916844#M22161</guid>
      <dc:creator>dm-p</dc:creator>
      <dc:date>2020-01-30T18:50:10Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916873#M22163</link>
      <description>&lt;P&gt;I really appreciate your help.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Below is the settings.ts file.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;My goal with this chart is to compare to values across one or more categories.&amp;nbsp; For example comparing budgeted amounts to actual amounts for each sales region where the green bars are the budget and the yellow bars are the actuals.&amp;nbsp; So to answer your question more directly, each bar would be the sume of different measures (e.g. actual, budget).&amp;nbsp; I hope that makes sense.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;"use strict";

import { dataViewObjectsParser } from "powerbi-visuals-utils-dataviewutils";
import DataViewObjectsParser = dataViewObjectsParser.DataViewObjectsParser;
import powerbi from "powerbi-visuals-api";
import Fill = powerbi.Fill;

export class VisualSettings extends DataViewObjectsParser {
  // public dataPoint: dataPointSettings = new dataPointSettings();
  public barchartProperties: BarchartProperties = new BarchartProperties();
}

export class BarchartProperties {
  sortBySize: boolean = true;
  xAxisFontSize: number = 10;
  yAxisFontSize: number = 10;
  barColor: Fill = { "solid": { "color": "#018a80" } }; // default color is  teal
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 19:17:28 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916873#M22163</guid>
      <dc:creator>cogsie</dc:creator>
      <dc:date>2020-01-30T19:17:28Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916892#M22165</link>
      <description>&lt;P&gt;Hi &lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/175974"&gt;@cogsie&lt;/a&gt;.,&lt;/P&gt;&lt;P&gt;Thanks very much - I can get the code to compile now.&lt;/P&gt;&lt;P&gt;Looks like you're trying something like a &lt;A href="https://appsource.microsoft.com/en-us/product/power-bi-visuals/wa104380953" target="_self"&gt;bullet chart&lt;/A&gt;?&lt;/P&gt;&lt;P&gt;If so, I'd suggest creating specific data roles for each measure as they each have an intended purpose. This will make your code easier to manage rather than using a single data role with multiple measures and more intuitive to the end-user. Using the same data role with multiple measures will cause a challenge in that&amp;nbsp;they will all have the same role type, processing the data view and assigning the measures to the appropriate bar will depend on the order they're added by the end user.&lt;/P&gt;&lt;P&gt;I'll proceed on the basis that we want two distinct measure roles - for the sake of illustration, I'll call them &lt;STRONG&gt;actual&lt;/STRONG&gt; and &lt;STRONG&gt;budget&lt;/STRONG&gt; and provide you with the changes required to make that work. Does that sounds like a good approach to you? If you want to stick with the existing approach, let me know and I'll provide you with a solution as per your requirements.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Daniel&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 19:34:01 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916892#M22165</guid>
      <dc:creator>dm-p</dc:creator>
      <dc:date>2020-01-30T19:34:01Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916904#M22167</link>
      <description>&lt;P&gt;This sounds like a great approach.&amp;nbsp; And you are correct, it is similar to the bullet chart, but much simpler.&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 19:42:11 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916904#M22167</guid>
      <dc:creator>cogsie</dc:creator>
      <dc:date>2020-01-30T19:42:11Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916950#M22168</link>
      <description>&lt;P&gt;Great!&lt;/P&gt;&lt;P&gt;I've added &lt;A href="https://gist.github.com/dm-p/f3a0470cd913350a0f29252743b16644" target="_self"&gt;all files to this gist&lt;/A&gt; for you to download the full code, as I'd like to focus on explaining the changes I made so that you can build on them accordingly.&lt;/P&gt;&lt;P&gt;&lt;FONT size="5"&gt;&lt;STRONG&gt;capabilities.json - &lt;FONT face="courier new,courier"&gt;dataRoles&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;I've modified the &lt;FONT face="courier new,courier"&gt;dataRoles&lt;/FONT&gt; to the following:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    "dataRoles": [
        {
            "displayName": "Bar Grouping",
            "name": "myCategory",
            "kind": "Grouping"
        },
        {
            "displayName": "Actual",
            "name": "actual",
            "kind": "Measure"
        },
        {
            "displayName": "Budget",
            "name": "budget",
            "kind": "Measure"
        }
    ]&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;This will modify the visual's data roles as follows:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image.png" style="width: 178px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/230659iB2AB48B0CD44D858/image-size/large?v=v2&amp;amp;px=999" role="button" title="image.png" alt="image.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#FF0000"&gt;&lt;STRONG&gt;Note&lt;/STRONG&gt; &lt;/FONT&gt;that your development visual will likely still have the now removed &lt;STRONG&gt;myMeasure&lt;/STRONG&gt; role in there, so your best bet is to ensure everything is fully removed and re-applied when working with the new code I've provided.&lt;/P&gt;&lt;P&gt;&lt;FONT size="5"&gt;&lt;STRONG&gt;capabilities.json - &lt;FONT face="courier new,courier"&gt;dataViewMappings&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;The &lt;FONT face="courier new,courier"&gt;dataViewMappings&lt;/FONT&gt; now look as follows:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    "dataViewMappings": [
        {
            "conditions": [
                {
                    "myCategory": {
                        "max": 1
                    },
                    "actual": {
                        "max": 1
                    },
                    "budget": {
                        "max": 1
                    }
                }
            ],
            "categorical": {
                "categories": {
                    "for": {
                        "in": "myCategory"
                    },
                    "dataReductionAlgorithm": {
                        "top": {}
                    }
                },
                "values": {
                    "select": [
                        {
                            "bind": {
                                "to": "actual"
                            }
                        },
                        {
                            "bind": {
                                "to": "budget"
                            }
                        }
                    ]
                }
            }
        }
    ]&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This will group by &lt;STRONG&gt;myCategory&lt;/STRONG&gt; and then bind both measures to each. For my test data, the visual table looks as follows:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image.png" style="width: 134px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/230660i9786F1F9FB90BB2C/image-size/large?v=v2&amp;amp;px=999" role="button" title="image.png" alt="image.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Note that this is a public dataset and I'm treating &lt;EM&gt;Tip&lt;/EM&gt; as &lt;STRONG&gt;actual&lt;/STRONG&gt; and &lt;EM&gt;Total&lt;/EM&gt; Bill as &lt;STRONG&gt;budget&lt;/STRONG&gt;.&lt;/P&gt;&lt;P&gt;Let's take a look at the &lt;FONT face="courier new,courier"&gt;dataViewMapping&lt;/FONT&gt; in the developer visual for the data I've added:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image.png" style="width: 457px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/230661i4C75D0FCE84E53D0/image-size/large?v=v2&amp;amp;px=999" role="button" title="image.png" alt="image.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;The values array now has two entries - one for &lt;STRONG&gt;actual&lt;/STRONG&gt; and one for &lt;STRONG&gt;budget&lt;/STRONG&gt;. We can see this if we expand the &lt;FONT face="courier new,courier"&gt;source&lt;/FONT&gt; object for each and then &lt;FONT face="courier new,courier"&gt;roles&lt;/FONT&gt; - and this is how you can determine which entry is performing which role. The measure values for each are then in the associated &lt;FONT face="courier new,courier"&gt;values&lt;/FONT&gt; array (which will match the order of &lt;FONT face="courier new,courier"&gt;myCategory&lt;/FONT&gt;). For brevity, I've only expanded this for &lt;STRONG&gt;actual&lt;/STRONG&gt;.&lt;/P&gt;&lt;P&gt;&lt;FONT size="5"&gt;&lt;STRONG&gt;visual.ts -&amp;nbsp;&lt;SPAN&gt;&lt;FONT face="courier new,courier"&gt;BarchartDataPoint&lt;/FONT&gt; interface&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;We need to change the interface spec to ensure that the 'shape' of each data point is correct. This now looks as follows:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;export interface BarchartDataPoint{
    category: string;
    actual: number;
    budget: number;
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;(it's not essential, but good practice to use camelCase for properties, so I have modified all to suit)&lt;/P&gt;&lt;P&gt;This now means that our view model expects two numeric values for each category, which matches our &lt;FONT face="courier new,courier"&gt;dataViewMappings&lt;/FONT&gt;, so we need to map them into the view model next.&lt;/P&gt;&lt;P&gt;&lt;FONT size="5"&gt;&lt;STRONG&gt;visual.ts - &lt;FONT face="courier new,courier"&gt;createViewModel&lt;/FONT&gt; function&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;If you're making the above changes incrementally, you'll now see errors in your code, because the &lt;FONT face="courier new,courier"&gt;BarchartDataPoint&lt;/FONT&gt; interface 'shape' does not match the object you're assigning in the &lt;FONT face="courier new,courier"&gt;createViewModel&lt;/FONT&gt; function. We need to update this.&lt;/P&gt;&lt;P&gt;With the above in mind, and how the &lt;FONT face="courier new,courier"&gt;dataViewMapping&lt;/FONT&gt; looks, we need to change the way we iterate over it.&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;You were previously iterating over the measure values; I have modified this to iterate over the category values just to make the next bit easier.&lt;/LI&gt;&lt;LI&gt;I'm going to do the simplest possible solution for the measures using array accessors of &lt;FONT face="courier new,courier"&gt;[0]&lt;/FONT&gt; for &lt;STRONG&gt;actual&lt;/STRONG&gt; and &lt;FONT face="courier new,courier"&gt;[1]&lt;/FONT&gt; for &lt;STRONG&gt;budget&lt;/STRONG&gt;.&lt;/LI&gt;&lt;LI&gt;To make your code super-resilient, you would &lt;FONT face="courier new,courier"&gt;filter&lt;/FONT&gt; the values array by &lt;FONT face="courier new,courier"&gt;role&lt;/FONT&gt; to ensure the value is definitely provided, but we can worry about that waaaaay later &lt;span class="lia-unicode-emoji" title=":winking_face:"&gt;😉&lt;/span&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;The portion of the function code to map the view model now looks as follows:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    categoryNames.map((c, ci) =&amp;gt; { /** c= category, ci = category array index */
        BarchartDataPoints.push({
            category: &amp;lt;string&amp;gt;c,
            actual: &amp;lt;number&amp;gt;categoricalDataView.values[0].values[ci],
            budget: &amp;lt;number&amp;gt;categoricalDataView.values[1].values[ci]
        });
    });&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You have a sort lower down, so that's been modified to use the &lt;STRONG&gt;actual&lt;/STRONG&gt; value:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    if(SortBySize){
        BarchartDataPoints.sort((x,y) =&amp;gt;{return y.actual - x.actual})
    }&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;FONT size="5"&gt;&lt;STRONG&gt;visual.ts - &lt;FONT face="courier new,courier"&gt;update&lt;/FONT&gt; function&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;It's now a case or binding everything from the view model correctly to your chart logic.&lt;/P&gt;&lt;P&gt;The first fix is your &lt;FONT face="courier new,courier"&gt;maxValueY&lt;/FONT&gt; assignment - we just get this to match the highest value now that you have two measures:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    let maxValueY: number = d3.max(
        viewModel.DataPoints,
        (dataPoint:BarchartDataPoint) =&amp;gt; 
            /** Get the higher of either measure per group */
            +Math.max(dataPoint.actual, dataPoint.budget) 
    );&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Now, the actual shape! &lt;FONT face="courier new,courier"&gt;barSelectionMerged&lt;/FONT&gt; gets updated to now use the &lt;STRONG&gt;actual&lt;/STRONG&gt; property from the data point:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    barSelectionMerged
        .attr("x", (dataPoint: BarchartDataPoint) =&amp;gt; xScale(dataPoint.category))
        .attr("y", (dataPoint: BarchartDataPoint) =&amp;gt; yScale(Number(dataPoint.actual)))
        .attr("width", xScale.bandwidth())
        .attr("height", (dataPoint: BarchartDataPoint) =&amp;gt; (plotArea.height - yScale(Number(dataPoint.actual))))
        .style("fill",(dataPoint:BarchartDataPoint) =&amp;gt; viewModel.BarColor);&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;...and barSelectionMerged2 gets the&amp;nbsp;&lt;STRONG&gt;budget&lt;/STRONG&gt; property as part of its &lt;FONT face="courier new,courier"&gt;yScale&lt;/FONT&gt;:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    barSelectionMerged2
        .attr("x", (dataPoint: BarchartDataPoint) =&amp;gt; xScale(dataPoint.category) + xScale.bandwidth() / 4)
        .attr("y", (dataPoint: BarchartDataPoint) =&amp;gt; yScale(Number(dataPoint.budget)))
        .attr("width", xScale.bandwidth() / 2)
        .attr("height", (dataPoint: BarchartDataPoint) =&amp;gt; (plotArea.height - yScale(Number(dataPoint.budget))))
        .style("fill", (dataPoint: BarchartDataPoint) =&amp;gt; 'yellow')
        .style("fill-opacity", (dataPoint: BarchartDataPoint) =&amp;gt; 1);&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;FONT size="5"&gt;&lt;STRONG&gt;Verifying&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;We can now test in the developer visual! Here's how it looks for my data above:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image.png" style="width: 430px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/230671iCC8A1C880BC80850/image-size/large?v=v2&amp;amp;px=999" role="button" title="image.png" alt="image.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;And hopefully, this is where you need to be &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Good luck!&lt;/P&gt;&lt;P&gt;Daniel&lt;/P&gt;&lt;HR /&gt;&lt;P&gt;&lt;FONT size="2"&gt;If my post solves your challenge, then please consider accepting as a solution to help other forum members find the answer more quickly &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/FONT&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 20:48:07 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/916950#M22168</guid>
      <dc:creator>dm-p</dc:creator>
      <dc:date>2020-01-30T20:48:07Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/917011#M22171</link>
      <description>&lt;P&gt;Wow, this is incredible.&amp;nbsp; This is exactly what I need.&amp;nbsp; And thank you for your detailed explanation.&amp;nbsp; I have learned a tremendous amount from all this.&amp;nbsp; Thanks.&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 21:56:24 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/917011#M22171</guid>
      <dc:creator>cogsie</dc:creator>
      <dc:date>2020-01-30T21:56:24Z</dc:date>
    </item>
    <item>
      <title>Re: Adding a Second Measure to Custom Visual</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/917016#M22172</link>
      <description>&lt;P&gt;You're very welcome! Glad you found it useful &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jan 2020 21:59:33 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Adding-a-Second-Measure-to-Custom-Visual/m-p/917016#M22172</guid>
      <dc:creator>dm-p</dc:creator>
      <dc:date>2020-01-30T21:59:33Z</dc:date>
    </item>
  </channel>
</rss>

