使用DotNet.HighCharts库根据来自Webservice的DataTable结果创建图表

使用DotNet.HighCharts库根据来自Webservice的DataTable结果创建图表,highcharts,vb.net-2010,Highcharts,Vb.net 2010,我们正试图从基于Silverlight的图表控件转移到更多的无插件控件。我们喜欢HighCharts,现在正在测试将其实现到现有的代码库中。 我们发现DotNet.HighCharts是一个可能的竞争者,可以快速创建图表,而无需解析所有javascript 我的问题是,当数据包含在数据表中时,如何传入图表中要使用的数据?下面是我看到的答案,即Linq可能是一种方法。然而,我很难让代码真正生成。DotNet.HighCharts的文档没有显示任何拉取非静态数据的示例,因此这里没有运气。这是我迄今为

我们正试图从基于Silverlight的图表控件转移到更多的无插件控件。我们喜欢HighCharts,现在正在测试将其实现到现有的代码库中。 我们发现DotNet.HighCharts是一个可能的竞争者,可以快速创建图表,而无需解析所有javascript

我的问题是,当数据包含在
数据表中时,如何传入图表中要使用的数据?下面是我看到的答案,即Linq可能是一种方法。然而,我很难让代码真正生成。DotNet.HighCharts的文档没有显示任何拉取非静态数据的示例,因此这里没有运气。这是我迄今为止的代码片段:

    Dim da3 As New SqlDataAdapter(sql3, conn3)
    da3.Fill(dt3)
    da3.Dispose()
    conn3.Close()

    Dim chart3 As Highcharts = New Highcharts("chart").InitChart(New Chart() With { _
     .PlotShadow = False _
    }).SetTitle(New Title() With { _
     .Text = "Browser market shares at a specific website, 2010" _
    }).SetTooltip(New Tooltip() With { _
     .Formatter = "function() { return '<b>'+ this.point.name +'</b>: '+ this.percentage +' %'; }" _
    }).SetPlotOptions(New PlotOptions() With { _
     .Column = New PlotOptionsColumn With { _
      .AllowPointSelect = True, _
      .Cursor = Cursors.Pointer, _
      .DataLabels = New PlotOptionsColumnDataLabels() With { _
       .Color = ColorTranslator.FromHtml("#000000"), _
       .Formatter = "function() { return '<b>'+ this.point.name +'</b>: '+ this.percentage +' %'; }" _
      } _
     } _
    }).SetSeries(New Series() With { _
     .Type = ChartTypes.Column, _
     .Name = "Browser share", _
     .Data = New Helpers.Data(dt3.Select(Function(x) New Options.Point() With {.X = x.periodyear, .Y = x.rate}).ToArray()) _
    })
    ltrChart3.Text = chart3.ToHtmlString()
我得到的错误出现在
.Data=New Helpers.Data(dt3.Select(Function(x)New Options.Point(),带有{.x=x.periodyear,.Y=x.rate})。ToArray())
行。我得到的
Lambda表达式无法转换为'String',因为'String'不是委托类型
,因为我在
函数….rate}
位上出错

编辑: 首次尝试修改现有代码

    Dim chart1 As Highcharts = New DotNet.Highcharts.Highcharts("test")

    Dim series As Series = New Series()
    series.Name = "CO Rates"
    For i As Integer = 0 To dt.Rows.Count - 1
        series.Data = New Helpers.Data(New Object() {dt.Rows(i)("periodyear"), dt.Rows(i)("rate")})
    Next
    chart1.SetSeries(series).InitChart(New Chart() With { _
                                       .Type = ChartTypes.Column})
这只生成2列,第一列位于x位置0,其值为2011,另一列位于x位置1,其值为8.3。这是非常奇怪的,因为在我看来,它好像是取了数据表中的最后一个点,然后将它的{x,y}值({2011,8.3})分成两个不同的点,x和y值都是y值,比如{0,x}和{1,y}。 我需要得到:

  • 从数据表中获取{periodyear,rate}的单个序列
  • 在未来,我想有一个系列的每个位置与它的 {periodyear,rate}取自数据表
编辑2: 好的,我已经将结果转换成数据字典,我正在让图表显示所有的点。现在唯一的问题是将
dt.Rows(i)(“periodyear”)
转换为日期时间值。这是迄今为止的代码(在PaseExact方法上失败):

