Camera shape, as the name suggests, is a mirror image of a referenced area in a spreadsheet. It is a dynamic image, meaning that any change in the referenced region is reflected in the image as well. You can create a camera shape by referring to Creating Camera Shapes topic.
Additionally, Spread for Winforms provides an enhanced camera shape that inherits all the features of the enhanced shape engine. For example, the enhanced camera shape can be moved, resized, rotated, and supported for Excel I/O. They can also be grouped or ungrouped with other shapes and copy-pasted from one sheet to another.
The enhanced camera shape displays the contents of a cell range by linking the cell range to a shape. On selecting the camera shape, it displays the source cell range in the formula bar. You can edit this cell range or defined name (of any cell range) to dynamically switch the camera shape's source data.
You can add the enhanced camera shape using the IPicture.Paste method. It accepts parameters such as the destination in the sheet and whether to establish a link to the source of the pasted picture. The RichClipboard property needs to be true to use this method.
You can also convert a picture to a camera shape by using IShape.Formula property to set the shape formula.
The implementation of the new camera shape takes effect if EnhancedShapeEngine is true.
C# |
Copy Code
|
---|---|
fpSpread1.Features.EnhancedShapeEngine = true; fpSpread1.Features.RichClipboard = true; // Adding camera shape by using IPictures.Paste method TestActiveSheet.Cells["A1:E7"].Copy(true); // Have to Copy with bool showUI = true TestActiveSheet.Pictures.Paste("D11", true); // CameraShape refers to Sheet1!$A$1:$E$7 is created TestActiveSheet.Pictures.Paste("F11", false); // A picture that snap content of A1:E7 is created // Changing a picture to camera shape IShape picture = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 1, 3); picture.Formula = "A1:E7"; TestWorkBook.Names.Add("_name", "$A$1:$B$1"); IShape picture1 = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 6, 0); picture1.Formula = "_name"; |
Visual Basic |
Copy Code
|
---|---|
FpSpread1.Features.EnhancedShapeEngine = True FpSpread1.Features.RichClipboard = True 'Adding camera shape by using IPictures.Paste method TestActiveSheet.Cells("A1:E7").Copy(True) 'Have to Copy with bool showUI = true TestActiveSheet.Pictures.Paste("D11", True) 'Camera Shape refers to Sheet1!$A$1:$E$7 is created TestActiveSheet.Pictures.Paste("F11", False) 'A picture that snap content of A1:E7 is created 'Changing a picture to camera shape Dim picture As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 1, 3) picture.Formula = "A1:E7" TestWorkBook.Names.Add("_name", "$A$1:$B$1") Dim picture1 As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 6, 0) picture1.Formula = "_name" |
An enhanced camera shape is capable of being displayed inside another camera shape. Unlike Excel, camera shapes in Spread for Winforms do not display inside itself or another camera shapes if they create a recursive painting.
You can observe the different behaviors in the examples below:
Show Code
C# |
Copy Code
|
---|---|
// Camera shape creating recursive painting over itself fpSpread1.Features.EnhancedShapeEngine = true; GrapeCity.Spreadsheet.IWorksheet TestActiveSheet = fpSpread1.AsWorkbook().ActiveSheet; GrapeCity.Spreadsheet.Color greenColor = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Green); TestActiveSheet.Cells["A1:D6"].Interior.Color = greenColor; TestActiveSheet.Cells[0, 0, 1, 1].Value = 1; IShape picture = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 5, 2); picture.Formula = "Sheet1!$A$1:$E$10"; |
Visual Basic |
Copy Code
|
---|---|
'Camera shape creating recursive painting over itself FpSpread1.Features.EnhancedShapeEngine = True Dim TestActiveSheet As GrapeCity.Spreadsheet.IWorksheet = FpSpread1.AsWorkbook().ActiveSheet Dim greenColor As GrapeCity.Spreadsheet.Color = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Green) TestActiveSheet.Cells("A1:D6").Interior.Color = greenColor TestActiveSheet.Cells(0, 0, 1, 1).Value = 1 Dim picture As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 5, 2) picture.Formula = "Sheet1!$A$1:$E$10" |
Show Code
C# |
Copy Code
|
---|---|
// Camera shape creating recursive painting over another camera shape fpSpread1.Features.EnhancedShapeEngine = true; GrapeCity.Spreadsheet.IWorksheet TestActiveSheet = fpSpread1.AsWorkbook().ActiveSheet; GrapeCity.Spreadsheet.Color yellowColor = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Yellow); GrapeCity.Spreadsheet.Color redColor = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Red); TestActiveSheet.Cells[0, 0, 1, 1].Value = 1; TestActiveSheet.Cells["G1:G10"].Interior.Color = redColor; TestActiveSheet.Cells["F1:F10"].Interior.Color = yellowColor; IShape picture = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 1, 6); picture.Formula = "Sheet1!$A$1:$D$10"; IShape picture1 = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 0, 2); picture1.Formula = "Sheet1!$F$1:$G$10"; TestActiveSheet.Shapes.Range(new int[] { 0, 1 }).Line.ForeColor.ARGB = System.Drawing.Color.Black.ToArgb(); |
Visual Basic |
Copy Code
|
---|---|
'Camera shape creating recursive painting over another camera shape FpSpread1.Features.EnhancedShapeEngine = True Dim TestActiveSheet As GrapeCity.Spreadsheet.IWorksheet = FpSpread1.AsWorkbook().ActiveSheet Dim yellowColor As GrapeCity.Spreadsheet.Color = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Yellow) Dim redColor As GrapeCity.Spreadsheet.Color = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Red) TestActiveSheet.Cells(0, 0, 1, 1).Value = 1 TestActiveSheet.Cells("G1:G10").Interior.Color = redColor TestActiveSheet.Cells("F1:F10").Interior.Color = yellowColor Dim picture As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 1, 6) picture.Formula = "Sheet1!$A$1:$D$10" Dim picture1 As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 0, 2) picture1.Formula = "Sheet1!$F$1:$G$10" TestActiveSheet.Shapes.Range(New Integer() {0, 1}).Line.ForeColor.ARGB = System.Drawing.Color.Black.ToArgb() |
Show Code
C# |
Copy Code
|
---|---|
// Camera shape displays inside another camera shape without creating recursive painting fpSpread1.Features.EnhancedShapeEngine = true; GrapeCity.Spreadsheet.IWorksheet TestActiveSheet = fpSpread1.AsWorkbook().ActiveSheet; GrapeCity.Spreadsheet.Color greenColor = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Green); TestActiveSheet.Cells["A1:D6"].Interior.Color = greenColor; TestActiveSheet.Cells[0, 0, 1, 1].Value = 1; IShape picture = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 6, 2); picture.Formula = "Sheet1!$A$1:$D$3"; IShape picture1 = TestActiveSheet.Shapes.AddPictureToCell(null, true, true, 6, 7); picture1.Formula = "Sheet1!$A$1:$E$10"; |
Visual Basic |
Copy Code
|
---|---|
'Camera shape displays inside another camera shape without creating recursive painting FpSpread1.Features.EnhancedShapeEngine = True Dim TestActiveSheet As GrapeCity.Spreadsheet.IWorksheet = FpSpread1.AsWorkbook().ActiveSheet Dim greenColor As GrapeCity.Spreadsheet.Color = GrapeCity.Spreadsheet.Color.FromKnownColor(GrapeCity.Core.KnownColor.Green) TestActiveSheet.Cells("A1:D6").Interior.Color = greenColor TestActiveSheet.Cells(0, 0, 1, 1).Value = 1 Dim picture As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 6, 2) picture.Formula = "Sheet1!$A$1:$D$3" Dim picture1 As IShape = TestActiveSheet.Shapes.AddPictureToCell(Nothing, True, True, 6, 7) picture1.Formula = "Sheet1!$A$1:$E$10" |
The enhanced camera shape is imported if EnhancedShapeEngine is true. Otherwise, the old camera shape is imported.
When exporting camera shapes to Excel:
Consider a scenario where the sales data of different products across a supermarket is maintained to analyze the sales trends. The data for different product categories like Fruits, Vegetables, Bakery, Meat, etc., is managed in worksheets of a spreadsheet.
You can display the summarized monthly sales data on a consolidated 'Dashboard' worksheet which shows camera shapes for the products' sales across different product categories. Any change made to the sales data is reflected in the 'Dashboard' sheet as well.
C# |
Copy Code
|
---|---|
// Set header data in row 0 of Dashboard sheet and its setting sheetDashboard.Cells[0, 0].Text = "Monthly Trend Analysis"; sheetDashboard.AddSpanCell(0, 0, 1, 14); // Set style for header text // Get range range = worksheet0.Cells["A1:A14"]; // Apply style to range range.Font.ApplyFont(new GrapeCity.Spreadsheet.Font() { Name = "Arial", Size = 12, Bold = true }); range.VerticalAlignment = GrapeCity.Spreadsheet.VerticalAlignment.Center; range.HorizontalAlignment = GrapeCity.Spreadsheet.HorizontalAlignment.Center; worksheet0.Cells[0, 0].Interior.Color = GrapeCity.Spreadsheet.Color.FromArgb(unchecked((int)0xFF8CA4B9)); // Add camera shapes in Dashboard sheet worksheet1.Cells["A1:C8"].Copy(true); // Have to Copy with bool showUI = true worksheet0.Pictures.Paste("A3", true); // CameraShape refers to worksheet1!$A$1:$C$8 is created worksheet2.Cells["A1:C7"].Copy(true); // Have to Copy with bool showUI = true worksheet0.Pictures.Paste("H3", true); // CameraShape refers to worksheet2!$A$1:$C$7 is created worksheet3.Cells["A1:C6"].Copy(true); // Have to Copy with bool showUI = true worksheet0.Pictures.Paste("A17", true); // CameraShape refers to worksheet2!$A$1:$C$5 is created worksheet4.Cells["A1:C8"].Copy(true); // Have to Copy with bool showUI = true worksheet0.Pictures.Paste("H17", true); // CameraShape refers to worksheet2!$A$1:$C$8 is created // Set activesheet to dashboard sheet fpSpread1.ActiveSheetIndex = 0; |
Visual Basic |
Copy Code
|
---|---|
'Set header data in row 0 of Dashboard sheet and its setting sheetDashboard.Cells(0, 0).Text = "Monthly Trend Analysis" sheetDashboard.AddSpanCell(0, 0, 1, 14) 'Set style for header text 'Get range range = worksheet0.Cells("A1:A14") 'Apply style to range range.Font.ApplyFont(New GrapeCity.Spreadsheet.Font() With { .Name = "Arial", .Size = 12, .Bold = True }) range.VerticalAlignment = GrapeCity.Spreadsheet.VerticalAlignment.Center range.HorizontalAlignment = GrapeCity.Spreadsheet.HorizontalAlignment.Center worksheet0.Cells(0, 0).Interior.Color = GrapeCity.Spreadsheet.Color.FromArgb(&HFF8CA4B9) 'Add camera shapes in Dashboard sheet worksheet1.Cells("A1:C8").Copy(True) 'Have to Copy with bool showUI = true worksheet0.Pictures.Paste("A3", True) 'CameraShape refers to worksheet1!$A$1:$C$8 is created worksheet2.Cells("A1:C7").Copy(True) 'Have to Copy with bool showUI = true worksheet0.Pictures.Paste("H3", True) 'CameraShape refers to worksheet1!$A$1:$C$7 is created worksheet3.Cells("A1:C6").Copy(True) 'Have to Copy with bool showUI = true worksheet0.Pictures.Paste("A17", True) 'CameraShape refers to worksheet1!$A$1:$C$5 is created worksheet4.Cells("A1:C8").Copy(True) 'Have to Copy with bool showUI = true worksheet0.Pictures.Paste("H17", True) 'CameraShape refers to worksheet1!$A$1:$C$8 is created 'Set activesheet to dashboard sheet FpSpread1.ActiveSheetIndex = 0 |
Spread for Winforms provides the ICamera interface that represents the visual of a cell range in a single cell. You can use the following ICamera members:
The following GIF illustrates a custom CAMERA function that you can apply in cells. The function is used to show a cell range inside a cell.
Show Code
You can create the CAMERA function shown above by following the code below.
C# |
Copy Code
|
---|---|
public partial class CameraShapeInterface : Form { public CameraShapeInterface() { InitializeComponent(); } private void CameraShapeInterface_Load(object sender, EventArgs e) { fpSpread1.AddCustomFunction(new CameraFunction()); IWorkbook workbook = fpSpread1.AsWorkbook(); workbook.Worksheets.Add(); IWorksheet sheet2 = workbook.Worksheets[1]; sheet2.Cells["B2"].Value = 5; IWorksheet sheet1 = workbook.Worksheets[0]; sheet1.Cells["A1"].ColumnWidth = sheet2.Cells["A1"].ColumnWidth * 2 + 1; sheet1.Cells["A1"].RowHeight = sheet2.Cells["A1"].RowHeight * 2 + 1; sheet1.Cells["A1"].Formula = "CAMERA(Sheet2!A1:B2)"; } } public class CameraFunction : VisualFunction { public CameraFunction() : base("CAMERA", 1, 1, FunctionAttributes.Variant, (IFunctionVisualizer)CameraVisualizer.Instance, false) { } protected override bool IsArrayParameter(int argIndex) { return true; } protected override bool Evaluate(IArguments arguments, IValue result) { IEvaluationContext context = arguments.EvaluationContext; IValue range = arguments[0]; switch (range.ValueType) { case GrapeCity.CalcEngine.ValueType.Reference: case GrapeCity.CalcEngine.ValueType.AdjustableReference: if (range.GetReferenceSource(context) is GrapeCity.Spreadsheet.IWorksheet worksheet) { ICamera camera = worksheet.Range(range.GetReference(context)).CreateCamera(); VisualizationData data = new VisualizationData(camera); result.SetValue(data, true); break; } else { goto default; } default: context.Error = CalcError.Reference; break; } return true; } private class CameraVisualizer : FunctionVisualizer { internal static CameraVisualizer Instance; static CameraVisualizer() { Instance = new CameraVisualizer(); } private CameraVisualizer() { } public override bool IsVisual => true; public override bool IsBackgroundSupported => true; protected override void PaintCell(IPaintingContext context, Rectangle rect, object cellValue, ref StyleFormat styleFormat) { if (cellValue is VisualizationData data && data.Value.ValueType == GrapeCity.CalcEngine.ValueType.Object && data.Value.GetObject() is ICamera camera) { GrapeCity.Drawing.ImageBrush imageBrush = camera.Image; if (imageBrush != null) { Brush brush = context.ToGdiBrush(imageBrush, rect); context.Graphics.FillRectangle(brush, rect); brush.Dispose(); } } } } } |
Visual Basic |
Copy Code
|
---|---|
Public Class CameraShapeInterface Private Sub CameraShapeInterface_Load(sender As Object, e As EventArgs) Handles MyBase.Load FpSpread1.AddCustomFunction(New CameraFunction()) Dim workbook As IWorkbook = FpSpread1.AsWorkbook() workbook.Worksheets.Add() Dim sheet2 As IWorksheet = workbook.Worksheets(1) sheet2.Cells("B2").Value = 5 Dim sheet1 As IWorksheet = workbook.Worksheets(0) sheet1.Cells("A1").ColumnWidth = sheet2.Cells("A1").ColumnWidth * 2 + 1 sheet1.Cells("A1").RowHeight = sheet2.Cells("A1").RowHeight * 2 + 1 sheet1.Cells("A1").Formula = "CAMERA(Sheet2!A1:B2)" End Sub End Class Public Class CameraFunction Inherits VisualFunction Public Sub New() MyBase.New("CAMERA", 1, 1, FunctionAttributes.[Variant], CType(CameraVisualizer.Instance, IFunctionVisualizer), False) End Sub Protected Overrides Function IsArrayParameter(ByVal argIndex As Integer) As Boolean Return True End Function <Obsolete> Protected Overrides Function Evaluate(ByVal arguments As IArguments, ByVal result As IValue) As Boolean Dim context As IEvaluationContext = arguments.EvaluationContext Dim range As IValue = arguments(0) Dim worksheet As IWorksheet = Nothing Select Case range.ValueType Case ValueType.Reference, ValueType.AdjustableReference If CSharpImpl.__Assign(worksheet, TryCast(range.GetReferenceSource(context), IWorksheet)) IsNot Nothing Then Dim camera As ICamera = worksheet.Range(range.GetReference(context)).CreateCamera() Dim data As VisualizationData = New VisualizationData(camera) result.SetValue(data, True) Exit Select Else GoTo _Select0_CaseDefault End If Case Else _Select0_CaseDefault: context.[Error] = CalcError.Reference End Select Return True End Function Private Class CameraVisualizer Inherits FunctionVisualizer Friend Shared Instance As CameraVisualizer Shared Sub New() Instance = New CameraVisualizer() End Sub Private Sub New() End Sub Public Overrides ReadOnly Property IsVisual As Boolean Get Return True End Get End Property Public Overrides ReadOnly Property IsBackgroundSupported As Boolean Get Return True End Get End Property <Obsolete> Protected Overrides Sub PaintCell(ByVal context As IPaintingContext, ByVal rect As Rectangle, ByVal cellValue As Object, ByRef styleFormat As StyleFormat) Dim data As VisualizationData = Nothing, camera As ICamera = Nothing If CSharpImpl.__Assign(data, TryCast(cellValue, VisualizationData)) IsNot Nothing AndAlso data.Value.ValueType = GrapeCity.CalcEngine.ValueType.Object AndAlso CSharpImpl.__Assign(camera, TryCast(data.Value.GetObject(), ICamera)) IsNot Nothing Then Dim imageBrush As GrapeCity.Drawing.ImageBrush = camera.Image If imageBrush IsNot Nothing Then Dim brush As Brush = context.ToGdiBrush(imageBrush, rect) context.Graphics.FillRectangle(brush, rect) brush.Dispose() End If End If End Sub Private Class CSharpImpl <Obsolete("Please refactor calling code to use normal Visual Basic assignment")> Shared Function __Assign(Of T)(ByRef target As T, value As T) As T target = value Return value End Function End Class End Class Private Class CSharpImpl <Obsolete("Please refactor calling code to use normal Visual Basic assignment")> Shared Function __Assign(Of T)(ByRef target As T, value As T) As T target = value Return value End Function End Class End Class |