Archive for the ‘Excel 2011’ Category
Excel PowerPivot & DAX
I’ve worked with every release of Microsoft Excel, and I know it takes effort to keep up to date with certain releases. Clearly, the Data Analysis eXpression (DAX) Language introduced in Excel 2010 went unnoticed by many, which was sad. DAX is truly a powerful extension to the analytical and modeling approaches in Microsoft Excel.
I’d like to recommend Microsoft Excel 2013 Building Data Models with PowerPivot to those who haven’t learned how to use DAX in Excel 2010, 2011, or 2013. DAX works with tables but if you don’t use tables, I guess you can skip DAX because you must have infinite time to produce marginal analytical outcomes (tongue in cheek humor). However, if you’re like most folks, you want a book to get you up-to-speed quickly, and that’s what this book will do for you.
Just one caveat if you’re using an Oracle or MySQL database, use the prepackaged analytic functions before you download the data set. You should always pre-select data before applying analytics in Excel. Remember the more refined the data model you start with the easier it is to structure analytical tools to leverage the data model. While DAX is powerful, it doesn’t replace the speed and query optimized behaviors of effective Oracle or MySQL queries.
Excel: Navigate a range
Somebody posted a comment on my Excel UDF Tutorial, and on reflection it appears he’d like to navigate a range in VBA. While I don’t see a purpose in that because it duplicates either the VLOOKUP
or HLOOKUP
function (depending on whether you’re navigating a column or row).
Anyway, here’s how you’d do it in VBA:
Function Finding(lookupWord As String, lookupRange As Range, lookupColumn As Integer) As Integer ' Define variables. Dim lookupIndex As Integer Dim lookupMax As Integer Dim returnValue As Integer ' Assign values to variables. lookupIndex = 1 lookupMax = lookupRange.Rows.Count returnValue = 1 ' Print starting and ending index values. MsgBox ("[" + CStr(lookupIndex) + "][" + CStr(lookupMax) + "]") ' Loop until found, but exit when not found. Do Until lookupRange.Cells(lookupIndex, 1).Value = lookupWord ' Print diagnostic value to determine what's evaluated. MsgBox ("[" + CStr(lookupIndex) + "] [" + CStr(lookupRange.Cells(lookupIndex, 1).Value) + "]") ' Fail safe exit when no matching value is found. If lookupIndex = (lookupMax + 1) Then ' Assign a 0 (zero) as a false return flag value. returnValue = 0 Exit Do End If ' Increment counting index value. lookupIndex = lookupIndex + 1 Loop 'Return a 1 when the value is found and zero when it isn't. Finding = returnValue End Function |
I only chose a DO UNTIL
loop because that was in the comment. It would be more appropriate to, from my perspective, use a FOR
range loop, like this:
For lookupIndex = 1 To lookupMax ' Loop contents. Next lookupIndex |
Hope this helps.
Excel: How-to-use SUMIF
Debbie asked a question about why a comparison wasn’t working in the Microsoft Excel SUMIF
function when the initial array value was empty. This post answers that question.
The SUMIF
function takes a lookup range, which anticipates a one column with a lookup value and another column with a value. The SUMIFS
function works along the same line but accepts multiple lookups against a series of lookup list columns.
This shows a simple model of the SUMIF
function:
The formula in cell G3
is:
=SUMIF(B$3:B$5,"<"&$E$3,C$3:C$5) |
If you left off the $ symbol and made the comparison "<"&E3
, you could add the sums for any number of values that are less than a value in the same row (or counting index with named ranges). You could also make the inequality symbol a parameter with this modified formula:
=SUMIF(B$3:B$5,$E$5&$E$3,C$3:C$5) |
Now, your analysis model lets you choose whether you want to look for the sum greater than or less than a specific number in the lookup range. Named ranges compare index values between the lookup range and comparison range values, which allows them to be in different rows or spreadsheets. The only problem is that the label has an inverted inequality sign. You can fix that by constantly editing the description or by simply replace the text of the label with a dynamic text string, like this:
=CONCATENATE("Comparison """,$E$5,""" Value") |
After applying the fix to the label, it looks like:
When the lookup column contains all nulls, the same formula returns a zero, as shown in the illustration.
You'll also get an error flag, unless you unchecked the Flag formulas that refer to empty cells in the error checking options. The IFERROR
function can't be used to suppress this type of error.
Why doesn't the error return a null value? That's because an equality operator compares values in the array against a static or dynamic lookup value. While equality operators don't implicit cast values for comparison, they also don't compare null values. Only the ISBLANK
function lets you find an empty cell and it can't be used inside a SUMIF
function call.
Excel AVERAGEIFS Limit
Somebody asked how to solve a problem with the =AVERAGEIFS
function and non-contiguous ranges. The solution requires a combination that uses a group of =SUMIFS
function divided by an equivalent group of =COUNTIFS
functions.
The following illustration shows the problem. It has groups of quarters, and within the quarter groups rows hold products and columns hold weeks. Unfortunately, the =AVERAGEIFS
function disallows non-continguous source ranges. It does support multiple criteria, which may be non-contiguous ranges provided they match the number of elements in the source range.
While the sums can be calculated by adding the Total column, the average can’t. You would use the following to calculate the actual average:
=IFERROR(((SUMIFS(D5:P5,D5:P5,">0")+SUMIFS(D18:P18,D18:P18,">0")+SUMIFS(D31:P31,D31:P31,">0")+SUMIFS(D44:P44,D44:P44,">0"))/(COUNTIFS(D5:P5,">0") + COUNTIFS(D18:P18,">0") + COUNTIFS(D31:P31,">0") + COUNTIFS(D44:P44,">0"))),0) |
The resolution adds a set of range sums and divides it by an equivalent set of range counts where both values are greater than zero. An =IFERROR
function substitutes a zero in the event that the denominator is zero. This last step ensures that the an empty set of cells won’t raise an exception.
I know it helps the person who asks but hope it helps others too.
Excel-Oracle ODBC Driver
Somebody was trying to query Oracle via Microsoft Excel 2007, and didn’t have an Oracle ODBC Data Source that enable them to choose Oracle. I’d referred them to this post on adding MySQL’s ODBC driver to Windows 7 but that didn’t help enough. Posting this screen shot may not have helped either.
It appears I assumed too, like everyone would know that it’s on Windows 7 when Oracle 11g (or another Oracle database) is installed locally. The person who posed the question doesn’t have Oracle installed locally and can’t install it.
For those who don’t have an Oracle instance running locally, you can download the Oracle Data Access Components for Windows from the Oracle web site. It’s in the driver sections, as shown in the screen capture below:
This driver contains the necessary OLE DB and ODBC drivers, as you can see in this screen shot.
Once you’ve downloaded it, you can return to this post where you set up an Excel query against a remote Oracle database. You should take note that Microsoft’s future direction adopts Oracle ODBC, like the approach they’ve chosen with MySQL’s ODBC driver. As always, I hope this helps.
Add Image Comment – VBA
Quite some time ago, summer 2008, I wrote a post about how you could embed an image in a cell comment. It was for the then current version of the product – Excel 2007. Here’s a User-Defined Function (UDF) in VBA to perform that trick that works in Excel 2010/2011. A comment on that older post fed my disappointment that Excel 2011 doesn’t even support the navigation but it does perform it with VBA. This includes the UDF to add an image and an ordinary Excel Macro to remove the image when you want to preserve the text.
Let’s assume you have a list of image files in a directory and that you’ve entered their fully qualified or absolute path values column B
of your worksheet. Now you want to load them as comment images in Column A
and insert a value in each column A
cell that describes the comment image.
Unfortunately, as I’ve explained before you can’t assign the image as a property of the cell (or more precisely, I’ve never found a way to do it). If this is wrong, please post the magic here for all to enjoy without a fee or registration. 😉
The following UDF takes a string value to describe the image and a cell reference that holds a string value that holds an absolute file name, which is a logical drive letter (C:\
), a file path, and file name.
Function InsertCommentImage(title As String, cellAddress As Range) Dim commentBox As comment ' Clear any comments before attempting to add them. Application.ActiveCell.ClearComments ' Define the comment as a local variable and assign the file name from the ' cellAddress input parameter to the comment of a cell. Set commentBox = Application.ActiveCell.AddComment With commentBox .Text Text:="" With .Shape .Fill.UserPicture (cellAddress.Value) .ScaleHeight 3#, msoFalse, msoScaleFormTopLeft .ScaleWidth 2.4, msoFalse, msoScaleFromTopLeft End With ' Set the visible to True when you always want the image displayed, and ' to False when you want it displayed only when you click on the cell. .Visible = False End With InsertCommentImage = title End Function |
A fully qualified address for the cellAddress
parameter on a PC would look like this in let’s say cell B1
:
C:\Data\Images\WizardChess.png |
While it would be like this for the cellAddress
parameter on a Mac OS X installation in cell B1
:
Macintosh HD:Users:mclaughlinm:Desktop:WizardChess.png |
You would call this from a cell like this when the text is provided as a string and fully qualified file name is in cell B1
of a worksheet named ImageSource
:
=InsertCommentImage("Wizard Chess",B1) |
Alternatively, you rewrite InsertCommentImage()
as follows, which takes a string for the cell value and a string for the absolute file name:
Function InsertCommentImage(title As String, absoluteFileName As String) Dim commentBox As Comment ' Clear any comments before attempting to add them. Application.ActiveCell.ClearComments ' Define the comment as a local variable and assign the file name from the ' cellAddress input parameter to the comment of a cell. Set commentBox = Application.ActiveCell.AddComment With commentBox .Text Text:="" With .Shape .Fill.UserPicture (absoluteFileName) .ScaleHeight 3#, msoFalse, msoScaleFormTopLeft .ScaleWidth 2.4, msoFalse, msoScaleFromTopLeft End With ' Set the visible to True when you always want the image displayed, and ' to False when you want it displayed only when you click on the cell. .Visible = False End With InsertCommentImage = title End Function |
With the change of the second parameter, you would call the InsertCommentImage()
function with two strings, like:
=InsertCommentImage("Wizard Chess","C:\Data\Images\WizardChess.png") |
Here’s how it would look if you’d put the formula in cell A1
:
This is a simple Excel macro for which you could create a button. You run it when you want to delete only the image comment from a cell. The macro works by highlighting the cell and running it. Naturally, you could wrap it in another Excel macro to navigate through the list and clean up a bunch of comment images at one time.
Sub RemoveComment() Application.ActiveCell.ClearComments End Sub |
If you want to allow the macro to detach all comments for a range, you would rewrite it this way:
Sub RemoveComment() Application.Selection.ClearComments End Sub |
As always, I hope this helps and furthers sharing information.
Excel 2011 Query MySQL
I finally got around to finishing my testing of Excel 2011 querying MySQL. That meant installing and configuring Excel 2011 and MySQL 5.5.9 on Mac OS X (Snow Leopard). While installing Microsoft Office is pretty trivial, installing and configuring MySQL wasn’t. You can read about installing and configuring MySQL here. A quick test after this, led me to discover that you still need a third party ODBC, as covered in this earlier blog. You should take note that Microsoft’s future direction adopts Oracle ODBC, like the approach they’ve chosen with MySQL’s ODBC driver.
I downloaded and installed one of third party ODBC tool sets. I opted for OpenLink Software’s ODBC Driver. Instructions for the install with screen shots are in this blog page. The only downside of this was the discovery that Microsoft’s solution requires Rosetta, like Excel 2008. Rosetta enables Power PC application to run on Intel-based Mac OS X.
Launching the Database icon from Excel 2011, I configured the Data Source Name, which you can find here with screen shots. After you configure the Data Source Name, restarting Excel 2011 is the best choice because otherwise you may see several non-fatal errors.
The following screen shots show you how to establish a connection between Excel 2011 and MySQL, and how to query data from the MySQL database:
- After you click the Database icon, you see the following dialog. Select a Data Source Name and click the OK button to begin a query.
- The OpenLink MySQL Lite Login screen requires the user name and password. Click the Connect button to launch the Microsoft Query, which appears to be a native Power PC application that requires Rosetta to run it
- Microsoft Query appears to be a native Power PC application that requires Rosetta to run it. If you want to enter a query, click the SQL View button.
- Having clicked the SQL View button you now have a work area where you can enter a standard SQL
SELECT
statement, like the one below. Then, you click the Return Data button.
- This dialog lets you select where you want to put the return result set from the query. The default is the absolute cell reference of the top and left most cell,
$A$1
. Click the OK button to query and load the data into the worksheet.
- Now you can see the data in the worksheet. The only problem is the extraneous characters returned into the column headers of the table. While tedious, they’re easy to fix. The following illustrates the downloaded result set from the previous query:
- If you perform a query with a join operation, the column names are never displayed whether you provide aliases to the query or not. It means you have to convert the table to a range, remove the false headers, and recreate the table. This appears to be a limitation of Microsoft Query and unlike the behavior in Excel 2010 on Windows. Perhaps it’s all wrapped up in the emulation provided by Rosetta but I couldn’t find any information about what’s happening. That leaves me with pure speculation, which I never like. If you find the reason, post a comment with a link because everyone would benefit.
As always, I hope this helps those who want to work only in the Mac OS X environment. The risk is Rosetta because it will go away, the only question is when and whether the vendors will fix their dependency first or not. The problem with this solution is that Microsoft Query doesn’t return any tables when it appears that it should.
Excel 2011 Needs ODBC Files
I’d hoped for a better solution with Excel 2011 on Mac OS X but it appears we still need the third party drivers to connect Excel to MySQL. It’s the same as I reported earlier on Excel 2008. Here’s the message and you can click on it to go the web site and links to buy the drivers.
I tried getting away with installing the MySQL Connector/ODBC before downloading one of those recommended by Microsoft. I discovered that it didn’t work.
Therefore, I download and installed the OpenLink Software ODBC Software, instructions with screen shots are in this blog page. I discovered that this software support track isn’t purely native Mac OS X on Intel-based software because it requires Rosetta like Excel 2008. It also only connects with Microsoft Query, which appears to be a Power PC native application too, at least based on the interface and look and feel. I didn’t do much more research because I’ve concluded that connectivity isn’t ready for prime time on the Mac OS X platform. Microsoft still has more work to do.
Excel Data Validation List
A second Excel 2011 question in as many days, February is off and running. The question posed: “How do you create a data validation list without referring to a range of cells?”
You can create a data validation list without referring to a cell range. There’s a small trick to it. You enter the list of values as comma delimited strings, but you don’t enclose them in double quotes. Excel reads a set of literal text strings as if they’re a list of cell values, which is why you don’t provide the double quotes that you use in every function.
The desired list was either TRUE or FALSE, and the required behavior was that they function like Boolean variables. Fortunately, that’s straightforward when you remember that the case insensitive text strings TRUE
and FALSE
are Boolean values.
You create a data validation list by navigating to the Data Tab (Windows Excel 2010 it’s a Ribbon), and choose Validate. You’ll see the following list. Click on Data Validation… in the list, as shown below.
The selection launches the Data Validation dialog box. Choose List from the Allow poplist. Then, enter TRUE,FALSE
in the Source entry field, like this:
Now click OK and you have a poplist. Hope this answer the question for others too.
Excel 1st Day of Next Month
I had an interesting reaction when I told my students they had to create a dynamic Excel model that required them to enter the months of the year without AutoFill feature. They were stumped. They couldn’t find a function to perform it for them.
It’s really quite easy, the EDATE
function lets you find it directly. Enter any day in the current month as the first parameter and one as the number of months to add as the second parameter to the function. Voilà , you have a function to add a month to any date. The only time it returns the first of the next month is when the source date was the first day of the current month.
Here’s the solution when cell B1
contains January 14, 2011 and you want cell C1
calculated as the fourteenth day of February in the same year or February 14, 2011:
=EDATE(B1,1) |
Here’s the solution when cell B1
contains January 14, 2011 and you want cell C1
calculated as the fourteenth day of December in the prior year or December 14, 2010:
=EDATE(B1,-1) |
You can also use the EOMONTH
function to find the first or last day of the month. It lets you find it the first day of the next month regardless of the start date. All you need is a simple trick.
Enter any day in the current month as the first parameter and zero as the number of months to add as the second parameter to the function, and then add one.
Here’s the solution when cell B1
contains any day in January and you want cell C1
calculated as the last day of January in the same year (rounding up).
=EOMONTH(B1,0) |
Here’s the solution when cell B1
contains any day in January and you want cell C1
calculated as the first day of January in the same year (rounding down).
=EOMONTH(B1,-1)+1 |
A subsequent question asked how to calculate the 15th day of the current month, and here’s the formula:
=EOMONTH("10-Jul-2012",-1)+15 |
Hope this helps them and others looking for the trick.