Color non-consecutive cells in an Excel sheet

5

This is what happens:

enter image description here

xlValues is set as an Excel.Range object.

I have tried the following as well, all giving me the same error:

//xlValueRange = xlSheet...
.get_Range("A1:A5,A15:A25,A50:A65");
.UsedRange.Range["A1:A5,A15:A25,A50:A65"];
.Range["A1:A5,A15:A25,A50:A65"];

xlApp.ActiveWorkbook.ActiveSheet.Range["A1:A5,A15:A25,A50:A65"];
//I have also tried these alternatives with ".Select()" after the brackets and 
//", Type.Missing" inside the brackets

//This works though...
xlSheet.Range["A1:A5"];

I'm trying to recolor specific cells in an excel sheet, I have found a solution by using two loops but it's simply too slow. Running through a column of 30 000 cells takes minutes.

I have never done anything like this before and I used this tutorial to get me started.

This solution uses a bool array with cells to be colored set to true.(recolored)

//using Excel = Microsoft.Office.Interop.Excel;

xlApp = new Excel.Application();
xlApp.Visible = true;
xlBook = xlApp.Workbooks.Add(Type.Missing);
xlSheet = (Excel.Worksheet)xlBook.Sheets[1];

for (int i = 1; i < columns + 1; i++)
{
    for (int j = 1; j < rows + 1; j++)
    {
        if (recolored[j, i])
            xlSheet.Cells[j+1, i+1].Interior.Color = Excel.XlRgbColor.rgbRed;
        }
    }
}

What I would like to do is something like this:

Excel.XlRgbColor[,] color;
//Loop to fill color with Excel.XlRgbColor.rgbRed at desired cells.

var startCell = (Excel.Range)xlSheet.Cells[1, 1];
var endCell = (Excel.Range)xlSheet.Cells[rows, columns];
var xlRange = xlSheet.Range[startCell, endCell];

xlRange.Interior.Color = color;

This one gives me an error on the final line though;

Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))


My first guess would be to make an Excel.Range object that covers the cells I want to have red and use that object in place of xlRange, something like this:

RangeObject.Interior.Color = Excel.XlRgbColor.rgbRed;

I don't know if it's possible to make an Excel.Range object with gaps like that though, I could use some help on this one.

c#
excel
office-interop
asked on Stack Overflow May 2, 2013 by Hjalmar Z • edited May 16, 2016 by Hjalmar Z

5 Answers

2

You can select non-consecutive cells by using comma-separated list of ranges like this:

this.Application.ActiveWorkbook.ActiveSheet.Range["A2:A4,B3:B16"].Select();

You can then re-color the selection using:

Selection.Interior.Color = ColorTranslator.ToOle(Color.Yellow);

This will get rid of the coloring loop you're having trouble with.

Also, in a VSTO add-in, you should normally never need to do new Excel.Application() in your code. this.Application in the Add-in class should give you access to the active instance of Excel.

UPDATE

Here's a piece of code that should help you pin-point your problem. I added a Ribbon to my add-in and a simple button to the Ribbon. Behind the click event of this button, I have added the following code:

    private void button1_Click(object sender, RibbonControlEventArgs e)
    {
        try
        {
            var App = Globals.ThisAddIn.Application;

            if (App == null)
                System.Windows.Forms.MessageBox.Show("App is null");
            else
            {
                var Sheet = App.ActiveSheet;

                if (Sheet == null)
                    System.Windows.Forms.MessageBox.Show("Sheet is null");
                else
                {
                    var Rng = Sheet.Range["A1:A5,A15:A25,A50:A65"];

                    if (Rng == null)
                        System.Windows.Forms.MessageBox.Show("Rng is null");
                    else
                    {
                        Rng.Select();
                    }
                }
            }
        }
        catch (Exception ee)
        {
            System.Windows.Forms.MessageBox.Show("Exception: " + ee.Message);
        }
    }

On my end this code runs successfully and selects the non-contiguous range of cells. Try this on your end and let me know what you see.

UPDATE 2

The same code works for me in a WinForms application with reference to Excel 14.0 (will hopefully work with Excel 12.0 too). Just a couple of minor changes are required. Here's the full code.

    private void button1_Click(object sender, RibbonControlEventArgs e)
    {
         try
        {
            var App = new Microsoft.Office.Interop.Excel.Application();

            if (App == null)
                System.Windows.Forms.MessageBox.Show("App is null");
            else
            {
                App.Workbooks.Add();

                var Sheet = App.ActiveSheet;

                if (Sheet == null)
                    System.Windows.Forms.MessageBox.Show("Sheet is null");
                else
                {

                    Microsoft.Office.Interop.Excel.Range Rng = Sheet.get_Range("A1");

                    Rng.Select();

                    Rng = Sheet.get_Range("A1:A5,A15:A25,A50:A65");

                    if (Rng == null)
                        System.Windows.Forms.MessageBox.Show("Rng is null");
                    else
                    {
                        Rng.Select();

                        App.Selection.Interior.Color = Microsoft.Office.Interop.Excel.XlRgbColor.rgbYellow;

                        App.ActiveWorkbook.SaveAs("testtest.xlsx");

                        App.Quit();
                    }
                }
            }
        }
        catch (Exception ee)
        {
            System.Windows.Forms.MessageBox.Show("Exception: " + ee.Message);
        }
    }
answered on Stack Overflow May 2, 2013 by dotNET • edited May 13, 2013 by dotNET
1

[RangeObject].Interior.Color changes the cell background color. Use this

[RangeObject].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);

For cell text, use

[RangeObject].Font.Color
answered on Stack Overflow May 2, 2013 by Linga
1

I had the same problem and it turned out that it was a bad list separator - in my case instead of comma there should be a semicolon.

So instead of

.Range["A1:A5,A15:A25,A50:A65"];

try:

private string listSep = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator;

.Range["A1:A5" + listSep + "A15:A25" + listSep + "A50:A65"];
answered on Stack Overflow Feb 17, 2014 by banantaffer
1

I've struggled with this issue for a long time, too. But today I believe I finally found the solution (and the cause).

The problem is that Excel uses the current regional settings to determine the comma operator, ie. the separator between two ranges (don't ask me why - to me it's as insane as localizing the function names).

Anyway, on my computer I have the Czech locale set so the separator to use is a semicolon, not a comma! If I use it in the parameter for the Range method, it works perfectly.

From the discussion I got the impression that you are Swedish so you likely have the Swedish locale set. Its default list separator is also a semicolon, so it seems likely to me that this might solve your problem, too. You can always check the separator set in the computer regional settings by calling

System.Globalization.CultureInfo.InstalledUICulture.TextInfo.ListSeparator

Hope this helps!

answered on Stack Overflow May 12, 2016 by crypto_rsa
0

The maximum length of the range address string is 255. So, you need to chunk your list so that the combined range address of each section is less than 255 long.

answered on Stack Overflow Aug 7, 2015 by Glen Little

User contributions licensed under CC BY-SA 3.0