The Dew Review – DevExpress TestCafe

Hot on the heels of my last review for DevExpress Universal 2014.2, I will next dive into my recent experiences with DevExpress TestCafe.

Introduction

TestCafe is the functional web testing tool from DevExpress. While many web test products work in conjunction with browser plugins, TestCafe works without plugins on any browser that supports HTML5. In today’s world, that translates to ‘any modern browser’.

You can also run on the big three operating systems, Windows, Mac OSX and Linux. I have been working with TestCafe on Windows 8.1, Windows 10 and OSX Yosemite. This operating system and browser agnostic ability affords maximum flexibility for web developers to test applications across multiple versions of browsers. All that is required is another physical or virtual machine running the desired browser(s).

That all sounds great, but you probably hear a lot about cross-browser, cross-platform ability these days. Take a minute and think about what that really means for a functional web testing tool. I can open TestCafe from any browser that can access the machine(s) where TestCafe and my application under test have been installed. So, I can pull out my Ultrabook on the road and record new tests over my company’s VPN. I could also break out my iPod Touch, tablet or Windows Phone and execute test fixtures. That is pretty powerful.

Getting Started

TestCafe claims to be “Functional Web Test, Made Easy”. Let’s see how easy it is to get started using the product. Until last month, I have never used TestCafe. In fact, I never used any kind of web test automation product. I’ve been lucky enough to work for organizations that understand the value to QA and hire dedicated testers who find my bugs that get past my own unit testing and manual testing.

So, how does a newbie like me get started?

DevExpress Demo Pages

A great first place to start is by trying TestCafe through the online demo pages. There are three pages available for selection.

  • TestCafe Example Page
  • ASPxGridView Demo Page
  • ASPxFileManager Demo Page

I decide to try the ASPxGridView Demo Page, so I select it from the list and click the ‘Run Demo’ button. Here is what I see initially.

TestCafe 3 - Demo Step 1 

Figure 1 – Run the online demo

I click the Start Demo link and click through some controls on the grid to auto generate a few test steps.

TestCafe 4 - Demo Step 2

Figure 2 – Online demo test steps

TestCafe includes all of my clicks and keystrokes into the test steps (even my screen capture keystrokes in Step 5 J). Now I can add some assertions to my test fixture or playback the steps that have been generated so far.

After completing this quick demo, I feel ready to jump into the Online Tutorial and create some of my own tests on my development machine.

Online Tutorial

From the main page for TestCafe, there’s a big button that will take you to an online tutorial with videos and step-by-step instructions for getting started with your first tests.

TestCafe 01 - The big button

Figure 3 – The big button.

The online tutorial steps you through creating a project, recording tests, running them, and finally running on remote devices. Here’s a look at the complete outline of the tutorial’s steps.

Test Cafe 02 - Tutorial Steps

Figure 4 – Tutorial Steps

Completing the online tutorial will give you an idea of the base functionality and capabilities of TestCafe. Now it’s time to take that knowledge to the next step.

AngularJS PhoneCat Tutorial App

Now that I have taken some time to familiarize myself with TestCafe using web pages created by DevExpress, I want to try creating a few simple test fixtures with a page that uses one of today’s most popular JavaScript frameworks, AngularJS. I have been working mainly in the world of Windows desktop applications and WPF for the last 18 months, so I turn to Bing to find out how to set up and run a simple AngularJS site.

Not surprisingly, Bing takes me to the AngularJS site where I see that there is a Tutorial under the Develop menu. The tutorial walks you through downloading their sample site, setting it up with Node.js and npm, and running it. The sample site is a simple catalog of Android devices with a list view and detail view.

TestCafe 05 - PhoneCat 1

Figure 5 – AnguluarJS tutorial application – list view

TestCafe 06 - PhoneCat 2

Figure 6 – AngularJS tutorial application – detail view

I create a new Test Project and Test Fixture and record a few tests for the List View page.

TestCafe 07 - Phone List Tests

Figure 7 – Phone List tests

