how to get range in excel sheet using openxml and c# - c#

I have to read Excel(.xlsx) file. I am using OpenXML NuGet pkg.
I am trying to get the range(xlRange), so I can fetch the data from a particular cell. But not getting success. This code is created in console environment.
static void Main(string[] args)
{
bool flagDataError = false;
string sDuplicateRows = string.Empty;
string sCreatedRows = string.Empty;
string sFileTypeError = string.Empty;
string filepath = #"C:\test.xlsx";
var fileName = Path.GetFileName(filepath);
var fileExtension = Path.GetExtension(filepath);
if ((fileExtension != ".xlsx") && (fileExtension != ".xls"))
sFileTypeError = "Invalid file. \n\nPlease browse a correct Excel file to upload.";
else
{
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(filepath, false))
{
WorkbookPart workbookPart = doc.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
List<AxisData> data = new List<AxisData>();
for (int i = 5; i <= 16; i++)
{
for (int j = 2; j <= 13; j++)
{
AxisData axisDetails = new AxisData();
axisDetails.ProductCode = "AXIS " + xlRange.Cells[i, 1].Value;
axisDetails.ContractPeriod = Convert.ToDateTime(xlRange.Cells[4, j].Value);
axisDetails.SettlePrice = Convert.ToDecimal(xlRange.Cells[i, j].Value);
axisDetails.EffectiveStartDate = efectiveStartDate;
}
}
}
}
}
}
}

IEnumerable<Row> ShRows = sheetData.Elements<Row>();
var _RCount = SHRows.Count();

Related

Is there anyway to upload a large Excel into a database quickly using C#?

I am trying to upload a large Ms Excel file into a relational database using C#.
Using following code:
But the process takes a very long time to read the excel (Approximated 45 hours to read an excel file with 185,000 record).
public static DataTable GetSpreadsheetWorkbookSheet(string filepath)
{
DataTable dataTable = new DataTable();
List<string> sheetList = new List<string>();
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filepath, true))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
int sheetCount = workbookPart.Workbook.Descendants<Sheet>().Count();
string relationshipId = "";
dataTable.Columns.Add("Sheet");
dataTable.Columns.Add("Path");
for (int i = 0; i < sheetCount; i++)
{
DataRow dataRow = dataTable.NewRow();
string sheetName = workbookPart.Workbook.Descendants<Sheet>().ElementAt(i).Name;
relationshipId = workbookPart.Workbook.Descendants<Sheet>().ElementAt(i).Id;
dataTable.Rows.Add(sheetName, filepath);
}
}
return dataTable;
}
public static DataTable CreateSpreadsheetWorkbook(string filepath, string sheetName)
{
DataTable dataTable = new DataTable();
List<string> sheetList = new List<string>();
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filepath, true))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
string relationshipId = "";
int x = sheets.ToList().Count;
if (sheets.ToList().Count > 1)
{
relationshipId = sheets.ToList().Find(io => io.Name.ToString().Equals(sheetName)).Id;
}
else
{
relationshipId = sheets.ToList().First().Id.Value;
}
WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
Worksheet workSheet = worksheetPart.Worksheet;
SheetData sheetData = workSheet.GetFirstChild<SheetData>();
IEnumerable<Row> rows = sheetData.Descendants<Row>();
foreach (Cell cell in rows.ElementAt(0))
{
dataTable.Columns.Add(GetCellValue(spreadSheetDocument, cell));
}
foreach (Row row in rows)
{
int t = row.Descendants<Cell>().Count();
DataRow dataRow = dataTable.NewRow();
for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
{
Thread.Sleep(1);
dataRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i));
Thread.Sleep(1);
}
dataTable.Rows.Add(dataRow);
Thread.Sleep(1);
}
}
dataTable.Rows.RemoveAt(0);
return dataTable;
}
private static string GetCellValue(SpreadsheetDocument document, Cell cell)
{
SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
string value = cell.InnerText;
if (cell.DataType != null && (cell.DataType.Value == CellValues.SharedString))
{
string txt = stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText.ToString();
Thread.Sleep(1);
return txt;
}
else if (cell.DataType != null && (cell.DataType.Value == CellValues.String))
{
string txt = value;
Thread.Sleep(1);
return txt;
}
else if (cell.DataType != null && (cell.DataType.Value == CellValues.InlineString))
{
string txt = stringTablePart.ToString();
Thread.Sleep(1);
return txt;
}
else if (cell.DataType == null)
{
string txt = value;
Thread.Sleep(1);
return txt;
}
else
{
if (String.IsNullOrEmpty(value) || String.IsNullOrWhiteSpace(value))
{
value = "0";
}
return Convert.ToDecimal(value).ToString("N4");
}
}
I need to upload the file quickly, Is there anyway to doing it quickly, Please help?

