How to merge cells in Excel? - c#

I have a list of objects and I am trying to dedicate three rows for every object and I am using the "Office Open Xml library" with this routine:
int row = 1, col = 1;
for (int i = 0; i < MyList.Count * 3; i+=3)
{
MySheet.Cells[row + i, col, row + i + 1, col].Merge = true; // merge two and get a "result"
MySheet.Cells[row + i + 1, col, row + i + 2, col].Merge = true; // merge "result" with third row
}
However it pops an error saying can't merge already merged cell.
So the question is How to merge more than two cells in Excel?

The indexes specify a range of cells, not only two adjacent cells. To merge cells across three rows you can write
MySheet.Cells[row + i, col, row + i + 2, col].Merge = true;
Or you can merge a 3x2 block
MySheet.Cells[row + i, col, row + i + 2, col+1].Merge = true;
Everything in Excel is a range. Even a single cell is treated as a single-cell. This makes working with single cells a bit weird but it makes applying styles and formulas a lot easier

Use this for merge 2x3
MySheet.get_Range(MySheet.Cells[row, col], MySheet.Cells[row + 2, col + 3]).MergeCells = true;

Related

Skip Rows in Column Sum in Excel using C#

I am trying to calculate the column sum by skipping specific rows with excel interop in C#.i am not able to figure out how to do that please help. I want to sum highlighted rows and skip the others in the attached image.
Excel array indices are generally 1-based, not 0-based (i.e. lowest element is number 1).
var xl = new Microsoft.Office.Interop.Excel.Application();
var b = xl.Workbooks.Open("C:\\Junk\\Junk.xlsx");
Microsoft.Office.Interop.Excel.Worksheet s = b.Worksheets[1]; //1-based
var r = s.Range["A1", "E4"];
int sum = 0;
for (var row = 1; row <= 4; row += 2)
{
sum += r.Value2[row, 1]; //also 1-based
}
xl.Quit();

How can i left-align a whole row with numbers

I have a listbox full of numbers. I am exporting these values to excel but I Want to left align the the numbers in each cell. Every time I try this my program crashes
I tried to add an extra row of code in my for loop to try to align it left but it crashes it gives the following error:
Additional information: Exception from HRESULT: 0x800A03EC
This is what I tried:
for (int i = 0; i < listBox3.Items.Count; i++)
{
worksheet.Cells[i + 21, 1] = listBox3.Items[i].ToString();
worksheet.Cells[21, i].HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
}
but it crashes. What I want is that all the values align left.
Why are you using different indices for worksheet.Cells inside the loop? Shouldn't they be the same? Like this:
for (int i = 0; i < listBox3.Items.Count; i++)
{
worksheet.Cells[i + 21, 1] = listBox3.Items[i].ToString();
worksheet.Cells[i + 21, 1].HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
}

How to iterate on Excel.Range with an index in c#

I'm writing a c# Add in for excel that takes values from a column of an excel sheet and does some operations. This is a part of the code that I wrote:
Excel.Range aqRange = currentSheet.Range["C3:C" + cRowCount];
Excel.Range vcRange = currentSheet.Range["D3:D" + cRowCount];
Excel.Range k0R = currentSheet.Range["F2"];
double[] sgVett = new double[cRowCount];
foreach (Range aq in aqRange)
{
if (i == 0) sgVett[i] = k0R.Value + aq.Value;
else sgVett[i] = sgVett[i - 1] + aq.Value;
i++;
}
i = 0;
foreach (Range vc in vcRange)
{
if (i == 0) sgVett[i] -= vc.Value;
else sgVett[i] -= vc.Value;
i++;
}
I want to know if is there some way to do something like this:
for(int j = 0; j<cRowCount; j++) {
if (i == 0) sgVett[i] = k0R.Value + aqRange[i].Value;
else sgVett[i] = sgVett[i - 1] + aqRange[i].Value;
}
I know that I can't use a Excel.Range as a vector, but is there some way to use an index to scroll aqRange and vcRange or, at least, if it's possible to use just one for or one foreach instead of two (as I done).
You can use the Range's Cells property a bit like a 2 dimensional array.
It is important to note that although the syntax used is similar to a C# 2D array (Cells[RowIndex, ColIndex]), the Cells property accesses a COM object that uses 1 as it's start offset, rather than 0.
So you should be able to write something like :
for(int j = 1; j<=cRowCount; j++)
{
if (i == 0) sgVett[i] = k0R.Value + aqRange.Cells[j,1].Value;
}
Also see here : Fastest way to get an Excel Range of Rows & How do I get an Excel range using row and column numbers in VSTO / C#?

Write to Cells in a for-loop with EPPLUS result in duplicate values

I do not understand why the following code write 2,2,2 to Excel while it should be 0,1,2. The code is straightforward - create an ExcelPackage, add a Worksheet, and iterate a loop to write values to a cells.
using (ExcelPackage p = new ExcelPackage())
{
p.Workbook.Worksheets.Add("Foo");
for (int j = 0; j < 3; j++)
p.Workbook.Worksheets["Foo"].Cells[1, 1, 1, 1 + j].Value = j;
p.SaveAs(new FileInfo(#"C:\FooFolder\Foo.xlsx"));
}
You are writting in a range instead of a unique cell. With Cells[1, 1, 1, 1 + j] you are writting from cell 1,1 to cell 1,1+j : the complete range take the assigned value.
Use Cells[1, j, 1, 1 + j] instead

Strange behavior from Excel.Worksheet.Cells[row, column]

I have the following method:
public static object getValue(Excel.Worksheet sheet, int row, int col)
{
Excel.Range r = sheet.Cells[row, col] as Excel.Range;
//I've also tried using sheet.get_Range(cell, cell); here, with the same result
if (r.Row != row || r.Column != col)
{
//Why does this debug statement sometimes print?
Debug.Print("Tried to read (" + row.ToString() + ", " + col.ToString() + ") but got (" + r.Row.ToString() + ", " + r.Column.ToString() + ")");
}
return r.Value2;
}
Based on my understanding of Excel.Worksheet.Cells[row, column], my code should never enter the if statement. However, when I call getValue repeatedly to read multiple cells, every so often the row and column of the range it returns are different than the row and column I called Excel.Worksheet.Cells with.
Example output: "Tried to read (19, 1) but got (56, 5)"
Furthermore, if I break in the if statement, then rewind my execution point and run Excel.Worksheet.Cells again, I get the correct range.
Why could this be?
This isn't an answer to your direct question, but may solve the problem.
Is getValue in a tight loop? If so then I would approach it a different way. Since Accessing Cells and Value2 are COM-calls they are slower than normal array accessors. If you have a particular range you're looping over I would get the array of values for that range in memory and access the array directly rather than looping through the cells.
e.g. instead of
for(int r = 1; r <= 10; r++)
for(int c = 1; c <= 20; c++)
double val = sheet.Cells[r,c];
do
object[,] values = sheet.Range("A1:J20").Value
for(int r = 1; r <= 10; r++)
for(int c = 1; c <= 20; c++)
double val = values[r,c];
This may fix your problem by removing the COM access from tight loop and eliminating whatever problem is giving you the strange results.

Categories

Resources