Up to this point everything has been produced for us by TestCafe. Let’s take a moment analyze what has been generated for the tests I created for the Phone List Page. Here’s the JavaScript that is presented when clicking the Edit button on one of the tests or on the Test Fixture itself.

"@fixture Phone List Page";
"@page http://localhost:8000/app/index.html";

"@test"["Sort Phone List"] = {
    "1.Click select": function() {
        var actionTarget = function() {
            return $(".ng-pristine.ng-untouched.ng-valid").eq(1);
        };
        act.click(actionTarget);
    },
    '2.Click option "Alphabetical"': function() {
        act.click(":containsExcludeChildren(Alphabetical)");
    },
    "3.Click select": function() {
        act.click(".ng-untouched.ng-valid.ng-dirty.ng-valid-parse");
    },
    '4.Click option "Newest"': function() {
        act.click(":containsExcludeChildren(Newest)");
    }
};

"@test"["Search Dell"] = {
    "1.Click input": function() {
        var actionTarget = function() {
            return $(".ng-pristine.ng-untouched.ng-valid").eq(0);
        };
        act.click(actionTarget);
    },
    "2.Type in input": function() {
        var actionTarget = function() {
            return $(".ng-pristine.ng-untouched.ng-valid").eq(0);
        };
        act.type(actionTarget, "Dell");
    }
};

"@test"["Search Samsung"] = {
    "1.Click input": function() {
        var actionTarget = function() {
            return $(".ng-pristine.ng-untouched.ng-valid").eq(0);
        };
        act.click(actionTarget);
    },
    "2.Type in input": function() {
        var actionTarget = function() {
            return $(".ng-pristine.ng-untouched.ng-valid").eq(0);
        };
        act.type(actionTarget, "Samsung");
    }
};

"@test"["Search Motorola sort by name and assert first device name"] = {
    "1.Type in input": function() {
        var actionTarget = function() {
            return $(".ng-pristine.ng-untouched.ng-valid").eq(0);
        };
        act.type(actionTarget, "Motorola");
    },
    "2.Click select": function() {
        act.click(".ng-pristine.ng-untouched.ng-valid");
    },
    '3.Click option "Alphabetical"': function() {
        act.click(":containsExcludeChildren(Alphabetical)");
    },
    "4.Assert": function() {
        eq($(":containsExcludeChildren(DROID 2 Global by Motorola)").text(), "DROID™ 2 Global by Motorola", "First Moto Device");
    }
};

Notice that the test fixture is designated with @fixture, and each test definition with @test… pretty straightforward. Each test step is a function that returns the UI element to act upon followed by the action to perform on that element. My final test includes an assert as a final step. This checks that the first list element’s text is equal to what is expected after searching for Motorola and sorting the results alphabetically.

I can access the test fixture on my Windows Phone’s browser.

wp_ss_20150307_0002

Figure 8 – TestCafe on Windows Phone 8.1

And I can kick off a test run.

wp_ss_20150307_0001

Figure 9 – Tests executing on Windows Phone 8.1

So, that is a quick look at some of the basics of getting TestCafe up and running. There is a lot you can accomplish without knowing much more than what the Online Tutorial provides. To learn some more advanced features of the test fixtures in TestCafe, refer to the Test Fixture API Reference guide in the online documentation.

Feature Focus – Continuous Integration

I am a big fan of automated builds and continuous integration (CI) in development. I think it is one of the essentials of creating quality software. CI can do things for your team like running unit tests, code analysis and enabling continuous deployments to dev and test environments. Even at a bare minimum, CI can provide immediate feedback if a change one developer makes in a software component breaks something else in the system.

Automating and integrating functional web tests with CI builds is an extremely valuable proposition. It means that the number of regression bugs discovered by QA will be greatly reduced as builds that fail test steps in TestCafe will never be deployed to QA environments.

TestCafe has an entire section of their online documentation dedicated to continuous integration as well as a CI API reference.

At a glance, these are the steps that will need to be completed to set up CI for most types of servers (taken from the online docs).

  • Copy your tests to the server.
  • Setup TestCafe on the server.
  • Write a Node.js application that runs the tests and logs the results.
  • Call the application from your Continuous Integration system.

