Question

I can't seem to get at the properties for individual cells in my Excel sheet. The function that I have creates an Excel worksheet, populates it with data from a DataSet and then prints the sheet.

The issue that I'm having is that when I print the sheet, the formatting is all out of whack- the cells are too small and a lot of the information is truncated. How would I set the width of the cells and change the font?

Here's a little snippet of what I'm working with, for your perusal:

// Add rows
iRow = 1;

foreach (DataRow row in table.Rows)
{
    iCol = 1;

    foreach (DataColumn col in table.Columns)
    {
        Parameters = new Object[2];
        Parameters[0] = iRow + 1;
        Parameters[1] = iCol;
        excelCell = excelSheet.GetType().InvokeMember("Cells",
          BindingFlags.GetProperty, null, excelSheet, Parameters);

        Parameters = new Object[1];
        Parameters[0] = row[col.ColumnName];
        excelCell.GetType().InvokeMember("Value",
          BindingFlags.SetProperty, null, excelCell, Parameters);

        iCol++;
    }
    iRow++;
}

There seem to be plenty of examples of how to achieve something similar with early-binding, but I must be missing something with late-binding.

Was it helpful?

Solution 3

Using what Siddharth showed me, I was able to get a cell Range from the Worksheet and change the ColumnWidth property on that range:

//Get the first worksheet.
Parameters = new Object[1];
Parameters[0] = 1;
excelSheet = excelSheets.GetType().InvokeMember("Item",
    BindingFlags.GetProperty, null, excelSheets, Parameters);

//Set the Column Width within a large Range of cells.
Parameters = new Object[2];
Parameters[0] = "A1";
Parameters[1] = "E55";
excelRange = excelSheet.GetType().InvokeMember("Range",
    BindingFlags.GetProperty, null, excelSheet, Parameters);

Parameters = new Object[1];
Parameters[0] = 26;
excelRange.GetType().InvokeMember("ColumnWidth",
BindingFlags.SetProperty, null, excelRange, Parameters);

I can use this method to change any of the cell properties in that range by replacing "ColumnWidth" with whichever property I wanted to set.


To change the font, I first needed to get the Font propery of the cell as an object, and then use that object to access the font properties:

object cellFont = excelCell.GetType().InvokeMember("Font",
    BindingFlags.GetProperty, null, excelCell, null);

Parameters = new Object[1];
Parameters[0] = true;
cellFont.GetType().InvokeMember("Bold",
BindingFlags.SetProperty, null, cellFont, Parameters);

Thanks!

OTHER TIPS

I'm not a fan of going through this via reflection. It's painful. If you can, I'd really suggest looking at the new "dynamic" keyword. You lose Intellisense (no big deal since it's not all that useful in this case anyway), but the code is a LOT easier to write and understand.

Here's an example of opening Excel, creating a Workbook, setting a cell value, setting the font size, and finally changing the column width:

var excelType = Type.GetTypeFromProgID("Excel.Application");
dynamic excel = Activator.CreateInstance(excelType);
excel.Visible = true;
excel.Workbooks.Add();
excel.Cells(1, 1).Value = "Hello";
excel.Cells(1, 1).Font.Size = "14";
excel.Columns(@"A:A").ColumnWidth = 20;

If you're not sure about how to do something, you can basically just record a Macro in Excel, then view the code. You can almost cut and paste it into your C# code.

Changing the width of the cell is the same as changing the width of the column

See if this help? (UNTESTED)

// Set the column width
public void SetColWdth(string rng, double wdth)
{
    Range = excelSheet.GetType().InvokeMember("Range",
    BindingFlags.GetProperty,null, excelSheet, new object [] {rng});
    object [] args = new object [] {wdth};
    Range. GetType().InvokeMember ("Columnwdth",
    BindingFlags.SetProperty, null, Range, args);
}

For the Font, see if this help?

Quote from the above link in case it ever dies

foreach (string line in header)
{

    Object entireRow = GetRow(sheet, columnCount, rowOffset);
    entireRow.GetType().InvokeMember("MergeCells",
    BindingFlags.SetProperty, null, entireRow,
    new object[] { true });
    entireRow.GetType().InvokeMember("HorizontalAlignment",
    BindingFlags.SetProperty, null, entireRow, new object[] { 3 });
    Object tlCell = GetCell(sheet, 1, rowOffset);
    tlCell.GetType().InvokeMember("Value2", BindingFlags.SetProperty,
    null, tlCell, new object[] { "'" + line });
    Object font = tlCell.GetType().InvokeMember("Font",
    BindingFlags.GetProperty, null, tlCell, null);

    rowOffset++;
}

for (int col = 0; col < data.Columns.Count; col++)
{
    Object test = GetCell(sheet, col + 1, rowOffset);
    //DataTable Headers
    {
        Object erow = test.GetType().InvokeMember("EntireRow",
        BindingFlags.GetProperty, null, test, null);
        Object font = erow.GetType().InvokeMember("Font",
        BindingFlags.GetProperty, null, erow, null);
        erow.GetType().InvokeMember("HorizontalAlignment",
        BindingFlags.SetProperty, null, erow, new object[] { 3 });
        font.GetType().InvokeMember("Bold", BindingFlags.SetProperty,
        null, font, new object[] { true });
        test.GetType().InvokeMember("Value2", BindingFlags.SetProperty,
        null, test, new object[] { data.Columns[col].ColumnName.ToString() });
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top