ActiveWorkbook Returning NULL Error

thomson02

New Member
Joined
May 17, 2009
Messages
3
Hi,

Hopefully somebody will be able to help me. I'm developing an excel addin using Visual Studio 2008. At the moment i'm trying to display a popup showing the value contained in cell A1. However, i'm getting a runtime error saying that xlWorkBook is null. I've been able to get this to work if i open a workbook but i want to be able to execute my code on the currently active workbook. I thought that ActiveWorkbook (also tried ThisWorkbook) would let me do this but i'm having no success.

The code i'm using is below. I hope somebody will be able to point me in the right direction.

Thanks,
Andrew.

Code:
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
...
...
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;

xlApp = new Excel.ApplicationClass();
xlWorkBook = (Excel.Workbook) xlApp.ActiveWorkbook;
xlWorkSheet = (Excel.Worksheet) xlWorkBook.Worksheets.get_Item(1);

MessageBox.Show(xlWorkSheet.get_Range("A1", "A1").Value2.ToString());
 

Excel Facts

How can you turn a range sideways?
Copy the range. Select a blank cell. Right-click, Paste Special, then choose Transpose.
Hi Andrew,

Welcome to the Forum. :)

Your code is actually *extremely close* to being correct. Only a tiny subtlety is causing your code to have problems.

The key is this:
Code:
xlWorkBook = (Excel.Workbook) xlApp.ActiveWorkbook;
xlWorkBook.Worksheets.get_Item(1);

Your first line is successfully getting the active workbook (assuming that there is one!). Note that Application.ActiveWorkbook can return null, if there is no visible workbook, so you probably want to test for it. On most systems, creating a new Excel.Application also creates a new workbook by default, so you are fine, but it's usually best to check.

The second line is the problem. The second line is accessing the first Worksheet (the worksheet on the farthest left) in the Worksbook, but this is not necessarily the active sheet -- the user could have Sheet2 or Sheet3 selected, for example.

In order to get the active sheet, you are best off accessing it directly via Application.ActiveSheet and then casting to a Excel.Worksheet. It's best to cast using the 'as' operator in this case and then testing for 'null' because the active sheet can be a Chart sheet, which cannot be safely cast to a Worksheet. And if there is no active sheet, then the Application.ActiveSheet property will also return 'null'. So casting via the 'as' operator and then checking for 'null' is the way to go:

Code:
xlApp = new Excel.Application();
xlWorkSheet = xlApp.ActiveSheet as Excel.Worksheet 
if (xlWorkSheet != null)
{
    // Etc...
}

Ok, a couple of other very minor items:

(1) You should not make use of the Excel.ApplicationClass. You should, instead, utilize the 'Excel.Application' instead. So instead of:
Code:
xlApp = new Excel.ApplicationClass();
You should use:
Code:
xlApp = new Excel.Application();

For many things there is no difference, but you will hit problems at some point if you keep using the ApplicationClass. Use the Excel.Application instead. (Technically, 'Excel.Application' is an interface, so it seems confusing to use the 'new' keyword on it, but the Primary Interop Assemblies (PIAs) know how to handle this correctyl for you.

Ok, one last minor item:
Code:
xlWorkSheet = (Excel.Worksheet) xlWorkBook.Worksheets.get_Item(1);
The above works fine. But you'll be happy to know that the indexers work just fine with Excel, so you don't have to call the get_Item() accessor method the way you are. That is, you can just do this:
Code:
xlWorkSheet = (Excel.Worksheet) xlWorkBook.Worksheets[1];

You also might want to be careful of your line:
Code:
MessageBox.Show(xlWorkSheet.get_Range("A1", "A1").Value2.ToString());
The problem is that if the cell is empty, the call to 'Value2.ToString()' will be, effectively, a call to 'null.ToString()' and you will get a null reference exception. Instead, I would test for 'null' explicitly:

Code:
object theValue = xlWorkSheet.get_Range("A1", "A1").Value2;
if (theValue != null)
{
    MessageBox.Show(theValue.ToString());
}
else
{
    MessageBox.Show("The value is empty!");
}
Or, alternatively, you could use the static Convert.ToString() method to safely convert the object to string (returning an empty string if the object is null):

Code:
object theValue = xlWorkSheet.get_Range("A1", "A1").Value2;
MessageBox.Show(Convert.ToString(theValue));

Putting this all together, I think your code could look something like this:

Code:
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;

xlApp = new Excel.Application();
xlWorkSheet = xlApp.ActiveSheet as Excel.Worksheet;
if (xlWorkSheet != null)
{
    xlWorkBook = (Excel.Workbook)xlWorkSheet.Parent;
}
else
{
    // Either no active sheet at all (because no visble workbook)
    // or the active sheet is a chart sheet (not a worksheet).
    // Not sure what you want to do here! Up to you!!
}

object theValue = xlWorkSheet.get_Range("A1", "A1").Value2;
MessageBox.Show(Convert.ToString(theValue));

I hope this helps, Andrew. Good luck with it, it looks like you're on the right track...

:-),
Mike
 