The sample node.js app in the online docs logs results to the console. Depending on your CI system, you will either use this method and pick up the results through the console output, or you may want to log the output to a file. There is an example of file output on another online documentation example. Here’s a snippet of that example:

var fs = require('fs');
 
testCafe.runTests(runOptions, function () {
      testCafe.on('taskComplete', function (report) {
           log('\n' + new Date().toString() + ':\n' + JSON.stringify(report));
       });
});
 
function log(mssg) {
       fs.appendFile(LOG_FILE_NAME, mssg, function (err) {
             if (err) 
                throw err;
       });
}

My current build server of choice at home and at work is JetBrains TeamCity. I have also used CruiseControl .NET in the past. While the basic steps were a good starting point, I wanted to find more detailed instructions specific to my TeamCity implementation.

Getting Support

I want to find out more information about TestCafe continuous integration with TeamCity. Where do I turn? To me, the logical first step is to try the Support page on the TestCafe site.

I kept it simple and searched for “TeamCity” and got just a single search result. Luckily, this one result was exactly what I needed. There is no direct support between TestCafe and TeamCity, but they can be integrated using the node.js app approach detailed in the online CI documentation. The method for doing this is similar for Jenkins CI servers, and Marion the DevExpress support representative who answered the question provided a link to the Jenkins information.

The TeamCity equivalent of these Jenkins steps include:

· Create a node.js app and place it on the build server. (The app in the Jenkins example will serve.)

· Install node.js on the build server.

· Add a Windows Command Line step to the desired build configuration in TeamCity that executes the node.js app.

· Capture the result.xml as the build report output.

If you want immediate feedback on your continuous builds, you will probably want to limit the number of tests run. I recommend creating either an hourly or daily build that executes all of your unit tests, integration tests and TestCafe functional tests.

Wrapping Up

Automating your functional tests can provide a great deal of value to any product. It takes a huge load off of the QA department once a full test suite has been created for your web applications. The licensing cost of TestCafe makes it something that every development shop should consider, regardless of the company or team size.

Go give it a try. There’s a 30-day free trial plus a 60-day money back guarantee if you’re not satisfied with the product.

 

Happy coding!

 

 

Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.

The Dew Review – DevExpress Universal 14.2.4

Intro

Over the last several years, I have reviewed DevExpress components a number of times. Here are four of my most recent reviews.

This year I have been looking at and starting to use several components from the Universal 14.2.4 release. The DevExpress Universal subscription encompasses controls and modules for all types of .NET development as well as cross platform web and mobile development with DevExtreme. From WinForms to WPF and Windows Universal apps on the client, and WebForms, MVC, HTML5/JS on the web, DevExpress has something for every modern developer on the Microsoft stack.

What’s New

Something that is easily noticed about the 14.2.4 release of DevExpress is that there is a focus on delivering components that enable developers to create great experiences on today’s devices. First and foremost, that means touch. Unless you’re buying a server, it’s hard to find a new Windows device that isn’t touch enabled in some way, either the screen itself or via a multi-touch touchpad. Today’s apps need to support taps, pinches, flicks, and swipes. The Windows and web components from DevExpress help make that possible. Read more about it here.

Let’s call out a few specific new and/or improved features of the 14.2 release.

WinForms

  • Ratings Control
  • TimeSpan Editor
  • SQL Data Access Component
  • Workspace Manager

ASP.NET WebForms

  • Rich Text Editor
  • New Design-Time Wizards to create controls
  • Adaptive Panels – Get responsive layouts for your content
  • Spreadsheet – Password Protected Sheets and Elements added (Demo)

ASP.NET MVC

  • MVC Spell Checker
  • Spreadsheet – Password Protected Sheets and Elements added (Demo)

WPF

  • Radial Menu
  • Spell Checker – Check-as-You-Type Mode added
  • Chart Control – New series types added: Spline, Spline Area, Stacked Spline Area & Full-Stacked Spline Area

Windows 8 XAML

  • Tile Bar
  • MVVM Support

