using System; using System.Windows.Forms; using System.IO; using System.Web.UI; using System.Drawing; using System.Drawing.Imaging; using TheArtOfDev.HtmlRenderer.WinForms; namespace AdvertsingProfitControl { internal class FrontPageGenerator { FrmLogConsole _console = FrmLogConsole.GetStaticInstance; public void RenderHtmlToImage() { var htmlCode = File.ReadAllLines(Application.StartupPath + "\\FrontPage.html"); var code = ""; foreach (var line in htmlCode) { code = code + "\r\n" + line; } try { var imageFromHtml = HtmlRender.RenderToImage(code); imageFromHtml.RotateFlip(RotateFlipType.Rotate90FlipNone); imageFromHtml.Save(Application.StartupPath + "\\FrontPage.png", ImageFormat.Png); imageFromHtml.Dispose(); } catch (Exception e) { _console.WriteToLog(FrmLogConsole.Level.Critical, "Failed to generate an updated image for the front page of Advertising Profit Control."); _console.WriteToLog(FrmLogConsole.Level.Debug, e.Message); _console.WriteToLog(FrmLogConsole.Level.Info, "This is most likely a screw you from the GDI+ subsystem of Windows."); } } public void BuildFormFrontCompressedLayout(string dateId, double departmentSales, double salesProducedByAdItems, double remainingSales, double totalProfitReturnFromAdItems, double totalProfitReturnFromRemainingSales, double totalProfitReturn, string comments) { var databaseTracker = new DatabaseTracker(); var databaseReader = new DatabaseReader(); var stringWriter = new StringWriter(); var writer = new HtmlTextWriter(stringWriter); var table = databaseReader.ReturnApcTableForReport(dateId, databaseTracker.DatabaseConnectionString); var dateString = databaseReader.RetrieveDateStringById(dateId, databaseTracker.DatabaseConnectionString); var spam = dateString.Split(' '); dateString = spam[0]; //Begin evaluating the size of the table. var isCompressedFormat = false; var willGenerateCommentRow = false; if ((table.Rows.Count + 1) == 15) { willGenerateCommentRow = true; } else if ((table.Rows.Count + 1) < 15) { isCompressedFormat = true; } writer.Write("\n"); writer.RenderBeginTag(HtmlTextWriterTag.Html); writer.RenderBeginTag(HtmlTextWriterTag.Head); writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css"); writer.RenderBeginTag(HtmlTextWriterTag.Style); writer.Write("th{margins:0; padding:0; vertical-align:bottom; height:35px; font-size:14px; border:1px solid black}"); writer.Write("td{margins:0; padding:0; border:1px solid black; font-size:14px; text-align:center; height:35px}"); writer.RenderEndTag();//style writer.RenderEndTag(); // Head writer.AddAttribute(HtmlTextWriterAttribute.Style, "width:11in; height:8in"); writer.RenderBeginTag(HtmlTextWriterTag.Body); //Begin building the header for the page, the HTML engine doesn't seem to like putting content in the Head. writer.AddAttribute(HtmlTextWriterAttribute.Style, "margin-top:200px; width:100%"); writer.RenderBeginTag(HtmlTextWriterTag.Table); writer.AddAttribute(HtmlTextWriterAttribute.Style, "margin:0px; padding:0px"); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddAttribute(HtmlTextWriterAttribute.Style, "font-size:14px; width:20%; vertical-align:bottom; border:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("

Store Name: Allen's of Hastings

"); writer.RenderEndTag();//td writer.AddAttribute(HtmlTextWriterAttribute.Style, "width:50%; font-size:15px; margin:0px; padding: 0px 0px 0px 0px; border:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); //

(Mode: " + (willGenerateCommentRow ? "Generates Comment row" : "Compressed Format") + ") writer.Write("

Advertising Profit Control v " + Application.ProductVersion + "

"); writer.RenderEndTag();//td writer.AddAttribute(HtmlTextWriterAttribute.Style, "width:33%; padding: 0px 0px 0px 0px; margin:0px; border:none; vertical-align:bottom"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("

Week Ending: " + dateString + "
Department: Produce

"); writer.RenderEndTag();//td writer.RenderEndTag();//tr writer.AddAttribute(HtmlTextWriterAttribute.Style, "margin:0px; padding:0px"); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag();//td writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("

ProjectionActual

"); writer.RenderEndTag();//td writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("

Profit Analysis

"); writer.RenderEndTag();//td writer.RenderEndTag();//tr writer.RenderEndTag();//table //END of header table structure writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-collapse: collapse; width:11in; height:7.0in; table-layout:fixed"); //style for the table writer.RenderBeginTag(HtmlTextWriterTag.Table); writer.RenderBeginTag(HtmlTextWriterTag.Tr); //Begin building the header row. writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-left:none"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Ad Items"); writer.RenderEndTag(); //th writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Sold"); writer.RenderEndTag(); //th writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Sale
Price"); writer.RenderEndTag(); //th writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Total
Sales"); writer.RenderEndTag(); //th writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Cost"); writer.RenderEndTag(); //th writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("$
Prof.
Retn."); writer.RenderEndTag(); //th writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9"); writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Total
$
Prof.
Retn."); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Beg.
Inv."); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Rec'd"); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Total"); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("End.
Inv."); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Sold"); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Sale
Price"); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Total
Sales"); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Cost"); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("$
Prof.
Retn."); writer.RenderEndTag(); //th writer.RenderBeginTag(HtmlTextWriterTag.Th); writer.Write("Total
$
Prof.
Retn."); writer.RenderEndTag(); //th //Department Sales writer.AddAttribute(HtmlTextWriterAttribute.Style, "width:159px; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Department
Sales

1"+ $"{departmentSales:C}" + "

"); writer.RenderEndTag();//td writer.RenderEndTag();//End of header row code. var isRowMember = false; var isRenderingGroup = false; var adSpecialRowIndex = -1; //Variables for the Totals row. double projectionProfitReturn = 0; double projectionTotalProfitReturn = 0; double actualProfitReturn = 0; double actualTotalProfitReturn = 0; var adSpecialOffset = 0; //Profit Analysis values. for (var rowIndex = 0; rowIndex < (table.Rows.Count < 19 ? 19 : table.Rows.Count); rowIndex++) //The comparison in the for loop is index based, so no need to add one to the row count. { var isProfitAnalysisCell = false; //IF the row index goes beyond the number of rows that are in the table, then start padding with blank cells to fit the Profit Analysis cells. if (rowIndex < table.Rows.Count) { var row = table.Rows[rowIndex]; var rowAttribute = 0; var groupId = 0; if (int.TryParse(row.ItemArray[17].ToString(), out rowAttribute)) { if (rowAttribute != 0) { if (rowAttribute == 1) { isRowMember = false; } else { isRowMember = true; } isRenderingGroup = true; } else { isRenderingGroup = false; isRowMember = false; } } if (adSpecialRowIndex == -1 && int.TryParse(row.ItemArray[18].ToString(), out groupId)) { if (groupId != 0) { adSpecialRowIndex = rowIndex; writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "17"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-left:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
" + databaseReader.ReturnGroupNameFromGroupId(groupId.ToString(), databaseTracker.DatabaseConnectionString) + "
"); writer.RenderEndTag(); //td writer.RenderEndTag(); //tr BuildProfitAnalysisCell(ref writer, rowIndex, out isProfitAnalysisCell, salesProducedByAdItems, remainingSales, totalProfitReturnFromAdItems, totalProfitReturnFromRemainingSales, totalProfitReturn); adSpecialOffset++; } } writer.RenderBeginTag(HtmlTextWriterTag.Tr); for (var i = 0; i < row.ItemArray.Length; i++) { if (i >= 17) continue; if (i == 0) { writer.AddStyleAttribute(HtmlTextWriterStyle.TextAlign, "left"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-left:none"); } else if (i > 0 && i < 7) { //background-color:#e9e9e9 writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, "#e9e9e9"); } writer.RenderBeginTag(HtmlTextWriterTag.Td); decimal number; if (decimal.TryParse(row.ItemArray[i].ToString(), out number)) { //Check for the inventory columns and the sold columns. if (!isRowMember) { if (i == 1 || i > 6 && i < 12) { writer.Write(number == 0 ? "0" : row.ItemArray[i].ToString()); } if (i > 1 && i < 7 || i > 11) { writer.Write(number == 0 ? "0.00" : $"{number:N}"); } } switch (i) { case 3: projectionProfitReturn += double.Parse(row.ItemArray[3].ToString()); break; case 6: projectionTotalProfitReturn += double.Parse(row.ItemArray[6].ToString()); break; case 13: actualProfitReturn += double.Parse(row.ItemArray[13].ToString()); break; case 16: actualTotalProfitReturn += double.Parse(row.ItemArray[16].ToString()); break; } } else { writer.Write(row.ItemArray[i]); } writer.RenderEndTag(); //td } } else { //Padding writer.RenderBeginTag(HtmlTextWriterTag.Tr); //Generate padding rows to fit the Profit Analysis cells properly onto the sheet. //Check to see if the row index is equal to the number of rows in the table. if (rowIndex == table.Rows.Count) { //IF so, then that means the current row index represents the index of the Totals row. So build the totals row with the added values from above. //Begin rendering the totals row. writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:1px solid black; border-left:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9; text-align:right"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("Total"); writer.RenderEndTag(); //td writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9; padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(A) " + $"{projectionProfitReturn:C}"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9; padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(B) " + $"{projectionTotalProfitReturn:C}"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "text-align:right"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "5"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("Total"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(A) " + $"{actualProfitReturn:C}"); writer.RenderEndTag(); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(B) " + $"{actualTotalProfitReturn:C}"); writer.RenderEndTag();//td //END rending the totals row. BuildProfitAnalysisCell(ref writer, rowIndex + adSpecialOffset, out isProfitAnalysisCell, salesProducedByAdItems, remainingSales, totalProfitReturnFromAdItems, totalProfitReturnFromRemainingSales, totalProfitReturn); } else if (rowIndex == (table.Rows.Count + 1)) //Check to see if the current index is equal to the row after the totals row and, if so, create the comments row. { writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "17"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-left:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write( "Comments: " + comments); writer.RenderEndTag(); //td BuildProfitAnalysisCell(ref writer, rowIndex + adSpecialOffset, out isProfitAnalysisCell, salesProducedByAdItems, remainingSales, totalProfitReturnFromAdItems, totalProfitReturnFromRemainingSales, totalProfitReturn); } else { var cellCount = 0; while (cellCount < 17) { writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag();//td cellCount++; } } } //Check for every 3rd row to append a Profit Analysis cell onto. switch (rowIndex + adSpecialOffset) { case 0: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Sales Produced By
Ad Items (A)

2" + $"{salesProducedByAdItems:C}" + "

"); writer.RenderEndTag(); break; case 3: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-top:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Remaining
Sales

3" + $"{remainingSales:C}" + "

"); writer.RenderEndTag(); break; case 6: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-top:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Total $ Profit Return
From Ad Items (B)

4" + $"{totalProfitReturnFromAdItems:C}" + "

"); writer.RenderEndTag(); break; case 9: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-top:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Total $ Profit Return
From Remaining Sales

5" + $"{totalProfitReturnFromRemainingSales:C}" + "

"); writer.RenderEndTag(); break; case 12: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Total $ Profit
Return

6" + $"{totalProfitReturn:C}" + "

"); writer.RenderEndTag(); break; case 15: //IF either the compressed format or the generate comment row flags are set, then ignore this case. Only tables with 19 or more rows can generate a full comments cell due to the amount of text it can contain. if (isCompressedFormat || willGenerateCommentRow) break; writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "4"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("Comments: " + comments); writer.RenderEndTag(); break; } writer.RenderEndTag();//tr }//end for loop if (!willGenerateCommentRow && !isCompressedFormat) { //Begin rendering the totals row. writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:1px solid black; border-left:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9; border:1px solid black; font-size:12px; border-left: 1px solid #000; text-align:right"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("Total"); writer.RenderEndTag(); //td writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9; border:1px solid black; font-size:12px; border-left: 1px solid #000; padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(A) " + $"{projectionProfitReturn:C}"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "background-color:#e9e9e9; border:1px solid black; font-size:12px; border-left: 1px solid #000; padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(B) " + $"{projectionTotalProfitReturn:C}"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:1px solid black; font-size:12px; border-left: 1px solid #000; text-align:right"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "5"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("Total"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:1px solid black; font-size:12px; border-left: 1px solid #000; padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(A) " + $"{actualProfitReturn:C}"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:1px solid black"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:1px solid black; font-size:12px; border-left: 1px solid #000; padding: 0px 0px 0px 5px"); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("(B) " + $"{actualTotalProfitReturn:C}"); writer.RenderEndTag();//td writer.RenderEndTag(); //tr } writer.RenderEndTag();//table writer.RenderEndTag();//body writer.RenderEndTag();//HTML using (var streamWriter = new StreamWriter(Application.StartupPath + "\\FrontPage.html")) { streamWriter.WriteLine(stringWriter.ToString()); } RenderHtmlToImage(); } private void BuildProfitAnalysisCell(ref HtmlTextWriter writer, int rowIndex, out bool isProfitAnalysisCell, double salesProducedByAdItems, double remainingSales, double totalProfitReturnFromAdItems, double totalProfitReturnFromRemainingSales, double totalProfitReturn) { isProfitAnalysisCell = false; switch (rowIndex) { case 0: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-right:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Sales Produced By
Ad Items (A)

2" + $"{salesProducedByAdItems:C}" + "

"); writer.RenderEndTag(); break; case 3: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-right:1px solid black; border-top:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Remaining
Sales

3" + $"{remainingSales:C}" + "

"); writer.RenderEndTag(); break; case 6: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-right:1px solid black; border-top:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Total $ Profit Return
From Ad Items (B)

4" + $"{totalProfitReturnFromAdItems:C}" + "

"); writer.RenderEndTag(); break; case 9: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border:none; border-right:1px solid black; border-top:1px solid black; border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Total $ Profit Return
From Remaining Sales

5" + $"{totalProfitReturnFromRemainingSales:C}" + "

"); writer.RenderEndTag(); break; case 12: writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Style, "border-right:none"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("
Total $ Profit
Return

6" + $"{totalProfitReturn:C}" + "

"); writer.RenderEndTag(); break; } } } }