Quantcast
Channel: SoftArtisans
Viewing all 140 articles
Browse latest View live

Excel’s color palette explained

$
0
0

Problem

Excel’s color palette contains 56 colors, all of which can be accessed and most of which can be replaced using ExcelWriter (v6 or later). This post describes the layout of the palette and enumerate the default palette colors.

This content is most pertinent to the Excel 2003 color palette, which only has 56 colors. In Excel 2007 and later, workbooks can support millions of colors, but there is still an underlying workbook palette that has 56 colors. For more information about colors in multiple versions of Excel, we have enough post about workbook colors that are not displayed properly in older versions of Excel.

Solution

The palette is split up into a few different sections:

  • 40 Standard colors, which includes 8 system colors
  • 8 Chart fill colors
  • 8 Chart line colors

The 40 standard colors are available in all color selection dialogs in Excel, including the drop-down dialogs on the Formatting toolbar. In ExcelWriter, they can all be accessed through the Palette class’s “get” methods. The system colors can also be accessed through the Palette.SystemColor enumeration. For example:

 //--- Get black using the SystemColor enumeration Color black = Palette.SystemColor.Black; 

Chart Fills and Chart Lines are what Excel uses when automatically setting fill and line colors on charts. Chart fills and lines not limited to these colors however. These colors are available as options in Patterns and Chart color dialogs (i.e. Format > Cells > Patterns). In ExcelWriter, all Chart fill and line colors can be accessed and replaced using the Palette’s “get” and “set” methods.

All standard and chart colors can be replaced with other colors using the Palette class’s “set” methods except for the system colors. For example:

 //--- Replace color at index 4 with RGB values (162, 221, 138) wb.Palette.SetColorAt(4, 162, 221, 138); 

This would be equivalent to changing the color palette in Excel through Tools > Options > Color.

Palette Color Reference Charts

Provided below are two views of the default palette. The first is ordered by palette index, and the second is similar to how the palette is displayed from within Excel.

The colors in order of palette index

 //--- Get the color at palette index 9 Color darkGreen = wb.Palette.GetColorAt(9); 

The RGB and HEX equivalents of each color are provided

Palette Index Color RGB HEX System Color
0 0, 0, 0 #000000 Black
1 255, 255, 255 #FFFFFF White
2 255, 0, 0 #FF0000 Red
3 0, 255, 0 #00FF00 Green
4 0, 0, 255 #0000FF Blue
5 255, 255, 0 #FFFF00 Yellow
6 255, 0, 255 #FF00FF Magenta
7 0, 255, 255 #00FFFF Cyan
8 128, 0, 0 #800000
9 0, 128, 0 #008000
10 0, 0, 128 #000080
11 128, 128, 0 #808000
12 128, 0, 128 #800080
13 0, 128, 128 #008080
14 192, 192, 192 #C0C0C0
15 128, 128, 128 #808080
16 153, 153, 255 #9999FF Chart Fills
17 153, 51, 102 #993366
18 255, 255, 204 #FFFFCC
19 204, 255, 255 #CCFFFF
20 102, 0, 102 #660066
21 255, 128, 128 #FF8080
22 0, 102, 204 #0066CC
23 204, 204, 255 #CCCCFF
24 0, 0, 128 #000080 Chart Lines
25 255, 0, 255 #FF00FF
26 255, 255, 0 #FFFF00
27 0, 255, 255 #00FFFF
28 128, 0, 128 #800080
29 128, 0, 0 #800000
30 0, 128, 128 #008080
31 0, 0, 255 #0000FF
32 0, 204, 255 #00CCFF
33 204, 255, 255 #CCFFFF
34 204, 255, 204 #CCFFCC
35 255, 255, 153 #FFFF99
36 153, 204, 255 #99CCFF
37 255, 153, 204 #FF99CC
38 204, 153, 255 #CC99FF
39 255, 204, 153 #FFCC99
40 51, 102, 255 #3366FF
41 51, 204, 204 #33CCCC
42 153, 204, 0 #99CC00
43 255, 204, 0 #FFCC00
44 255, 153, 0 #FF9900
45 255, 102, 0 #FF6600
46 102, 102, 153 #666699
47 150, 150, 150 #969696
48 0, 51, 102 #003300
49 51, 153, 102 #339966
50 0, 51, 0 #003300
51 51, 51, 0 #333300
52 153, 51, 0 #993300
53 153, 51, 102 #993366
54 51, 51, 153 #333399
55 51, 51, 51 #333333

* The colors as displayed in Excel *

The following is similar to how the palette is displayed in Excel. To find the RGB and HEX equivalents, simply match up the palette index to the chart above.

Excel Palette / Palette Indexes
Standard Colors
0 52 51 50 48 10 54 55
8 45 11 9 13 4 46 15
2 44 42 49 41 40 12 47
6 43 5 3 7 32 53 14
37 39 35 34 33 36 38 1
Chart Fills
16 17 18 19 20 21 22 23
Chart Lines
24 25 26 27 28 29 30 31

Note: When accessing the palette through VBA, the color indexes are 1-based, not 0-based as they are when using ExcelWriter. Therefore, when using VBA, simply add 1 to the indexes listed above.

Excel version of this information

An Excel file containing similar information about default palette colors is attached to this article. You may find it useful for testing different effects on the palette when changing colors using ExcelWriter.

Related Links

Attachments

Color_Palette_Example.zip


Workbook colors are not displayed as expected in older versions of Excel

$
0
0

Problem

When using ExcelWriter’s ExcelApplication object to generate a new workbook, custom colors that are assigned in code to fonts, charts, cell backgrounds, etc., display incorrectly on the client when the workbook is generated.

OR

When creating an Excel File or an Excel file to use as a template with the ExcelTemplate object using Excel 2007 and above, colors are not colors are not preserved in Excel 2003 or older.

The Excel .XLSX file format supports millions of colors, so when working in newer versions of Excel, the user interface will give you the option to select any color because Excel does not know what file format you will save in.

  • When creating a document using Excel 2007 and later and you save your file as XLS format, everything will appear as normal, but when the XLS file is opened in Excel 2003 the colors will revert to the closest 56 colors in the workbook palette. Depending on your application settings you may or may not receive a Minor loss of fidelity warning.
  • If you save the file as an XLSX file you will not receive a warning, but when an XLSX file is opened in Excel 2003 with the compatibility pack, Excel will perform a file conversion back to XLS, which limits the workbook to the 56 colors in the palette.

Since the XLS file format is limited to 56 colors stored in the workbook, special consideration must be taken when designing a document that will be viewed in previous versions of Excel.

To ensure that colors appear the same in all versions of Excel, one can customize the workbook palette to include the colors needed. This can be done both manually, and automatically with 3rd party tools.

Solution

Creating a custom palette using Excel Application

If you are using ExcelApplication to programmatically set colors using Palette.GetClosestColor, ExcelWriter will attempt to find the closest color in the palette. If the color or similar color is not in the workbook’s palette, the colors may not appear as expected. You can use ExcelWriter’s SetColorAt method to replace a color in the palette and ensure that your color will be found.  You can also use ExcelWriter’s Palette.GetColorAt method to retrieve specific colors.  By ensuring the colors you are using are in the Workbook Palette you can ensure the document will render with the colors desired.

 ExcelApplication xla = newExcelApplication(); Workbook wb = xla.Create(); //Set a color in the Palette wb.Palette.SetColorAt(1, 240, 217, 216); //Can also use GetColorAt(1); wb[0].Cells["A1"].Style.BackgroundColor = wb.Palette.GetClosestColor(240, 217, 216); xla.Save(wb,"colors.xls"); 

Creating a custom palette using Excel

When designing a template in Excel, the colors in the workbook’s palette can be modified.