如果我将其更改为字符串值(例如1980),然后将x轴的AxisTypes更改为Linear,我将显示数据。不知怎么的,它刚刚结束——1980年看起来像1980年。婴儿步

编辑N: 这是最终的工作解决方案。这似乎需要一些清理。例如,我不确定是否需要创建一个字典来输入X/Y值,然后在字典上迭代以将数据添加到我的chartData对象。这似乎是双重工作

    Dim stfipsList = (From r In dt.AsEnumerable() Select r("stfips")).Distinct().ToList()
    Dim SeriesList As New List(Of Series)(stfipsList.Count)
    Dim seriesItem(stfipsList.Count) As Series
    Dim xDate As DateTime
    Dim fakeDate As String
    Dim sX As Integer

    sX = 1
    For Each state In stfipsList
        Dim data As New Dictionary(Of DateTime, Decimal)
        Dim stateVal As String = state.ToString
        Dim recCount As Integer = dt.Rows.Count - 1

        For i As Integer = 0 To recCount
            If dt.Rows(i)("stfips").ToString = stateVal Then
                fakeDate = "1/1/" + dt.Rows(i)("periodyear").ToString
                xDate = DateTime.Parse(fakeDate)
                data.Add(xDate.Date, dt.Rows(i)("unemprate"))
            End If
        Next
        Dim chartData As Object(,) = New Object(data.Count - 1, 1) {}
        Dim x As Integer = 0
        For Each pair As KeyValuePair(Of DateTime, Decimal) In data
            chartData.SetValue(pair.Key, x, 0)
            chartData.SetValue(pair.Value, x, 1)
            x += 1
        Next
        seriesItem(sX) = New Series With {
                    .Name = state.ToString, _
                    .Data = New Helpers.Data(chartData)
        }

        SeriesList.Add(seriesItem(sX))

        sX = sX + 1
    Next

    Dim chart1 As Highcharts = New Highcharts("chart1").InitChart(New Chart() With { _
     .Type = ChartTypes.Line _
    }).SetTitle(New Title() With { _
     .Text = "Annual Unemployment Rate" _
    }).SetTooltip(New Tooltip() With { _
     .Formatter = "function() { return '<b>'+ this.series.name + ': ' + Highcharts.dateFormat('%Y', this.x) +'</b>: '+ this.y +' %'; }" _
    }).SetXAxis(New XAxis() With { _
     .Type = AxisTypes.Datetime _
     }).SetYAxis(New YAxis() With { _
       .Min = 0, _
       .Title = New YAxisTitle() With { _
        .Text = "Unemployment Rate", _
        .Align = AxisTitleAligns.High _
      } _
    }).SetSeries(SeriesList.[Select](Function(s) New Series() With { _
                 .Name = s.Name, _
                 .Data = s.Data _
                }).ToArray())

    ltrChart1.Text = chart1.ToHtmlString()
Dim stfipsList=(从dt.AsEnumerable()中的r选择r(“stfips”)).Distinct().ToList()
Dim系列列表作为新列表(系列)(stfipsList.Count)
Dim系列项目(stfipsList.Count)作为系列
Dim xDate作为日期时间
将假日期设置为字符串
作为整数的Dim sX
sX=1
对于stfipsList中的每个状态
作为新字典的Dim数据(日期时间,十进制)
Dim stateVal As String=state.ToString
Dim recCount As Integer=dt.Rows.Count-1
对于i作为整数=0进行重新计数
如果dt.Rows(i)(“stfips”).ToString=stateVal,则
fakeDate=“1/1/”+dt.行(i)(“周期年”).ToString
xDate=DateTime.Parse(fakeDate)
添加数据(xDate.Date,dt.Rows(i)(“未计算”))
如果结束
下一个
Dim chartData作为对象(,)=新对象(data.Count-1,1){
尺寸x为整数=0
作为数据中的KeyValuePair(日期时间,十进制)的每对
chartData.SetValue(pair.Key,x,0)
chartData.SetValue(pair.Value,x,1)
x+=1
下一个
系列项目(sX)=具有{
.Name=state.ToString_
.Data=新的助手.Data(图表数据)
}
序列列表。添加(序列项(sX))
sX=sX+1
下一个
Dim chart1 As Highcharts=新的Highcharts(“chart1”).InitChart(新图表(),带{_
.Type=图表类型.Line_
}).SetTitle(带有{_
.Text=“年度失业率”_
}).SetTooltip(带有{_
.Formatter=“function(){return'+this.series.name+':'+Highcharts.dateFormat('%Y',this.x)+':'+this.Y+'%;}”_
}).SetXAxis(带{_
.Type=AxisTypes.Datetime_
}).SetYAxis(带{_
.Min=0_
.Title=带有{_
.Text=“失业率”_
.Align=轴标题对齐。高_
} _
}).SetSeries(SeriesList.[Select](函数)带有{_
.Name=s.Name_
.Data=s.Data_
}).ToArray())
ltrChart1.Text=chart1.ToHtmlString()

