2016-09-23 45 views
1

我有一个以这种格式将数据返回一个GridView:ASP.NET C#如何在GridView变化数据和写入XML

Member ID | Yesterday Pounds | Yesterday Tons | Yesterday Dollars | Total Pounds | Total Tons | Total Dollars 
000100-001 | 10,000.00  | 5.00   | $10,000.00  | 1,000,000.00 | 3,000.00 | $2,000,000.00 
000100-002 | 40,000.00  | 20.00   | $10,500.00  | 4,000,000.00 | 22,000.00 | $1,000,000.00 
000102-001 | 80,000.00  | 40.00   | $20,000.00  | 2,000,000.00 | 9,000.00 | $4,000,000.00 
000200-005 | 40,000.00  | 20.00   | $14,000.00  | 600,000.00 | 300.00  | $200,000.00 

我询问我们的数据库需要编译并发送信息到XML文档中的另一家公司。

我正在做的第一件事就是将我们的公司ID转换成他们的公司ID,我写了一个能够做到这一点的类。例如,会员ID 000100-001,000100-002和000102-001全部转换为1200,而成员ID 000200-005转换为1201.

我还需要按公司ID合计所有列。因此,对于会员ID 000100-001,000100-002和000102-001,我需要总结昨天的磅数,昨天的吨数,昨天的美元,总磅数,总吨数和总美元,并将结果作为一行发送,成员编号为1200 。成员ID 00200-005不需要任何操作,它在这种情况下是独立的。结果看起来像这样:

Member ID | Yesterday Pounds | Yesterday Tons | Yesterday Dollars | Total Pounds | Total Tons | Total Dollars 
    1200 | 130,000.00  | 65.00  |  $40,000.00 | 7,000,000.00 | 34,000.00 | $7,000,000.00 
    1201 | 40,000.00  | 20.00  |  $14,000.00 | 600,000.00 | 300.00 | $200,000.00 

我确实有类转换成员ID和计算总数。我遇到的问题是,当数据写入XML时它将写入所有记录,因此我为id 1200获得三个条目,而不是最后一个包含总数的条目。

所以我想我会移动数据到一个DataTable,迭代通过它做我的计算,然后重新创建DataTable只有我想要的记录,然后将DataTable移动到XML。从句法上来说,我很难搞清楚这一点。
如果有更好的方法,我全部都是耳朵。我欢迎所有的建议。

这里是我的代码:

GridView控件:背后的GridView

<asp:GridView ID="grdDailyShipments" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="False" ForeColor="Gray" OnRowDataBound="grdDailyShipments_RowDataBound"> 
    <AlternatingRowStyle BackColor="#CCCCCC" /> 
     <Columns> 
      <asp:BoundField DataField="MEMBERID" HeaderText="MEMBER ID" ReadOnly="True" SortExpression="MEMBERID" /> 
      <asp:BoundField DataField="YESTERDAYPOUNDS" HeaderText="YESTERDAY POUNDS" ReadOnly="True" DataFormatString="{0:N}" SortExpression="YESTERDAYPOUNDS" /> 
      <asp:BoundField DataField="YESTERDAYTONS" HeaderText="YESTERDAY TONS" ReadOnly="True" DataFormatString="{0:N}" SortExpression="YESTERDAYTONS" /> 
      <asp:BoundField DataField="YESTERDAYDOLLARS" HeaderText="YESTERDAY DOLLARS" ReadOnly="True" DataFormatString="{0:C}" SortExpression="YESTERDAYDOLLARS" /> 
      <asp:BoundField DataField="TOTALPOUNDS" HeaderText="TOTAL POUNDS" ReadOnly="True" DataFormatString="{0:N}" SortExpression="TOTALPOUNDS" /> 
      <asp:BoundField DataField="TOTALTONS" HeaderText="TOTAL TONS" ReadOnly="True" DataFormatString="{0:N}" SortExpression="TOTALTONS" /> 
      <asp:BoundField DataField="TOTALDOLLARS" HeaderText="TOTAL DOLLARS" ReadOnly="True" DataFormatString="{0:C}" SortExpression="TOTALDOLLARS" /> 
     </Columns> 
</asp:GridView> 

代码:

DataTable dt = new DataTable(); 
dt.Columns.Add("DailyReportRecordId", typeof(string)); 
dt.Columns.Add("Date", typeof(string)); 
dt.Columns.Add("ProgramID", typeof(string)); 
dt.Columns.Add("MemberID", typeof(string)); 
dt.Columns.Add("YesterdayPounds", typeof(string)); 
dt.Columns.Add("YesterdayTons", typeof(string)); 
dt.Columns.Add("YesterdayDollars", typeof(string)); 
dt.Columns.Add("TotalPounds", typeof(decimal)); 
dt.Columns.Add("TotalTons", typeof(decimal)); 
dt.Columns.Add("TotalDollars", typeof(string)); 

for (int i = 0; i < grdDailyShipments.Rows.Count; i++) 
{ 
    recordId = (i + 1).ToString(); 
    memberId = grdDailyShipments.Rows[i].Cells[0].Text.ToString(); 
    memberId = MemberIdConversion.convertId(memberId); 
    yesterdayPounds = grdDailyShipments.Rows[i].Cells[1].Text.ToString(); 
    yesterdayTons = grdDailyShipments.Rows[i].Cells[2].Text.ToString(); 
    yesterdayDollars = grdDailyShipments.Rows[i].Cells[3].Text.ToString(); 

    // Get the value returned to the Grid 
    totalPounds = Convert.ToDecimal(grdDailyShipments.Rows[i].Cells[4].Text.ToString()); 
    // Call combine totals to total all the subsidiaries 
    totalPounds = CombineTotalPounds.combineTotalPounds(memberId, totalPounds); 

    // Get the value returned to the Grid 
    totalTons = Convert.ToDecimal(grdDailyShipments.Rows[i].Cells[5].Text.ToString()); 
    // Call combine totals to total all the subsidiaries 
    totalTons = CombineTotalTons.combineTotalTons(memberId, totalTons); 

    // Get the value returned to the Grid 
    totalDollarsStr = grdDailyShipments.Rows[i].Cells[6].Text.ToString(); 
    // Strip off the $, if you don't to this the Convert.ToDecimal WILL NOT 
    // work due to formatting issues 
    totalDollarsStr = totalDollarsStr.Substring(1); 
    // Convert the string to a decimal and round it. 
    totalDollars = Math.Round(Convert.ToDecimal(totalDollarsStr), 2); 
    // Convert back to a string. 
    totalDollarsStr = totalDollars.ToString(); 
    // Format to Currency. 
    totalDollarsStr = String.Format("{0:C}", totalDollars); 

    DataRow dr = dt.NewRow(); 
    dr[0] = recordId; 
    dr[1] = invoiceDateStr; 
    dr[2] = "1202"; 
    dr[3] = memberId; 
    dr[4] = yesterdayPounds; 
    dr[5] = yesterdayTons; 
    dr[6] = yesterdayDollars; 
    dr[7] = totalPounds; 
    dr[8] = totalTons; 
    dr[9] = totalDollarsStr; 

    xmlWriter.WriteStartElement("DailyReportRecordId"); 
    xmlWriter.WriteAttributeString("id", recordId); 

    xmlWriter.WriteStartElement("Date"); 
    xmlWriter.WriteString(invoiceDateStr); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("ProgramID"); 
    xmlWriter.WriteString("1202"); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("MemberID"); 
    xmlWriter.WriteString(memberId); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("YesterdayPounds"); 
    xmlWriter.WriteString(yesterdayPounds); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("YesterdayTons"); 
    xmlWriter.WriteString(yesterdayTons); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("YesterdayDollars"); 
    xmlWriter.WriteString(yesterdayDollars); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("TotalPounds"); 
    xmlWriter.WriteString(totalPounds.ToString("#,##0.00")); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("TotalTons"); 
    xmlWriter.WriteString(totalTons.ToString("#,##0.00")); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteStartElement("TotalDollars"); 
    //xmlWriter.WriteString(totalDollarsStr.ToString()); 
    xmlWriter.WriteString(totalDollarsStr); 
    xmlWriter.WriteEndElement(); 

    xmlWriter.WriteEndElement(); // End of Daily Report Record Id 
} 

我明白,每个记录被写入到XML在for循环它遍历网格。会员ID转换工作,总计也是如此。重申一下,问题是只有最后一条记录(如果有多条记录)具有正确的总数,那么上面的记录会随着代码的进展而累积。

所以现在在DataTable中的数据我想要做这样的事情:

for(int i = 0; i < dt.Rows.Count; i ++) 
{ 
    if(dt(i).memberid = dt(i - 1).memberid) 
    (
     set variable here to write to XML 
    ) 
} 

但是,这是伪代码,因为我无法搞清楚了这一点。

再一次,如果我的方法不是最好的,我愿意接受。