Manually creating a custom palette in Excel 2010:

  • Open the Workbook whose palette you wish to modify.
  • In the upper left hand corner select File
  • select Options
  • Select the Save menu
  • Under Preserve Visual Appearance of a workbook, next to choose what colors will be seen in previous versions of Excel select Colors…
  • Select a color you wish to change and press Modify
  • Change the color and repeat sets as needed.
  • Press OK until you are back to the Workbook

Manually creating a custom palette in Excel 2007:

  • Open the Workbook whose palette you wish to modify.
  • In the upper left hand corner press the Microsoft Office Button and select Excel Options
  • Select the Save menu
  • Under Preserve Visual Appearance of a workbook, next to choose what colors will be seen in previous versions of Excel select Colors…
  • Select a color you wish to change and press Modify
  • Change the color and repeat sets as needed.
  • Press OK until you are back to the Workbook

Manually creating a custom palette in Excel 2003:

  • Open the Workbook whose palette you wish to modify.
  • From the Tools menu select Options, and then select the Color tab.
  • Select a color you wish to change and press Modify
  • Change the color and repeat sets as needed.
  • Press OK until you are back to the Workbook

Automatically converting colors to custom palette:

Since manually editing the workbook color palette can be a time consuming process, some people have tried to automate the process.  Jon from Excel Campus has done just this with his color palette conversion tool.

By ensuring the colors you are using are in the workbook’s palette, you can ensure that your workbook will appear the same throughout different versions of Excel.

How to open a report from SQL Server Reporting Services with the Application object

$
0
0

Problem

You want to modify your reports with the WordApplication or ExcelApplication object after they’ve been populated with data by SQL Server Reporting Services. The ExcelApplication or WordApplication object’s Open method can’t pull a report from a report server, so how do you open a SSRS report with OfficeWriter?

Solution

For simplicity and ease of reading the code examples and text in this article refer to the ExcelApplication object exclusively. However, the exact same techniques can be used with the WordApplication object. The only strict requirement for opening reports from SSRS is for the Open method to have an overload that takes a Stream argument, which both objects have.

SQL Server Reporting Services exposes a web service that lets programs access and work with the reports on the server. The web service has a number of functions for interacting with a report server and in fact is the same API that the Report Manager tool is built on top of. One of its functions will let us retrieve a fully rendered report that we can then pass to the ExcelApplication object. Once the ExcelApplication object has opened the report, it can be used as if it were any other file.

Getting a Reference to the Report Server

There are a number of different ways to access a report server to manage your reports. The MSDN documentation has detailed instructions for all the different techniques. The most powerful way, and the one that the Report Manager application uses, is to use the report server’s web service, or SOAP API. The easiest way to use the web service is to add the report server as a web reference in Visual Studio. This will allow us to make web service calls to the report server as though it were any other object in a .NET project. I’ll provide a brief overview of the steps to add a report server as a web reference; details can be found at MSDN.

  1. After opening the project you want to open a report in, select ‘Add Web Reference’ from the Project menu (or by right-clicking on the project name in the Solution Explorer).
  2. Enter the URL of the report server in the text box. In most cases, this should be “http:///reportserver/reportservice.asmx”. Click ‘go’.
  3. Visual Studio should find a single reference named ‘reportservice’. Enter a friendly name for the service in the text box on the right. For this example, I’ll use the name “MyReportService”.
  4. Click ‘Add Reference’.

Creating a ReportingService Object

Adding the web reference in the last section created a special namespace that contains the object we’ll use to render the report. This namespace is .. In the example I used above this would be ReportingServiceRender.MyReportService. This namespace contains a ReportingService object that we’ll use to do the actual rendering of the report. To create a ReportingService object, use its default (empty) constructor. You can either fully qualify the class name or add a using (imports in VB.NET) statement to your code like I do in the sample below.

Note that while the default behavior is to add the report service in the project’s namespace, this is not always guaranteed, especially if the project name changes. If you add a web reference and cannot find it in the project namespace, right click on the web service in the Solution Explorer and select ‘View in Object Browser’. This will open the object browser and highlight the web service with its full namespace.

After creating the ReportingService object, we have to tell it how to authenticate itself to the report server. As long as the account your program is running as has permissions to render reports, you can use the default credentials here. If you need the code to run under a different set of credentials, you’ll need to create those at this step using the CredentialCache object.

 // Replace this name with whatever you named your reporting service instance using ReportingServiceRender.MyReportService; // ... Namespace and class declarations, etc ... ReportingService rs = new ReportingService(); rs.Credentials = System.Net.CredentialCache.DefaultCredentials; 

Calling the Render Function

The function we’ll use to get a copy of the populated report is ReportingService.Render. For our purposes, all we need are the first two arguments: the path of the report and the name of the rendering extension.

The path to a report always begins with a ‘/’, and does not include the ‘.rdl’ extension. For example, a report in the Home folder named “MyFancyReport” will have a path of “/MyFancyReport”. If we moved that same report to the “ExtraFancy” folder, the path would be “/ExtraFancy/MyFancyReport”. Note that all the slashes are forwards, as in a URL, instead of backwards, as in a Windows path.

The rendering extension is a string that tells Reporting Services what format to return the report in. By default, SSRS can render reports to a few simple formats including HTML, XML, PDF and basic, limited Word and Excel documents. To render a report as an Excel workbook with the SoftArtisans OfficeWriter renderer, use the “XLTemplate” extension. For Word documents, use the “WordTemplate” extension.

Because the last five arguments are output arguments in C#, we need to create variables to pass to the function instead of simply using null. Even though we don’t use the values in those variables, the variables must exist for the code to compile.

 // These variables are all the output variables the Render function takes. // We don't use them, but we need to create them to pass to the function. // Note that the ParameterValue array and the Warning array are members of // the ReportingServiceRender.MyReportService namespace we created earlier string optionalEncoding = null; string optionalMimeType = null; ParameterValue[] optionalParams = null; Warning[] optionalWarnings = null; string[] streamIDs; // The first argument tells Render where to find the report, the second // argument tells it what extension to use to render the report. string reportPath = "/ExtraFancy/MyFancyReport"; string reportFormat = "XLTemplate"; // The actual call to Render. The only important parameters are the first // two; the rest are either null or unused. byte[] result = rs.Render(reportPath, reportFormat, null, null, null, null, null, out optionalEncoding, out optionalMimeType, out optionalParams, out optionalWarnings, out streamIDs); 

Opening the Report in the Application Object

