Export a multidimensional string array to a new Excel spreadsheet - c#

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/

Related

Write Range Values from an excel file to another excel in C#

I have the following code and I am trying to copy certain Range values from one Excel file to another.
I have managed to select the range from the first excel, but it does not "paste" it where I've selected the range to.
In this example, it copies it to the first cells in the second excel.
Could anyone help please?
Thank you!
Microsoft.Office.Interop.Excel.Application application = new Microsoft.Office.Interop.Excel.Application();
Workbook workbook = application.Workbooks.Open(#"Excel.xlsx", 1);
Worksheet xlWorksheet = (Worksheet)workbook.Sheets[9];
Workbook workbook1 = application.Workbooks.Open(#"Excel2.xlsx", 1);
Worksheet xlWorksheet1 = (Worksheet)workbook1.Sheets[1];
Range range1 = xlWorksheet.get_Range("C1", "C5");
object[,] valueArray = (object[,])range1.get_Value(XlRangeValueDataType.xlRangeValueDefault);
Range range2 = xlWorksheet1.get_Range("F1", "F5");
object[,] valueArray2 = (object[,])range2.get_Value(XlRangeValueDataType.xlRangeValueDefault);
for (int i = 2; i <= valueArray.GetLength(0); i++)
{
for (int j = 1; j <= valueArray.GetLength(1); j++)
{
for (int k = 1; k <= valueArray2.GetLength(0); k++)
{
for (int l = 1; l <= valueArray2.GetLength(1); l++)
{
valueArray2[i,j] = valueArray[i, j].ToString();
}
}
}
}
workbook1.Save();
workbook.Close();
workbook1.Close();
application.Quit();
Solution
Microsoft.Office.Interop.Excel.Application application = new
Microsoft.Office.Interop.Excel.Application();
Workbook workbook = application.Workbooks.Open(#"D:\Excel.xlsx", 1);
Worksheet xlWorksheet = (Worksheet)workbook.Sheets[1];
Workbook workbook1 = application.Workbooks.Open(#"D:\Excel2.xlsx", 1);
Worksheet xlWorksheet1 = (Worksheet)workbook1.Sheets[1];
Range range1 = xlWorksheet.get_Range("C1", "C5");
Range range2 = xlWorksheet1.get_Range("F1", "F5");
range1.Copy(range2);
workbook1.Save();
workbook.Save();
workbook.Close();
workbook1.Close();
application.Quit();
Thank you!

I want find duplicated values in my excel sheet and change the text colors in c#

I want find duplicated values in my excel sheet and change the text colors in c#
with this code:
Excel.Application xlApp =
new Excel.Application();
//xlApp.Visible = true;
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(DtaSource1);
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for(int k=1;k<=rowCount;k++)
{
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j] == xlRange.Cells[k, 1])
{
xlRange.Cells[i, j].value = "00000";
xlWorksheet.SaveAs(DtaSource1);
}
}
}
}
but it's does not working and when i want to save changes it's throw out the error excel sheet read- only!
Here's an example of highlight duplicate and unique values in Excel by using Spire.XLS, maybe you can have a try.
//Load the Excel file
Workbook workbook = new Workbook();
workbook.LoadFromFile("Input.xlsx");
//Get the first worksheet
Worksheet sheet = workbook.Worksheets[0];
//Use conditional formatting to highlight duplicate values in range "A2:A10" with IndianRed color
ConditionalFormatWrapper format1 = sheet.Range["A2:A10"].ConditionalFormats.AddCondition();
format1.FormatType = ConditionalFormatType.DuplicateValues;
format1.BackColor = Color.IndianRed;
//Save the file
workbook.SaveToFile("HighlightDuplicates.xlsx", ExcelVersion.Version2013);

C# and Reading Excel Data: Rows.Count is 0 despite having data in my excel file