XAF

  • End-User Report Designer
  • New Notifications Module

DevExtreme

  • A Slew of new HTML5/JS Widgets
  • iOS 8 and Android 5 Support

Areas of Focus

Due to the breadth of the DevExpress Universal product, I’m going to focus on a couple of areas within the WPF and DevExtreme products.

WPF

Sample – Video Rental

One of the WPF sample applications provided with DevExpress Universal is the Video Rental application. It is a full-featured application for managing the operation of a video rental shop. Here are a few screen shots of the application in action.

View WPF Video Rental Sample Application

The application makes use of some of the rich Office-style controls you might find in Outlook, including a ribbon-style toolbar, whose contents are context aware and change while navigating through the application.

The code is extensive and well designed. The ViewModels are broken out into their own project, with other projects for UI, Resources, and Data/Platform Services. Here’s a diagram of the project dependencies.

Screen Shot 2015-02-07 at 1.57.40 PM

This is a good example of a fully baked, line-of-business app that can be built with WPF and DevExpress.

Templates

DevExpress Universal includes a template wizard to select the starting point that best suits your project based on platform, DX version, and programming language. When selecting WPF as the platform, the following templates are available.

WPF Templates 1

Selecting the ‘Project Wizard’ option, guides the developer through a series of choices to build the best possible starting point for the project. I’ve included the steps I have chosen in this gallery.

View WPF New Project Wizard

Obviously, not every project requires all of these features, and every step is an optional selection. Completing the wizard with all of the selections above produces a main window that looks like this. A complete UI ready to be hooked up to a view model with the DevExpress MVVM framework or any other MVVM framework. A reference to DevExpress.Mvvm.dll v14.2 is automatically added to the starting project.

WPF Main Window

Feature Focus – MVVM Support with POCO ViewModels

There are a handful of popular MVVM frameworks available to .NET developers, including MVVM Light and Caliburn.Micro. The DevExpress MVVM Framework has one feature that sets it apart from many others.

A developer can create a POCO (plain old CLR object), and turn it into a ViewModel based on convention and a call to the DevExpress.Mvvm.POCO.ViewModelSource class. The following conventions define how ViewModelSource will create the resulting ViewModel from the provided POCO.

  • All public virtual and auto properties with public getters and public/protected setters will have bindable properties generated.
  • If specific logic is to be executed when a property changes, a method should be created with either of these formats:  On[Property Name]Changed() or On[Property Name]Changing().
  • Commands are generated for all public methods with 0 or 1 parameters. There is an optional Command attribute and a fluent API to control the creation of the commands.
  • IDataErrorInfo can be added to POCO classes for validation by adding a class level attribute

Here’s a simple POCO that will be turned into a full-featured ViewModel at runtime by ViewModelSource using Reflection Emit.

using System;
using System.ComponentModel.DataAnnotations;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Mvvm.POCO;

namespace Alvin.DXWPF.Sample1
{
    [POCOViewModel(ImplementIDataErrorInfo = true)]
    public class MainViewModel
    {
        //Bindable SummaryName property will be created with validation
        [Required(ErrorMessage = "Please enter the summary name.")] 
        public virtual string SummaryName { get; set; }

        //Bindable Categories property will be created
        public virtual IObservable<string> Categories { get; set; } 

        //SaveSettingsCommand will be created
        public void SaveSettings(string fileName) {
            // save logic here
        }

        //Will validate if the SaveSettingsCommand can be executed
        public bool CanSaveSettings(string fileName) {
            return !String.IsNullOrEmpty(fileName);
        }

        //Method that will NOT become a Command
        [Command(isCommand: false)]
        public void DoSomethingThatIsNotACommand()
        {
            // doing stuff
        }

        //prevent creating the View Model without the ViewModelSource 
        protected MainViewModel() { }

        //Use the ViewModelSource class to create a MainViewModel instance 
        public static MainViewModel Create()
        {
            return ViewModelSource.Create(() => new MainViewModel());
        } 
    }
}

As you can see, this method of creating view models can keep classes simple and clean.

DevExtreme

Sample – DX Hotels