在这里,您可以找到如何从DataTable创建系列的示例:


此外,您还可以从中找到如何“从字典绑定数据”和“从对象列表绑定数据”

请参见下面的我的控制器操作结果,它执行您所要求的操作。它是用C#编写的,但是可以很容易地用VB修改。有比您要求的更多的信息,但在VisualStudio中使用Highcharts时,可能会看到其他问题

我正在做的是创建一个系列列表,然后将列表传递给highcharts。这样做的好处是,您不必单独创建每个系列

public ActionResult CombinerBarToday(DateTime? utcStartingDate = null,
                                             DateTime? utcEndingDate = null)
        {
            //TEMPORARILY USED TO FORCE A DATE
            //utcStartingDate = new DateTime(2012, 1, 9, 0, 0, 1);
            //utcEndingDate = new DateTime(2012, 1, 9, 23, 59, 59);

            //GET THE GENERATED POWER READINGS FOR THE SPECIFIED DATETIME
            var firstQ = from s in db.PowerCombinerHistorys
                         join u in db.PowerCombiners on s.combiner_id equals u.id
                         where s.recordTime >= utcStartingDate
                         where s.recordTime <= utcEndingDate
                         select new
                         {
                             Combiner = u.name,
                             Current = s.current,
                             RecordTime = s.recordTime,
                             Voltage = s.voltage,
                             Power = s.current * s.voltage
                         };

            //APPLY THE GROUPING
            var groups = firstQ.ToList().GroupBy(q => new
            {
                q.Combiner,
                Date = q.RecordTime.Date,
                Hour = q.RecordTime.Hour
            });

            List<CombinerKwh> stringGroupedKwhlist = new List<CombinerKwh>();

            //CALCULATE THE AVERAGE POWER GENERATED PER HOUR AND ADD TO LIST
            foreach (var group in groups)
            {
                stringGroupedKwhlist.Add(new CombinerKwh(
                                         group.Key.Combiner,
                                         new DateTime(group.Key.Date.Year, group.Key.Date.Month, group.Key.Date.Day, group.Key.Hour, 0, 0),
                                         group.Average(g => g.Power) / 1000d
                                         ));
            }

            //GET A LIST OF THE COMBINERS CONTAINS IN THE QUERY
            var secondQ = (from s in firstQ 
                           orderby s.Combiner 
                           select new
                                {
                                    Combiner = s.Combiner
                                }
                           ).Distinct();

            /* THIS LIST OF SERIES WILL BE USED TO DYNAMICALLY ADD AS MANY SERIES 
             * TO THE HIGHCHARTS AS NEEDEDWITHOUT HAVING TO CREATE EACH SERIES INDIVIUALY */
            List<Series> allSeries = new List<Series>();

            TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

            //LOOP THROUGH EACH COMBINER AND CREATE SERIES
            foreach (var distinctCombiner in secondQ)
            {
                var combinerDetail = from h in stringGroupedKwhlist
                                     where h.CombinerID == distinctCombiner.Combiner
                                     orderby TimeZoneInfo.ConvertTimeFromUtc(h.Interval,easternZone)
                                     select new
                                            {
                                                CombinerID = h.CombinerID,
                                                //CONVERT FROM UTC TIME TO THE LOCAL TIME OF THE SITE
                                                Interval = TimeZoneInfo.ConvertTimeFromUtc(h.Interval,easternZone),
                                                KWH = h.KWH
                                            };

                //REPRESENTS 24 PLOTS FOR EACH HOUR IN DAY
                object[] myData = new object[24];

                foreach (var detailCombiner in combinerDetail)
                {
                    if (detailCombiner.KWH != 0)
                    {
                        myData[detailCombiner.Interval.Hour] = detailCombiner.KWH;
                    }
                }

                allSeries.Add(new Series
                                    {
                                        Name = distinctCombiner.Combiner,
                                        Data = new Data(myData)
                                    });
            }

            Highcharts chart = new Highcharts("chart")
            .InitChart(new Chart { DefaultSeriesType = ChartTypes.Spline })
            .SetTitle(new Title { Text = "Combiner History" })
            .SetXAxis(new XAxis
            {
                Categories = new[] { "0:00 AM", "1:00 AM", "2:00 AM", "3:00 AM", "4:00 AM", "5:00 AM", "6:00 AM", "7:00 AM", "8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM", "5:00 PM", "6:00 PM", "7:00 PM", "8:00 PM", "9:00 PM", "10:00 PM", "11:00 PM" },
                Labels = new XAxisLabels
                                       {
                                           Rotation = -45,
                                           Align = HorizontalAligns.Right,
                                           Style = "font: 'normal 10px Verdana, sans-serif'"
                                       },
                Title = new XAxisTitle { Text = "Time(Hour)" },
                //Type = AxisTypes.Linear
            })
            .SetYAxis(new YAxis
            {
                //Min = 0,
                Title = new YAxisTitle { Text = "Kwh" }
            })

            .SetSeries(allSeries.Select(s => new Series { Name = s.Name, Data = s.Data }).ToArray());

            return PartialView(chart);
        }