Need to convert scientific value to text

I am trying to convert csv to xls in which there is Bank Account No (16 digit) need to convert it to text
I tried with EPPlus package by which xls is getting generated easily but Bank Account column gets converted to scientific value.Also tried to convert column to numeric and text but thats not working
private void csvToXls(string source,string destination,string fileName)
{
string csvFileName = source;
string excelFileName = destination+"/"+fileName+".xls";
string worksheetsName = "sheet 1";
bool firstRowIsHeader = false;
var format = new ExcelTextFormat();
format.Delimiter = '|';
format.EOL = "\n"; // DEFAULT IS "\r\n";
// format.TextQualifier = '"';
using (ExcelPackage package = new ExcelPackage(new FileInfo(excelFileName)))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(worksheetsName);
worksheet.Cells["A1"].LoadFromText(new FileInfo(csvFileName), format, OfficeOpenXml.Table.TableStyles.None, firstRowIsHeader);
foreach (var cell in worksheet.Cells["C:C"])
{
cell.Value = Convert.ToString(cell.Value);
}
foreach (var cell in worksheet.Cells["AC:AC"])
{
cell.Value = Convert.ToString(cell.Value);
}
worksheet.Cells["C:C"].Style.Numberformat.Format = "#0";
worksheet.Cells["C:C"].Style.Numberformat.Format = "#";
worksheet.Cells["AC:AC"].Style.Numberformat.Format = "#";
package.Save();
}
}
Need to convert columns to text which should not be scientific value.Please suggest
Input : In test.csv below input is there
IMDATA||12345678910124567895274|1|NAME|||||||||TEST|||||||||||TESTING||||3301003726558|TDATASTING|TESTING|27-09-2019
Getting Output :
Expected Output :
You need to provide eDataTypes to LoadFromText method for each column, if no types provide for the column it will set to the General by default
So, provide the `eDataTypes to ExcelTextFormat.
I just added for 3 columns and its worked well.
public static void csvToXls(string source, string destination, string fileName)
{
string csvFileName = source;
string excelFileName = destination + "/" + fileName + ".xls";
string worksheetsName = "sheet 1";
bool firstRowIsHeader = false;
var format = new ExcelTextFormat();
var edataTypes = new eDataTypes[] { eDataTypes.String, eDataTypes.String, eDataTypes.String };
format.DataTypes = edataTypes;
format.Delimiter = '|';
format.EOL = "\n"; // DEFAULT IS "\r\n";
// format.TextQualifier = '"';
using (ExcelPackage package = new ExcelPackage(new FileInfo(excelFileName)))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(worksheetsName);
worksheet.Cells["A1"].LoadFromText(new FileInfo(csvFileName), format, OfficeOpenXml.Table.TableStyles.None, firstRowIsHeader);
package.Save();
}
}
OR
You can try to read the text manually
public static void csvToXls(string source, string destination, string fileName)
{
string csvFileName = source;
string excelFileName = destination + "/" + fileName + ".xls";
string worksheetsName = "sheet 1";
using (ExcelPackage package = new ExcelPackage(new FileInfo(excelFileName)))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(worksheetsName);
var text = File.ReadAllText(source);
var rows = text.Split('\n');
for (int rowIndex = 0; rowIndex < rows.Length; rowIndex++)
{
var excelRow = worksheet.Row(rowIndex+1);
var columns = rows[rowIndex].Split('|');
for (int colIndex = 0; colIndex < columns.Length; colIndex++)
{
worksheet.Cells[rowIndex +1, colIndex +1].Value = columns[colIndex];
}
}
package.Save();
}
}

EPPlus excel read IndexOutOfRangeException

I want to read data from excel (.xlsx or .xls) file
I am using EPPlus
but it give that error IndexOutOfRangeException: Worksheet position out of range.
in this line
OfficeOpenXml.ExcelWorksheet workSheet = package.Workbook.Worksheets[0];
here is my all code.Here is my excel file for redad(http://yazilimsozluk.com/a.xlsx )
.Are there any solution for excel read which works with .xlsx and .xls excel file?
if (Request != null) {
HttpPostedFileBase file = Request.Files["UploadedFile"];
if ((file != null) && (file.ContentLength > 0) && !string.IsNullOrEmpty(file.FileName)) {
string fileName = file.FileName;
string fileContentType = file.ContentType;
byte[] fileBytes = new byte[file.ContentLength];
var data = file.InputStream.Read(fileBytes, 0, Convert.ToInt32(file.ContentLength));
var existingFile = new System.IO.FileInfo(fileName);
var package = new OfficeOpenXml.ExcelPackage(existingFile);
OfficeOpenXml.ExcelWorksheet workSheet = package.Workbook.Worksheets[0];
for (int i = workSheet.Dimension.Start.Column; i <= workSheet.Dimension.End.Column; i++) {
for (int j = workSheet.Dimension.Start.Row; j <= workSheet.Dimension.End.Row; j++) {
object cellValue = workSheet.Cells[i, j].Value;
}
}
}
}
First of all EPPlus can not handle .xls files. See this answer:
Error when trying to read an .xls file using EPPlus
Sample code for reading a file:
var package = new ExcelPackage(new FileInfo("sample.xlsx"));
ExcelWorksheet workSheet = package.Workbook.Worksheets.FirstOrDefault();
for (int i = workSheet.Dimension.Start.Column;
i <= workSheet.Dimension.End.Column;
i++)
{
for (int j = workSheet.Dimension.Start.Row;
j <= workSheet.Dimension.End.Row;
j++)
{
object cellValue = workSheet.Cells[i, j].Value;
}
}

Open XML Sheetview Right to left

I need to add SheetView settings in ExporToExcel Class. But after export, it's showing that Excel Cell Content is empty even though the worksheet is created and SheetView settings are set. I checked all of the posts on this site and other site's as well, but I was not successful. Every time I am getting a Document corrupted message or the spreadsheet is empty.
private static void WriteExcelFile(DataSet ds, SpreadsheetDocument spreadsheet)
{
spreadsheet.AddWorkbookPart();
spreadsheet.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
spreadsheet.WorkbookPart.Workbook.Append(new BookViews(new WorkbookView()));
WorkbookStylesPart workbookStylesPart = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>("rIdStyles");
//Stylesheet stylesheet = new Stylesheet();
workbookStylesPart.Stylesheet = CreateStylesheet();
uint worksheetNumber = 1;
Sheets sheets = spreadsheet.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
foreach (DataTable dt in ds.Tables)
{
string worksheetName = dt.TableName;
WorksheetPart newWorksheetPart = spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
Sheet sheet = new Sheet() { Id = spreadsheet.WorkbookPart.GetIdOfPart(newWorksheetPart), SheetId = worksheetNumber, Name = worksheetName };
newWorksheetPart.Worksheet = new Worksheet(new SheetViews(new SheetView() { WorkbookViewId=0,RightToLeft=true}),new SheetData());
newWorksheetPart.Worksheet.Save();
sheets.Append(sheet);
WriteDataTableToExcelWorksheet(dt, newWorksheetPart);
worksheetNumber++;
}
spreadsheet.WorkbookPart.Workbook.Save();
}
private static void WriteDataTableToExcelWorksheet(DataTable dt, WorksheetPart worksheetPart)
{
OpenXmlWriter writer = OpenXmlWriter.Create(worksheetPart, Encoding.ASCII);
writer.WriteStartElement(new Worksheet());
writer.WriteStartElement(new SheetData());
string cellValue = "";
int numberOfColumns = dt.Columns.Count;
bool[] IsNumericColumn = new bool[numberOfColumns];
bool[] IsDateColumn = new bool[numberOfColumns];
string[] excelColumnNames = new string[numberOfColumns];
for (int n = 0; n < numberOfColumns; n++)
excelColumnNames[n] = GetExcelColumnName(n);
//
// Create the Header row in our Excel Worksheet
//
uint rowIndex = 1;
writer.WriteStartElement(new Row { RowIndex = rowIndex });
for (int colInx = 0; colInx < numberOfColumns; colInx++)
{
DataColumn col = dt.Columns[colInx];
AppendTextCell(excelColumnNames[colInx] + "1", col.ColumnName, ref writer);
IsNumericColumn[colInx] = (col.DataType.FullName == "System.Decimal") || (col.DataType.FullName == "System.Int32") || (col.DataType.FullName == "System.Double") || (col.DataType.FullName == "System.Single");
IsDateColumn[colInx] = (col.DataType.FullName == "System.DateTime");
}
writer.WriteEndElement(); // End of header "Row"
double cellNumericValue = 0;
foreach (DataRow dr in dt.Rows)
{
++rowIndex;
writer.WriteStartElement(new Row { RowIndex = rowIndex });
for (int colInx = 0; colInx < numberOfColumns; colInx++)
{
cellValue = dr.ItemArray[colInx].ToString();
cellValue = ReplaceHexadecimalSymbols(cellValue);
if (IsNumericColumn[colInx])
{
cellNumericValue = 0;
if (double.TryParse(cellValue, out cellNumericValue))
{
cellValue = cellNumericValue.ToString();
AppendNumericCell(excelColumnNames[colInx] + rowIndex.ToString(), cellValue, ref writer);
}
}
else if (IsDateColumn[colInx])
{
// This is a date value.
DateTime dtValue;
string strValue = "";
if (DateTime.TryParse(cellValue, out dtValue))
strValue = dtValue.ToShortDateString();
AppendTextCell(excelColumnNames[colInx] + rowIndex.ToString(), strValue, ref writer);
}
else
{
AppendTextCell(excelColumnNames[colInx] + rowIndex.ToString(), cellValue, ref writer);
}
}
writer.WriteEndElement(); // End of Row
}
writer.WriteEndElement(); // End of SheetData
writer.WriteEndElement(); // End of worksheet
writer.Close();
}
The code to make the sheet read RightToLeft sheet was correct. However, the code for WriteDataTableToExcelWorksheet and CreateStylesheet was not complete and had some problems.
I was able to find the original code for the WriteDataTableToExcelWorksheet at this link. Then I reversed engineered a plain Excel file with the Open XML Productivity Tool to C# code and reused a method to create a new Stylesheet.
The excel file I generated with this code is shown here:
I've pushed this new code to GitHub. There is a wrapper WPF application that guides where to generate the file on your machine.
Here is a guide on installing the Open XML Productivity Tool.

Insert a new worksheet into a spreadsheet document OpenXml

What im trying to do is create multiple worksheets within a work book using datasets the code i have to create a sheet data object from a data set is:
public static SheetData CreateDataSheet(DataSet ds)
{
var xlSheetData = new SheetData();
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
var tbl = ds.Tables[0];
foreach (DataRow row in tbl.Rows)
{
var xlRow = new Row();
foreach (DataColumn col in tbl.Columns)
{
var cellData = row[col];
Cell xlCell = null;
if (cellData != null)
{
xlCell = new Cell(new InlineString(new Text(cellData.ToString())))
{
DataType = CellValues.InlineString
};
}
else
{
xlCell = new Cell(new InlineString(new Text(String.Empty)))
{
DataType = CellValues.InlineString
};
}
xlRow.Append(xlCell);
}
xlSheetData.Append(xlRow);
}
}
return xlSheetData;
}
Then to create the spreadsheet and append the above to the spreadsheet i have:
public static void CreateSpreadsheetWorkbook(string filepath, List<SheetData> sd)
{
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
foreach (var x in sd)
{
var newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(x);
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
uint sheetId = 1;
if (sheets.Elements<Sheet>().Any())
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
var sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(newWorksheetPart), SheetId = sheetId, Name = "mySheet" + sheetId };
sheets.Append(sheet);
workbookpart.Workbook.Save();
}
spreadsheetDocument.Close();
}
This runs with out any errors however when i come to open the document its unable to be opened because it is corrupt.
EDIT - final working version:
public static void CreateSpreadsheetWorkbook(string filepath, List<SheetData> sd)
{
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
foreach (var x in sd)
{
var newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(x);
sheets = spreadsheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>();
uint sheetId = 1;
if (sheets.Elements<Sheet>().Any())
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
var sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(newWorksheetPart), SheetId = sheetId, Name = "mySheet" + sheetId };
sheets.Append(sheet);
workbookpart.Workbook.Save();
}
spreadsheetDocument.Close();
}
After comparing with some similar code of mine I found these possible problems:
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
//should be
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.DocumentType);
And
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
//should be
var sheets = spreadsheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>();
after the first time since by the second time you already have a Sheets element.
See this blogpost for more details:
http://blogs.msdn.com/b/brian_jones/archive/2009/02/19/how-to-copy-a-worksheet-within-a-workbook.aspx

Categories