This is what happens:
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.
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);
}
}
[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
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"];
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!
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.
User contributions licensed under CC BY-SA 3.0