As you can see in the code snippet above, the Render function returns a byte array. The ExcelApplication object can’t open a byte array directly, but it can open a MemoryStream object (ExcelApplicationWordApplication. We can create a MemoryStream object by passing it a byte array in the constructor.

Once the Application object has opened the stream we can use it just like any other file, including streaming the file to users with one of the overloads of Save (ExcelApplicationWordApplication.

 // Turn the byte[] to a stream object that Open can read. MemoryStream reportStream = new MemoryStream(result); ExcelApplication xla = new ExcelApplication(); Workbook wb = xla.Open(reportStream); reportStream.Close(); // ... Modify the report with the Application object ... // Stream the rendered and modified report back to the user. xla.Save(wb, Page.Response, "RenderedReport.xls", false); 

Note that this code should be executed as part of a postback in a web form. By invoking this code through a web form you can create an interface that lets users request a report by clicking on a button or link, then stream that report back to them as though it were any other downloaded file.

Attached to this article is a zip file containing a Visual Studio 2008 project with this code in it. The project also contains a web form with a button that fires the code. Note that the web reference in the project assumes that the report server is hosted on the same machine that the code runs on, so it may need to be updated before the code will run. Also keep in mind that the project looks for a report named MyFancyReport in the /ExtraFancy folder. If you don’t have a report there, you’ll either need to create one or change the path in Default.aspx.cs.

Attachments

Internet Week New York 2013 in Review

$
0
0

Joan Rivers

Digital Cities PanelA whirlwind week of panels, classroom discussions, and events is the only way to describe Internet Week NY. Bringing together masterminds behind the digital space, Internet Week NY covered how companies from startups to non-profits to corporations like MLB are harnessing the power of online personalities to market their brand and really integrate customers into their brand experience. Much like the internet itself (and was discussed by several panels), there was much “noise” or information to sift through. While valuable, it can be overwhelming. Thus, I wanted to provide a general guide with the most helpful info. While I’m tempted to talk about famous celebrities, Joan Rivers and Erica Oyama, I’ll save those and my favorite classes for later discussions. For now, I’ll attempt to boil down the overarching themes that wove the conference together and overlapped all of the different industries (from fashion to food to sports) taking over the digital arena. For all of the entrepreneurs, advertisers, and marketers out there, these are the key takeaways of which to make note.

Key Takeaways from Internet Week NY:

  • Humanize your brand - Social media and the internet in general allow for a more personalized customer experience. Not only that, they allow for customers to have an active involvement with your brand. People buy from people.
  • Encourage customer involvement with your brand – In other words, create experiences that involve people with your brand, such as holding contests, recognizing fans, and providing people the ability to vote on different elements of your brand. (Fun fact: People like their name and their voice. A representative from USA Mini Cooper and a panel speaker for a crowdfunding class both touched on this. USA Mini Cooper found out people liked to name their cars, so they had a contest where people could name the next Mini Cooper. The crowdfunding class found that rewards on Kickstarter projects that used those two elements, did well. For instance, if you’re trying to raise money on Kickstarter, offer donors an incentive that involves their name or voice, such as having their name in the credits of your film.) Active involvement with your brand gives customers a sense of ownership in your brand.
  • Be customer-centric – Bob Bowman from MLB said you need to be product-centric as well as customer-centric in your marketing approaches. One moment that really stuck out in my mind was when Bob Bowman emphasized that you need to be mindful and respectful of people’s time. I completely agree. In this day and age people are busy. They’re multi-tasking; they’re using multiple devices; they can choose when and if they want to listen to and interact with you; they have many activities crammed into their everyday lives. Be respectful of that, and give them quick, high-quality ways to engage with you and come back at a later time. Don’t insult your audience with low-quality, long-winded content, because that conveys to them that you don’t care about their time. Which brings me to my next point of…
  • Focus on quality over quantity – The mantra, “Content is king,” still stands. Providing valuable, quality content to your audience is still an important asset to any company. That is how you attract and keep an audience. That is how you get people to pay for your content (Andrew Sorkin). That is how you get people to find your company and interact with your brand.
  • Understand there isn’t necessarily a one-size-fits-all solution - Technology is constantly changing. The ways in which people are using technology are constantly changing. Therefore, the ways in which people interact with your brand are constantly changing. As a marketer/advertiser/entrepreneur, you need to be flexible and adapt to those changes. In order to reach your audience, you must be adept at moving along with them, at altering your content to fit with the different platforms and your different audiences’ needs.

Internet Week NY

How to Download Files Containing Special or Non-ASCII Characters in the Filename Using ASP.NET

$
0
0

Credit: http://lifehacker.com/5690522/how-to-enable-non+ascii-characters-on-linuxA couple months ago, I worked with file downloads that had filenames with non-ASCII Unicode characters, as well as special characters, such as semi-colons, commas, periods, and others (@, %, +, {, }, [, ], $, #, &, =). Here is an example of a filename that has all of those characters:  日本人 中國的 ~=[]()%+{}@;’#!$_&-  éè  ;∞¥₤€   .txt    

After a couple days of online research,  I finally found a solution that worked across different major browsers like IE8, IE9 and IE10, Firefox 21, Chrome 27, Safari 5 (on Windows). These are the most up-to-date versions as of this writing. Opera mostly works fine as well; however, I noticed that it doesn’t like the space and curly bracket characters.

Without going into detail about character encodings in the HTTP headers, I’d like to mention two major pieces of information you should know that I found regarding this issue:

1. According to the section 2.3 in RFC-2183 (Content-Disposition header field), the “filename” parameter in the Content-Disposition header can only use the US-ASCII characters.

2. However, as specified by RFC-5987 and RFC-2231, the correct encoding can be included right in the header field by using the filename* syntax and then by percent-encoding the non-ASCII characters in the filename. For example, for the filename ”test-€.txt,” the content-disposition header would look like the following:  attachment; filename*=utf-8”test-%E2%82%AC.txt. Here is the .NET code that I had for writing the response header:

Response.AddHeader(“Content-Disposition”, “attachment; filename*=utf-8”” + Server.UrlEncode(fileName);

However, when I tried that syntax with my test filename  “日本人 中國的 ~=[]()%+{}@;’#!$_&-  éè  ;∞¥₤€   .txt,” I saw that all the spaces were replaced with “+” signs in Firefox, Chrome, IE9 and IE10 (“日本人+中國的+~=[]()%+{}@;’#!$_&-++éè++;∞¥₤€+++.txt”)

In Opera, it was worse. In addition to the “+” signs, the curly brackets were removed. In IE8 and Safari, the filename didn’t even appear. In the download dialog, it displayed the name of the ASP.NET page instead (Default.aspx in my case).

After that, I tried using “Uri.EscapeDataString(fileName)” instead of Server.UrlEncode() in the code above. The results were a little bit better but still varied depending on the browser.  In Firefox, IE10 and IE9, the filename showed correctly. However, IE8 and Safari still showed the ASP.NET page and now Chrome did too. As for Opera, it was still missing the curly brackets.

After further testing, I finally came up with the following solution that worked for all popular browsers that I tested with:

var headerValue = (Request.UserAgent.ToLower().Contains(“msie”))

? string.Format(“attachment; filename=\”{0}\”", Uri.EscapeDataString(fileName))

: string.Format(“attachment; filename=\”{0}\”", fileName); //for Firefox, Chrome, Safari, Opera

Response.Clear();

Response.ContentType = “text/plain”;

Response.AddHeader(“Content-Disposition”, headerValue);

Response.TransmitFile(filePath);

Response.End();

The trick was to set the content-encoding header based on the user-agent. For IE, I percent-encoded the filename using the Uri.EscapeDataString() method.  For the other browsers, I just left the filename string as is. It turned out the other browsers (at least the most recent versions as of this writing) didn’t need to use the RFC-5987 filename* syntax.

Excel or Word file generated by OfficeWriter opens in protected view (yellow)

$
0
0

Problem

A report generated using ExcelWriter or WordWriter opens and there is a yellow warning banner saying that the file has been opened in Protected View.

Solution

Starting in Office 2010, Microsoft introduced a security feature that scans files before opening them in Excel or Word. If there is something wrong with the file format definition, it will open in Protected Mode with a red warning banner.

One of the common scenarios for opening a file in Protected View is opening the file from an unsafe location, such as the Temporary Internet Files folder. This means that if the file is streamed to an end-user, it will open in protected view.

For more information about Protected View settings in Office 2010, please refer to this Microsoft TechNet article on how to configure Protected View settings in Office 2010.

Welcome Back Privacy Concerns: Big Data, Healthcare, and PRISM

$
0
0

Photo Credit: Mashable.com

I suppose I shouldn’t say, “Welcome back, privacy concerns,” as I’m sure they never left, just quietly assumed their position humming in the background and shadows of the internet noise. This week, however, they took center stage both in the healthcare space and in government news.

This week, The New York Times published an article on a significant announcement for the healthcare industry. A group of global partners spanning 41 countries and including 70 medical, research and advocacy organizations agreed to share a heap of genetic data. “Their aim is to put the vast and growing trove of data on genetic variations and health into databases that would open to researchers and doctors all over the world, not just to those who created them,” The New York Times wrote. Currently, research labs and facilities are very much siloed. Each institution has their own research within their own walls and with their own records and system of operations. There is no universal method for representing and sharing genetic data, which could lead to advanced findings in cures and other health-related research.

One reason for the lack of a central system is the sheer volume of data. There is just too much information being produced by the minute. Not only that, but it is often unstructured and not of quality (meaning information was entered or gathered incorrectly/differently, such as January being entered in as Jan, 1, 01, or January, making it difficult to analyze). While volume and quality of data is an issue, the overarching problem, or rather challenge, healthcare professionals face lies mostly in the security space. With all of that sensitive patient data, there need to be strict, infallible measures to protect that information. Along those same lines is the question of who will have access to that information.

This is especially significant as it comes at the same time of privacy concerns regarding the NSA’s reported access to granular consumer data. The NSA is taking heat on a project called PRISM. PRISM is reported to be a secret government program whereby the government can access your data from certain company’s servers. And by certain company’s, I mean tech giants like Apple, Microsoft, and Facebook. What’s most concerning about this program is the type of content the government can access through it. Instead of looking at data in the aggregate or general consumer behavior patterns, PRISM allows the government to access specific content within emails, online conversations, calls, etc. President Obama maintained the government is acting within legal measures and only doing so to protect citizens. AOL, Facebook, and others reported to be involved with this government program have turned to Twitter and their other social media accounts to deny their involvement with the program. Anonymous, an advocacy hacker group, published NSA documents today, and citizens aren’t too happy about PRISM. For the average citizen, I maintain that they don’t mind if you’re watching them, just so long as you don’t point out that you’re watching.

Issues of privacy concerns around big data are not new. Who owns and has access to all of the information you are publishing/generating/recording about yourself has cropped up again and again. Not even one year ago Facebook came under fire for changing its privacy statements and settings without properly informing users. Privacy laws are confusing and questions around who owns and should have access to data, for the most part, remain vaguely addressed and unanswered. With new initiatives like PRISM and genetic data happening within healthcare and government, you can bet privacy concerns surrounding who has access to your data and how they use that information will continue to hog the spotlight.

Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.

Truth in Tech Ep. 20: The Internship

$
0
0

So you want to be a programming intern? Take it from these all-star students who’ve maneuvered the tech waters to land hands-on programming internships. They give you the inside scoop on where to look, secret interview questions, and what it’s really like at a summer internship. Listen in on itunes.

Truth in Tech E20: The InternshipTech internships have been getting a lot of play in the news and pop culture lately, but what are they actually like? Our summer interns spill the deets.

Embedly Powered


What Causes Error 1154 in WiX

$
0
0

Credit: www.joyofsetup.com

Recently, as I was working on one of our installers, I had a very strange issue crop up. This particular installer is fairly complicated, but also fairly stable.  It has many managed custom actions, and I was merely adding some functionality to it. I was testing the installer and ran into an 1154 error:

“There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run.“

That’s fine. This happens. It’s pretty common, actually.

  • Check the names in the custom action declaration.  Do they match the DLL and method name, including case?
  • Are you trying to run a 64bit DLL using a 32bit installer?
  • Are you running MakeSfxCA.exe correctly with the most recent version of the DLL and installer?
  • Does the method you’re trying to call have the correct signature?

[CustomAction]Public static ActionResult MyCustomAction(Session session){….}

In this case, my problem action was, let’s say, HereIsMyCA. I checked through all of the above items several times. Most confusing was that other custom actions from the same DLL worked just fine. One might say I was getting a bit frustrated.  Eventually, I changed the name of the action and method – ThisIsAwfulPleaseWork.

…and it did.

After some experimentation I discovered that the problem lay in the capitalization of the C# method.  HereIsMyCA was breaking, but HereIsMyCa was fine. Most other methods with similar capitalization (several capitals in a row) worked fine. I’ve had one other method break. There is no rhyme or reason to it, but I hope that I save someone some hours with my discovery.

[Webinar] Grand Slam Your SSRS Reports

$
0
0

June Webinar

Tune in next week Friday, June 28, 2013 at 1 P.M. for our June webinar as we give you another inside look at how OfficeWriter enhances SQL Server Reporting Services (SSRS), making your reports a home run. Senior Sales Engineer, Chad Evans, will walk you through using both single and multi-value parameters and formulas in SSRS. Using baseball data on players’ batting averages and salaries, this webinar is sure to impress. Don’t miss out! Seating is limited.


*Can’t attend? Register anyway, and we’ll send a copy of the slides and recording following the webinar.

Binding bordered images to GridViews

$
0
0

Here’s a neat trick: bind an image with a border to a GridView!
The first rule of web development is “nothing is as easy as it seems.” I think the second rule is something about choosing from standards? I don’t really care. The point is, this seemed like it would be too easy, but the implementation threw some curves at me. Let’s hearken back to a simpler time and begin our journey with a list of possible horrors:

  • The image object links to a physical location. It does not write BLOB objects. Friggen nothing writes BLOB objects.
  • Sometimes there are null values.
  • I need a border. This will create a little empty black square if a null is encountered.
  • What the heck is the difference between <%# and <%= again? And how the heck do I search for it? (Look here for explanation and links. Please read this. You’ll be so happy you did.)

Now we follow our hero on her continued path of – yes, hero is the male form. Don’t judge me. You don’t know – discovery. The first step is, of course, to point the Image object to an HttpHandler and pass that the ID for the data row containing the image. The handler itself is a pretty straightforward interface. There’s only one method: ProcessRequest() where you need to implement a method to grab the data from SQL. There’s also one property:  good ol’ IsReusable(). IsReusable is a boolean value that indicates whether or not the HttpHandler object can be reused. There’s a lot to take into consideration here:

  • Threading
    • If you have multiple threads accessing this at the same time you can completely screw up the state. What I’m doing is getting the query string within the process request. This is fine since the variable is local to the method it will be unique to the thread. You don’t have to stick to my code, though. If you are reusing the object, remember that any thread can, at any time, be changing a global variable.
  • End state of the handler
    • This is especially important here, since we’re using a lot of data objects, we need to make sure everything is properly disposed before the method is done executing.
  • Memory considerations
    • If IsReusable is false, then a new handler will be created for each request. This can cause performance issues if you have a lot of, say, users, accessing this, say, all at once. However, a simple httphandler doesn’t usually cause a lot of memory bloat. This is one of those application-specific things.

Whether you set IsReusable to true or false really comes down to what you need this handler to do. If you’re really uncertain, leave it at false – it will at least guarantee there are no multithreading nightmares, like in the sopranos.

So, I set my IsReusable to false. I also pass the ID rather than the image name, so I can get the image from the handler with a simple query. I took a lot of tips and some code from Pankaj Mishra’s article, and what I ended up with for ProcessRequest was roughly this:

public void ProcessRequest(HttpContext context)
    {
     //Get the query string, if you recall, it's the row ID
        string id = context.Request.QueryString["id"];

        if (!string.IsNullOrEmpty(id))
        {
            //Make that string an int!
            int ID = Convert.ToInt32(id);

            MemoryStream memoryStream = new MemoryStream();
            SqlConnection connection = new SqlConnection(ConnString);
            string sql = "SELECT image FROM MyDatabase WHERE ID = @ID";

            SqlCommand cmd = new SqlCommand(sql, connection);
            cmd.Parameters.AddWithValue("@ID", ID);
            connection.Open();

            SqlDataReader reader = cmd.ExecuteReader();
            reader.Read();

            //Get Image Data
            if (reader["image"] != DBNull.Value)
            {
      //Read up the BLOB
                byte[] file = (byte[])reader["image"];
      //Close your objects
                reader.Close();
                connection.Close();
      //Write the file and send the response
                memoryStream.Write(file, 0, file.Length);
                context.Response.Buffer = true;
                context.Response.BinaryWrite(file);
            }
            //Now get rid of the last thing
            memoryStream.Dispose();
        }
    }

The final leg of our adventure finds the hero, weary and victorious, resolving the little black box for a null value. Base the visible property on the returned byte stream being a null value. You can cast it to a string. It really doesn’t matter if you bind the image here, since we’re just looking for a null value.

Like this (I love ternary statements because a part of me still thinks FORTRAN’s 1995 standard changes are AWESOME):

Visible='<%# (Eval("image").ToString() == "")?false:true %>'

Now you set the image URL to the image handler address and concat the ID as so:

<%# “/Namespace/Page/ImgHandler.ashx?id=" + Eval("ID") %>

Now the ID gets sent to the handler on binding. Then the image URL is the handler address, which returns the picture!

And here’s the image tag altogether:

<asp:Image ID="ImageBind" runat="server" BorderStyle="Solid" BorderColor="Black"
    Visible='<%# (Eval("image").ToString() == "")?false:true %>' BorderWidth="1px"
            Width="100px" ImageUrl='<%# “/Namespace/Page/ImgHandler.ashx?id=" + Eval("ID") %>' />

And the hero and the really awesome hawk that I just now decided she has, have bound images to a GridView. You’re all welcome.

ExcelTemplate: How to format alternating row colors

$
0
0

Problem

A common way to display data in Excel is to alternate the background color of every other row when displaying a large table of data. With ExcelWriter there are multiple ways to accomplish this. This post covers some possible ways to apply alternating row colors with ExcelTemplate.

There is another post that discusses how to do this with ExcelApplication.

Solution

Option 1: Format as Table in Excel 2007/2010

Starting in Excel 2007, Excel provides pre-formatted table styles which already contain alternating row or column colors. This is the easiest way to format your data with alternating row colors. Note: these table styles may not render properly in Excel 2003 or in the XLS file format.

To format an area of cells as a table:

1. Highlight the area of cells.

2. Go to Format as Table in the ribbon.

3. Select a table style from the available styles.

4. If you chose to include your table header row, make sure to check off “My table has headers” in the confirmation dialog.

There are basic options for modifying the banding patterns:

You can also create new table styles:

You can do this for ExcelTemplate templates:

When the rows of data are inserted, the color banding will be applied:

Option 2: Use Conditional Formatting

The other approach is to use conditional formatting in the template to achieve alternating row colors. This may be more appropriate if you are not certain if your end-users will have Excel 2007/2010.

1. Create an ExcelWriter template with data markers in Excel.

2. Highlight the cells with data markers that correspond to the data you wish to display with alternating background colors.

3. From the menu, choose Format>Conditional Formatting. The formatting you define for this row will be applied to every new row that will be inserted by ExcelTemplate at runtime.

4. First define the formatting for even rows. In the “Condition1″ field, choose “Formula Is” and in the formula field, type the following formula:

 =MOD(ROW(),2) = 0 

This formula uses the MOD( ) function to determine if the number of the current row (returned by the ROW( ) function) can be evenly divided by 2.

5. Click on the “format” button.

6. Click on the “patterns” tab and select a background color.

7. Now set a condition for odd rows, by clicking “ADD” and following the same steps as above but with a different formula:

 =MOD(ROW(),2) = 1 

8. Save the template and use it in your ExcelWriter application.

When ExcelTemplate imports new rows of data, the conditional formatting will also be applied to all the new rows:

How to create a custom SQL Server Reporting Services error page

$
0
0

Problem

When SQL Server Reporting Services (SSRS) encounters an error, it returns an error message which is displayed by Report Manager. The error message can include technical details that reveal more information than necessary or are potentially confusing or intimidating to a user. One example is the scenario in which the user attempts to export a report from Report Manager using the “Excel designed by OfficeWriter” option, but the report is not created using the OfficeWriter Designer. In this case, SSRS would return the following error:

 Error SA008050: This report was not designed for the selected OfficeWriter rendering extension. 

Depending on configuration, Report Manager may also display a detailed error message and a stack trace. In this case, the error message is self-explanatory. However, often it is desirable to provide a friendly custom error page that hides the technical details of the internal exception and provides more helpful instructions to users.

Configuring a custom error page for Report Manager is no different from doing so for other ASP.NET applications. The custom error page is simply a web page that you create. You can configure ASP.NET to display a custom error page to all users. Alternatively, the custom error page can be displayed only to users accessing Report Manager from a remote machine, which is usually the case in production. For users accessing Report Manager from the same machine, the full error would be displayed. Typically, a detailed error message is helpful for debugging purpose during development.

Additionally, you can configure a custom error page to be displayed for specific HTTP status codes. For example, the OfficeWriter error above is an internal server error, which results in HTTP status code 500.

Solution

To configure a custom error page for Report Manager:

  1. Browse to Report Manager folder.
    • For SSRS 2005, its typical location is DRIVE:\Program Files\Microsoft SQL Server\MSSQL.x\Reporting Services\ReportManager, where x is the instance
    • For SSRS 2008 and SSRS 2008 R2, DRIVE:\Program Files\Microsoft SQL Server\MSRS10.SSRS\Reporting Services\ReportManager .
  2. Make a copy of the existing Web.config as backup
  3. Open Web.config in a text editor, or in Visual Studio to get Intellisense support
  4. Under the section, locate the `1 section
  5. Modify the existing section, or insert a new one, with the appropriate settings
  6. Restart the Report Server

The possible values for the mode attribute of the tag are Off, On, and RemoteOnly. The default is Off. In order to enable a custom error page, mode must be set to On or RemoteOnly. For example, the below section specifies the following: 1) a custom error page be displayed for remote users only, 2) a specific page for HTTP status code 500, and 3) a default page for all other HTTP status codes. Note that attributes are case-sensitive.

Summer 2013 Interns

$
0
0

Our favorite time of year is upon us. It’s summertime, and that means kayaking down the Charles, BBQ’s in the parking lot, and best of all summer interns. We’re handing over the blogging reins to this talented crew. Each week follow along as they give you an inside look at SoftArtisans and Riparian Data, life as an intern at a start up, and any other random musings that pop into their heads. They’ve already taken over with their podcast. Listen in on itunes!

Summer 2013 Interns

(Top row: Kyle, Justin, Daniel, Front row: Madalyn, Alex, Shane)

The questions:
1. Where do you go to school?
2. What do you study?
3. Give us a unique/random fact of your choosing.

The answers:

Kyle:

1. Olin College of Engineering.
2. Software Engineering and Applied Mathematics.
3. A random fact about me is that I am the music director of Olin’s premier a cappella group, the PowerChords.

Justin:

1. Rochester Institute of Technology
2. Game Design
3. The average color of the universe is known as Cosmic Latte.  (If it was actually supposed to be about me, then… uh… on good days, I could see Canada from the house where I grew up?)

Daniel:

1. Gann Academy

Madalyn:

1. I go to Worcester Polytechnic Institute (WPI)
2. I study Computer Science and Digital Art.
3. The longest (documented) that a person has ever lived was to the age of 124 years.

Shane: 

1. Olin College of Engineering
2. I’m currently an Electrical and Computer Engineering major, but that could easily be Robotics Engineering within a few months.
3. Over the past three years, I have gone to my favorite dining establishment, Ihop, with 42 different people.

Alex:

1. Oberlin College
2. Computer Science
3. Random Fact: I took a contemporary dance class last semester, and it was awesome.

Questions for the new crew? Email us at elisek@softartisans.com or leave your thoughts in the comments section.

The Intern Diaries: Alex

$
0
0

interns_alexThis is the first installment of our Intern Diaries series, wherein each week our lovely interns give you the inside scoop on what being a programming intern at a high-tech startup is really like. This week Alex walks you through first impressions of his internship.

Hello, my name is Alex, and I am a sophomore at Oberlin College. I have been interning at SoftArtisans for a little over a month and am happy to report that my expectations have already been exceeded. I do real work, get to code, and have learned about the different parts of a software company.

Before arriving at SoftArtisans I didn’t have any warm and fuzzy feelings associated with offices. My dad works at a big law firm in Boston and over the years, my visits have shaped my perception of the work world. His office is a sterile and quiet place. The walls are white and the floors are so clean that I almost feel funny walking in with my sneakers on. However, after entering and sensing the atmosphere, it is evident shoes are not to be removed.

This leads me to why I love being at SoftArtisans. Sure it’s great to walk around barefoot and wear casual clothing, but more than that, it is all the other reasons that I feel comfortable at work.

I am a technical support intern and every day the Technical Services (TS) department does something called Stand-Up. During Stand-Up the team circles up and takes turns saying what they are working on. In addition to keeping the team organized, Stand-Up is a great opportunity to voice any concerns or ask for help.

In one of my first Stand-Ups, everyone seemed like they had a million things to do and that it would be best if I worked independently. To my pleasant surprise, our meeting ended and everyone told me that even if chaos strikes and people seem busy, I should not hesitate to ask questions.

Asking questions is a key part of my learning style and one of the reasons why I have been able to progress so much. It was extremely reassuring to hear that questions were expected and that my bosses and coworkers were happy to offer me guidance.

Just recently I asked if I could attend the OfficeWriter stakeholder’s meeting. This meeting was not on my schedule but it looked interesting.  My boss said yes and now I have a recurring stakeholder’s invite. The meeting doesn’t directly help me with my assignments, but it has been awesome to learn more about the company and see how management, development, support, and sales make joint strategic decisions.


How to create a drill-down report in Excel with hyperlinks

$
0
0

Problem

Reporting Services provides drill-down report behavior, where clicking on a populated data field generates another report based on the value of the data field clicked. This post addresses how to acheive similar behavior within Excel with OfficeWriter using Reporting Sevices URL access and Excel’s HYPERLINK function.

Solution

Overview

When the OfficeWriter renderer populates the Excel report with data, it inserts new rows for each row of data. This means that all Excel formulas are updated, including the HYPERLINK function formula. This approach uses this formula update functionality and imported data values to dynamically create hyperlinks that point to the Reporting Services URLs.

For the sake of example, “SalesReport” is the original report that contains a list of invoice IDs. “InvoiceReport” is the linked report that takes an InvoiceID as a parameter.

Reporting Services URL Access

Typically, Reporting Service reports are rendered through an application, such as the Report Manager. Reporting Services also allows for rendering reports using just URLs. The basic syntax to render a report wtith a parameter is:

 http://[servername]/reportserver?/[File path to report on Report Server] &rs:Command=Render&rs:Format=[Rendering Format]&[ParamID]=[Param Value] 

The URL for rendering the “InvoiceReport” in the OfficeWriter for Excel format, with Invoice ID 12345, is as follows:

 http://myservername/reportserver?/ InvoiceReport&rs:Command=Render&rs:Format=XLTemplate&InvoiceID=12345 

Notes:

  • The rendering extension for OfficeWriter for Excel is “XLTemplate.”
  • For more information about SSRS URL access, read this MSDN article.

HYPERLINK function in Excel

The HYPERLINK function in Excel has two parameters: URL and display text. In this example, the URL will be the Reporting Services URL and the display text will be the invoice number.

  1. Open “SalesReport” with the OfficeWriter Designer in Excel
  2. Create a hidden column that will contain the invoice IDs, which will be referenced in the hyperlink. Put the data marker for the invoice ID in this column, for now, let the cell that data marker resides in be A5.
  3. To create a hyperlink for each linked report, the invoice ID in the Reporting Services URL has to be hardcoded for each separate report URL. CONCATENATE will be used to combine the first part of the Reporting Services URL, which is the same for all the reports, with the specific invoice IDs, which are in the hidden column. This concatenated URL will be used to create the hyperlink.
  4. In the column that will actually display the links, in the same row as the invoice ID data marker, use the HYPERLINK formula.

Example of formula that would appear in B5:

 =HYPERLINK(CONCATENTATE("http://myservername/reportserver?/ InvoiceReport&rs:Command=Render&rs:Format=XLTemplate&InvoiceID=", A5), A5) 

This will create a hyperlink that, when clicked, will make a call to the Report Server to render “InvoiceReport” with the invoice ID value from A5. The report will be streamed back to the client in a new instance of Excel.

How to prevent line breaks after an empty merge field

$
0
0

Problem

When you use the WordTemplate object to populate a WordWriter template document with data retrieved from a data source, you may have situations in which a merge field is not bound to a value. The most common scenario is creating a mailing address. Each field of a mailing address may be represented by a merge field. Typically, the second line of the address is optional. In the generated document, if the merge field corresponding to the second line of the address does not have a value, a blank line may be present.

In Microsoft Word, a blank line generated during a mail merge can be suppressed using application settings. With WordWriter, a blank line is not automatically removed.

WordWriter template document:

Generated document:

Solution

The following discussion uses a merge field called AddressLine2 as an example, but is applicable to any field with optional value.

In the WordWriter template document, if the line break is separate from the AddressLine2 merge field, the line break will be present in the generated document whether or not there is a value for AddressLine2.

In order to prevent a line break if AddressLine2 is not present, do not put a line break after the AddressLine2 merge field in the WordWriter template document. Instead, insert the line break only when the AddressLine2 is present. To do so, perform the following steps in Microsoft Word:

1. Remove the line break, if any, after the AddressLine2 merge field

2. In the WordWriter template document, insert a line break within the AddressLine2 data marker itself:

  • Right-click on the AddressLine2 merge field
  • Select Toggle Field Codes
  • After the merge field name, enter \f, followed by a space, then press Enter to get a new line
  • If the merge field contains a * MERGEFORMAT string (i.e., the “Preserve formatting during updates” option is enabled), insert a space before it

3. You should see the following:

 { MERGEFIELD Address_Line_2 \f \* MERGEFORMAT } 

4. If you select “View Paragraph marks” (Tools, Options, View, Paragraph marks), you should see a paragraph mark (¶) in the field code as follows:

Each dot represents a space. Note that there is a space between each part of the merge field.

5. As a final check, if you right-click on the AddressLine2 merge field, then select Edit field, the “Text to be inserted after” option should be checked

After you follow the above steps, the address in the generated document should no longer contain a blank line, as shown in the below image:

The Intern Diaries: Shane – I’ve Made a Huge Mistake

$
0
0

When I chose Riparian Data, I had no idea what I was getting into. I showed up to my first day excited to organize filing cabinets and get print outs. I can get a mean cup of coffee or drop something off at the post office in under 2 minutes. Much to my dismay, there were no filing cabinets, and developers got their own coffee. I didn’t even realize we had a printer for the first four weeks. Instead the team expected me to write code. Not just any code, though, they wanted me to write actual code for the app. I realized they were a little confused and tried to explain to them that I was an intern. They just didn’t get it and kept trying to give me real work, as if they actually expected me to provide productive contributions.

After talking to a few friends, I realized how unlucky I was. One has to play with the company’s app all day everyday without ever seeing the code. Another does have to work on code, but, not to worry, it will never actually touch his company’s product (phew!). I need to acknowledge, though, that it could be so much worse. One friend has been tasked with creating an entire web application for his company. Not only must he code, but he must design and plan an application for actual use. Dreadful, I know.

Really, though, internships are pretty sweet. I get 2 months to check out a company and work with their full time devs on a real product. I’m expected to jump right in and learn as I go. I came in with zero iOS experience and was supposed to spend my first few days simply learning Objective C and Xcode (the IDE for Apple Apps). Over the past month, I’ve worked on everything from finding the best way of connecting the server to our database to localizing our app so it could potentially be translated into other languages.

For college kids like me, internships are like the 90-Day Money Back Guarantees of the working world. We get the chance to jump into a company and see it from the inside. It is about more than just getting to do “real world” code. It also gives us a glimpse into how companies really function and what type of company matches our personality. Some of my friends loved the idea of working at a huge company with products that play a part of our everyday life, so they went to Facebook or Google. A few others were interested in the startup culture, so they found tiny startups to work for.

With my friends working all over the place, I’ve been asking them about their experiences and teams. For this post, I decided to send out a little survey to get a little bit of a bigger picture on my friend’s internships. I received about 60 responses, mostly from Olin students. Here are the questions along with the most common answer:

  • What type of internship is it? Computer Engineering/Software
  • Given the chance, would you return to this company? Yes
  • On a scale from 1-10, how much responsibility are you given compared to a full-time employee? 7.317
  • Was this internship your first choice? Yes
  • What class are you in? 2015
  • How large is the company? 15-50 People or 1000+ People

I found a few interesting stats when I started to punch the numbers.

  • Interns at software internships were given the most responsibilities, while interns at Mechanical Engineering internships were given the least.
  • Interns at their first choice internship were given significantly more responsibility than other interns.
  • As the graph shows, interns at mid-size companies are the most likely to return.
  • As the two pie charts show, interns have a much higher chance of returning to their company if it was their first choice.

As much as I’d love to keep playing with the data, my team has just given me more code to write. Ugghhh this is the worst :-).


Shane
About

Shane is a second-time around intern with our partner company Riparian Data. This is the second installment of our Intern Diaries series, wherein each week our lovely interns give you the inside scoop on what being a programming intern at a high-tech startup is really like. Read the first post or listen to this group’s first podcast.

How to create stock charts using ExcelApplication

$
0
0

Problem

You need to create stock charts like the High-Low-Close or candlestick charts that Excel provides, but ExcelApplication does not have an enumeration for these charts.

Solution

Introduction to Stock Charts

Excel can create four kinds of charts intended for analyzing stock data. These are often referred to as high-low-close or candlestick charts because of their distinctive shape. These charts can be easily created with the Chart Wizard in Excel.

It is possible to use these charts with ExcelTemplate as you would any other chart. While ExcelApplication contains enumerations for many kinds of charts it does not have one for stock charts. Because of this, they cannot be created directly. In this article I’ll explain how to use a line chart and some special formatting to create charts that look exactly like each type of stock chart provided by Excel.

Setting up the data

Stock charts require very specific data in a very specific order. If you look at the names of the charts in Excel, you’ll note that each of them is actually a list of the data that chart needs, in the order that chart needs it. The four kinds of charts are High-Low-Close, High-Low-Open-Close, Volume-High-Low-Close and Volume-High-Low-Open-Close. As you can see, there is significant overlap and the data always appears in the same order; only the presence or absence of Volume and Open Data is different. For all of the following examples, we’ll use the same data pictured below:

For simplicity, we’ll create areas for each section of data and name them volumeAreaopenAreahighArealowArea and closeArea. Now that we have that, we can start creating stock charts.

A Basic High-Low-Close Chart

The simplest chart to create is a High-Low-Close chart. This chart displays the high and low values for a stock as a vertical line, with a tick mark at the point where the stock closed for the day. To begin creating this chart, we’ll follow a formula that will remain the same for all of the other stock charts.

First, createLine.StandardLine chart. Anchor it wherever you like, then add the series you want for this chart. It is very important that you add the series to the chart in the same order that they are listed in the chart name. In this case, that means that first we create the high series, then the low one, then the close one. From this point on the steps to create each chart will be similar, and contain significant overlap, but just different enough that we should take them one at a time.

To create the high/low lines, set ShowHighLowLines to true in one of the Series from this chart. Then, to create the tick marks showing the close values, set the ShapeType of the close series DataPointMarkers to DowJones, and set their ForegroundColor to black.

Finally, remove all the visual elements of a regular line chart that we don’t want. Running the code below will produce the chart just below that. To make the screenshots small enough to fit on the page I took the liberty of resizing the charts with the Chart.Width and Chart.Height properties. This code is not shown, and does not effect the fundamentals of the chart.

// This anchor will put the chart just to the right of the data shown above.
Anchor a = ws.CreateAnchor(0, 7, 0, 0);
Chart c = ws.Charts.CreateChart(ChartType.Line.StandardLine, a);


// Create the series *in the same order* as they're listed
// in the name of the chart
Series high = c.SeriesCollection.CreateSeries(highArea);
Series low = c.SeriesCollection.CreateSeries(lowArea);
Series close = c.SeriesCollection.CreateSeries(closeArea);


// Set the name of each series so the legend shows correctly.
high.Name = "High";
low.Name = "Low";
close.Name = "Close";


// This adds the vertical lines
high.SettingsLineAreaScatter.ShowHighLowLines = true;


// This adds the little horizontal markers
close.DataPointMarker.MarkerType = DataPointMarker.ShapeType.DowJones;
close.DataPointMarker.ForegroundColor = Color.SystemColor.Black;


// This makes all the extra stuff in a line chart
invisible high.Line.Visible = false;
high.DataPointMarker.Visible = false;
low.Line.Visible = false;
low.DataPointMarker.Visible = false;
close.Line.Visible = false;

Creating Up/Down Bars for Fun and Profit: Open-High-Low-Close Charts

The next most complicated type of chart is the Open-High-Low-Close chart. This chart replaces the single tick mark of the High-Low-Close chart with a bar showing the difference between opening and closing prices of a stock. If the stock closed higher than it opened, this bar will be white. If it closed lower, black.

Making this chart is so similar to making the previous one that it will actually be easier to just highlight the differences between them. The first is that we create an extra series at the beginning, the high series. Note that we create it first, since it appears first in the name of the chart.

The next difference is that in addition to setting ShowHighLowLines to true, we also set ShowUpDownBars to create the boxes. Since we don’t want the tick marks on this chart, we don’t change the MarkerType of the close series, and in fact set its DataPointMarkers to be invisible along with the rest of the series. Here is the code to produce a Open-High-Low-Close chart, with the changes from the last section:

// Add the new 'open' series as well as the three from before.
// Note that we create them in the same order they appear in the chart title
Series open = c.SeriesCollection.CreateSeries(openArea);
Series high = c.SeriesCollection.CreateSeries(highArea);
Series low = c.SeriesCollection.CreateSeries(lowArea);
Series close = c.SeriesCollection.CreateSeries(closeArea);


// Name the series so they show up in the legend.
open.Name = "Open";
high.Name = "High";
low.Name = "Low";
close.Name = "Close";


// This adds the vertical lines and boxes
high.SettingsLineAreaScatter.ShowHighLowLines = true;
high.SettingsLineAreaScatter.ShowUpDownBars = true;


// The data marker for the close series will be invisible, so we don't do
// anything to it
// Make all the extra bits of a line chart invisible, including the new
// open series, and the close data markers.
open.Line.Visible = false;
open.DataPointMarker.Visible = false;
high.Line.Visible = false;
high.DataPointMarker.Visible = false;
low.Line.Visible = false;
low.DataPointMarker.Visible = false;
close.Line.Visible = false;
close.DataPointMarker.Visible = false;

Adding a Second Axis: Volume-High-Low-Close Charts

This next brand of stock chart adds a significant wrinkle to the mix: volume data. Volume data measures the amount of stock sold, and as such needs to be plotted on a different axis than the price data. For the reason behind this, look at the sample data we’re using: the volume in a given row is often well over 100,000 while the prices are less than 100. Trying to plot data separated by four orders of magnitude on the same axis would force the price data down along the bottom making it unreadable.

The second trick with volume data is that it needs to be represented as a column, but the base type of our chart is Line.StandardLine. Fortunately, ExcelWriter supports creating and modifying combination charts.

This technique is very similar to the first chart we made. In fact, the only differences are that when we create the series we explicitly set their types and axes, and we hide the secondary category axis. By setting the AxisType and ChartType of the series we put the volume data on the primary axis and the price data on the secondary axis, just like the stock charts Excel makes.


// The type of the chart (and thus the default type of all its
// series is Line.StandardLine. To set the volume series to be a column chart,
// we need to pass that option to its constructor.
// Similarly, the default axis of all series is the primary one. To change
// the price data to be on the secondary axis, we need to pass
// that option to the constructor.
// As always, the series are added to chart in the order of the chart name.
Series volume = c.SeriesCollection.CreateSeries(volumeArea, ChartType.Column.Clustered, AxisType.Primary);
Series high = c.SeriesCollection.CreateSeries(highArea, ChartType.Line.StandardLine, AxisType.Secondary);
Series low = c.SeriesCollection.CreateSeries(lowArea, ChartType.Line.StandardLine, AxisType.Secondary);
Series close = c.SeriesCollection.CreateSeries(closeArea, ChartType.Line.StandardLine, AxisType.Secondary);


// Name the series so they show up in the legend properly.
volume.Name = "Volume";
high.Name = "High";
low.Name = "Low";
close.Name = "Close";


// The SecondaryCategoryAxis gets automatically made visible when we
// create a series with an AxisType of Secondary, but we don't want
// to see it, so we turn it off.
c.SecondaryCategoryAxis.Visible = false;


// Create the vertical lines
high.SettingsLineAreaScatter.ShowHighLowLines = true;


// Create the tick marks to show the closing value
close.DataPointMarker.MarkerType = DataPointMarker.ShapeType.DowJones;
close.DataPointMarker.ForegroundColor = Color.SystemColor.Black;


// Remove the cruft left over from the line chart.
high.Line.Visible = false;
high.DataPointMarker.Visible = false;
low.Line.Visible = false;
low.DataPointMarker.Visible = false;
close.Line.Visible = false;

This chart is the one most commonly referred to as a candlestick chart, because of the way the columns resemble the base of a candle, and the high/low lines coming out the top wicks (especially column eight). Note that the color of the volume columns may be different from the default color of volume columns in Excel Volume-High-Low-Close charts. If you’d rather have the default (or any other) color, simply change the Interior.ForegroundColor property of the volume series to whatever you’d like.

The Kitchen Sink: Volume-Open-High-Low-Close Charts

The final kind of stock chart that Excel has combines all the data we have and all the techniques we’ve used to far to create a truly impressive piece of data visualization: the Volume-Open-High-Low-Close chart. Having come this far, this is almost the easiest chart to create. There is only one line of code that we haven’t seen before. This chart contains up/down bars on top of columns, and if we leave the up/down bars at their default width this will look awkward. Excel’s solution is to increase the width of the up/down bars so that they are just slightly wider than the columns. The way to do this (in both Excel and ExcelWriter) is to decrease the space between the up/down bars, called the “gap width”.


// Create all five series in the correct order. Also make
// the volume data be columns on the left axis, while the price
// data goes on the right axis.
Series volume = c.SeriesCollection.CreateSeries(volumeArea, ChartType.Column.Clustered, AxisType.Primary);
Series open = c.SeriesCollection.CreateSeries(openArea, ChartType.Line.StandardLine, AxisType.Secondary);
Series high = c.SeriesCollection.CreateSeries(highArea, ChartType.Line.StandardLine, AxisType.Secondary);
Series low = c.SeriesCollection.CreateSeries(lowArea, ChartType.Line.StandardLine, AxisType.Secondary);
Series close = c.SeriesCollection.CreateSeries(closeArea, ChartType.Line.StandardLine, AxisType.Secondary);


// Name all the series so that the legend shows them properly.
volume.Name = "Volume";
open.Name = "Open";
high.Name = "High";
low.Name = "Low";
close.Name = "Close";


// Hide the top axis.
c.SecondaryCategoryAxis.Visible = false;


// Create the vertical lines and boxes, and make the boxes slightly wider
// than the volume columns.
high.SettingsLineAreaScatter.ShowHighLowLines = true;
high.SettingsLineAreaScatter.ShowUpDownBars = true;
high.SettingsLineAreaScatter.UpDownBar.GapBetweenBars = 100;


// Remove all the cruft left over from the line chart.
open.DataPointMarker.Visible = false;
open.Line.Visible = false;
high.DataPointMarker.Visible = false;
high.Line.Visible = false;
low.DataPointMarker.Visible = false;
low.Line.Visible = false;
close.DataPointMarker.Visible = false;
close.Line.Visible = false;

And there it is. That’s everything you need to know about modifying line charts to create stock charts in ExcelWriter. These charts can now be modified with ExcelApplication just like you would any other chart.

Baseball’s All-Star Break: Predicting the Game Using Excel

$
0
0
Major League Baseball

Credit: Ampsportsduo.blogspot.com

In keeping with my sports theme from March, on March Madness and predicting the NCAA tournament, it is time to look at this season’s sport: Baseball. As you might know, Major League Baseball’s All-Star game is tonight, so let’s use Excel to pick which league (the AL or NL) will be victorious, so we can kick back and enjoy the game.

Baseball has long been associated with using stats to predict outcomes and player performances. This was made famous in the movie Moneyball, and has its own cottage industry around helping fantasy baseball players perform better. There is no shortage of information that can be gathered about baseball, with the whole industry even having deemed the term: sabermetrics.

Before jumping into the vastness of data, however, I want to point out where we are getting the data from. There are many different sources for baseball stats, many requiring a fee, but I will be referring to the Sean Lahman Baseball Stats Database. It is open source, so you can just download a version that works for you, and run with it. I am only going to look at the players who have actually appeared in the All-Star game and their year’s performance.

The other source of data is the year-to-date stats for the All-Star players. These can be gathered from the many, many sports sites (like ESPN.com), but is a manual process. I will leave it as an exercise for the reader to copy and paste those! You can find the sum of those in the example file attached.

Just to simplify things, we are going to use the old standbys: Earned Run Averages (ERA) and Batting Averages (BA) to compare the two Major League Baseball leagues. The other consideration is to analyze data from just the “Long Ball Era,” which started in 1994. Since the sport has been around so very long, it helps to categorize the data so you get a better apples-to-apples comparison.

The first step is to get the data into your database. I used the Access file download, since SQL Server 2008 R2 can import that directly, and you don’t have to do any of the conversions. The data is also available in CSV and MySQL format. Now that we have a nice almost relational database, all we need are a couple of SQL statements to get the data for our processing needs. (They have been attached for reference.)

On to building our Excel workbook. My completed version is attached. First, we will deal with the Pitching calculation. The method to calculate the ERA is (# of Earned Runs) / (# of Outs Pitched * 3 Outs per Inning * 9 Innings per Game). This is done for each league. Batting works very similarly, but the calculation needed is for Batting Average, which is (# of Hits) / (# of At Bats).

Before we continue, there are two items we need to address. First, we need a way to represent the outcome of the All-Star game. This can be done using positives for the American League (AL) winning, negatives for the National League (NL) winning, and zero for ties. Second, we need to compare the ERAs and BAs. I like to use a simple differential. So take (AL – NL) for the relevant metric.

Next, format them nicely and we have a working model of the data. Then we can start to see some patterns to help us predict the outcome.
AllstarGameComparisonCharts

Next, we tie the information about 2013 that we gathered earlier together with the working data model. If you added them to the database, you can do a UNION with the queries I have provided. Otherwise, just add the totals to the data above, and expand the charts and you get:
AllstarGamePredictionChart

The prediction. The trend is that the NL has improved its pitching relative to the AL with the current crop of NL All-Stars and their performance-to-date as compared to their counterparts in the AL. Prediction: NL will be victorious.

Download the final Excel file here: All-Star 2013 Excel File

If you want to see how I automate this using SQL Server Reporting Services (SSRS) and OfficeWriter, check out the webinar on July 26th, where I will go through step-by-step how I put this together.




// ]]>

Viewing all 140 articles
Browse latest View live