VSTO Excel - How to create a range with multiple areas - c#

If I have one or more ranges how can I combine them into a range with multiple areas?
One might think to do it like this... but this won't even compile...
Excel.Worksheet sheet = workbook.ActiveSheet;
Excel.Range rng1 = (Excel.Range) sheet.get_Range(sheet.Cells[1, 1], sheet.Cells[3,42]);
Excel.Range rng2 = (Excel.Range) sheet.get_Range(sheet.Cells[5, 1], sheet.Cells[6,42]);
Excel.Range result = new Excel.Range();
result.Areas.Add(rng1);
result.Areas.Add(rng2);
UPDATE:
This is not a duplicate... this is about creating a range with two Areas... not about creating a range from two ranges each with a single cell (which would result in a range with only one area)

Derived from one of the answers in the above referred to "duplicate" question.
Note: it seems if the areas can be combined a Union will do this (for example, two adjacent rows) but if they cannot be combined like this then it creates multiple areas. (not 100% sure on this)
Also, Union can have more than two parameters... e.g. Union(range1, range2, range3, etc...)
var excelApp = Globals.ThisAddIn.Application as Excel.Application;
var sheet = workbook.ActiveSheet as Excel.Worksheet;
var range1 = sheet.get_Range(sheet.Cells[1, 1], sheet.Cells[3,42]) as Excel.Range;
var range2 = sheet.get_Range(sheet.Cells[5, 1], sheet.Cells[6,42]) as Excel.Range;
var result = excelApp.Union(range1, range2) as Excel.Range;

Related

C# Reorder columns of Excel worksheet

