C# Interop Excel format like Excel's format as table - c#

I'm exporting a table from SQLite to Excel (2010) in C#. It works fine. I'm using the Excel.Range.set_Value() method.
How can I format an Excel.Range like Excel's format (like a table) would?

To expand upon my comment and add to D Stanley.
Range range = ws.get_Range("A1:D5");
wrksheet.ListObjects.AddEx(XlListObjectSourceType.xlSrcRange, range, missing, Microsoft.Office.Interop.Excel.XlYesNoGuess.xlNo, missing).Name = "MyTableStyle";
wrksheet.ListObjects.get_Item("MyTableStyle").TableStyle = "TableStyleMedium1";

This example selects a rectangular range of every cell in the active sheet. Also, it uses indexed parameters of Range to get the range points. Furthermore, AddEx() (and most methods in Interop.Excel) uses default parameters so you don't have to use System.Reflection.Missing.
// define points for selecting a range
// point 1 is the top, leftmost cell
Excel.Range oRng1 = oSheet.Range["A1"];
// point two is the bottom, rightmost cell
Excel.Range oRng2 = oSheet.Range["A1"].End[Excel.XlDirection.xlToRight]
.End[Excel.XlDirection.xlDown];
// define the actual range we want to select
oRng = oSheet.Range[oRng1, oRng2];
oRng.Select(); // and select it
// add the range to a formatted table
oRng.Worksheet.ListObjects.AddEx(
SourceType: Excel.XlListObjectSourceType.xlSrcRange,
Source: oRng,
XlListObjectHasHeaders: Excel.XlYesNoGuess.xlYes);

Here's the VBA that does it:
ActiveSheet.ListObjects.Add xlSrcRange, Range("$J$10:$N$12"), , xlYes
Shouldn't be too hard to translate into an automation call. You can read the documentation as well.

Related

Applying formatting to a big range

