Live Razor Page Samples

SpreadsheetGear Image Rendering Utility

The SpreadsheetGear Image Rendering Utility is meant to demonstrate a design pattern you can follow to make generating images from charts and ranges easier. You can use this utility as the start of a reusable image generator which you can then reference from your web pages.

This sample shows how to use the image rendering utility to convert the Excel Report with Formatted Chart(Open XML) sample on the Excel Reporting Samples page to a bitmap image.

Supporting Files

The following files are utilized by this sample:

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

// The execution flow of this sample is as follows:
//   - A workbook is loaded either through generating it from another SpreadsheetGear Sample (PagePath property) 
//     or from a pre-existing file (FileName property) stored on the server.
//   - The rendered image is based on passing in either:
//       - A formula (RangeFormula property), which can consist of a range address, defined name or Excel-compatible 
//         formula that evaluates to a range of cells.
//       - Name of a shape, typically of a chart in the case of these samples.
//   - Additional RangeFormula/Value pairs can be provided on the query string, which will be used to set values on the 
//     provided range for the workbook being operated on.
//   - Image rendering is provided by the SpreadsheetGear.Drawing.Image class.
//   - The file format of the rendered image can be either PNG or GIF, depending on the provided ImageFileFormat value.
namespace Website.Pages.Support.Samples.RazorPages.Imaging
{
    public partial class SpreadsheetGearImageModel : PageModel
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public SpreadsheetGearImageModel(IHttpClientFactory clientFactory)
        {
            _httpClientFactory = clientFactory;
        }

        // Path to a Razor Page on this website.
        [BindProperty(SupportsGet = true)]
        public string PagePath { get; set; }

        // Name of a physical Excel file stored on the server.
        [BindProperty(SupportsGet = true)]
        public string FileName { get; set; }

        // The name of the worksheet for which the target image object is located.
        [BindProperty(SupportsGet = true)]
        public string WorksheetName { get; set; }

        // When rendering a range of cells, use this to specify the range address or defined name.
        [BindProperty(SupportsGet = true)]
        public string RangeFormula { get; set; }

        // When rendering only a chart, use this property to specify the chart's shape's name.
        [BindProperty(SupportsGet = true)]
        public string ShapeName { get; set; }

        // File format to use when saving the rendered image "png" or "gif"
        [BindProperty(SupportsGet = true)]
        public string ImageFileFormat { get; set; } = "png";

