I have a [,] string array that is 40 rows by 40 column items. I am trying to write them into an excel sheet but the output keeps writing the same word on the first row of every column. What am I doing wrong?
public static void writeToFile(this string [,] result)
{
try
{
//open instance of excel
Microsoft.Office.Interop.Excel.Application app = null;
app = new Excel.Application();
app.Workbooks.Add();
Excel._Worksheet sheet = app.ActiveSheet;
sheet.Name = "Sheet 1";
int resultCount = result.Length;
for (int i = 0; i < 40; i++)
{
for (int j = 0; j < 40; j++ )
{
sheet.Cells[i].Value = result[i,j];
j++;
}
i++;
}
If you got an array with rows at first dimension and columns at second dimension, you can simply write:
sheet.Range[sheet.Cells[1,1], sheet.Cells[40,40]].Value = result;
Related
I am trying to transform a datatbale to Excel using this funtion
internal static bool DataTableToExcel(System.Data.DataTable dataTable, string path)
{
_Excel.Application objXL = objXL = new _Excel.Application();
_Excel.Workbook objWB = null;
_Excel.Worksheet ExcelWorkSheet = null;
try
{
objWB = objXL.Workbooks.Add(_Excel.XlWBATemplate.xlWBATWorksheet);
ExcelWorkSheet = objWB.Worksheets[1];
for (int i = 0; i < dataTable.Rows.Count; i++)
{
for (int j = 0; j < dataTable.Columns.Count; j++)
{
ExcelWorkSheet.Cells[i + 1, j + 1] = dataTable.Rows[i][j].ToString();
}
}
objWB.SaveAs(path);
objWB.Close();
objXL.Quit();
return true;
}
catch(Exception ex)
{
objWB.Close();
objXL.Quit();
return false;
}
}
But the final result is missing the header cells in the document: I am only obtaining the date but i need to add the header cells in the excell document too.
In this case I believe you are missing adding the columns names before start the loop in your rows.
Try something like this for sheet's first row:
ExcelWorkSheet.Cells[0,0] = datatable.Columns["columnName"].ColumnName
I am trying to get data from an Excel file. I know that indexing in excel starts from 1, but still when reading a simple matrix, I am getting an Index exceeds bounds error.
Here is a simple method I'm using:
public static string[,] ReadFromExcel(Worksheet excelSheet)
{
if (excelSheet == null) return new string[1,1];
Microsoft.Office.Interop.Excel.Range xlRange = excelSheet.UsedRange;
int firstRow = xlRange.Row;
int firstColumn = xlRange.Column;
int lastRow = xlRange.Row + xlRange.Rows.Count - 1;
int lastColumn = xlRange.Column + xlRange.Columns.Count - 1;
string[,] data = new string[xlRange.Rows.Count - xlRange.Row, xlRange.Columns.Count - xlRange.Column];
for (int i= 0; i<= lastRow - firstRow; i++)
{
for (int j= 0; j <= lastColumn - firstColumn; j++)
{
data[i,j] = (string)(excelSheet.Cells[firstRow + i][firstColumn + j] as Range).Value;
//When I try to read values I get an error
System.Windows.MessageBox.Show(data[i, j]);
}
}
return data;
}
What am I missing?
The size of your "data" array should match the number of rows & columns:
string[,] data = new string[xlRange.Rows.Count, xlRange.Columns.Count];
Although the start index for Excel Interop is 1, rather than zero, the count is correct & you don't need to subtract the start row & column.
I want to read xlsx elements and print them 4 by 4 till all element are printed but i have a problem because it prints me all elements of the file. Any idea how to print them 4 by 4
// Open the Excel file.
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(Path.GetFullPath(#"C:\Users\user\Documents\Book2.xlsx"));
// Get the first worksheet.
Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlWorkbook.Sheets.get_Item(1);
// Get the range of cells which has data.
Excel.Range xlRange = xlWorksheet.UsedRange;
// Get an object array of all of the cells in the worksheet with their values.
object[,] valueArray = (object[,])xlRange.get_Value(
Excel.XlRangeValueDataType.xlRangeValueDefault);
for (int row = 1; row <= xlWorksheet.UsedRange.Rows.Count; ++row)
{
for (int col = 1; col <= xlWorksheet.UsedRange.Columns.Count; ++col)
{
Console.WriteLine(valueArray[row, col].ToString());
}
int y = xlWorksheet.UsedRange.Rows.Count / 4;
for() {
Console.WriteLine("4 addresat e para u printuan");
Console.WriteLine(" ");
}
}
Don't loop until you get to the end of columns/tows collection. Loop 1 through 4 (or 0 to 3)...
for (int row = 1; row <= 4; ++row)
{
for (int col = 1; col <= x4; ++col)
{
Console.WriteLine(valueArray[row, col].ToString());
}
}
Using Interop I managed to import an excel document (that contains a population) to a multidimensional string array of this format:
public string[,] DataArray;
I used this method to populate the array:
try
{
Excel.Application xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(FilePath);
Excel._Worksheet xlWorksheet = xlWorkBook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
rowCount = xlRange.Rows.Count;
colCount = xlRange.Columns.Count;
InitialiserTableauPopulation(rowCount, colCount);
for (int x = 1; x <= colCount; x++)
{
for (int y = 1; y <= rowCount; y++)
{
DataArray[x - 1, y - 1] = xlRange.Cells[y, x].Value2.ToString();
}
}
xlApp.Workbooks.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.message);
}
While debugging, I can see that the format is correct, for every X (column name), I have multiple Y (row data).
Example : DataArray[0,0] = NAME, DataArray[0,1] = JAMES, DataArray[0,2] = ERIC, etc.
Now what I'm trying to do is take a sample of this population, make a new multidimensional string array then export this "sample" to a new excel document : but I'm lost.
How should I proceed to export an existing two dimensional string array to a new excel sheet, keeping the same Array[column][row] format?
You just need to create a new Excel.Application, add a new Excel.Workbook and get the Excel.Worksheet from the Excel.Workbook.
Then you can iterate over your DataArray with a nested for-loop and add your values as needed using the Cell-Property of the Excel.Worksheet.
Then you save your new workbook and close it appropriately. This could look something like this
private void SaveDataArray(string excelFileName, string[,] dataArray)
{
var xlApp = new Application();
var xlWorkBook = xlApp.Workbooks.Add();
var xlWorkSheet = (Worksheet)xlWorkBook.Worksheets.Item[1];
for (int i = 0; i < dataArray.GetLength(0); i++)
{
for (int j = 0; j < dataArray.GetLength(1); j++)
{
xlWorkSheet.Cells[j + 1, i + 1] = dataArray[i, j];
}
}
xlWorkBook.SaveAs(excelFileName);
xlWorkBook.Close(true);
xlApp.Quit();
}
And then call the method like this
// create some sample data ...
string[,] dataArray = new string[1, 3];
dataArray[0, 0] = "NAME";
dataArray[0, 1] = "JAMES";
dataArray[0, 2] = "ERIC";
SaveDataArray("c:\\temp\\exceltest.xlsx", dataArray);
While I dont have a great answer for you, you didnt exactly give us the interop you are using. First I would ask why you are trying to do this the hard way? Can you not use a 3rd part lib like http://epplus.codeplex.com/
Now I am struggling with returning 2 values of different type from one of my helper classes to my main class with my form.
So I am passing to my method path to the xls file. Then I am loading values from that xls file to 2D array. After each row is loaded I am updating variable percent. This variable is telling me the percentage of loading process. Now I want to return this value to my main class so I can update one of my Labels.
After the loading process is completed I am returning the loaded array. So how can I update the label when returning 2D array?
This is my helper class and its method:
class LoadReflexTime
{
Excel.Application xlApp = new Excel.Application();
Form1 frm = new Form1();
Label percenta;
int percent;
string[,] reflexTime1;
public string[,] reflexTime(string cesta )
{
// LOAD XLS to ARRAY
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(cesta);
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
reflexTime1 = new string[rowCount, colCount];
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
string str = xlRange.Cells[i, j].Text;
reflexTime1[i - 1, j - 1] = str;
}
percent = ((100 * i) / rowCount);
// UPDATE LABEL (worked in my main class)
percenta.BeginInvoke(new Action(() => percenta.Text = percent.ToString()+"%"));
}
MessageBox.Show("Súbor načítaný");
return reflexTime1;
}
You can define a new class to wrap the two variables you want to return:
public class ReturnValue
{
public string[,] Array { get; set; }
public double Percent { get; set; }
}
You can then redefine your method to return that type:
public ReturnValue reflexTime(string cesta )
{
ReturnValue output = new ReturnValue();
// LOAD XLS to ARRAY
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(cesta);
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
output.Array = new string[rowCount, colCount];
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
string str = xlRange.Cells[i, j].Text;
output.Array[i - 1, j - 1] = str;
}
output.Percent = ((100 * i) / rowCount);
}
MessageBox.Show("Súbor načítaný");
return output;
}
And then both values are available at the same time.