Hi I have an excel file settings.xlsx. I want to read the data from this file and assign the variables used in my code with the data.
example
Column1 Column2
Row1 Data 500
Row2 Address 30
Row3 Value FPGA
I have Data,Address and Value as variables in my code.
Can someone assist me with a pseudocode of c# to open a file and read the contents from it as per my requirement?
I want to search "Data" word in the excel file and take the value next to the cell containing "Data" and assign it to the variable "Data". I know it is confusing but I really want the final data to look like something below.
Data=500 //Finally I want my variables to have the data as follows
Address=30
Value= FPGA
I tried opening a file in my code.But since I am new to c#,i am not able to understand what is going wrong in my code.
I am stuck at this point. Open function is giving an error. Kindly help me. I tried to open the excel file in my c# code. But somehow it is saying Open function overload method doesn't take one argument. How to open and read the file?
string Filepath = #Filename;
Excel.Application excelapp = new Excel.Application();
excelapp.Visible = true;
var MyBook = excelapp.Workbooks.Open(Filepath);
It will be really helpful if somone gives a pseudocode for the same.
Hi,
I was able to open the file.
string Filepath = Path.Combine(Directory.GetCurrentDirectory(), Filename);
Excel.Application excelapp = new Excel.Application();
excelapp.Visible = true;
var Workbook = excelapp.Workbooks.Open(Filepath, 0, false, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0,true,1, 0);
var xlWorkSheet = (Excel.Worksheet)Workbook.Worksheets.get_Item(2);
Excel.Range range = xlWorkSheet.UsedRange;
But when I try to store the cell value in my variable, it gives me an error. I somehow cannot use Cells.value. I tried using the following but not able to store the data. Can anybody help?
uint pbaudRate2 = Convert.ToUInt32(range.Value2.ToString());
If you can make a slight change in your excel file, there is a much easier way to read the data. You need to have Column names in the first row (any names will do e.g. "ColumnName", "ColumnValue"), and data in subsequent rows. Then you can use code like this:
string xlConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=yourfullfilepathandname.xlsx;Extended Properties='Excel 8.0;HDR=Yes;';";
var xlConn = new OleDbConnection(xlConnStr);
var da = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", xlConn);
var xlDT = new DataTable();
da.Fill(xlDT);
You will now be able to access the values from the DataTable. In your case: xlDT.Rows[1][1] will hold the value of address (in this case 30). One thing to note: numbers in an Excel spreadsheet need to be retrieved as doubles and then cast if you want something else:
int myAddress = (int)(double)xlDT.Rows[1][1];
Here is a small demo how to read a range of Excel cells
// cf. http://support.microsoft.com/kb/302084/en-us
Excel.Application XL = new Microsoft.Office.Interop.Excel.Application();
Excel._Workbook WB = XL.Workbooks.Open(fileName, ReadOnly: true);
Excel._Worksheet WS = (Excel._Worksheet)WB.Sheets[sheetName];
Excel.Range R = WS.get_Range(GetAddress(row1, col1), GetAddress(row2, col2));
object[,] arr = (object[,])R.Value;
....
private string GetAddress(int rowNumber, int columnNumber)
{
int dividend = columnNumber;
string columnName = String.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName + rowNumber;
}
The cell values are copied to a 2D array of objects. Further processing depends on the value types.
Note that the transfer of an array is much faster than a nested loop of single cell copy operations.
Related
I am using c# program to search a text in my excel sheet. i have excel sheet called "MASTER" and in that sheet, there are a lot of text in column B. I want to look for
text "apple" inside column B. here is my code:
Excel.Worksheet workSheet;
workSheet = (Excel.Worksheet)xlWorkBook.Worksheets["MASTER"];
string result;
string utterance = "apples";
range1 = workSheet.Columns["B:B"] as Excel.Range;
Excel.Range findRange
findRange = range1.Find(utterance);
result = (string) (range2.Cells[findRange1.Row, 2] as Excel.Range).Value2;
it can search through the column B for input utterance "apples". however, in that column, there are a lot of apples. "applepie", "applejam","apple", etc. and the result from above code is "applepie". I think it because it just find the text contain "apple". my question is how to make it find the exact string so the output will be "apple" from column B?
Range.Find has many other arguments (see documentation), especially LookAt, see demo below:
var app = new Excel.Application();
var workbook = app.Workbooks.Open("C:\\Path\\File.xlsx");
var sheet = workbook.Worksheets["MASTER"];
var range = (Excel.Range)sheet.Columns["B:B"];
var result = range.Find("apples", LookAt: Excel.XlLookAt.xlWhole);
var address = result.Address;//cell address
var value = result.Value2;//cell value
//close or do something else
You can use the method Split, to treat every word as an array element
range1 = workSheet.Columns["B:B"] as Excel.Range;
var words = range1.Split(' ');
foreach(var word in words)
{
if (word == utterance)
Console.WriteLine(word);
}
How to create and set styles in Excel cells using C#?
I want to write something like "April 1st" with st as a superscript.
I would be using a string format not a date format.
I have tried http://msdn.microsoft.com/en-us/library/f1hh9fza.aspx but getting an The name 'Globals' does not exist in the current context error. I have added assembly Microsoft.Office.Interlop.Excel. Am I missing any other assembly?
Excel.Style style = Globals.ThisWorkbook.Styles.Add("NewStyle");
You actually don't want to change the font of the whole cell but you to change a portion of the text in the cell I take it.
You'll still need to retrieve the cell range and then adjust the characters within that range. here is an example where it's just adjusting the first cell. A1.
If you wanted to change the whole cell range to be superscript it would be done like this
currentRange.Font.Superscript = true;
void Main()
{
var app = new Application();
app.Visible = true;
var workbook = app.Workbooks.Add(1);
Sheets excelSheets = workbook.Worksheets;
string currentSheet = "Sheet1";
Worksheet worksheet1 = (Worksheet)excelSheets.get_Item(currentSheet);
worksheet1.Cells[1, 1] = "April 1st";
worksheet1.Cells[1, 2] = "April 2nd";
worksheet1.Cells[1, 3] = "April 3rd";
worksheet1.Cells[1, 4] = "April 4th";
// fill in the starting and ending range programmatically this is just an example.
string startRange = "A1";
string endRange = "A1";
Range currentRange = worksheet1.get_Range(startRange , endRange );
var text = currentRange.Text.ToString();
int length = text.Length;
int index = 0;
if(text.Contains("st"))
{
index =text.IndexOf("st");
}
//The other checks for "nd", "rd", "th" obviously check to see a # precedes these.
if(index > 0)
{
currentRange.get_Characters( index+1, 2).Font.Superscript = true;
}
}
As the MSDN article you've linked to states:
Applies to: The information in this topic applies to document-level
projects and application-level projects for Office 2013 and Office
2010. See Features Available by Office Application and Project Type.
To use Globals class you have to create Office project. For another reference you can check this question about creating Office add-in:
Globals.ThisAddin.Application can be only used in VSTO Add-In
I have an Excel Sheet where I've named the cells I have to fill from my code.
The reason for the named fields is that the customer has the possibility to re-arrange the cells.
To make it a little clearer: I used the field shown below to name the cells.
My problem is now that I have no idea how to address these fields from C# using office interop.
Range r = Sheet.get_Range("M_Leitung", Type.Missing);
doesn't work. Since I don't have any ranges defined, just single cells where I have to insert the values, I'd need a function that returns the named cell.
I just simulated your scenario and the following code worked like a charm (where I labeled A1 in sheet2 as M_Leitung):
Edit: updated code - When you have multiple sheets, you need to refer the names at workbook scope which will return fully qualified address (and hence the resulting range knows which sheet to pick the address from)
private static void Main(string[] args)
{
string FileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Book2.xlsx");
Application excelApp = new Application();
Workbooks excelWorkbooks = excelApp.Workbooks;
Workbook report = excelWorkbooks.Open(FileName, 0, false, 5, "", "", true, XlPlatform.xlWindows, "", true, false, 0, false, false, false);
var y = report.Names.Item("M_Leitung").RefersToRange.Value;
Console.WriteLine(y);
excelWorkbooks.Close();
excelApp.Quit();
}
Note that you do create a named range automatically when you rename a cell. If you created a range of say A1:B1 and you selected that. Excel would show you the named range in that corner label rather than the addresses which proves it works both ways.
HTH
Defined Names in Excel have scope, either Workbook or Sheet (ie Global or Local). Typing them in like you've done creates them as Workbook scope. Use the Name Manager to check scope.
Use the Names & RefersToRange properties, not Range to access them. The syntax is slightly different:
Workbook scope: Workbook.Names("M_Leitung").RefersToRange.Value
Worksheet scope: Workbook.Sheet.Names("M_Leitung").RefersToRange.Value
The reason for this is so you can create the same Name on different sheets.
Excel.Application app = new Excel.ApplicationClass();
Excel.Workbook book = app.Workbooks.Open(Filename: System.IO.Path.Combine( Environment.CurrentDirectory, "Book1.xls"));
Excel.Name MyRange = book.Names.Item(Index:"MyRange");
Console.WriteLine(MyRange.RefersToRange.Value);
MyRange.RefersToRange.Value = "55";
book.Save();
app.Quit();
Above code open a file and get the value from workbook and update the range. I think this will solve the problem.
I am trying to replace formulas on column D with their values.
eg. currently D1 = C1 / 2
If C1 = 10, I want D1 to be 5
I need to do this because I need to delete the column C.
I tried changing the format to Text like below but it doesn't seem to replace formulas with their values
Excel.Style style = workbook.Styles.Add("styleText", Missing.Value);
style.NumberFormat = "#";
Excel.Range range = (Excel.Range)sheet.get_Range("D1", Missing.Value);
range.Style = style;
Here's a macro in VBA that does what you need... It's VB code but I dont think woould be a problem to translate it in C#
Sub ValuesOnly()
Dim rRange As Range
On Error Resume Next
Set rRange = Application.InputBox(Prompt:="Select the formulas", Title:="VALUES ONLY", Type:=8)
If rRange Is Nothing Then Exit Sub
rRange = rRange.Value
End Sub
Another way to do it is to simply mimic the command Paste Special -> Values. I have just recorded a macro that does it (C5 in my sample is a cell that contains a function)
Sub Macro1()
Range("C5").Select
Selection.Copy
Range("D5").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
How do you format a comment??
Here is the solution I got, thanks to Lorenzo
private static void ReplaceFormulasWithValues(ref Excel.Worksheet sheet, char column)
{
Excel.Range range = (Excel.Range)sheet.get_Range(column + "1", Missing.Value).EntireColumn;
range.Copy(Missing.Value);
range.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteValues,
Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
}
This is another way to do it (C1 contains a formula, the result is placed in D1)
static void Main( string[] args ) {
string fileName = #"D:\devprj\Temp\TempProject\bin\Debug\Cartel1.xlsx";
Application ac = new Application();
Workbook wb = ac.Workbooks.Open( fileName );
Worksheet ws = wb.Sheets[1];
Range rangeOrigin = ws.get_Range( "C1" );
Range rangeDestination = ws.get_Range( "D1" );
rangeDestination.Value = rangeOrigin.Value2;
wb.Save();
}
You can't just change the display style, because that doesn't change the content of the cell. When you're doing this manually in Excel you need to copy the column and then choose Paste Special -> Values to paste the values rather than the formulae. I imagine there's a programatic way to do the same operation.
I am losing the leading zeros when I copy values from a datatable to an Excel sheet. That's because probably Excel treats the values as a number instead of text.
I am copying the values like so:
myWorksheet.Cells[i + 2, j] = dtCustomers.Rows[i][j - 1].ToString();
How do I format a whole column or each cell as Text?
A related question, how to cast myWorksheet.Cells[i + 2, j] to show a style property in Intellisense?
Below is some code to format columns A and C as text in SpreadsheetGear for .NET which has an API which is similar to Excel - except for the fact that SpreadsheetGear is frequently more strongly typed. It should not be too hard to figure out how to convert this to work with Excel / COM:
IWorkbook workbook = Factory.GetWorkbook();
IRange cells = workbook.Worksheets[0].Cells;
// Format column A as text.
cells["A:A"].NumberFormat = "#";
// Set A2 to text with a leading '0'.
cells["A2"].Value = "01234567890123456789";
// Format column C as text (SpreadsheetGear uses 0 based indexes - Excel uses 1 based indexes).
cells[0, 2].EntireColumn.NumberFormat = "#";
// Set C3 to text with a leading '0'.
cells[2, 2].Value = "01234567890123456789";
workbook.SaveAs(#"c:\tmp\TextFormat.xlsx", FileFormat.OpenXMLWorkbook);
Disclaimer: I own SpreadsheetGear LLC
If you set the cell formatting to Text prior to adding a numeric value with a leading zero, the leading zero is retained without having to skew results by adding an apostrophe. If you try and manually add a leading zero value to a default sheet in Excel and then convert it to text, the leading zero is removed. If you convert the cell to Text first, then add your value, it is fine. Same principle applies when doing it programatically.
// Pull in all the cells of the worksheet
Range cells = xlWorkBook.Worksheets[1].Cells;
// set each cell's format to Text
cells.NumberFormat = "#";
// reset horizontal alignment to the right
cells.HorizontalAlignment = XlHAlign.xlHAlignRight;
// now add values to the worksheet
for (i = 0; i <= dataGridView1.RowCount - 1; i++)
{
for (j = 0; j <= dataGridView1.ColumnCount - 1; j++)
{
DataGridViewCell cell = dataGridView1[j, i];
xlWorkSheet.Cells[i + 1, j + 1] = cell.Value.ToString();
}
}
Solution that worked for me for Excel Interop:
myWorksheet.Columns[j].NumberFormat = "#"; // column as a text
myWorksheet.Cells[i + 2, j].NumberFormat = "#"; // cell as a text
This code should run before putting data to Excel. Column and row numbers are 1-based.
A bit more details. Whereas accepted response with reference for SpreadsheetGear looks almost correct, I had two concerns about it:
I am not using SpreadsheetGear. I was interested in regular Excel
communication thru Excel interop without any 3rdparty libraries,
I was searching for the way to format column by number, not using
ranges like "A:A".
Before your write to Excel need to change the format:
xlApp = New Excel.Application
xlWorkSheet = xlWorkBook.Sheets("Sheet1")
Dim cells As Excel.Range = xlWorkSheet.Cells
'set each cell's format to Text
cells.NumberFormat = "#"
'reset horizontal alignment to the right
cells.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight
I've recently battled with this problem as well, and I've learned two things about the above suggestions.
Setting the numberFormatting to # causes Excel to left-align the value, and read it as if it were text, however, it still truncates the leading zero.
Adding an apostrophe at the beginning results in Excel treating it as text and retains the zero, and then applies the default text format, solving both problems.
The misleading aspect of this is that you now have a different value in the cell. Fortuately, when you copy/paste or export to CSV, the apostrophe is not included.
Conclusion: use the apostrophe, not the numberFormatting in order to retain the leading zeros.
Use your WorkSheet.Columns.NumberFormat, and set it to string "#", here is the sample:
Excel._Worksheet workSheet = (Excel._Worksheet)_Excel.Worksheets.Add();
//set columns format to text format
workSheet.Columns.NumberFormat = "#";
Note: this text format will apply for your hole excel sheet!
If you want a particular column to apply the text format, for example, the first column, you can do this:
workSheet.Columns[0].NumberFormat = "#";
or this will apply the specified range of woorkSheet to text format:
workSheet.get_Range("A1", "D1").NumberFormat = "#";
if (dtCustomers.Columns[j - 1].DataType != typeof(decimal) && dtCustomers.Columns[j - 1].DataType != typeof(int))
{
myWorksheet.Cells[i + 2, j].NumberFormat = "#";
}
I know this question is aged, still, I would like to contribute.
Applying Range.NumberFormat = "#" just partially solve the problem:
Yes, if you place the focus on a cell of the range, you will read text in the format menu
Yes, it align the data to the left
But if you use the type formula to check the type of the value in the cell, it will return 1 meaning number
Applying the apostroph behave better. It sets the format to text, it align data to left and if you check the format of the value in the cell using the type formula, it will return 2 meaning text
//where [1] - column number which you want to make text
ExcelWorksheet.Columns[1].NumberFormat = "#";
//If you want to format a particular column in all sheets in a workbook - use below code. Remove loop for single sheet along with slight changes.
//path were excel file is kept
string ResultsFilePath = #"C:\\Users\\krakhil\\Desktop\\TGUW EXCEL\\TEST";
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook ExcelWorkbook = ExcelApp.Workbooks.Open(ResultsFilePath);
ExcelApp.Visible = true;
//Looping through all available sheets
foreach (Excel.Worksheet ExcelWorksheet in ExcelWorkbook.Sheets)
{
//Selecting the worksheet where we want to perform action
ExcelWorksheet.Select(Type.Missing);
ExcelWorksheet.Columns[1].NumberFormat = "#";
}
//saving excel file using Interop
ExcelWorkbook.Save();
//closing file and releasing resources
ExcelWorkbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(ExcelWorkbook);
ExcelApp.Quit();
Marshal.FinalReleaseComObject(ExcelApp);
You need to format the column to be a string.
You can use the link https://supportcenter.devexpress.com/ticket/details/t679279/import-from-excel-to-gridview
For converting the ExcelDataSource, you can also refer to https://supportcenter.devexpress.com/ticket/details/t468253/how-to-convert-exceldatasource-to-datatable