The DX Hotels sample application is a web application for booking hotel rooms. It is built on the DevExtreme platform using ASP.NET MVC, Razor views, OData, Entity Framework, jQuery and Knockout.js. Here’s a peek at the project structure.

Screen Shot 2015-02-07 at 12.29.39 PM

This is what the page looks like when first loaded. The web application’s user can select a location and dates for booking.

DX Hotels Screen

The amount of code in this project is much less than the WPF sample project for Video Rentals, but it also has a good deal of feature function. Users can search for, select and book hotels, and there is a simple login function that takes any user/password combo and simulates a logged-in state.

Templates

DevExtreme templates provide options to create JavaScript or TypeScript applications, as well as OData service projects in Visual Basic or C#.

Screen Shot 2015-02-07 at 2.55.18 PM

Selecting the “DevExtreme 14.2 Basic Application” template produces the following for a new project.

Screen Shot 2015-02-07 at 3.04.45 PM

In addition, there are 13 CSS files inside the css folder. The project is a cross-platform mobile web app which will launch in web based simulators in the selected browser when running the solution. By default, iOS is the selected simulator. Here’s the bare-bones project running as an iOS DX app.

Screen Shot 2015-02-07 at 3.07.15 PM

Because DevExtreme apps take advantage of Apache Cordova, your apps can access native platform features like camera and location across device types. There has been a lot of discussion around Cordova app development recently, with the capability to build these apps being built in to Visual Studio 2013 and 2015. DevExtreme has been making this possible for a couple of years now.

Wrapping Up

This article has taken a look at just a small part of what is possible with the controls and modules available in DevExpress Universal 14.2. Visit the DevExpress website to learn more about what their control suite can do to accelerate your application development in 2015, and don’t forget to download a free trial.

My next review will focus on DevExpress TestCafé, a powerful to make functional web testing easy and fun. Check back soon to read all about it.

 

Happy Coding!

 

Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.

 

The Dew Review – Aspose.Cells for .NET

Introduction

It is time for another development component review. Last June, I reviewed the Aspose.Email for .NET component and demonstrated how to work with email messages in PST files or via IMAP. Well, I am back again for a look at another Aspose package. This one is Aspose.Cells for .NET.

Aspose.Cells provides full access to hundreds of Excel file features without the need to install or distribute Microsoft Excel.

Aspose.Cells Features

For a full list of features visit the Aspose.Cells site. Here is a summary of some of the highlights.

File Manipulation

There are so many file formats supported by Aspose.Cells including Excel (XLS, XLSM, etc.), HTML, CSV, Tab Delimited and PDF. Developers can open/save files, encrypt saved files, convert Excel documents to PDF or even save a worksheets as a SVG file.  You can also manipulate the file properties of existing Excel files.

Need to capture part of a workbook into an image file? There are APIs available to export Charts and entire Worksheets to an image, which can then be saved or manipulated like any other bitmap in .NET.

Worksheets, Rows and Columns

Aspose.Cells has Worksheet APIs to add and remove worksheets from workbooks. New worksheets can also be added to an existing PDF file with these APIs. Within a sheet, developers can manipulate scrollbar visibility, tabs, zoom factor as well as freezing and splitting panes on a sheet.

You can also take advantage of the APIs for working with rows and columns on a sheet. Your application can insert, delete, copy, hide/unhide, and adjust height/width.

Data and Formatting

Aspose.Cells can import data into worksheets from many different sources, including:

  • Arrays and ArrayLists
  • Custom .NET Objects and Collections
  • DataTable / DataView / DataColumn
  • Manual Data Entry

Once data is in a worksheet, it can be sorted, accessed and searched upon.

Cells includes a formula engine which can run with formulas embedded in existing spreadsheets or with new formulas created at runtime.

Think of any kind of data formatting you can perform in a cell in Excel, and you can probably do it with these APIs… fonts, colors, text formatting… you name it.

Tables and Charts

Lists can easily be formatted as tables on a worksheet with Aspose.Cells. Once part of a table, the data can be styled, formatted, grouped, and summed.

