Tabulation Script for setting inline style to Table Chart
Contents
Introduction
Customer sometimes need to highlight some fields in a table chart using CGScript, thus a couple of methods have been defined for this need. It's part of the Tabulation Script
StyleSheet Review
StyleSheet defines the layout of chart (both table and image charts). There are 2 kinds of stylesheets: external and internal. External stylesheet is stylesheet that is defined separately and can be reused through out many reports/diagrams. Inline stylesheet, in the other hand, is specific to a diagram only.
The order of applying stylesheet is as below:
Report Diagram Diagram | => | => | StyleSheet StyleSheet Inline StyleSheet
The inline stylesheet is as a higher priority than the external one.
TableChart's CellTypes
Each cell in table chart must belong to at least a cell type. The full list of cell types is below:
public enum StyleType
{
TableDiagram_AllTable, // All cell
TableDiagram_ColumnHeader, // All column header
TableDiagram_ColumnHeaderLevel1, // Only column header level 1
TableDiagram_ColumnHeaderLevel2, // Only column header level 2
TableDiagram_ColumnHeaderLevel3, // Only column header level 3
TableDiagram_RowHeader, // All row header
TableDiagram_RowHeaderLevel1, // Only row header level 1
TableDiagram_RowHeaderLevel2, // Only row header level 2
TableDiagram_RowHeaderLevel3, // Only row header level 3
TableDiagram_AbsoluteColumn, // All cells of column that contains absolute value
TableDiagram_AbsoluteColumnHeader, // Column header cells of column that contains absolute value
TableDiagram_AbsoluteColumnValue, // Column data cells of column that contains absolute value
TableDiagram_PercentageColumn, // All cells of column that contains percentage value
TableDiagram_PercentageColumnHeader, // Column header cells of column that contains percentage value
TableDiagram_PercentageColumnValue, // Column data cells of column that contains percentage value
TableDiagram_TotalColumn, // All cells of column that contains total value
TableDiagram_TotalColumnHeader, // Column header cells of column that contains total value
TableDiagram_TotalColumnValue, // Column data cells of column that contains total value
TableDiagram_TotalRow, // All cells of row that contains total value
TableDiagram_TotalRowHeader, // Row header cells of row that contains total value
TableDiagram_TotalRowValue, // Row data cells of row that contains total value
TableDiagram_AnswerRow, // All cells that is on even rows
TableDiagram_AnswerRowAlternate, // All cells that is on odd rows
TableDiagram_VarianceRow, // All cells of Variance row
TableDiagram_VarianceRowHeader, // Row header cells of Variance row
TableDiagram_VarianceRowValue, // Row data cells of Variance row
TableDiagram_AverageRow,
TableDiagram_AverageRowHeader,
TableDiagram_AverageRowValue,
TableDiagram_StdDevRow,
TableDiagram_StdDevRowHeader,
TableDiagram_StdDevRowValue,
TableDiagram_StdErrorRow,
TableDiagram_StdErrorRowHeader,
TableDiagram_StdErrorRowValue,
TableDiagram_MedianRow,
TableDiagram_MedianRowHeader,
TableDiagram_MedianRowValue,
TableDiagram_QuantilesRow,
TableDiagram_QuantilesRowHeader,
TableDiagram_QuantilesRowValue,
TableDiagram_PercentileRow,
TableDiagram_PercentileRowHeader,
TableDiagram_PercentileRowValue,
TableDiagram_SignificanceRow,
TableDiagram_SignificanceRowHeader,
TableDiagram_SignificanceRowValue,
// You could add the other style types of other diaram types here.
}
Sample Scripts
Set External Style
setReportStyleSheetId(1);
Set Internal Style
Set style for cells that belong to TableDiagramAllTable type:
array bgcolor = Color_getByName("Olive");
array font = DiagramFontStyle_getDefault();
font[DIAGRAM_FONT_STYLE_FACE] = "Tahoma";
font[DIAGRAM_FONT_STYLE_SIZE] = 10 ;
font[DIAGRAM_FONT_STYLE_BOLD] = false;
array fill_style = DiagramFillStyle_getDefault();
fill_style[DIAGRAM_FILL_STYLE_COLOR] = bgcolor;
fill_style[DIAGRAM_FILL_STYLE_TYPE] = Diagram_Fill_Style_SolidFill;
array style = Tabulation_getDefaultDiagramStyle(Diagram_Type_Table);
style[TABLE_DIAGRAM_STYLE_FILL] = fill_style;
style[TABLE_DIAGRAM_STYLE_FONT] = font;
Tabulation_setDiagramStyle(TableDiagram_AllTable, style);
createCrossDiagram({"Test_Single"},{});
Design
See this link for a detail of report/diagram generation. As a reminder, table chart are not converted to usable presentation type right after calling to CatGlobe.Framework.Report.Diagrams.Builder.ChartBuilder.BuildChart method, instead the returned result is an IEnumerable<ChartTable>. And framework's user must call CopyTo method of ChartTable to convert to concrete presentation table like PDF, HTML, PPT tables.
During the processing of CopyTo the external stylesheet is applied, developers even has a chance to put in inline stylesheet also. The copy method is as below:
public static T CopyTo<T>(this ChartTable sourceTable, T targetTable)
{
return sourceTable.CopyTo(targetTable, null);
}
public static T CopyTo<T>(this ChartTable sourceTable, T targetTable, IDictionary<StyleType, StyleBase> inlineStyles)
{
ChartTable targetChartTable;
if (targetTable is HtmlTable)
targetChartTable = new HtmlChartTable(
targetTable as HtmlTable,
sourceTable.RowCount, sourceTable.ColumnCount);
else if (targetTable is Aspose.Pdf.Table)
targetChartTable = new PdfChartTable(
targetTable as Aspose.Pdf.Table, sourceTable.RowCount,
sourceTable.ColumnCount);
else if (targetTable is Aspose.Slides.Table)
targetChartTable = new PptChartTable(
targetTable as Aspose.Slides.Table,
sourceTable.RowCount, sourceTable.ColumnCount);
else
throw new NotSupportedException(targetTable.GetType() + " is not supported for creating a ChartTable.");
// Copy data for all cells
sourceTable.ForEachCell(cell => targetChartTable[cell.RowIndex, cell.ColumnIndex].CopyData(cell));
// Apply external style
targetChartTable.ApplyStyle(sourceTable.Style);
// Apply inline styles
if (inlineStyles != null && inlineStyles.Count > 0)
targetChartTable.ApplyStyle(inlineStyles);
return (T)targetChartTable.InnerTable;
}
As you might see, the processing is straight forward:
- Create a ChartTable wrapper for correspondence presentation type. For example: System.Web.UI.HtmlTable has a wrapper type HtmlChartTable which inherits from ChartTable
- Copy cells from source ChartTable to another ChartTable
- Then apply the external stylesheet
- After all, apply the inline stylesheet (because in this case, the 2 stylesheets can not be merged)
- Return the inner table of wrapper ChartTable which is the same object that has been passed to the method
ChartTable(s)
The overall idea is hiding the detail of presentation's table implementation behind a ChartTable. Thus, for each kind of presentation table implementation (html/pdf/ppt) there is a correspondence ChartTable's sub class (HtmlChartTable, PdfChartTable, PptChartTable). The same rule is also applied to ChartTableCell which wrap the the presentation cell implementation.
Table Style Applier
ChartTable provides 2 entry methods for applying external and inline stylesheet. Both methods, in anyway, must delegate the applying to its all ChartTableCell(s) with custom processing as required. See the code below:
public void ApplyStyle(IDictionary<StyleType, StyleBase> inlineStyles)
{
if (inlineStyles == null || inlineStyles.Count == 0) return;
IDictionary<StyleType, ICollection<ChartTableCell>> typesMapping = CreateStyleMapping(inlineStyles.Keys);
Debug.Assert(typesMapping != null);
Debug.Assert(typesMapping.Count == inlineStyles.Count);
// Apply using the order in given list
foreach (KeyValuePair<StyleType, StyleBase> pair in inlineStyles)
foreach (ChartTableCell cell in typesMapping[pair.Key])
if (pair.Value is TableDiagramStyle)
cell.ApplyStyle((TableDiagramStyle) pair.Value);
else
throw new ApplicationException("Accept only TableDiagramStyle.");
}
public void ApplyStyle(TableChartStyle externalStyle)
{
if (externalStyle == null) return; // Do nothing if there is no externalStyle
ForEachCell(c => c.ApplyStyle(externalStyle));
}
Method CreateStyleMapping create a dictionary whose entry's key is a StyleType and entry's value is a collection of ChartTableCell that belongs to key StyleType. The code come below:
public IDictionary<StyleType, ICollection<ChartTableCell>> CreateStyleMapping(IEnumerable<StyleType> types)
{
IDictionary<StyleType, ICollection<ChartTableCell>> mapping = new Dictionary<StyleType, ICollection<ChartTableCell>>();
// Init the mapping
foreach (StyleType type in types)
mapping[type] = new List<ChartTableCell>();
// Populate mapping content
ForEachCell(
cell =>
{
foreach (var type in cell.Types)
if (mapping.Keys.Contains(type))
mapping[type].Add(cell);
});
return mapping;
}
Cell Style Applier
Using the same idea of hiding detail presentation's implementation of stylesheet, each presentation's table must introduce a new class which implements ICellStyleApplier. In the above diagram, only HtmlTableChartCellStyleApplier is drawn, but in reality there must be the same classes for pdf and ppt presentation types. The implementation of such class is very specific to the presentation's implementation and below is implementation for html presentation type.
internal class HtmlChartTableCellStyleApplier : ICellStyleApplier
{
private readonly HtmlTableCell _cell;
public HtmlChartTableCellStyleApplier(HtmlTableCell cell)
{
if (cell == null) throw new ArgumentNullException("cell");
_cell = cell;
}
public void Apply(FillProperty fillStyle)
{
if (fillStyle == null) return;
switch (fillStyle.StyleSheetFillType)
{
case FillProperty.FillType.NoFill:
case FillProperty.FillType.GradientFill:
break;
case FillProperty.FillType.SolidFill:
_cell.BgColor = StyleUtilities.ToHexColor(fillStyle.BackGroundColor);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
...
}
Document revisions
Version No. | Date | Changed By | Description |
0.1 | 21.07.2009 | Nguyen Trung Chinh | Create the first version |