sectionBoundaries, bool bScrollableTable, bool bAddMinMaxColumns, int maxColumnStringLength, SummaryTableColumnFormatInfoCollection columnFormatInfoList, string weightByColumnName)
{
System.IO.StreamWriter htmlFile = new System.IO.StreamWriter(htmlFilename, false);
int statColSpan = hasMinMaxColumns ? 3 : 1;
int cellPadding = 2;
if (isCollated)
{
cellPadding = 4;
}
htmlFile.WriteLine("");
htmlFile.WriteLine("Performance summary");
// Figure out the sticky column count
int stickyColumnCount = 0;
if (bScrollableTable)
{
stickyColumnCount = 1;
if (isCollated)
{
for (int i = 0; i < columns.Count; i++)
{
if (columns[i].name == "Count")
{
stickyColumnCount = i + 1;
break;
}
}
}
}
if (bScrollableTable)
{
// Insert some javascript to make the columns sticky. It's not possible to do this for multiple columns with pure CSS, since you need to compute the X offset dynamically
// We need to do this when the page is loaded or the window is resized
htmlFile.WriteLine("");
}
htmlFile.WriteLine("");
htmlFile.WriteLine("");
htmlFile.WriteLine("");
// Get format info for the columns
Dictionary columnFormatInfoLookup = new Dictionary();
foreach (SummaryTableColumn column in columns)
{
columnFormatInfoLookup[column] = (columnFormatInfoList != null) ? columnFormatInfoList.GetFormatInfo(column.name) : SummaryTableColumnFormatInfoCollection.DefaultColumnInfo;
}
// Automatically colourize the table
if (bScrollableTable)
{
foreach (SummaryTableColumn column in columns)
{
if (column.isNumeric)
{
column.ComputeAutomaticColourThresholds(columnFormatInfoLookup[column].autoColorizeMode);
}
}
}
string HeaderRow = "";
if (isCollated)
{
string TopHeaderRow = "";
if (bScrollableTable)
{
// Generate an automatic title
string title = htmlFilename.Replace("_Email.html", "").Replace(".html", "").Replace("\\", "/");
title = title.Substring(title.LastIndexOf('/') + 1);
TopHeaderRow += "" + title + " | ";
}
else
{
TopHeaderRow += " | ";
}
for (int i = 0; i < firstStatColumnIndex; i++)
{
HeaderRow += "" + columns[i].GetDisplayName() + " | ";
}
if (!bAddMinMaxColumns)
{
TopHeaderRow = HeaderRow;
}
for (int i = firstStatColumnIndex; i < columns.Count; i++)
{
string prefix = "";
string suffix = "";
string statName = GetStatNameWithPrefixAndSuffix(columns[i].GetDisplayName(), out prefix, out suffix);
if ((i - 1) % statColSpan == 0)
{
TopHeaderRow += "" + statName + suffix + " | ";
}
HeaderRow += "" + prefix.Trim() + " | ";
}
if (bAddMinMaxColumns)
{
htmlFile.WriteLine(" " + TopHeaderRow + "
");
htmlFile.WriteLine(" ");
}
else
{
htmlFile.WriteLine(" ");
}
}
else
{
foreach (SummaryTableColumn column in columns)
{
HeaderRow += "" + column.GetDisplayName() + " | ";
}
htmlFile.WriteLine(" ");
}
string[] stripeColors = { "'#e2e2e2'", "'#ffffff'" };
// Work out which rows are major/minor section boundaries
Dictionary rowSectionBoundaryLevel = new Dictionary();
if (sectionBoundaries != null)
{
foreach (SummarySectionBoundaryInfo sectionBoundaryInfo in sectionBoundaries)
{
// Skip this section boundary info if it's not in this table type
if (isCollated && !sectionBoundaryInfo.inCollatedTable)
{
continue;
}
if (!isCollated && !sectionBoundaryInfo.inFullTable)
{
continue;
}
string prevSectionName = "";
for (int i = 0; i < rowCount; i++)
{
int boundaryLevel = 0;
if (sectionBoundaryInfo != null)
{
// Work out the section name if we have section boundary info. When it changes, apply the sectionStart CSS class
string sectionName = "";
if (sectionBoundaryInfo != null && columnLookup.ContainsKey(sectionBoundaryInfo.statName))
{
// Get the section name
if (!columnLookup.ContainsKey(sectionBoundaryInfo.statName))
{
continue;
}
SummaryTableColumn col = columnLookup[sectionBoundaryInfo.statName];
sectionName = col.GetStringValue(i);
// if we have a start token then strip before it
if (sectionBoundaryInfo.startToken != null)
{
int startTokenIndex = sectionName.IndexOf(sectionBoundaryInfo.startToken);
if (startTokenIndex != -1)
{
sectionName = sectionName.Substring(startTokenIndex + sectionBoundaryInfo.startToken.Length);
}
}
// if we have an end token then strip after it
if (sectionBoundaryInfo.endToken != null)
{
int endTokenIndex = sectionName.IndexOf(sectionBoundaryInfo.endToken);
if (endTokenIndex != -1)
{
sectionName = sectionName.Substring(0, endTokenIndex);
}
}
}
if (sectionName != prevSectionName && i > 0)
{
// Update the row's boundary type info
boundaryLevel = sectionBoundaryInfo.level;
if (rowSectionBoundaryLevel.ContainsKey(i))
{
// Lower level values override higher ones
boundaryLevel = Math.Min(rowSectionBoundaryLevel[i], boundaryLevel);
}
rowSectionBoundaryLevel[i] = boundaryLevel;
}
prevSectionName = sectionName;
}
}
}
}
// Add the rows to the table
for (int i = 0; i < rowCount; i++)
{
string rowClassStr = "";
// Is this a major/minor section boundary
if (rowSectionBoundaryLevel.ContainsKey(i))
{
int sectionLevel = rowSectionBoundaryLevel[i];
if (sectionLevel < 3)
{
rowClassStr = " class='sectionStartLevel" + sectionLevel + "'";
}
}
htmlFile.Write("");
int columnIndex = 0;
foreach (SummaryTableColumn column in columns)
{
// Add the tooltip for non-collated tables
string toolTipString = "";
if (!isCollated)
{
string toolTip = column.GetToolTipValue(i);
if (toolTip == "")
{
toolTip = column.GetDisplayName();
}
toolTipString = " title='" + toolTip + "'";
}
string colour = column.GetColour(i);
// Alternating row colours are normally handled by CSS, but we need to handle it explicitly if we have frozen first columns
if (columnIndex < stickyColumnCount && colour == null)
{
colour = stripeColors[i % 2];
}
string bgColorString = (colour == null ? "" : " bgcolor=" + colour);
bool bold = false;
string numericFormat = columnFormatInfoLookup[column].numericFormat;
string stringValue = column.GetStringValue(i, true, numericFormat);
if (maxColumnStringLength > 0 && stringValue.Length > maxColumnStringLength)
{
stringValue = TableUtil.SafeTruncateHtmlTableValue(stringValue, maxColumnStringLength);
}
if (bSpreadsheetFriendlyStrings && !column.isNumeric)
{
stringValue = "'" + stringValue;
}
string columnString = "| " + (bold ? "" : "") + stringValue + (bold ? "" : "") + " | ";
htmlFile.Write(columnString);
columnIndex++;
}
htmlFile.WriteLine("
");
}
htmlFile.WriteLine("
");
string extraString = "";
if (isCollated && weightByColumnName != null)
{
extraString += " - weighted avg";
//htmlFile.WriteLine("Weighted by " + weightByColumnName +"
");
}
htmlFile.WriteLine("Created with PerfReportTool " + VersionString + extraString + "
");
htmlFile.WriteLine("");
htmlFile.Close();
}
public SummaryTable SortRows(List rowSortList, bool reverseSort)
{
List> columnRemapping = new List>();
for (int i = 0; i < rowCount; i++)
{
string key = "";
foreach (string s in rowSortList)
{
if (columnLookup.ContainsKey(s.ToLower()))
{
SummaryTableColumn column = columnLookup[s.ToLower()];
key += "{" + column.GetStringValue(i) + "}";
}
else
{
key += "{}";
}
}
columnRemapping.Add(new KeyValuePair(key, i));
}
columnRemapping.Sort(delegate (KeyValuePair m1, KeyValuePair m2)
{
return m1.Key.CompareTo(m2.Key);
});
// Reorder the metadata rows
List newColumns = new List();
foreach (SummaryTableColumn srcCol in columns)
{
SummaryTableColumn destCol = new SummaryTableColumn(srcCol.name, srcCol.isNumeric);
for (int i = 0; i < rowCount; i++)
{
int srcIndex = columnRemapping[i].Value;
int destIndex = reverseSort ? rowCount - 1 - i : i;
if (srcCol.isNumeric)
{
destCol.SetValue(destIndex, srcCol.GetValue(srcIndex));
}
else
{
destCol.SetStringValue(destIndex, srcCol.GetStringValue(srcIndex));
}
destCol.SetColourThresholds(destIndex, srcCol.GetColourThresholds(srcIndex));
destCol.SetToolTipValue(destIndex, srcCol.GetToolTipValue(srcIndex));
}
newColumns.Add(destCol);
}
SummaryTable newTable = new SummaryTable();
newTable.columns = newColumns;
newTable.rowCount = rowCount;
newTable.firstStatColumnIndex = firstStatColumnIndex;
newTable.isCollated = isCollated;
newTable.InitColumnLookup();
return newTable;
}
void InitColumnLookup()
{
columnLookup.Clear();
foreach (SummaryTableColumn col in columns)
{
columnLookup.Add(col.name.ToLower(), col);
}
}
public void AddRowData(SummaryTableRowData metadata, bool bIncludeCsvStatAverages, bool bIncludeHiddenStats)
{
foreach (string key in metadata.dict.Keys)
{
SummaryTableElement value = metadata.dict[key];
if (value.type == SummaryTableElement.Type.CsvStatAverage && !bIncludeCsvStatAverages)
{
continue;
}
if (value.GetFlag(SummaryTableElement.Flags.Hidden) && !bIncludeHiddenStats)
{
continue;
}
SummaryTableColumn column = null;
if (!columnLookup.ContainsKey(key))
{
column = new SummaryTableColumn(value.name, value.isNumeric);
columnLookup.Add(key, column);
columns.Add(column);
}
else
{
column = columnLookup[key];
}
if (value.isNumeric)
{
column.SetValue(rowCount, (double)value.numericValue);
}
else
{
column.SetStringValue(rowCount, value.value);
}
column.SetColourThresholds(rowCount, value.colorThresholdList);
column.SetToolTipValue(rowCount, value.tooltip);
}
rowCount++;
}
public int Count
{
get { return rowCount; }
}
Dictionary columnLookup = new Dictionary();
List columns = new List();
List rowWeightings = null;
int rowCount = 0;
int firstStatColumnIndex = 0;
bool isCollated = false;
bool hasMinMaxColumns = false;
};
}