Charts are one of the most powerful features in Excel and Aspose.Cells. I’ll be showing an example of the charting API in my sample application below. Additional features not shown in my app include 3D formatting, inserting controls into charts (labels, pictures, textboxes), and Excel Sparklines.

Multi-Platform Support

Not only are there tons of features in the Aspose.Cells library, but you can access those features from all of these platforms:

  • .NET Framework
  • PHP
  • Python
  • Mono

at-glace-diagram-Updated2

Sample App – Data and Pivots and Charts, Oh My!

Just like the last time I started out working on an application with Aspose, I immediately cracked open the Examples Dashboard to find out how to implement the features I needed for my app.

examples

Other NuGet Packages

I used a couple of other NuGet packages to help make my application development a little bit simpler.

MVVM Light – This is my go-to MVVM helper framework. It makes binding and messaging a breeze in WPF and other XAML applications.

CsvHelper – This package provides handy APIs for working with CSV files. Because I wanted to import my data from a CSV file into a .NET collection. I could have imported the CSV data directly with Aspose.Cells, but I wanted to see how the library worked with collections in case my data was coming from another source like a REST service or other API.

The App

The application itself is relatively simple. I first load some data from a CSV file which contains a list of sites and authors and the number of visits each had during a particular quarter. I load this into a List<AuthorSummary> collection with CsvHelper and import the collection to a sheet in a workbook I create in memory with Aspose.Cells.

// The path to the documents directory.
_dataDir = Path.GetFullPath("../../../Data/");

// Create directory if it is not already present.
bool IsExists = Directory.Exists(_dataDir);
if (!IsExists)
    Directory.CreateDirectory(_dataDir);

//Instantiating a Workbook object
_workbook = new Workbook();

//Obtaining the reference of the default first worksheet by passing its sheet index
Worksheet worksheet = _workbook.Worksheets[0];

var authorSummaries = new List<AuthorSummary>();

using (var csv = new CsvReader(new StreamReader("SitesChartSample.csv"), new CsvHelper.Configuration.CsvConfiguration { HasHeaderRecord = true, Delimiter = "," }))
{
    while (csv.Read())
    {
        var authorSummary = new AuthorSummary
                            {
                                Site = csv.GetField<string>(0),
                                Author = csv.GetField<string>(1),
                                Visits = csv.GetField<int>(2),
                                Quarter = csv.GetField<string>(3)
                            };

        authorSummaries.Add(authorSummary);
    }
}

var options = new ImportTableOptions { InsertRows = true };

worksheet.Cells.ImportCustomObjects(authorSummaries, 1, 0, options);

The next step is to create a pivot table. I want a better visualization of the number of visits each site is getting per quarter, but I still want to see the breakdown by author. I add a new PivotTable object with Aspose.Cells and point it to the range of cells to use as the source data. I then tell it which of the fields to use as the pivot Rows, Columns and Data.

Aspose.Cells.Pivot.PivotTableCollection pivotTables = worksheet.PivotTables;
int index = pivotTables.Add("=A2:D26", "F2", "VisitsBySiteAndQuarter");

//Accessing the instance of the newly added PivotTable
Aspose.Cells.Pivot.PivotTable pivotTable = pivotTables[index];

//Unshowing grand totals for rows.
pivotTable.RowGrand = false;

//Dragging the first field to the row area.
pivotTable.AddFieldToArea(Aspose.Cells.Pivot.PivotFieldType.Row, 0);
pivotTable.AddFieldToArea(Aspose.Cells.Pivot.PivotFieldType.Row, 1);

//Dragging the second field to the column area.
pivotTable.AddFieldToArea(Aspose.Cells.Pivot.PivotFieldType.Column, 3);

//Dragging the third field to the data area.
pivotTable.AddFieldToArea(Aspose.Cells.Pivot.PivotFieldType.Data, 2);

pivotTable.CalculateData();

The final step is to create a chart based on the summary data in the pivot table. I use Aspose.Cells to add a new Chart object to the worksheet and then add each series of data elements that is to be part of the chart.

