How to split multiple lines in a cell - c#

I'm trying to write a program that will allow me to read Excel files using C#.
These Excel files can contain information that has been entered with the use of "Alt-Enter" to create multiple lines within the cell. Each line denotes a different value.
How do I separate out the multiple values in the single cell?

Sample program:
Add a reference to Microsoft.Office.Interop
using Microsoft.Office.Interop.Excel;
string path = "C:\\Test.xlsx ";
Application excel = new Application();
Workbook wb = excel.Workbooks.Open(path);
Worksheet excelSheet = wb.ActiveSheet;
// Read the second row second column cell
string test = excelSheet.Cells[2, 2].Value.ToString();
string splittedString = test.Split('\n');

Related

My Program does not insert '00' to my excel [duplicate]

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

EPPlus How to add LineSeries with specific range of data from worksheet

I create an Excel file in code. So far, everything works out fine.
Created excel file (image)
I want to create the following chart in code
Excel with Chart (image)
(Notice the selected cells and xseries names)
In Excel its easy.
But how do I do that in code?
My experiment
string values = "='Overall Results'!B3;'Overall Results'!D3;'Overall Results'!F3;'Overall Results'!H3;'Overall Results'!J3";
string xSerie = "='Overall Results'!$B$1:$K$1";
linechart.Series.Add(values, xSerie);
didn't work.
You have to create a string with the EPPlus cell adresses.
string values = worksheet.Cells[3, 2].Address + ":" + worksheet.Cells[3, 4].Address + ":" + worksheet.Cells[3, 6].Address;
linechart.Series.Add(values, ExcelRange.GetAddress(1, 2, 1, 11));
Had this problem aswell, but i found a solution:
For some reason, in order to get multiple specific cells in EPPlus, every cell has to be in a range.
So creating multiple ranges, which each only contains 1 cell, is the way to go
string values = "sheetName!B3:sheetName!B3,sheetName!D3:sheetName!D3,sheetName!F3:sheetName!F3,sheetName!H3:sheetName!H3,sheetName!J3:sheetName!J3";
var valueCells = sheet.Cells[values];
string xSerie = (Same concept);
var xCells = sheet.Cells[xSerie];
linechart.Series.Add(valueCells, xCells);

EPPlus Calculate Excel Worksheet.Cells[3, 2].Value returns "#value"

I am using the Worksheet and the workbook and calling the calculate() method for every sheet and for the workbook:
foreach (var worksheet in eppWorlSheets)
{
worksheet.Calculate();
}
this.eppWorkBook.Calculate();
When trying to get the value of some calculated cells that contains double it returns #value! as a string
using the below code
Worksheet.Cells[3, 2].Value.ToString());
Even the Text property return #value! and the Value property without "ToString()"

Read Excel Formulas

