I have a table in Excel and I would like to import a selected area to a 2D array in excel. It must be same 2D array in C#. I have a picture, please look at it. I want to import that area to int array[81,81]:
You can use GemBox.Spreadsheet library for this (you can use its Free version to achieve this).
Here is a sample that you can use:
ExcelFile workbook = ExcelFile.Load("guncellenmis.xlsx");
ExcelWorksheet worksheet = workbook.Worksheets.ActiveWorksheet;
int count = 81;
int[,] data = new int[count, count];
// Get range from "C2" to "CE82".
CellRange range = worksheet.Cells.GetSubrangeRelative(1, 2, count, count);
// Or you can retrieve the required range differently, like:
//CellRange range = worksheet.Cells.GetSubrangeRelative("C2:CE82");
//CellRange range = worksheet.Cells.GetSubrangeRelative("C2", "CE82");
// etc.
for (int row = 0; row < range.Height; ++row)
for (int column = 0; column < range.Width; ++column)
data[row, column] = range[row, column].IntValue;
EDIT:
Is there a reason why you want to export the excel file as 2D array instead of DataTable.
You could retreive the required data as DataTable like the following:
ExcelFile workbook = ExcelFile.Load("guncellenmis.xlsx");
ExcelWorksheet worksheet = workbook.Worksheets.ActiveWorksheet;
DataTable table = worksheet.CreateDataTable(
new CreateDataTableOptions("C2", 81, 81));
Related
List<someClass> aList = new List<someClass>();
...
XLWorkbook workbook = new XLWorkbook();
IXLWorksheet worksheet = workbook.AddWorksheet("Data");
worksheet.Hide();
workbook.CalculateMode = XLCalculateMode.Manual;
var data = aList.ToArray();
var firstCell = worksheet.Cell(1, 1);
var lastCell = worksheet.Cell(numRows, numColumns); // numRows = 150, numColumns = 8
var writeRange = worksheet.Range(firstCell, lastCell); //firstCell = A1, LastCell = H150
writeRange.Value = data;
workbook.SaveAs(mySavePath);
This bit of code is meant to copy the data in aList into a new excel document, only, instead of starting at cell A1(1,1) and ending at cell H150 it copies the value from cell 1 into all of the cells between A1 and H299, the row values that should be in row 1 into column H-O from row 1-150, and finally my correctly grouped data from H150-O299.
Basically, my data starts at the offset of the range instead of filling in the range, and everything above and left of that range is default copied (garbage) data. someClass is just a public class with public fields for ints and strings.
Can anyone tell me why this is happening and how I can correct it?
As a solution, I found that using the same index for first and last cell will properly input my data, however why Range does not work as (assumed) intended has yet to be answered.
var firstCell = worksheet.Cell(1, 1);
var writeRange = worksheet.Range(firstCell, firstCell); //firstCell = A1, LastCell = H150
This will work as intended. I've completely removed lastCell as it is unnecessary.
I have a home-built utility to transfer data from a DataSet to an Excel spreadsheet. I want to put a formula (e.g. "=+RC[-2]-RC[-1]") in one of the columns. However, Excel is treating it a string and not interpreting it as a formula. The utility creates and transfers an array of objects to a Range in Excel. Is this the problem? I have written formulas to Excel in the past, but only when writing to a single cell.
for (int r = 0; r < nr; r++)
{
r = dt.Rows[r];
nOut++;
aRng = new object[nc];
for (int c = 0; c < nc; c++) else aRng[c] = dr[c];
oRng = oSheet.get_Range(CellAddress(nOut, 1), CellAddress(nOut, nc));
oRng.Value2 = aRng;
}
You have to use the .Formula property in order to force excel to treat it as a formula.
((Range)worksheet.Cells[row, col]).Formula = myFormula
You have to use the .Formula or FormulaR1C1 property of the Range object.
string s = "=+RC[-2]-RC[-1]";
...
oRng.FormulaR1C1 = s;
I have this C# code which converts a dataset to xlsx. Is there a way to set the cell or column width of the sheet of the xlsx file created?
//Get the filename
String filepath = args[0].ToString();
//Convert the file to dataset
DataSet ds = Convert(filepath.ToString(), "tblCustomers", "\t");
//Create the excell object
Excel.Application excel = new Excel.Application();
//Create the workbook
Excel.Workbook workBook = excel.Workbooks.Add();
//Set the active sheet
Excel.Worksheet sheet = workBook.ActiveSheet;
int i = 0;
foreach (DataRow row in ds.Tables[0].Rows)
{
for (int j = 0; j < row.ItemArray.Length; j++)
{
sheet.Cells[i + 1, j + 1] = row[j];
}
i++;
}
workBook.SaveAs(#"C:\fromCsv.xlsx");
workBook.Close();
sheet.Columns["D:D"].ColumnWidth = 17.57;
or
sheet.Columns[1].ColumnWidth = 17.57;
You can record Macros in Excel and then look to generated code (object model is the same).
To automaticaly set all column widths to "right-size" for their contents, you can take care of this by calling AutoFit, like so:
_xlSheet.Columns.AutoFit();
However, sometimes one or two "rogue" values in a column make that column go ultra-wide, and you have to drag the column way over to the left so as to see more of the data. You can overcome this Catch-22 by using both AutoFit and then, afterwards, specifying the width of any problematic columns. Here's the code for how to do that, which assumes column 1 is the one to be reined in, and 42 is the width you want it to assume:
private Worksheet _xlSheet;
private static readonly int ITEMDESC_COL = 1;
private static readonly int WIDTH_FOR_ITEM_DESC_COL = 42;
. . .
_xlSheet.Columns.AutoFit();
// Now take back the wider-than-the-ocean column
((Range)_xlSheet.Cells[ITEMDESC_COL, ITEMDESC_COL]).EntireColumn.ColumnWidth = WIDTH_FOR_ITEM_DESC_COL;
Note: As an added nicety, you can have the over-long content wrap (especially useful if they are in a Merged (multi-row) range) like so (where "range" is the Range you defined when populating the column):
range.WrapText = true;
Note: You need to add the Microsoft.Offie.Interop.Excel assembly for this code to work.
Im trying to insert RoomType array into the excel book. Range of RoomType is From D22 To D25 so problem is that this code only put the firts value In this range. if i insert RoomType.set_Value into the for loop, excel range filling with last array item. can anyone help me?
Object[,] RoomtypeArray = new object[1, _RoomType.Count];
for (int i = 0; i < _RoomType.Count; i++)
{
RoomtypeArray[0, i] = _RoomType[i];
}
RoomType.set_Value(Type.Missing, RoomtypeArray);
This is what you need:
//Microsoft.Office.Interop.Excel.Range RoomType;
//List<double> _RoomType;
object[,] roomTypeArray = Array.CreateInstance(
typeof(object),
new int[] { 1, _RoomType.Count},
new int[] { 1, 1 });
for (int i = 0; i < _RoomType.Count; i++)
{
roomTypeArray[1, i + 1] = _RoomType[i];
}
RoomType.Value2 = roomTypeArray;
because setting an array for a range requires 1-based indexes instead of 0-based which are used with the new statment in C#.
(look also in the accepted answer of How can I quickly up-cast object[,] into double[,]? to find a neat trick going between object[,] and double[,] for use in Excel Inerop).
With EPPlus and OpenXML does anyone know the syntax on how to count the rows?
Say my worksheet is called "worksheet"
int numberRows = worksheet.rows.count()? or worksheet.rows.dimension
I'm certainly interested in the answer, but how to find the answer would be cool to, like "Go to definition" and look for this or that, etc.
With a worksheet object called worksheet, worksheet.Dimension.Start.Row and worksheet.Dimension.End.Row should give you the information you need.
worksheet.Dimension.Address will give you a string containing the worksheet dimensions in the traditional Excel range format (e.g. 'A1:I5' for rows 1-5, columns 1-9).
There is a documentation file available. In many cases it might be just as quick to play around with the library and find the answer that way. EPPlus seems to be well designed - everything seems to be logically named, at least.
Thanks for that tip Quppa. I used it in my bid to populate a DataTable from a Workbook Spreadsheet as below:
/// <summary>
/// Converts a Worksheet to a DataTable
/// </summary>
/// <param name="worksheet"></param>
/// <returns></returns>
private static DataTable WorksheetToDataTable(ExcelWorksheet worksheet)
{
// Vars
var dt = new DataTable();
var rowCnt = worksheet.Dimension.End.Row;
var colCnt = worksheet.Dimension.End.Column + 1;
// Loop through Columns
for (var c = 1; c < colCnt; c++ )
{
// Add Column
dt.Columns.Add(new DataColumn());
// Loop through Rows
for(var r = 1; r < rowCnt; r++ )
{
// Add Row
if (dt.Rows.Count < (rowCnt-1)) dt.Rows.Add(dt.NewRow());
// Populate Row
dt.Rows[r - 1][c - 1] = worksheet.Cells[r, c];
}
}
// Return
return dt;
}
I am working with version 4.1 and it looks like they have added some properties (mentioned in comments from previous answers) to make this easier.
string Filepath = "c:\excelfile.xlsx";
FileInfo importFileInfo = new FileInfo(FilePath);
using(var excelPackage = new ExcelPackage(importFileInfo))
{
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1];
int rowCount = worksheet.Dimension.Rows;
int colCount = worksheet.Dimension.Columns;
}
Quite easy with:
private int GetDimensionRows(ExcelWorksheet sheet)
{
var startRow = sheet.Dimension.Start.Row;
var endRow = sheet.Dimension.End.Row;
return endRow - startRow;
}