Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Color non-consecutive cells in an Excel sheet

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.

like image 631
Hjalmar Z Avatar asked May 02 '13 09:05

Hjalmar Z


People also ask

How do you apply conditional formatting to non-adjacent cells?

Select and copy the cell or range of cells that you wish to take the conditional formatting from. Select the destination cell or range of cells, right-click and select the 'Formatting' icon. This will paste just the formatting not the cell value.

What are non contiguous cells?

A non-contiguous range consists of two or more separate blocks of cells. These blocks can be separated by rows or columns as shown by the ranges A1 to A5 and C1 to C5. Both contiguous and non-contiguous ranges can include hundreds or even thousands of cells and span worksheets and workbooks.

Can you use an IF statement to color a cell?

Apply an If-Then rule to all cells by pressing “Ctrl-A” before assigning your rule. If you copy values from colored cells and paste them into new it new cells, the new cells acquire the color of the copied cell.


3 Answers

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);
        }
    }
like image 142
dotNET Avatar answered Oct 18 '22 05:10

dotNET


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"];
like image 34
banantaffer Avatar answered Oct 18 '22 05:10

banantaffer


[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
like image 1
Linga Avatar answered Oct 18 '22 06:10

Linga