I need to get all the excel formulas from the worksheet.I am using Range.SpecialCells and iterating through the each cell to get formula and it is really slow.Is there any better solution to get only formulas as list of strings?
Sample code:
Excel.Worksheet worksheet = Workbook.Worksheets["Sheet1"];
Range range = worksheet.UsedRange.SpecialCells(xlCellTypeFormulas);
foreach(Cell cell in range.Cells)
{
string formula = cell.formula.ToString();
//some code
}
You can try to use the range.formula property.
For example:
In cell A3, the cell formula is '=DATE(D3,C3,1)'
In cell B3, the cell formula is '=A3'
With the code:
Range r = activeWorksheet.get_Range("A3","B3");
var c = r.Formula;
The variable c will contain sort of like a list of the cells specified in that range and their respective formula.
Output of C:
[1,1] = "=DATE(D3,C3,1)"
[1,2] = "=A3"
This is a totally different way to do it, but it might help you,
Just press CRTL + ` (backquote), this will make all the formula visible in the excel sheet. You could then search what you want or copy paste in a txt file to make searches and modifications.
If you are just searching for some strings within a formula, you can use CTRL + F , select look in formulas and search the strings

Excel Date column returning INT using EPPlus

So i'm using EPPlus to read and write excel documents.
Workflow
User generates populated excel document
Opens document and adds a row
Uploaded and read
The dates that are generated when I create the document using EPPlus show correctly when I'm reading the value back but the row the user changes the date one or adds is showing as an INT value not something I can use as a real date.
When I enter the date 1/01/2014 and write it, the output when I open the file up shows 41640
I'm reading it as follows
sheet.Cells[i, "AE".ConvertExcelColumnIndex()].Value != null
? sheet.Cells[i, "AE".ConvertExcelColumnIndex()].Value.ToString().Trim()
: string.Empty
Update
When exporting the file I have added the following
DateTime testDate;
if (DateTime.TryParse(split[i], out testDate))
{
sheet.Cells[row, i + 1].Style.Numberformat.Format = "MM/dd/yyyy";
sheet.Cells[row, i + 1].Value = testDate.ToString("MM/dd/yyyy");
}
Also when reading the value back I have tried
sheet.Cells[i, "AE".ConvertExcelColumnIndex()].Style.Numberformat.Format = "MM/dd/yyy";
I still get an INT back
...when I need to read that excel file, the only dates that are
incorrect are the ones the user has changed
So when you read the modified excel-sheet, the modified dates are numbers whereas the unchanged values are strings in your date-format?
You could get the DateTime via DateTime.FromOADate:
long dateNum = long.Parse(worksheet.Cells[row, column].Value.ToString());
DateTime result = DateTime.FromOADate(dateNum);
With your sample-number:
Console.Write(DateTime.FromOADate(41640)); // -> 01/01/2014
I stumbled upon this issue today when trying to generate some Excel documents from some ASP.NET DataTables: I had no problem with strings, but ran into few issues with numeric types (int, doubles, decimals) and DataTables, which were formatted as string or as numeric representations (OADate).
Here's the solution I eventually managed to pull off:
if (dc.DataType == typeof(DateTime))
{
if (!r.IsNull(dc))
{
ws.SetValue(row, col, (DateTime)r[dc]);
// Change the following line if you need a different DateTime format
var dtFormat = "dd/MM/yyyy";
ws.Cells[row, col].Style.Numberformat.Format = dtFormat;
}
else ws.SetValue(row, col, null);
}
Apparently, the trick was to set the value as DateTime and then configure the proper Style.Numberformat.Formataccordingly.
I published the full code sample (DataTable to Excel file with EPPlus) in this post on my blog.
You should try using
string dateFromExcel = workSheet.Cells[row, col].Text.ToString();
DateTime localdt;
if (DateTime.TryParse(dateFromExcel, out localdt))
{
dateFromExcel = localdt.ToString("MM/dd/yyyy");
};
the Value reads the value in the general formatting while Text reads the value as it is from the excel with applied formatting.
you could check if the cell format is in date format,
then parse it to date
var cell = worksheet.Cells[row, col];
value = cell.Value.ToString();
if (cell.Style.Numberformat.Format == "[$-409]d\\-mmm\\-yy;#")
{
string inputString = DateTime.FromOADate(long.Parse(value.ToString())).ToString("dd-MMM-yyyy");
}
You can also change the 'NumberFormatLocal' property. This worked for me. If you format the Excel file before improting it using EPPLUS.
The following basic example of code formats column A in a typical excel file.
Sub ChangeExcelColumnFormat()
Dim ExcelApp As Excel.Application
Dim ExcelWB As Excel.Workbook
Dim ExcelWS As Excel.Worksheet
Dim formatRange As Excel.Range
Dim strFile As String = "C:\Test.xlsx"
Dim strSheetname As String = "Sheet1"
ExcelApp = New Excel.Application
ExcelWB = ExcelApp.Workbooks.Open(strFile)
strColSelect = "A:A"
strFormat = "dd/mm/yyyy"
formatRange = ExcelWS.Range(strColSelect)
formatRange.NumberFormatLocal = strFormat
ExcelWB.Save()
ExcelWB.Close()
ExcelApp.Quit()
ExcelWS = Nothing
ExcelWB = Nothing
ExcelApp = Nothing
End Sub

Categories