I'm trying to use the Excel Interop C# libraries to copy cell formatting from one cell to a range of other cells. To do this, I'm using the following code:
var excelWrapper = new Application();
excelWrapper.DisplayAlerts = false;
var workBook = excelWrapper.Workbooks.Open(#"C:\myFile.xlsx");
Worksheet ws = workBook.Sheets[1] as Worksheet;
Range formatSource = ws.Cells[8, 1] as Range; //cell containing formatting that I want to apply
Range startCell = ws.Cells[9, 1] as Range; //first cell to format
Range endCell = ws.Cells[300, 1] as Range; //last cell to format
Range formatTarget = ws.Range[startCell, endCell];
//Copy formatting from source cell to destination range
formatSource.Copy();
formatTarget.PasteSpecial(XlPasteType.xlPasteFormats, XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
As you can see, I'm applying the format from cell [8,1] to the entire range [9,1] -> [300,1].
The problem I'm having is that this only applies the formatting to the first ~80 or so cells, after that the formatting is not applied. In particular, the formatting stops after row 91, so it is only applied to the first 84 of the 291 cells in the range.
I don't understand why the formatting is not applied to the entire range I selected, but only to the first 84 cells. What am I missing here? Note that the range I'm applying the style to starts empty (I write the data only after setting the formatting), so it isn't a problem derived from the data in the cells.
Well, I figured it out: the excel file looked empty, but actually it contained a table that stopped at row 91. Evidently, when you paste a format to a range that is "hybrid" (half inside table and half normal cells) the format only gets applied to the portion inside the table.

Can Excel Ranges be jagged (rather than always contiguous)?

One can define ranges in C# Excel Interop like so:
var homeHomeOnTheRange = _xlSheet.Range[_xlSheet.Cells[3, 7], _xlSheet.Cells[42, 11]];
This range will encompass the subset of cells on the page from row 3 down to row 42, and across from columns 7 (or "G") through 11 (or "K").
What, though, if I want a "jagged" range - is it possible to concatenate an array of ranges into one range?
You can use this format sheet.Range("A1:A2,B2:B3,C3:C4").
Pay attention that sheet should be of type dynamic so don't use Worksheet class for this purpose.
Example
Set the specified range background color to red:
var range = sheet.Range("A1:A2,B2:B3,C3:C4");
range.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);

Spreadsheetgear set data flags for specific column?

I am attempting to do this:
IWorksheet worksheet = Factory.GetWorkbook().Worksheets[0];
IRange range = worksheet.Cells["A1"];
range.CopyFromDataTable(dataTable, SetDataFlags.None);
worksheet.Cells.Columns.AutoFit();
return worksheet;
This works great normally, however I've run into an issue. I have one column that has a really long number, possibly with zeroes in the front and I need it to be entered and displayed as text. If I do a lookup of that particular cell like:
var cell = range["U34"].Value;
The data has already been turned into scientific notation so no amount of formatting afterwards fixes it. I tried SetDataFlags.AllText and that works great, except it breaks the rest of the worksheet because all of the numbers are stored as text, which is unacceptable.
I'm at a loss of how to fix this.
Solution:
Since I'm just looking to change one column, if it's present and a lot of the columns are dynamic I went with the "preformatting" route. Find the column index from the datatable:
int ColumnIndex = -1;
for (int x = 0; x < dataTable.Columns.Count; x++)
{
if (dataTable.Columns[x].ColumnName.Equals("Whatever"))
{
ColumnIndex = x;
}
}
worksheet.Cells[0, ColumnIndex, 0, ColumnIndex].EntireColumn.NumberFormat = "#";
Then perform the CopyFromDataTable, with Flags set to None and everything is perfect!
The IRange.CopyFromDataTable(...) method can be passed in a SetDataFlags.InsertCells enum option, which allows you to pre-format your destination range so that the inserted DataTable data picks up the formatting you specify. This formatting includes a cell's IRange.NumberFormat, which can be set to "#" and specifies that input to that cell should be treated as Text.
So, if you know what columns will have these unusually-large numbers that trigger scientific notation, another option would be to pre-format your worksheet's destination range with IRange.NumberFormat = "#" and will preserve your values for these columns as-is.
Please see the documentation for the IRange.CopyFromDataTable(...) method, as it provides important information on what range needs this "pre-formatting." Also, assuming you've installed SpreadsheetGear on your machine, check out the Reporting > DataSet to Workbook example in the SpreadsheetGear Explorer Solutions for C#/VB (found in the "SpreadsheetGear" folder under the Start Menu) for a live demo of this SetDataFlags.InsertCells option.

How to pass non-contiguous cells to Excel UDF

in myUDF, I can reference a range of cells like "A1:A12", but how can I reference non-contiguous cells like "A1,B4,H3" etc.
I use ExcelDNA, the parameter type is object
but it seems it will take string, and a range of cells, not non-contiguous cells
[ExcelArgument(AllowReference = true, Name = "Relations", Description = "a set of relations")]object rels
It sounds like you're entering the formula onto the worksheet, along with its parameters, from your code, and you want users to then be able to edit the formula normally in Excel's formula bar. Is that correct?
If so, enclose the parameter in parens. For example, for a UDF like this...
Public Function MyUDF(my_param As Range)
'concatenate all cell values in a non-contiguous range:
Dim rgCell As Range, rgArea As Range
For Each rgArea In my_param.Areas
For Each rgCell In rgArea
MyUDF = MyUDF & CStr(rgCell.Value)
Next rgCell
Next rgArea
End Function
...enter it in the worksheet cell like this:
=MyUDF((A1,A3,A7:A11,C8:E10))
Note the extra set of parens compared to using a built-in function like SUM.
BTW as you may already know, when looping through a non-contiguous range you have to loop through the areas of the range, then loop through the cells in each area; looping through the cells in the range only gives you the cells in the first area.

How to Copy a matrix into Ms Word Table without loop with C#

I did copy a whole string [4273,11] into Word but it takes so much time by looping and inserting each cell every time. What I want to do is copy a whole string [4273,11] directly into the MS Word table. If there is also a way to copy the content of an Excel worksheet to MS Word I will be grateful because it will solve the problem any way.
public void WriteContent(string[,] array, Word.Table oDoc)
{
// This is where I fill the Excel worksheet with the string [4273,11] array
Range range = (Range)m_worksheet.Cells[1, 1];
range = range.get_Resize(4273, 11);
// Assign the 2-d array to the Excel Range
range.set_Value(Microsoft.Office.Interop.Excel.XlRangeValueDataType.xlRangeValueDefault, array);
//This is Where I want to Paste the Excel "range" into the word document
}
You can copy and paste between office applications, but that is a very large range to copy, so you will need some delay or check. This reply is from a knowledge of Office, not c#.
range.Copy();
_wordApp.Selection.Paste();
Than you . I already did it, the issue is how to select a specific range so I did this
m_Worksheet.get_Range("A1", "K5000").Copy();
This range = range.get_Resize(4273, 11);
and the next line means your range is already selected.

Categories