感谢

回答

1

有许多方法可以解决这个,但最简单的基础上你已经会遍历你的GridView倒退,因为你说你想获得每每个成员的最后一行-ID。我已经修改了你的伪代码来说明我的意思:

string lastId = null;  
for(int i = (dt.Rows.Count-1); i >= 0; i--) 
{ 
    if(lastId == null || lastId != dt(i).memberid) 
    { 
     //write XML, as we're at the last for the given memberid, 
     //assuming the GridView is sorted by memberid. 
    } 
    lastId = dt(i).memberid; 
} 

如果会员ID是不分组,我仍然会去通过DataGrid倒退,但增加了一个字典或列表变量来跟踪memberIds的已经被添加到XML:

List<string> memberIdsAddedToXml = new List<string>();  
for(int i = (dt.Rows.Count-1); i >= 0; i--) 
{ 
    if(!memberIdsAddedToXml.Contains(dt(i).memberid)) 
    { 
     memberIdsAddedToXml.Add(dt(i).memberid); 
     //write XML, as we're at the last row for the given memberid 
    } 
} 

更好,我想,会创建一个代表在网格视图中的数据类(Foo)。然后创建一个方法,该方法通过循环遍历将数据复制到列表中的网格视图行来返回Foo对象的列表。创建另一种方法,其中包含Foo对象的列表并将它们写入XML文档。最后,创建一个结合了前两种方法的方法。举个例子:

void ExportTotalsAsXml(DataTable dt, string xmlPath) 
{ 
    List<Foo> list = ExtractDataFromData(dt); 
    List<Foo> filteredList = new List<Foo> 
    //loop through the list backwards to get the total row per memberid, storing it in filteredList 
    WriteToXml(filteredList, xmlPath); 
} 

通过这种方式分离出来,你就可以更容易看到每一部分是干什么的,回来以后特别是当做出变更或错误修复。

+0

我会尝试第二个建议,写数据表转换成XML,它看起来像它可能工作。 – CuriousOne

+0

这是我的一个问题,dt(i)将不起作用。我收到“方法名称预期”。我似乎无法弄清楚如何引用DataTable中的特定行。 – CuriousOne

+0

尝试'grdDailyShipments.Rows [i] .Cells [0] .Text'来获取成员id单元格。 dt(i)只是psuedocode,以避免输入全部。顺便说一下,我不认为你需要在'Text'字段上使用ToString()。 – purplecat

0

我不知道我是否理解你是对的,但也许这会以某种方式帮助你。您可以使用LINQ来算总数和写入导致新的DataTable,然后使用DataTable.WriteXml方法 https://msdn.microsoft.com/en-us/library/system.data.datatable.writexml(v=vs.110).aspx

dt = new DataTable(); 

     dt.Columns.Add("MemberID", typeof(int)); 
     dt.Columns.Add("YesterdayPounds", typeof(double)); 
     dt.Columns.Add("YesterdayTons", typeof(double)); 
     dt.Columns.Add("YesterdayDollars", typeof(double)); 
     dt.Columns.Add("TotalPounds", typeof(decimal)); 
     dt.Columns.Add("TotalTons", typeof(decimal)); 
     dt.Columns.Add("TotalDollars", typeof(string)); 
     dt.Rows.Add("1200", 10000.00, 500, 10000.00, 1000, 3000.00, 2000000.00); 
     dt.Rows.Add("1200", 10000.00, 500, 10000.00, 1000, 3000.00, 2000000.00); 
     dt.Rows.Add("1201", 10000.00, 500, 10000.00, 1000, 3000.00, 2000000.00); 
     dt.Rows.Add("1202", 10000.00, 500, 10000.00, 1000, 3000.00, 2000000.00); 

     var result = dt.AsEnumerable() 
      .GroupBy(r => r.Field<int>("MemberID")) 
      .Select(g => 
      { 
       var row = dt.NewRow(); 

       row["MemberID"] = g.Key; 
       row["YesterdayPounds"] = g.Sum(r => r.Field<double>("YesterdayPounds")); 
       row["YesterdayTons"] = g.Sum(r => r.Field<double>("YesterdayTons")); 
       row["YesterdayDollars"] = g.Sum(r => r.Field<double>("YesterdayDollars")); 

       return row; 
      }).CopyToDataTable(); 

     ds = new DataSet(); 

     ds.Tables.Add(dt); 
     ds.Tables.Add(result); 

     result.WriteXml(@"G:\MyDataset.xml");