Upvote 0
Hi Nate!

Colin L has been flagging me whenever he sees a .NET post...

I'm up to 6 posts! Whoo-hoo! :cool:

It's good to be here! (finally).
 
Upvote 0
Nice answer, Mike. :pray:


[And a belated welcome... (join date 2004!?)] :eeek:
 
Upvote 0
And I was just thinking, the last time I saw an answer that complete, it was something to do with CopyMemory in a certain newsgroup... ;)
 
Upvote 0
[And a belated welcome... (join date 2004!?)] :eeek:
Hey Col, yeah, well... Something happened on the way to the store... 5 years later, I finally make my first post!

And I was just thinking, the last time I saw an answer that complete, it was something to do with CopyMemory in a certain newsgroup... ;)
Hi Rory, yeah, kinda familiar, lol :biggrin:
 
Last edited:
Upvote 0
Hi Mike,

First off thanks very much for such a detailed reply! Wasn't expecting that but is very much appreciated!

I took your advice and adjusted my code. However, the Worksheet is still being returned as NULL. Maybe i'm not understanding exactly what activeWorksheet returns so here's what i'm wanting to achieve:-

I want to be able to open Excel and enter a value into cell A1 and press run to execute my addin (via ribbon - which is working fine) which just displays the contents in a message box.

Below is my revised code:

Thanks,
Andrew

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using Excel = Microsoft.Office.Interop.Excel;
using System.Windows.Forms;

namespace ExcelAddIn2
{
    public partial class Ribbon1 : OfficeRibbon
    {
        public Ribbon1()
        {
            InitializeComponent();
        }

        private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {

        }

        private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            Excel.Application xlApp;
            Excel.Workbook xlWorkBook;
            Excel.Worksheet xlWorkSheet;

            xlApp = new Excel.Application();
            xlWorkSheet = xlApp.ActiveSheet as Excel.Worksheet;  // NULL
            if (xlWorkSheet != null)
            {
                xlWorkBook = (Excel.Workbook)xlWorkSheet.Parent;
                object theValue = xlWorkSheet.get_Range("A1", "A1").Value2;
                MessageBox.Show(Convert.ToString(theValue));
            }
            else
            {
                MessageBox.Show("argh!");  // getting frustrated! :)
            }


        }
    }
}
 
Upvote 0
Oh, this is an add-in! Well, then you don't want to create a 'new' Excel.Application, right? Your new Application did not have a visible workbook open, which is why your code is returning null...

You want to be manipulating your existing Excel.Application instance instead.

Is this a straight managed COM add-in, or are you using Visual Studio Tools for Office (VSTO) for this?

If you are using VSTO, then you would want to make use of the 'this.Application' field. If you are not, then you would want to use whatever you named your global Excel.Application variable in your OnConnection() event. (Probably 'xlApp', I'm guessing?)

Does this make sense?

Mike
 
Upvote 0
Hi Mike,

I'm slightly embarrased for not noticing that i was creating a new instance of Excel! Thanks very much for pointing me in the right direction. :)

Thanks,
Andrew.
 
Upvote 0

Forum statistics

Threads
1,223,230
Messages
6,170,883
Members
452,364
Latest member
springate

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top