        public async Task<FileResult> OnGet()
        {
            // Create the workbook for the requested PagePath or FileName.
            SpreadsheetGear.IWorkbook workbook = null;

            // Check for a Razor Page Path first...
            if (PagePath != null)
            {
                // Limit the Path to the Samples folder.
                if (!PagePath.StartsWith("/Support/Samples/", StringComparison.OrdinalIgnoreCase))
                    throw new InvalidOperationException($"Invalid PagePath='{PagePath}'");

                // Request the workbook from the server.
                workbook = await GetWorkbookFromServer(PagePath);
            }
            // Otherwise, check for a file name...
            else if (FileName != null)
            {
                // Check for known files.
                switch (FileName)
                {
                    case "chartgallery.xlsx":
                    case "1693analytics.xlsx":
                        break;
                    default:
                        throw new InvalidOperationException($"Invalid FileName='{FileName}'");
                }

                // Get the workbook from a file.
                workbook = GetWorkbookFromFile($"files/{FileName}");
            }

            // Check whether we have a valid workbook.
            if (workbook == null)
                throw new InvalidOperationException("Missing PagePath or FileName parameter.");

            // Get the requested worksheet or default to first worksheet.
            SpreadsheetGear.IWorksheet worksheet;
            if (WorksheetName != null)
                worksheet = workbook.Worksheets[WorksheetName];
            else
                worksheet = workbook.Worksheets[0];

            // Parse any "unknown" name=value pairs to see if values are being sent.
            foreach (string key in Request.Query.Keys)
            {
                switch (key.ToLower())
                {
                    case "pagepath":
                    case "filename":
                    case "worksheetname":
                    case "rangeformula":
                    case "shapename":
                    case "imagefileformat":
                        // Ignore known keys.
                        break;
                    default:
                        // Try to parse unknown keys.
                        SpreadsheetGear.IRange valRange = worksheet.EvaluateRange(key);

                        // Verify that a valid range or defined name was specified.
                        if (valRange != null)
                        {
                            // Get the value associated with the key.
                            string value = Request.Query[key];

                            // Avoid potential accidental or malicious attempts to
                            // set a large number of cells to the specified value which
                            // could degrade server performance.
                            if (valRange.CellCount != 1)
                                throw new InvalidOperationException("Only single cell values may be set.");

                            // Set the specified value in the specified cell.
                            valRange.Value = value;
                        }
                        break;
                }
            }

            // Create the Image renderer for the requested range or shape.
            SpreadsheetGear.Drawing.Image image = null;

            // Check for a range formula first...
            if (RangeFormula != null)
            {
                // Get the range for the specified formula.
                SpreadsheetGear.IRange range = worksheet.EvaluateRange(RangeFormula);

                // Make sure this is a valid range formula.
                if (range == null)
                    throw new InvalidOperationException($"Invalid range formula parameter='{RangeFormula}'");

                // Create the image class...
                image = new SpreadsheetGear.Drawing.Image(range);
            }
            else
            {
                // Otherwise, check for a shape name...
                if (ShapeName != null)
                {
                    // Get the shape for the specified name.
                    SpreadsheetGear.Shapes.IShape shape = worksheet.Shapes[ShapeName];

                    // Make sure this is a valid shape name.
                    if (shape == null)
                        throw new InvalidOperationException($"Invalid shape parameter='{ShapeName}'");

                    // Create the image class...
                    image = new SpreadsheetGear.Drawing.Image(shape);
                }
            }

            // Check whether we have something valid to render...
            if (image == null)
                throw new InvalidOperationException("Missing shape or range parameter.");

            // Get the size of the image to be generated.
            System.Drawing.Size size = image.GetSize();

            // Check the size of the image to see if it is reasonable.
            if (size.Width <= 0 || size.Width > 1024 || size.Height <= 0 || size.Height > 1024)
                throw new InvalidOperationException("Invalid Image Size (probably specified too large of a range.");

            // Get a new bitmap image of the represented range or shape.
            // NOTE: The default PixelFormat will be PixelFormat.Format32bppArgb
            //       Use the overloaded GetBitmap() method to return another format.
            using (System.Drawing.Bitmap bitmap = image.GetBitmap())
            {
                System.IO.MemoryStream imageStream = new System.IO.MemoryStream();
                string contentType;
                // Default to PNG if any extension other than GIF is provided.
                if (ImageFileFormat.ToLower() != "gif")
                {
                    contentType = "image/png";
                    bitmap.Save(imageStream, System.Drawing.Imaging.ImageFormat.Png);
                }
                else
                {
                    contentType = "image/gif";
                    bitmap.Save(imageStream, System.Drawing.Imaging.ImageFormat.Gif);
                }

                // Reset position to the beginning of the stream.
                imageStream.Seek(0, System.IO.SeekOrigin.Begin);

                // Stream the image to the client.
                return File(imageStream, contentType);
            }
        }


        private async Task<SpreadsheetGear.IWorkbook> GetWorkbookFromServer(string path)
        {
            // Create an HTTP Client for a workbook based on the path string.
            HttpClient httpClient = _httpClientFactory.CreateClient();

            // Get server's scheme and host name.
            string scheme = HttpContext.Request.Scheme;
            string host = HttpContext.Request.Host.Value;

            // Get stream for file content from provided path
            System.IO.Stream stream = await httpClient.GetStreamAsync($"{scheme}://{host}{path}");

            // Open a workbook using the response stream.
            return SpreadsheetGear.Factory.GetWorkbookSet().Workbooks.OpenFromStream(stream);
        }


        private SpreadsheetGear.IWorkbook GetWorkbookFromFile(string fileName)
        {
            // Open a workbook using the file path.
            return SpreadsheetGear.Factory.GetWorkbook(fileName);
        }
    }
}