//Adding a chart to the worksheet
int chartIndex = worksheet.Charts.Add(Aspose.Cells.Charts.ChartType.Pyramid, 2, 12, 14, 18);

//Accessing the instance of the newly added chart
Aspose.Cells.Charts.Chart chart = worksheet.Charts[chartIndex];

//Adding SeriesCollections (chart data sources) to the chart
chart.NSeries.Add("H10:K10", false);
chart.NSeries[0].Name = "C#";
chart.NSeries.Add("H16:K16", false);
chart.NSeries[1].Name = "VB";
chart.NSeries.Add("H20:K20", false);
chart.NSeries[2].Name = "F#";
chart.NSeries.Add("H31:K31", false);
chart.NSeries[3].Name = "JavaScript";

chart.Title.Text = "Quarterly Visits By Site";

One last bit I threw in was some styling/formatting. I wanted to see how easily I could change the appearance of a chart. Most of this code is taken from one of the samples in the Examples Dashboard application installed with Aspose.Cells.

private void SetChartAppearance(Aspose.Cells.Charts.Chart chart)
{
    //Setting the foreground color of the plot area
    chart.PlotArea.Area.ForegroundColor = Color.Blue;

    //Setting the foreground color of the chart area
    chart.ChartArea.Area.ForegroundColor = Color.Yellow;

    //Setting the foreground color of the 1st SeriesCollection area
    chart.NSeries[0].Area.ForegroundColor = Color.Red;

    //Setting the foreground color of the area of the 1st SeriesCollection point
    chart.NSeries[0].Points[0].Area.ForegroundColor = Color.Cyan;

    //Filling the area of the 2nd SeriesCollection with a gradient
    chart.NSeries[3].Area.FillFormat.SetOneColorGradient(Color.Lime, 1, Aspose.Cells.Drawing.GradientStyleType.Horizontal, 1);

    //Get the CellsColor of SolidFill
    CellsColor cc = chart.NSeries[0].Area.FillFormat.SolidFill.CellsColor;

    //Create a theme in Accent style
    cc.ThemeColor = new ThemeColor(ThemeColorType.Accent6, 0.6);

    //Apply the them to the series
    chart.NSeries[0].Area.FillFormat.SolidFill.CellsColor = cc;
}

And here is the output of the chart when exported to an image and displayed on my WPF form:

chart output

Ok, so I’m no graphic designer. I am a developer after all.

Exporting Charts and Saving Files

When the WPF form loads and the ViewModel prepares the data for the chart, it then exports the chart to a Bitmap object which gets converted to a BitmapSource which can be bound to a WPF Image control on the form. I found this handy image conversion code on StackOverflow.

ChartImage = LoadBitmap(chart.ToImage());

[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);

private static BitmapSource LoadBitmap(Bitmap image)
{
    IntPtr pointer = image.GetHbitmap();
    BitmapSource bitmapSource;

    try
    {
        bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(pointer,
           IntPtr.Zero, Int32Rect.Empty,
           BitmapSizeOptions.FromEmptyOptions());
    }
    finally
    {
        DeleteObject(pointer);
    }

    return bitmapSource;
}

Two buttons on the form are bound to commands to save the workbook as either an Excel file (.xls) or PDF document. The code to perform each of these actions is similar and very intuitive. I also added some code to launch each file after saving so I could view the results.

private void SavePDF()
{
    //Save in Pdf format
    _workbook.Save(_dataDir + "book1.pdf", SaveFormat.Pdf);

    Process.Start(_dataDir + "book1.pdf");
}

private void SaveXLS()
{
    //Saving the Excel file
    _workbook.Save(_dataDir + "book1.xls");

    Process.Start(_dataDir + "book1.xls");
}

The full source code for this project can be found here. The trial Aspose.Cells product is fully functional but adds watermarks to all of the files created.

Summary

If you are in the market for a library to give your spreadsheet application a jump-start, Aspose.Cells should be at the top of your list. I found the APIs really intuitive and the documentation and examples are thorough and comprehensive. I have really enjoyed my second experience with an Aspose product.

 

Happy Coding!

 

 

Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”