Tabulation Script for setting inline style to Table Chart
New Report Design - 2009 => 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 TableDiagram_AllTable 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.
Style Applier
At the top of the style applying process is the StyleManager class which provide input method ApplyTableStyle which accepts both external stylesheet and inline stylesheet as parameter. The method then determine table specific and cell specific styles, then apply them to table level and cell level by calling ApplyStyle method.
A little lower in the diagram is the interface IStyleApplicable which is implemented by both TableChart and TableChartStyle, implementing this interface indicates that the class is style realizable. By default, the generic TableChart/TableChartCell provide an empty implementation of GetStyleApplier method and leave that to concrete implementation to return the custom StyleApplier.
Concrete TableChart/TableChartCell must implement GetStyleApplier by returning classes that implement TableStyleApplier/CellStyleApplier respectively. The 2 classes in turn inherit from StyleApplier which implement VisitMethodImpl.
Thus, the process of applying style can be done using Generic object visitor pattern. There is only one thing to stay focus on is that, all Apply style method must conform to type Action<T, VisitContext> and must be registered as visit method. See code below:
internal abstract class StyleApplier : VisitMethodImpl
{
protected StyleApplier()
{
AddVisitMethod<TableBorderLineStyle>(Apply);
AddVisitMethod<PaddingProperty>(Apply);
AddVisitMethod<object>(Apply);
}
public void Apply(TableBorderLineStyle borderLineStyle, VisitContext context) { }
public void Apply(PaddingProperty padding, VisitContext context) { }
public void Apply(object genericStyle, VisitContext context) { }
}
}
Another thing to be careful of is that in project ReportLayout2006 there are 2 base classes of all stylesheet setting (why not just one???!!!) are StyleBase and StylePropertyBase. Because there is no common class for all style classes, then we MUST implement a generic Apply method which received object as parameter and in this method we limit the types that are accepted. See code below:
public void Apply(object genericStyle, VisitContext context)
{
if (genericStyle == null) return;
// Get target object's type
Type type = genericStyle.GetType();
// Accept only types of StyleBase or StylePropertyBase
if (!type.IsSubclassOf(typeof(StylePropertyBase)) &&
!type.IsSubclassOf(typeof(StyleBase)))
return;
// Now let's visit child properties
foreach (PropertyInfoWrapper info in GetStyleProperties(type))
Visitor.Visit(info.GetValue(genericStyle),
new VisitContext { ObjectName = info.PropertyInfo.Name });
return;
}
- Method GetStyleProperties returns all instance public properties whose type inherit from either StyleBase or StylePropertyBase.
NOTE: till now, all table specific stylesheet are applicable to cell stylesheet also, so the implementation is moved to a higher level in hierarchy and leave this class blank for forward compatible (in case we would have more specific settings for table)
Document revisions
Version No. | Date | Changed By | Description | Revision |
0.1 | 21.07.2009 | Nguyen Trung Chinh | Create the first version | NA |
0.1 | 21.07.2009 | Nguyen Trung Chinh | Update according to new design | 56374 |