I am attempting to read data from an excel file and store it in a 2D array. However, the functions that I call on my excel sheet seem to be returning 0, such as the row/column count, despite my excel sheet having data in it. Is there some sort of formatting I have to do to my excel sheet?
For example when I call the count row function on the general range, not the used range, on xlSheet, it returns 0 for some reason.
public static String[,] ReadExcelData(string fileName, string sheet)
{
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(fileName);
Excel.Worksheet xlSheet = (Excel.Worksheet)xlWorkbook.Sheets[sheet];
Excel.Range range = xlSheet.UsedRange;
int rowCount = range.Rows.Count;
int columnCount = range.Columns.Count;
String[,] dataArray = new String[rowCount, columnCount];
for (int currColumn = 1; currColumn <= columnCount; currColumn++)
{
for (int currRow = 1; currRow <= rowCount; currRow++)
{
if (range.Cells[currRow, currColumn] == null || range.Cells[currRow, currColumn].ToString() == "n/a")
{
dataArray[currRow - 1, currColumn - 1] = "";
}
else
{
dataArray[currRow - 1, currColumn - 1] = range.Cells[currRow, currColumn].ToString();
}
}
}
xlWorkbook.Close();
return dataArray;
}
I recomand ExcelDataReader if you only want to read data.
Example of ExcelDataReader: https://csharp.hotexamples.com/examples/-/ExcelDataReader/-/php-exceldatareader-class-examples.html

Returning 2 values of different type from one class to another and update GUI

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.

for loop not counting past 2 columns - even though there is data in the 3rd column in excel worksheet

string workbookPath = filePath;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
int rCnt = 0;
int cCnt = 0;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(workbookPath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
range = xlWorkSheet.UsedRange;
int rowCount = range.Rows.Count;
int columnCount = range.Columns.Count;
string[][] myArray = new string[rowCount][];
for (rCnt = 1; rCnt < rowCount; rCnt++)
{
myArray[rCnt] = new string[columnCount];
for (cCnt = 1; cCnt < columnCount; cCnt++)
{
object str = (range.Cells[rCnt, cCnt] as Excel.Range).get_Value();
-----> myArray[rCnt][cCnt] = str == null ? string.Empty : str.ToString();
}
}
xlWorkBook.Close(true, null, null);
xlApp.Quit();
return myArray;
Above is the code for uploading an excel file to a sql database.
Essentially when I pass over the rCnt and cCnt variables where the ----> is above... the row count goes up once everytime the column count goes up twice ... I want to the column count to go up to 3, or however many usable columns there are.
The reason it's doing this could be that in the first row of the excel csv - there is nothing in the cell - however, in the 4-5th row, there is data in the 3rd column.
Could anyone glance at what I am missing?
Any questions / help would be greatly appreciated.
My first guess is that your code string[][] myArray = new string[rowCount][]; and myArray[rCnt] = new string[columnCount]; is allowing you to return a jagged array and you're going beyond those bounds somehow. UsedRange can sometimes be finicky (especially if you've deleted data - the range doesn't shrink down to fit your current data).
This code works fine for me, I use it a bit at work. COM entry/release code not included, I can add that later if you want it.
public string[,] ReadArray(int SheetNumber)
{
worksheet = (Excel.Worksheet)sheets.get_Item(SheetNumber);
Excel.Range range = worksheet.UsedRange;
//Get array, use range values. Not always correct, esp if user has deleted data. Ignore null values
Object[,] arr = range.Cells.Value;
string[,] output = new string[arr.GetLength(0), arr.GetLength(1)];
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
//If nothing in the cell, write a blank
if (arr[i + 1, j + 1] == null)
{
output[i, j] = "";
continue;
}
//else, write the output
output[i, j] = arr[i + 1, j + 1].ToString();
}
}
if (range != null)
Marshal.ReleaseComObject(range);
if (worksheet != null)
Marshal.ReleaseComObject(worksheet);
return output;
}

Categories

Resources