我正在使用Google Visualization API制作一个自定义报告。它将有6个部分,每个部分两边都有表格,在中间有一张图表。
由于格式略有不同,我花了很多时间为每个一次性案例定义类。
我决定试试Google.DataTable.Net.Wrapper 3.1.0.0。
我创建了一个存储过程,该过程返回一个数据集,然后遍历我的控制器中的数据集并传递我需要的每个表。
数据看起来像这个
rownum charttypeid charttypename
----------- ----------- ------------------
1 1 Membership Sales
rownum chartareaid chartareaname
----------- ----------- -------------------------
1 1 Membership Sales Overview
2 2 Membership Sales Chart
title value display
------------------------- ----------- ----------
# of Walk-ins 25 25
# of Tours 17 17
# of New Members 35 35
Tour Conversion 78 78%
Percent to Goal 87 87%
Month value display goalvalue goaldisplay
----- ----------- ---------- ----------- -----------
Sep 3125 $3,125.00 1500 $1,500.00
Oct 4500 $4,500.00 1500 $1,500.00
有时图表会有货币格式或其他显示格式,有时还有日期等。我不知道如何添加/修改单元格的"f"部分,它提供了一种显示字符串的格式。我的控制器代码看起来像这个
[ResponseType(typeof(List<ChartPanel>))]
public IHttpActionResult GetChart(int gym, string dateCategory, string iso8601date, int id = -1)
{
if (!String.IsNullOrWhiteSpace(dateCategory))
{
dateCategory = dateCategory.ToLower();
string strConnString = ConfigurationManager.ConnectionStrings["PrimaryDBConnection"].ConnectionString;
// return DataSet From USP
DataSet dashBoardDataSet = GetDataSQL(strConnString, gym, dateCategory, iso8601date, 0);
if (dashBoardDataSet != null)
{
int chartPanelCount = dashBoardDataSet.Tables[0].Rows.Count;
List<ChartPanel> chartTypeList = new List<ChartPanel>(); // list for all the panels
// first table describes the Chart Panels
int tableCount = 0;
for (int chartPanelLoop = 0; chartPanelLoop < chartPanelCount; chartPanelLoop++)
{ // for every panel
tableCount++;
ChartPanel chartPanel = new ChartPanel();
chartPanel.name = dashBoardDataSet.Tables[0].Rows[chartPanelLoop][2].ToString();
// second table describes the following chart areas for the panel
int panelAreaCount = dashBoardDataSet.Tables[1].Rows.Count;
List<ChartArea> chartAreaList = new List<ChartArea>();
int areaTableCount = tableCount;
for (int panelAreaLoop = 0; panelAreaLoop < panelAreaCount; panelAreaLoop++)
{ // for every area
int areaTable = areaTableCount;
ChartArea chartArea = new ChartArea();
chartArea.name = dashBoardDataSet.Tables[areaTable].Rows[panelAreaLoop][2].ToString();
int chartAreaRowNum = panelAreaLoop + 1;
System.Data.DataTable systDT = new System.Data.DataTable();
systDT = dashBoardDataSet.Tables[areaTable + chartAreaRowNum];
var dt = systDT.ToGoogleDataTable(); //convert with wrapper
//issue ==> //dt = RemoveColumnsWithTitleLikeDisplayAndPassCellContentsAsFormattedStringToPreviousCell(dt);
chartArea.table = JsonConvert.DeserializeObject(dt.GetJson());
chartAreaList.Add(chartArea);
//}
if (chartAreaList.Count() > 0) chartPanel.areas = chartAreaList;
tableCount++;
}
if (chartPanel.areas != null && chartPanel.areas.Count() > 0) chartTypeList.Add(chartPanel);
}
return Ok(chartTypeList);
}
else { return NotFound(); }
}
else { return NotFound(); }
}
有更好的方法吗?
想明白了。这是我的工作代码,我使用了一个技巧来查找(colName.Contains("_display"))所在的任何列,并使其成为前一列的格式化("f")数据。
为了将列映射到格式化列,我创建了一个自定义类。
自定义类
class ColumnDisplayMap
{
public int columnToFormat { get; set; }
public int formatColumn { get; set; }
}
构建图表的方法
[ResponseType(typeof(List<ChartPanel>))]
public IHttpActionResult GetChart(int gym, string dateCategory, string iso8601date, int id = -1)
{
if (!String.IsNullOrWhiteSpace(dateCategory))
{
dateCategory = dateCategory.ToLower();
string strConnString = ConfigurationManager.ConnectionStrings["PrimaryDBConnection"].ConnectionString;
// return DataSet From USP
DataSet dashBoardDataSet = GetDataSQL(strConnString, gym, dateCategory, iso8601date, 0);
if (dashBoardDataSet != null)
{
int chartPanelCount = dashBoardDataSet.Tables[0].Rows.Count;
List<ChartPanel> chartTypeList = new List<ChartPanel>(); // list for all the panels
// first table describes the Chart Panels
int tableCount = 0;
for (int chartPanelLoop = 0; chartPanelLoop < chartPanelCount; chartPanelLoop++)
{ // for every panel
ChartPanel chartPanel = new ChartPanel();
chartPanel.name = dashBoardDataSet.Tables[0].Rows[chartPanelLoop][2].ToString();
// second table describes the following chart areas for the panel
DataRow[] areaTableRows = dashBoardDataSet.Tables[1].Select("charttype = " + (chartPanelLoop + 1).ToString());
int panelAreaCount = areaTableRows.Count();
List<ChartArea> chartAreaList = new List<ChartArea>();
for (int panelAreaLoop = 0; panelAreaLoop < panelAreaCount; panelAreaLoop++)
{ // for every area
int areaTable = 1;
ChartArea chartArea = new ChartArea();
chartArea.name = areaTableRows[panelAreaLoop][3].ToString(); // dashBoardDataSet.Tables[areaTable].Rows[panelAreaLoop][3].ToString();
DataColumnCollection columns = dashBoardDataSet.Tables[areaTable + tableCount + 1].Columns;
DataRowCollection rows = dashBoardDataSet.Tables[areaTable + tableCount + 1].Rows;
Google.DataTable.Net.Wrapper.DataTable gdt = new Google.DataTable.Net.Wrapper.DataTable();
List<ColumnDisplayMap> cMap = new List<ColumnDisplayMap>();
foreach (DataColumn col in columns)
{
string colName = col.ToString();
if (!colName.Contains("_display"))
{
ColumnType type = ColumnType.Number;
if (!col.IsNumeric()) type = ColumnType.String;
gdt.AddColumn(new Column(type, col.ToString(), col.ToString()));
}else
{
ColumnDisplayMap cdm = new ColumnDisplayMap(){columnToFormat = col.Ordinal - 1, formatColumn = col.Ordinal};
cMap.Add(cdm);
}
}
foreach (DataRow row in rows)
{
var r = gdt.NewRow();
for (int cellItem = 0; cellItem < row.ItemArray.Count(); cellItem++)
{
if (cMap.Any(c => c.columnToFormat.Equals(cellItem)))
{
r.AddCell(new Cell(row.ItemArray[cellItem], row.ItemArray[cellItem + 1].ToString()));
}
else if (cMap.Any(c => c.formatColumn.Equals(cellItem)))
{
// do nothing
}
else
{
r.AddCell(new Cell(row.ItemArray[cellItem], row.ItemArray[cellItem].ToString()));
}
}
gdt.AddRow(r);
}
chartArea.table = JsonConvert.DeserializeObject(gdt.GetJson());
chartAreaList.Add(chartArea);
//}
if (chartAreaList.Count() > 0) chartPanel.areas = chartAreaList;
tableCount++;
}
if (chartPanel.areas != null && chartPanel.areas.Count() > 0) chartTypeList.Add(chartPanel);
}
return Ok(chartTypeList);
}
else { return NotFound(); }
}
else { return NotFound(); }
}