public ActionResult CombinerBarToday(日期时间?utcStartingDate=null,
日期时间(utcEndingDate=null)
{
//临时用来强制约会的
//utcStartingDate=新的日期时间(2012,1,9,0,0,1);
//utcEndingDate=新的日期时间(2012,1,9,23,59,59);
//获取指定日期时间的发电量读数
var firstQ=来自s,单位为db.PowerCombinerHistorys
加入我
    Dim stfipsList = (From r In dt.AsEnumerable() Select r("stfips")).Distinct().ToList()
    Dim SeriesList As New List(Of Series)(stfipsList.Count)
    Dim seriesItem(stfipsList.Count) As Series
    Dim xDate As DateTime
    Dim fakeDate As String
    Dim sX As Integer

    sX = 1
    For Each state In stfipsList
        Dim data As New Dictionary(Of DateTime, Decimal)
        Dim stateVal As String = state.ToString
        Dim recCount As Integer = dt.Rows.Count - 1

        For i As Integer = 0 To recCount
            If dt.Rows(i)("stfips").ToString = stateVal Then
                fakeDate = "1/1/" + dt.Rows(i)("periodyear").ToString
                xDate = DateTime.Parse(fakeDate)
                data.Add(xDate.Date, dt.Rows(i)("unemprate"))
            End If
        Next
        Dim chartData As Object(,) = New Object(data.Count - 1, 1) {}
        Dim x As Integer = 0
        For Each pair As KeyValuePair(Of DateTime, Decimal) In data
            chartData.SetValue(pair.Key, x, 0)
            chartData.SetValue(pair.Value, x, 1)
            x += 1
        Next
        seriesItem(sX) = New Series With {
                    .Name = state.ToString, _
                    .Data = New Helpers.Data(chartData)
        }

        SeriesList.Add(seriesItem(sX))

        sX = sX + 1
    Next

    Dim chart1 As Highcharts = New Highcharts("chart1").InitChart(New Chart() With { _
     .Type = ChartTypes.Line _
    }).SetTitle(New Title() With { _
     .Text = "Annual Unemployment Rate" _
    }).SetTooltip(New Tooltip() With { _
     .Formatter = "function() { return '<b>'+ this.series.name + ': ' + Highcharts.dateFormat('%Y', this.x) +'</b>: '+ this.y +' %'; }" _
    }).SetXAxis(New XAxis() With { _
     .Type = AxisTypes.Datetime _
     }).SetYAxis(New YAxis() With { _
       .Min = 0, _
       .Title = New YAxisTitle() With { _
        .Text = "Unemployment Rate", _
        .Align = AxisTitleAligns.High _
      } _
    }).SetSeries(SeriesList.[Select](Function(s) New Series() With { _
                 .Name = s.Name, _
                 .Data = s.Data _
                }).ToArray())

    ltrChart1.Text = chart1.ToHtmlString()
public ActionResult CombinerBarToday(DateTime? utcStartingDate = null,
                                             DateTime? utcEndingDate = null)
        {
            //TEMPORARILY USED TO FORCE A DATE
            //utcStartingDate = new DateTime(2012, 1, 9, 0, 0, 1);
            //utcEndingDate = new DateTime(2012, 1, 9, 23, 59, 59);

            //GET THE GENERATED POWER READINGS FOR THE SPECIFIED DATETIME
            var firstQ = from s in db.PowerCombinerHistorys
                         join u in db.PowerCombiners on s.combiner_id equals u.id
                         where s.recordTime >= utcStartingDate
                         where s.recordTime <= utcEndingDate
                         select new
                         {
                             Combiner = u.name,
                             Current = s.current,
                             RecordTime = s.recordTime,
                             Voltage = s.voltage,
                             Power = s.current * s.voltage
                         };

            //APPLY THE GROUPING
            var groups = firstQ.ToList().GroupBy(q => new
            {
                q.Combiner,
                Date = q.RecordTime.Date,
                Hour = q.RecordTime.Hour
            });

            List<CombinerKwh> stringGroupedKwhlist = new List<CombinerKwh>();

            //CALCULATE THE AVERAGE POWER GENERATED PER HOUR AND ADD TO LIST
            foreach (var group in groups)
            {
                stringGroupedKwhlist.Add(new CombinerKwh(
                                         group.Key.Combiner,
                                         new DateTime(group.Key.Date.Year, group.Key.Date.Month, group.Key.Date.Day, group.Key.Hour, 0, 0),
                                         group.Average(g => g.Power) / 1000d
                                         ));
            }

            //GET A LIST OF THE COMBINERS CONTAINS IN THE QUERY
            var secondQ = (from s in firstQ 
                           orderby s.Combiner 
                           select new
                                {
                                    Combiner = s.Combiner
                                }
                           ).Distinct();

            /* THIS LIST OF SERIES WILL BE USED TO DYNAMICALLY ADD AS MANY SERIES 
             * TO THE HIGHCHARTS AS NEEDEDWITHOUT HAVING TO CREATE EACH SERIES INDIVIUALY */
            List<Series> allSeries = new List<Series>();

            TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

            //LOOP THROUGH EACH COMBINER AND CREATE SERIES
            foreach (var distinctCombiner in secondQ)
            {
                var combinerDetail = from h in stringGroupedKwhlist
                                     where h.CombinerID == distinctCombiner.Combiner
                                     orderby TimeZoneInfo.ConvertTimeFromUtc(h.Interval,easternZone)
                                     select new
                                            {
                                                CombinerID = h.CombinerID,
                                                //CONVERT FROM UTC TIME TO THE LOCAL TIME OF THE SITE
                                                Interval = TimeZoneInfo.ConvertTimeFromUtc(h.Interval,easternZone),
                                                KWH = h.KWH
                                            };

                //REPRESENTS 24 PLOTS FOR EACH HOUR IN DAY
                object[] myData = new object[24];

                foreach (var detailCombiner in combinerDetail)
                {
                    if (detailCombiner.KWH != 0)
                    {
                        myData[detailCombiner.Interval.Hour] = detailCombiner.KWH;
                    }
                }

                allSeries.Add(new Series
                                    {
                                        Name = distinctCombiner.Combiner,
                                        Data = new Data(myData)
                                    });
            }

            Highcharts chart = new Highcharts("chart")
            .InitChart(new Chart { DefaultSeriesType = ChartTypes.Spline })
            .SetTitle(new Title { Text = "Combiner History" })
            .SetXAxis(new XAxis
            {
                Categories = new[] { "0:00 AM", "1:00 AM", "2:00 AM", "3:00 AM", "4:00 AM", "5:00 AM", "6:00 AM", "7:00 AM", "8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM", "5:00 PM", "6:00 PM", "7:00 PM", "8:00 PM", "9:00 PM", "10:00 PM", "11:00 PM" },
                Labels = new XAxisLabels
                                       {
                                           Rotation = -45,
                                           Align = HorizontalAligns.Right,
                                           Style = "font: 'normal 10px Verdana, sans-serif'"
                                       },
                Title = new XAxisTitle { Text = "Time(Hour)" },
                //Type = AxisTypes.Linear
            })
            .SetYAxis(new YAxis
            {
                //Min = 0,
                Title = new YAxisTitle { Text = "Kwh" }
            })

            .SetSeries(allSeries.Select(s => new Series { Name = s.Name, Data = s.Data }).ToArray());

            return PartialView(chart);
        }