I have an Excel worksheet with some data. I also have a List of the column headers of the worksheet. The headers in the list are in a different order than the headers in the worksheet, and I need to reorder the Excel worksheet's columns to be the same order as the list.
List<string> dataset1Variables = new List<string>() { "Variable1", "Variable2", "Variable3", "Variable4" };
The headers of my Excel sheet may look like this:
Variable 3 | Variable 1 | Variable 4 | Variable 2
I have come across this code to shift columns but this is only for moving 1 column to a specific location. The list might be completely mixed up so I would need to shift many columns.
Excel.Range copyRange = xlWs.Range["C:C"];
Excel.Range insertRange = xlWs.Range["A:A"];
insertRange.Insert(Excel.XlInsertShiftDirection.xlShiftToRight,
copyRange.Cut());
What would be the best approach for doing this? Preferably using Interop.
If you have an empty row right above your worksheet with data, you can add matching formula right above headers. In below assuming your list is on Sheet2 range B2:B5 and your data headers start on Sheet1 range A2:D2
Excel.Workbook myBook = xlApp.Workbooks.Open(#"path\excel.xlsx");
Excel.Worksheet ws = myBook.Worksheets[1];
// You can use all dynamic ranges instead
// Excel.Range xlRng = ws.Range[ws.Cells[yourRow, firsColumn], ws.Cells[yourRow, lastColumn]];
Excel.Range xlRng = ws.Range[ws.Cells[1, 1], ws.Cells[1, 4]]; // ws.Range["A1:D1"];
xlRng.FormulaR1C1 = "=MATCH(R[-1]C,Sheet2!R2C2:$R5C2,0)";
// Below is how you can get full address for your list if it's in different workbook and replace Sheet2!R2C2:$R5C2 with rangeFullAddress
// string rangeFullAddress = xlRng.Address[true,true,Excel.XlReferenceStyle.xlR1C1,true];
xlRng.Calculate();
xlRng.Value = xlRng.Value;
After this you can just sort your data using Excel Sort by 1st row. After sorting your 1st row it would look like this: 1, 2, 3, 4. Then clear data on 1st row ws.Range["A1:D1"].Clear();.
Your sort key would be Key1: ws.Range["A1:D1"], here is c# sort example using c# to sort a column in excel only change Excel.XlSortOrientation and adjust for your range.
There are other ways to sort but this way you'll keep individual formats, comments of each cell within your data
I missed 1 important detail - that your list is not in Excel sheet, but you can add it to Excel, perhaps in temporary workbook or right on the same sheet:
object [,] columnHeaders = new object[3,0]; // or object[0,3]; if you'd like to add into 1 row
columnHeaders[0, 0] = "Variable1";
columnHeaders[1, 0] = "Variable2";
columnHeaders[2, 0] = "Variable3";
columnHeaders[3, 0] = "Variable4";
xlRng.FormulaR1C1 = columnHeaders; // xlRng would be in the above Sheet2!R2C2:$R5C2

C#/WPF: Defining an EXCEL range through row and column number

I have tried this
How do I get an Excel range using row and column numbers in VSTO / C#?
but it throw an undefined com exception
what I would like is something like (pseudocode)
Range myRange = new Range(new cell(1,1), cell(3,3));
so that I can then use it with (pseudocode again)
ws.myRange.Interior.Color = XlRgbColor.rgbDarkGray;
thank you
Please check that out:
Range range1 = ws.Range[ws.Cells[1, j], ws.Cells[1, j+1]];
Here, Range is :
Microsoft.Office.Interop.Excel.Range

Excel Range in C# using interop.Excel. Range both empty and not empty?

I have a Excel sheet that looks like this.
|A1|B1| "BLANK" |D1|E1|F1|
I.e. only the first row is populated and the third column is blank. I parse this in C# using interop.excel in the following way:
Excel.Application exApp = OpenExcel();
String mySheet = #"C:\c#\rapport.xlsx";
Excel.Workbook wb = exApp.Workbooks.Open(mySheet);
Excel.Worksheet ws = wb.Sheets[1];
Excel.Range row = ws.Rows[1];
I create a new range only containing the non-empty cells in row 1 by
Excel.Range rng = row.SpecialCells(Excel.XlCellType.xlCellTypeConstants);
Now: if I use rng.Select all the non-empty cells in my sheet is selected. And if I use rng.Count it will return 5, which is the number of non-empty cells in my sheet. But still when I print cell by cell using:
Console.WriteLine(rng[1,i].Value.ToString());
It shows that rng[1, 1-2] contains "A1 and B1", this is nice. But
rng[1, 3] is empty or null. And rng[1, 4-7] contains D1-F1.
How is this possible?
My main goal is to store all non-empty values in a string array. But I can't select the right values because my range rng is both empty and non-empty is some weird way.
Try using:
ws.Columns.ClearFormats();
ws.Rows.ClearFormats();
to be sure your Range excludes formatted but empty cells.
Another try could be to get :
Excel.Range rng = row.SpecialCells(Excel.XlCellType.xlCellTypeConstants,Type.Missing);
This solved it! However I didn't use the .Item method to store the values as Rory suggested suggested. Thnx Rory!
string[] str = new String[rng.Count];
int i = 0;
foreach (Excel.Range cell in rng.Cells)
{
str[i] = cell.Value.ToString();
i++;
}
for (int j = 0; j < str.Length; j++)
Console.WriteLine(str[j]);

How to set the data range for a Word chart?

I have a Word.Chart whose underlying worksheet I am populating with data from C#.
My problem is however, that the selected dataset in the worksheet contains just the default selection (eg. 5x4 cells or sg like that), and not ALL the data which I entered.
If the object were an Excel chart, I could do
Excel.Range rangeBegin = ws.Cells[1, 1];
Excel.Range rangeEnd = ws.Cells[xAxisContents.Count + 1, feeds.Count + 1];
Excel.Range chartRange = ws.get_Range(rangeBegin, rangeEnd);
wordChart.SetSourceData(chartRange);
However, the Word.Chart's SetSourceData method only accepts a string, and if I call it with an arbitrary range (just for testing), eg. wordChart.SetSourceData("A1:C3"), it fails with a ComException(E_FAIL).
I have also found this code on a Microsoft blog:
Excel.Range tblRng = dataSheet.get_Range("A1", "B5");
Excel.ListObject tbl = dataSheet.ListObjects["Table1"];
tbl.Resize(tblRng);
which I think is meant to resize the selected dataset to the size of the worksheet. This would also be perfect for me, however, "Table1" is reported as an unknown index (maybe because I am using a non-English version of Word.)
What should I do to select the appropriate dataset?

.net c# excel column AutoFit

I'm working with an excel object in c#. I want to auto-fit the columns, but like this: I want the columns' width to be 5 bigger than what the AutoFit method set.
How can I get the width after AutoFit() is used?
How can I make the columns 5 bigger than this width?
If you wish to use the Selection object and have IntelliSense with early binding, you need to cast the Selection object to a Range first:
Excel.Range selectedRange = (Excel.Range)myExcelApp.Selection;
selectedRange.Columns.AutoFit();
foreach (Excel.Range column in selectedRange.Columns)
{
column.ColumnWidth = (double)column.ColumnWidth + 5;
}
-- Mike
Assuming that you are on cell A1 & have long text in it, following code will make the column Autofit and then increase the width by 5 characters.
Selection.Columns.Autofit
Selection.Columns(1).ColumnWidth = Selection.Columns(1).ColumnWidth + 5
Try to loop through your rows to get the text length of it:
var row = 1;
ws.Column(1).AutoFit(ws.Cells[row, 1].Text.Length + 5);
Where ws is your Worksheet:
var pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Plan1")
Try Like this,
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Sheet1");
//Load the datatable into the sheet, starting from cell A1. Print the column names on row 1
ws.Cells["A1"].LoadFromDataTable(data_table, true);
//Set full Sheet Auto Fit
ws.Cells[1, 1, data_table.Rows.Count, data_table.Columns.Count].AutoFitColumns();

Categories