I have some data saved in some strings, now I would like to open an existing Excel file, and write these strings in order in the empty cells after the populated ones,
Example:
I have the file that in column A is written up to 10, I would like the code to check that 10 finds a datum and writes to 11 and then continue [11, B] [11, C] until I finish the strings and then save the file.
I'm using Interop
using Microsoft.Office.Interop.Excel;
using Excel = Microsoft.Office.Interop.Excel;
OpenFileDialog FileExcel = new OpenFileDialog();
if (FileExcel.ShowDialog() == DialogResult.OK)
{
try
{
var sr = new StreamReader(FileExcel.FileName);
}
catch (SecurityException ex)
{
MessageBox.Show($"Security error.\n\nError message: {ex.Message}\n\n" +
$"Details:\n\n{ex.StackTrace}");
}
}
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(FileExcel.FileName);
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[Convert.ToInt32(comboBox1.SelectedItem)];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.Write("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t");
//add useful things here!
}
}
Related
I have a dataGridView in a WindowsForms. I want a button to export this dataGridView to an Excel Worksheet.
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application ExcelApp;
Excel.Workbook ExcelWorkBook;
Excel.Worksheet ExcelWorkSheet;
ExcelApp = new Excel.Application();
ExcelWorkBook = ExcelApp.Workbooks.Add(Missing.Value);
ExcelWorkSheet = (Excel.Worksheet)ExcelWorkBook.Worksheets.get_Item(1);
try
{
for (int i = 0; i <= dataGridView1.RowCount - 1; ++i)
{
for (int j = 0; j <= dataGridView1.ColumnCount - 1; ++j)
{
DataGridViewCell cell = dataGridView1[j, i];
ExcelWorkSheet.Cells[i + 1, j + 1] = cell.Value;
}
}
} catch (Exception ex) { /*somestuff*/ }
// save ExcelWorkbook
This code works. But unfortunately the time complexity is bad. So I'm forced to implement a progressbar. If i wouldn't do it, the user would be thinking the program crashed, while exporting a big datagridview. Needless to say, this will of course slow down the export even more. (progressbar code is not included in this question)
I wonder, if there is a method to export a datagrid to an excel faster.
Thanks for the hints to use another third-party library.
I was giving EPPLus a chance.
Here is the code:
private void ExportWithEPPlus(string filepath)
{
using (ExcelPackage excelPackage = new ExcelPackage())
{
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add("Sheet 1");
try
{
for (int i = 0; i <= dataGridView1.RowCount - 1; ++i)
{
for (int j = 0; j <= dataGridView1.ColumnCount - 1; ++j)
{
DataGridViewCell cell = dataGridView1[j, i];
worksheet.Cells[i + 1, j + 1].Value = cell.Value;
}
}
catch (Exception ex) { /*somestuff*/ }
finally
{
FileInfo fi = new FileInfo(#filepath);
excelPackage.SaveAs(fi);
}
}
}
It's fast like hell. The drawback is: It's memory hungry.
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);
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
How can I use a select statement on an Excel sheet without using any oledb Provider? This is what I got so far by using using Excel = Microsoft.Office.Interop.Excel;. Iterating through each cell using a nested for-loop feels wrong...
// Create excel application object by calling constructor
Excel.Application xlApp = new Excel.Application();
// Open excel file using excel object
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"D:\Temp\file.xls");
// Open first sheet within excel document (index start at 1, not 0)
Excel._Worksheet xlWorksheet = (Excel.Worksheet)xlWorkbook.Sheets["SheetName"];
// Get used sheet bounderies
Excel.Range xlRange = xlWorksheet.UsedRange;
// Get row count
int rowCount = xlRange.Rows.Count;
// Get column count
int colCount = xlRange.Columns.Count;
//iterate over the rows and columns and print to the console as it appears in the file
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.Write("\r\n");
//write the value to the console if cell value ends on 'd'
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null && (xlRange.Cells[i, j].Value2.ToString()).EndsWith("d"))
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t");
}
}
While you could use the items interface to a range to go over all the cells, you are outputting for each row and conditionally outputting across columns, for is the right approach.
However, you could tighten the code up a little:
var rowCount = xlRange.Rows.Count;
var colCount = xlRange.Columns.Count;
for (int row = 1; row <= rowCount; ++row) {
Console.WriteLine();
for (int col = 1; col <= colCount; ++col) {
//write the value to the console if cell value ends on 'd'
if (xlRange.Cells[row, col]?.Value2?.ToString().EndsWith("d") ?? false)
Console.Write(xlRange.Cells[row, col].Value2.ToString() + "\t");
}
}
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/