Inserting text in Excel using Open Xml SDK and LINQ - c#

I have been trying really hard but my excel sheet is not populating as per my expectations. If the content is having string datatype then sheet is showing '0' in place of that, howsoever hard I tried by using conversions. I am pasting my code below if any one can help me:
public static void WriteExcelDocument(string FilePath)
{
try
{
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(FilePath, true))
{
WorkbookPart workbookPart = spreadSheet.WorkbookPart;
IEnumerable<Sheet> Sheets = spreadSheet.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>().Where(s => s.Name == "data");
if (Sheets.Count() == 0)
{
// The specified worksheet does not exist.
return;
}
string relationshipId = Sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)spreadSheet.WorkbookPart.GetPartById(relationshipId);
SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
int index = 2;
SpectrumNewEntities context = new SpectrumNewEntities();
var q = from result in context.Appraisers
select result;
foreach (var g in q)
{
string Name = g.AppraiserName!=null?g.AppraiserName:String.Empty;
string city = g.City != null ? g.City : String.Empty;
string Address = g.Address != null ? g.Address : "NA";
int AppId = g.AppraiserAppraiserCompanyId != null ? (int)g.AppraiserAppraiserCompanyId : 0;
string email = g.Email != null ? g.Email : String.Empty;
Row contentRow = CreateContentRow(index, Name, city, Address, AppId,email);
index++;
sheetData.AppendChild(contentRow);
}
// Save the worksheet.
worksheetPart.Worksheet.Save();
}
}
catch (Exception)
{
throw;
}
}
private static Row CreateContentRow(int index, string Name, string city, string Address, int AppId, string email)
{
try
{
//Create new row
Row r = new Row();
r.RowIndex = (UInt32)index;
//First cell is a text cell, so create it and append it
Cell firstCell = CreateTextCell(headerColumns[0], Name, index);
r.AppendChild(firstCell);//
//create cells that contain data
for (int i = 1; i < headerColumns.Length; i++)
{
Cell c = new Cell();
c.CellReference = headerColumns[i] + index;
CellValue v = new CellValue();
if (i == 1)
{
v.Text = city.ToString();
}
if (i == 2)
{
v.Text = Address.ToString();
}
if (i == 3)
{
v.Text =AppId.ToString();
}
if (i == 4)
{
v.Text = email.ToString();
}
c.AppendChild(v);
r.AppendChild(c);
}
return r;
}
catch (Exception)
{
throw;
}
}
private static Cell CreateTextCell(string header, string Name,int index)
{
try
{
//Create a new inline string cell
Cell c = new Cell();
c.DataType = CellValues.InlineString;
c.CellReference = header + index;
//Add text to text cell
InlineString inlineString = new InlineString();
Text t = new Text();
t.Text = Name;
inlineString.AppendChild(t);
c.AppendChild(inlineString);
return c;
}
catch (Exception)
{
throw;
}
}
I am not getting why display is something like this?

Use the CreateTextCell method to add all the text cells to the row; like you are doing for the Name field.

Related

I'm trying to pass DataTable to Class and I get this message: Input string was not in a correct format

I am taking an excel file to read the fields and pass it to a class, to be able to enter the DB, when I pass dt.AsEnumerable, it is giving me an error in the "Linea" field. This cell sometimes comes with the $ sign. I think that is what is generating the error, so i am trying to replace the character and then convert it to int, since it is an amount field.
using (var streamExcel = System.IO.File.Create(combineFilePath))
{
await file.CopyToAsync(streamExcel);
}
using (var excelWorkbook = new XLWorkbook(combineFilePath))
{
IXLWorksheet workSheet = excelWorkbook.Worksheet(2);
workSheet.Clear(XLClearOptions.AllFormats);
DataTable dt = new DataTable();
bool firstRow = true;
foreach (IXLRow row in workSheet.Rows())
{
//for row number check
if (firstRow)
{
foreach (IXLCell cell in row.Cells())
{
dt.Columns.Add(cell.Value.ToString());
}
firstRow = false;
}
else
{
//Add rows to DataTable.
dt.Rows.Add();
int i = 0;
foreach (IXLCell cell in row.Cells(1, 50))
{
if (cell.Address.ColumnNumber == 11)
{
workSheet.Cell(11, 11).Style.NumberFormat.Format = "#,##0";
cell.SetDataType(XLDataType.Number);
}
dt.Rows[dt.Rows.Count - 1][i] = cell.CachedValue.ToString();
i++;
}
}
}
try
{
var companys = dt.AsEnumerable().Select(row => new Company
{
Name = row.Field<string>("Nombre"),
Rut = row.Field<string>("Rut"),
Address = row.Field<string>("Dirección"),
AddressNumber = row.Field<string>(#"Nº"),
Location = row.Field<string>("Comuna"),
Region = row.Field<string>("Región"),
Giro = row.Field<string>("Giro Cliente"),
Linea = Convert.ToInt32(row.Field<string>("Monto línea Aprobada").Trim().TrimEnd().Replace(#"$", "")),
Observations = row.Field<string>("Observaciones Comité"),
}).ToList();
UserId = _companyService.AddList(companys);
}
catch (Exception e)
{
}
To visualize where it's failing, you could do something like this:
try{
var companysB = dt.AsEnumerable().Select(row => new
{
Name = row.Field<string>("Nombre"),
LineaRaw = row.Field<string>("Monto línea Aprobada"),
LineaProcessed = row.Field<string>("Monto línea Aprobada").Trim().TrimEnd().Replace(#"$", ""),
})
.ToList();
}
Put a breakpoint on 'companysB' and inspect after it's filled. One or more of the LineaRaw / LineaProcessed will not be a number.
The error was when the "Monto línea Aprobada" cell had a blank value, I did this:
var n = 0;
string cellEmty = "";
foreach (DataRow rowEmpty in dt.Rows)
{
cellEmty = rowEmpty["Monto línea Aprobada"].ToString();
if (string.IsNullOrEmpty(cellEmty))
{
cellEmty = "0";
dt.Rows[n].SetField("Monto línea Aprobada", cellEmty);
}
n++;
}

Converting Excel to CSV with C# getting extra , on each row

Am converting an Excel file to a CSV in a Azure WebJob to keep the file in blob storage during the process using C# but am getting an extra comma after each row in my csv file.
Example:
1,Test,Doe,
2,Test,John,
Here is my code for producing the csv:
public static class ExcelToCSVConvertor
{
public static List<BlobInput> Convert(List<BlobOutput> inputs)
{
var dataForBlobInput = new List<BlobInput>();
try
{
foreach (BlobOutput item in inputs)
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(item.BlobContent, false))
{
foreach (Sheet _Sheet in document.WorkbookPart.Workbook.Descendants<Sheet>())
{
WorksheetPart _WorksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(_Sheet.Id);
Worksheet _Worksheet = _WorksheetPart.Worksheet;
SharedStringTablePart _SharedStringTablePart = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
SharedStringItem[] _SharedStringItem = _SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().ToArray();
StringBuilder stringBuilder = new StringBuilder();
foreach (var row in _Worksheet.Descendants<Row>())
{
foreach (Cell _Cell in row)
{
string Value = string.Empty;
if (_Cell.CellValue != null)
{
if (_Cell.DataType != null && _Cell.DataType.Value == CellValues.SharedString)
Value = _SharedStringItem[int.Parse(_Cell.CellValue.Text)].InnerText;
else
Value = _Cell.CellValue.Text;
}
stringBuilder.Append(string.Format("{0},", Value.Trim()));
}
stringBuilder.Append("\n");
}
byte[] data = Encoding.UTF8.GetBytes(stringBuilder.ToString().Trim());
string fileNameWithoutExtn = item.BlobName.ToString().Substring(0, item.BlobName.ToString().IndexOf("."));
string newFilename = $"{fileNameWithoutExtn}_{_Sheet.Name}.csv";
dataForBlobInput.Add(new BlobInput { BlobName = newFilename, BlobContent = data });
}
}
}
}
catch (Exception Ex)
{
throw Ex;
}
return dataForBlobInput;
}
}
This line is adding comma after EVERY single value
stringBuilder.Append(string.Format("{0},", Value.Trim()));
1,
Test,
Doe,
2,
Test,
John,
You need to exclude the comma on last value in row (last iteration).
On last iteration foreach (Cell _Cell in row) stringBuilder.Append should be
stringBuilder.Append(string.Format("{0}", Value.Trim()));

Difficulties with C# + Excel

I have a problem.
I have an Excel File where sometimes the same customer is in 2 rows.
But not always.
Its like:
Click
Now, i want to create a DataGrid in C# which can list this in one row like:
Click
I know it would be easier to change the Excel file, but assume it wouldnt work that way(we get the file like this and we cant change it)
I know i could too just make another Excel File and make it with Excel(already did it this way, but we would need it more as C#)
Now i am at this point:
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel Arbeitsmappe |*.xlsx", ValidateNames = true };
if (ofd.ShowDialog() == DialogResult.OK)
textBox1.Text = ofd.SafeFileName;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = false;
string filename = ofd.FileName;
Excel.Workbook workbook = excelApp.Workbooks.Open(filename);
Excel.Worksheet worksheet = workbook.Worksheets[1];
dataGridView1.ColumnCount = 2;
dataGridView1.Columns[0].Name = "Number";
dataGridView1.Columns[1].Name = "Street";
int rows = worksheet.UsedRange.Rows.Count;
for (int i = 2; i <= rows; i++)
{
string combinehr = worksheet.Cells[i, 150].Text + worksheet.Cells[i, 151].Text;
dataGridView1.Rows.Add(worksheet.Cells[i,29].Text, combinehr);
}
}
How do i expand it that it works like i want?
I would be so grateful
(sorry for the english)
With a reference to ExcelDataReader, ExcelDataReader.DataSet and DataSetExtensions (.Net) you can read the Excel file pretty easy into a DataSet, then you just have to work with the logic:
Input file:
using System;
using System.Data;
using System.IO;
using System.Linq;
using ExcelDataReader;
public DataTable GetTableFromExcel(string filePath)
{
DataSet ds = new DataSet();
using (var stream = System.IO.File.Open(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
ds = reader.AsDataSet();
}
}
DataTable table = new DataTable();
table.Columns.Add(new DataColumn("CustomerNr"));
table.Columns.Add(new DataColumn("Address"));
// Set column names
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
{
// DataColumn.ColumnName can't be empty when DataColumn is part
// of a DataTable (throws ArgumentException)
string columnName = ds.Tables[0].Rows[0][i].ToString();
if (string.IsNullOrWhiteSpace(columnName))
{
columnName = $"Column{i}";
}
ds.Tables[0].Columns[i].ColumnName = columnName;
}
// Remove the first row containing the headers
ds.Tables[0].Rows.Remove(ds.Tables[0].Rows[0]);
// I don't have the benchmarks with me right now, but I've tested
// DataTable.Select vs DataTable.AsEnumerable.Select many times
// and the AsEnumerable method its faster, that's why you need the
// reference to System.Data.DataSetExtensions
var enumerableTable = ds.Tables[0].AsEnumerable();
// list of unique products
var products = enumerableTable.Select(row => row.Field<string>("Product")).Distinct();
// Add a column for each product
foreach (string product in products)
{
table.Columns.Add(new DataColumn(product));
}
// list of unique customers
var customerNumbers = enumerableTable.Select(row => row.Field<double>("CustomerNr")).Distinct();
foreach (var customerNumber in customerNumbers)
{
DataRow record = table.NewRow();
record["CustomerNr"] = customerNumber;
record["Address"] = enumerableTable.First(row => row.Field<double>("CustomerNr").Equals(customerNumber))[1];
for (int i = 2; i < table.Columns.Count; i++)
{
DataRow product = enumerableTable.FirstOrDefault(row => row.Field<double>("CustomerNr").Equals(customerNumber)
&& row.Field<string>("Product").Equals(table.Columns[i].ColumnName));
// Quantity = 0 if product is null
record[i] = product?["Quantity"] ?? 0;
}
table.Rows.Add(record);
}
return table;
}
Result DataTable:
The same result as #IvanGarcíaTopete via Microsoft.Office.Interop.Excel.
Class ExcelModel for Excel data:
public class ExcelModel
{
public string CustomerNr { get; set; }
public string Address { get; set; }
public string Product { get; set; }
public string Quantity { get; set; }
}
Read Excel and fill out model:
private void OpenReadExcel()
{
var dlg = new OpenFileDialog();
if (dlg.ShowDialog() != DialogResult.OK) return;
var exApp = new Microsoft.Office.Interop.Excel.Application();
Workbook exWbk = exApp.Workbooks.Open(dlg.FileName);
Worksheet wSh = exWbk.Sheets[1];
int k = 2;
Customers.Clear();
while (wSh.Cells[k, 1].Text != "" && wSh.Cells[k, 1].Value != null)
{
var rowExcelModel = new ExcelModel()
{
CustomerNr = wSh.Cells[k, 1].Text,
Address = wSh.Cells[k, 2].Text,
Product = wSh.Cells[k, 3].Text,
Quantity = wSh.Cells[k, 4].Text
};
Customers.Add(rowExcelModel);
k++;
}
exApp.Quit();
}
Generate Data table:
private void GenerateDataTable()
{
// unique products and customers
var products = Customers.Select(x => x.Product).Distinct().ToList();
var customers = Customers.Select(x => x.CustomerNr).Distinct().ToList();
// columns CustomerNr and Address
var dataTable = new System.Data.DataTable();
dataTable.Columns.Add(new DataColumn("CustomerNr"));
dataTable.Columns.Add(new DataColumn("Address"));
// columns for each product
foreach (var product in products)
{
dataTable.Columns.Add(new DataColumn(product));
}
//fill rows for each customers
foreach (var customer in customers)
{
var row = dataTable.NewRow();
row["CustomerNr"] = customer;
row["Address"] = Customers.Where(x => x.CustomerNr == customer).Select(x => x.Address).FirstOrDefault();
foreach (var product in products)
{
var quantity = Customers.Where(x => x.CustomerNr == customer && x.Product == product)
.Select(x => x.Quantity).FirstOrDefault();
row[product] = quantity ?? "0";
}
dataTable.Rows.Add(row);
}
dataGridView1.DataSource = dataTable;
}

C# OpenXML copy and paste excel sheet to new workbook

I have multiple workbooks with the same sheet name. I want to copy all the individual sheets to one workbook. The code I have so far copies the text but it doesn't keep formatting , so I lose the colors, borders etc. Can someone suggest any improvements to include styles also and keep formatting? Thanks
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.Linq;
namespace openxmlExcelTryout
{
class OpenXMLCopySheet
{
private static int tableId;
public static void CopySheet(string filename, string sheetName, string clonedSheetName, string destFileName)
{
//Open workbook
using (SpreadsheetDocument mySpreadsheet = SpreadsheetDocument.Open(filename, true))
{
WorkbookPart workbookPart = mySpreadsheet.WorkbookPart;
//Get the source sheet to be copied
WorksheetPart sourceSheetPart = GetWorkSheetPart(workbookPart, sheetName);
SharedStringTablePart sharedStringTable = workbookPart.SharedStringTablePart;
//Take advantage of AddPart for deep cloning
using (SpreadsheetDocument newXLFile = SpreadsheetDocument.Create(destFileName, SpreadsheetDocumentType.Workbook))
{
WorkbookPart newWorkbookPart = newXLFile.AddWorkbookPart();
SharedStringTablePart newSharedStringTable = newWorkbookPart.AddPart<SharedStringTablePart>(sharedStringTable);
WorksheetPart newWorksheetPart = newWorkbookPart.AddPart<WorksheetPart>(sourceSheetPart);
//Table definition parts are somewhat special and need unique ids...so let's make an id based on count
int numTableDefParts = sourceSheetPart.GetPartsCountOfType<TableDefinitionPart>();
tableId = numTableDefParts;
//Clean up table definition parts (tables need unique ids)
if (numTableDefParts != 0)
FixupTableParts(newWorksheetPart, numTableDefParts);
//There should only be one sheet that has focus
CleanView(newWorksheetPart);
var fileVersion = new FileVersion { ApplicationName = "Microsoft Office Excel" };
//Worksheet ws = newWorksheetPart.Worksheet;
Workbook wb = new Workbook();
wb.Append(fileVersion);
//Add new sheet to main workbook part
Sheets sheets = null;
//int sheetCount = wb.Sheets.Count();
if (wb.Sheets != null)
{ sheets = wb.GetFirstChild<Sheets>(); }
else
{ sheets = new Sheets(); }
Sheet copiedSheet = new Sheet
{
Name = clonedSheetName,
Id = newWorkbookPart.GetIdOfPart(newWorksheetPart)
};
if (wb.Sheets != null)
{ copiedSheet.SheetId = (uint)sheets.ChildElements.Count + 1; }
else { copiedSheet.SheetId = 1; }
sheets.Append(copiedSheet);
newWorksheetPart.Worksheet.Save();
wb.Append(sheets);
//Save Changes
newWorkbookPart.Workbook = wb;
wb.Save();
newXLFile.Close();
}
}
}
static void CleanView(WorksheetPart worksheetPart)
{
//There can only be one sheet that has focus
SheetViews views = worksheetPart.Worksheet.GetFirstChild<SheetViews>();
if (views != null)
{
views.Remove();
worksheetPart.Worksheet.Save();
}
}
static void FixupTableParts(WorksheetPart worksheetPart, int numTableDefParts)
{
//Every table needs a unique id and name
foreach (TableDefinitionPart tableDefPart in worksheetPart.TableDefinitionParts)
{
tableId++;
tableDefPart.Table.Id = (uint)tableId;
tableDefPart.Table.DisplayName = "CopiedTable" + tableId;
tableDefPart.Table.Name = "CopiedTable" + tableId;
tableDefPart.Table.Save();
}
}
static WorksheetPart GetWorkSheetPart(WorkbookPart workbookPart, string sheetName)
{
//Get the relationship id of the sheetname
string relId = workbookPart.Workbook.Descendants<Sheet>()
.Where(s => s.Name.Value.Equals(sheetName))
.First()
.Id;
return (WorksheetPart)workbookPart.GetPartById(relId);
}
}
}
I found the solution and post it here maybe someone will get some help from it.
public static void MergeXSLX(string spreadSheetPathSource, string spreadSheetPathDestination)
{
//string[] staticSheets = new string[] { "Index", "Proj Info", "Project Report", "Cust Proj Rpt", "Issues Register", "Risk Register", "Change Register", "Milestones Register", "Add Optional Sheets ==>" };
string[] staticSheets = new string[] { "Summaries", "limits" };
FileStream spreadSheetStreamSource = null;
FileStream spreadSheetStreamDestination = null;
try
{
if (!File.Exists(spreadSheetPathSource)) throw new Exception("Source excel document not found!");
if (!File.Exists(spreadSheetPathDestination)) throw new Exception("Destination excel document not found!");
spreadSheetStreamSource = new FileStream(spreadSheetPathSource, FileMode.Open, FileAccess.Read);
spreadSheetStreamDestination = new FileStream(spreadSheetPathDestination, FileMode.Open, FileAccess.ReadWrite);
using (SpreadsheetDocument spreadsheetDocumentSource = SpreadsheetDocument.Open(spreadSheetStreamSource, false))
{
using (SpreadsheetDocument spreadsheetDocumentDestination = SpreadsheetDocument.Open(spreadSheetStreamDestination, true))
{
WorkbookPart workbookPartSource = spreadsheetDocumentSource.WorkbookPart;
WorkbookPart workbookPartDestination = spreadsheetDocumentDestination.WorkbookPart;
foreach (Sheet sheet in workbookPartSource.Workbook.Sheets)
{
if (staticSheets.ToList().Contains(sheet.Name))
{
uint replaced = 0;
int index = 0;
if (workbookPartDestination.Workbook.Sheets.Elements<Sheet>().Count(s => s.Name.ToString().Equals(sheet.Name)) == 1)
{
Sheet org;
foreach (Sheet s in workbookPartDestination.Workbook.Sheets.Elements<Sheet>())
{
if (s.Name.ToString().Equals(sheet.Name))
{
org = s;
break;
}
index++;
}
replaced = sheet.SheetId;
DeleteWorkSheet(workbookPartDestination, sheet.Name);
}
//WorkbookPart workbookPart = mySpreadsheet.WorkbookPart;
////Get the source sheet to be copied
WorksheetPart sourceSheetPart = GetWorkSheetPart(workbookPartSource, sheet.Name);
//Take advantage of AddPart for deep cloning
SpreadsheetDocument tempSheet = SpreadsheetDocument.Create(new MemoryStream(), spreadsheetDocumentDestination.DocumentType);
WorkbookPart tempWorkbookPart = tempSheet.AddWorkbookPart();
WorksheetPart tempWorksheetPart = tempWorkbookPart.AddPart<WorksheetPart>(sourceSheetPart);
if(workbookPartDestination.SharedStringTablePart == null)
{
workbookPartDestination.AddPart<SharedStringTablePart>(workbookPartSource.SharedStringTablePart);
}
//Add cloned sheet and all associated parts to workbook
WorksheetPart clonedSheet = workbookPartDestination.AddPart<WorksheetPart>(tempWorksheetPart);
//Table definition parts are somewhat special and need unique ids...so let's make an id based on count
int numTableDefParts = sourceSheetPart.GetPartsCountOfType<TableDefinitionPart>();
int tableId = numTableDefParts;
//Clean up table definition parts (tables need unique ids)
if (numTableDefParts != 0)
FixupTableParts(clonedSheet, numTableDefParts);
//There should only be one sheet that has focus
CleanView(clonedSheet);
var values = workbookPartSource.SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().ToArray();
Dictionary<uint, uint> cacheCellFormat = new Dictionary<uint, uint>();
Dictionary<uint, uint> cacheCellStyleFormat = new Dictionary<uint, uint>();
Dictionary<uint, uint> cacheBorder = new Dictionary<uint, uint>();
Dictionary<uint, uint> cacheFill = new Dictionary<uint, uint>();
Dictionary<uint, uint> cacheFont = new Dictionary<uint, uint>();
Dictionary<uint, uint> cacheNumberFormat = new Dictionary<uint, uint>();
foreach (Cell cell in clonedSheet.Worksheet.Descendants<Cell>())
{
if (cell.DataType != null && cell.DataType == CellValues.SharedString)
{
var ssindex = int.Parse(cell.CellValue.Text);
cell.CellValue = new CellValue(InsertSharedStringItem_(values[ssindex].InnerText, workbookPartDestination.SharedStringTablePart).ToString());
}
if (cell.StyleIndex != null)
{
cell.StyleIndex = GetCellFormat(workbookPartSource, workbookPartDestination, cacheCellFormat, cacheCellStyleFormat, cacheBorder, cacheFill, cacheFont, cacheNumberFormat, cell);
}
}
//Add new sheet to main workbook part
Sheets sheets = workbookPartDestination.Workbook.GetFirstChild<Sheets>();
Sheet copiedSheet = new Sheet
{
Name = sheet.Name,
Id = workbookPartDestination.GetIdOfPart(clonedSheet),
SheetId = (uint)sheets.ChildElements.Count + 1
};
if (replaced != 0)
{
copiedSheet.SheetId = replaced;
sheets.InsertAt(copiedSheet, index);
}
else
{
sheets.Append(copiedSheet);
}
//Save Changes
workbookPartDestination.Workbook.Save();
}
}
}
}
}
finally
{
if (spreadSheetStreamSource != null)
spreadSheetStreamSource.Close();
if (spreadSheetStreamDestination != null)
spreadSheetStreamDestination.Close();
}
}
private static uint GetCellFormat(WorkbookPart workbookPartSource, WorkbookPart workbookPartDestination, Dictionary<uint, uint> cacheCellFormat, Dictionary<uint, uint> cacheCellStyleFormat, Dictionary<uint, uint> cacheBorder, Dictionary<uint, uint> cacheFill, Dictionary<uint, uint> cacheFont, Dictionary<uint, uint> cacheNumberFormat, Cell cell)
{
uint cellFormatIndex, cellStyleFormatIndex;
if (cacheCellFormat.Keys.Contains(cell.StyleIndex.Value))
{
cellFormatIndex = cacheCellFormat[cell.StyleIndex.Value];
}
else
{
CellFormat cellFormat = workbookPartSource.WorkbookStylesPart.Stylesheet.CellFormats.Descendants<CellFormat>().ToList()[int.Parse(cell.StyleIndex)];
CellFormat cellFormatClone = CellFormatClone(workbookPartSource, workbookPartDestination, cacheBorder, cacheFill, cacheFont, cacheNumberFormat, cellFormat);
if (cellFormat.FormatId != 0)
{
if (cacheCellStyleFormat.Keys.Contains(cellFormat.FormatId.Value))
{
cellStyleFormatIndex = cacheCellStyleFormat[cellFormat.FormatId.Value];
}
else
{
CellFormat cellStyleFormat = workbookPartSource.WorkbookStylesPart.Stylesheet.CellStyleFormats.Descendants<CellFormat>().ToList()[int.Parse(cellFormat.FormatId)];
if (workbookPartDestination.WorkbookStylesPart.Stylesheet.CellStyleFormats.Descendants<CellFormat>().ToList().Count > int.Parse(cellFormat.FormatId) &&
workbookPartDestination.WorkbookStylesPart.Stylesheet.CellStyleFormats.Descendants<CellFormat>().ToList()[int.Parse(cellFormat.FormatId)].OuterXml == cellStyleFormat.OuterXml)
{
cellStyleFormatIndex = (uint)int.Parse(cellFormat.FormatId);
}
else
{
CellFormat cellStyleFormatClone = CellFormatClone(workbookPartSource, workbookPartDestination, cacheBorder, cacheFill, cacheFont, cacheNumberFormat, cellStyleFormat);
workbookPartDestination.WorkbookStylesPart.Stylesheet.CellStyleFormats.Append(cellStyleFormatClone);
cellStyleFormatIndex = (uint)workbookPartDestination.WorkbookStylesPart.Stylesheet.CellStyleFormats.Descendants<CellFormat>().ToList().IndexOf(cellStyleFormatClone);
cacheCellStyleFormat.Add(cellFormat.FormatId.Value, cellStyleFormatIndex);
}
}
cellFormatClone.FormatId = cellStyleFormatIndex;
}
workbookPartDestination.WorkbookStylesPart.Stylesheet.CellFormats.Append(cellFormatClone);
cellFormatIndex = (uint)workbookPartDestination.WorkbookStylesPart.Stylesheet.CellFormats.Descendants<CellFormat>().ToList().IndexOf(cellFormatClone);
cacheCellFormat.Add(cell.StyleIndex.Value, cellFormatIndex);
}
return cellFormatIndex;
}
private static CellFormat CellFormatClone(WorkbookPart workbookPartSource, WorkbookPart workbookPartDestination, Dictionary<uint, uint> cacheBorder, Dictionary<uint, uint> cacheFill, Dictionary<uint, uint> cacheFont, Dictionary<uint, uint> cacheNumberFormat, CellFormat cellFormat)
{
CellFormat cellFormatClone = new CellFormat();
cellFormatClone.ApplyAlignment = cellFormat.ApplyAlignment;
cellFormatClone.ApplyBorder = cellFormat.ApplyBorder;
cellFormatClone.ApplyFill = cellFormat.ApplyFill;
cellFormatClone.ApplyFont = cellFormat.ApplyFont;
cellFormatClone.ApplyNumberFormat = cellFormat.ApplyNumberFormat;
cellFormatClone.ApplyProtection = cellFormat.ApplyProtection;
cellFormatClone.PivotButton = cellFormat.PivotButton;
cellFormatClone.QuotePrefix = cellFormat.QuotePrefix;
GetBorder(workbookPartSource, workbookPartDestination, cacheBorder, cellFormat, cellFormatClone);
GetFill(workbookPartSource, workbookPartDestination, cacheFill, cellFormat, cellFormatClone);
GetFont(workbookPartSource, workbookPartDestination, cacheFont, cellFormat, cellFormatClone);
GetNumberFormat(workbookPartSource, workbookPartDestination, cacheNumberFormat, cellFormat, cellFormatClone);
if (cellFormat.Protection != null)
cellFormatClone.Protection = (Protection)cellFormat.Protection.Clone();
if (cellFormat.Alignment != null)
cellFormatClone.Alignment = (Alignment)cellFormat.Alignment.Clone();
return cellFormatClone;
}
private static void GetNumberFormat(WorkbookPart workbookPartSource, WorkbookPart workbookPartDestination, Dictionary<uint, uint> cacheNumberFormat, CellFormat cellFormat, CellFormat cellFormatClone)
{
uint numberFormatIndex = 0;
if (cellFormat.NumberFormatId.Value != 0)
{
if (cacheNumberFormat.Keys.Contains(cellFormat.NumberFormatId.Value))
{
numberFormatIndex = cacheNumberFormat[cellFormat.NumberFormatId.Value];
}
else
{
NumberingFormat numberFormat = workbookPartSource.WorkbookStylesPart.Stylesheet.NumberingFormats.Descendants<NumberingFormat>().Where(nf => nf.NumberFormatId.Value == uint.Parse(cellFormat.NumberFormatId)).FirstOrDefault();
if (numberFormat != null)
{
if (workbookPartDestination.WorkbookStylesPart.Stylesheet.NumberingFormats != null)
{
if (workbookPartDestination.WorkbookStylesPart.Stylesheet.NumberingFormats.Descendants<NumberingFormat>().ToList().Count > int.Parse(cellFormat.NumberFormatId) &&
workbookPartDestination.WorkbookStylesPart.Stylesheet.NumberingFormats.Descendants<NumberingFormat>().ToList()[int.Parse(cellFormat.NumberFormatId)].OuterXml == numberFormat.OuterXml)
{
cellFormatClone.NumberFormatId = (uint)int.Parse(cellFormat.NumberFormatId);
return;
}
NumberingFormat nfclone = new NumberingFormat();
nfclone.FormatCode = numberFormat.FormatCode;
nfclone.NumberFormatId = workbookPartDestination.WorkbookStylesPart.Stylesheet.Descendants<NumberingFormat>().Max(nf => nf.NumberFormatId.Value) + 1;
workbookPartDestination.WorkbookStylesPart.Stylesheet.NumberingFormats.Append(nfclone);
numberFormatIndex = nfclone.NumberFormatId;
cacheNumberFormat.Add(cellFormat.NumberFormatId.Value, numberFormatIndex);
}
}
else
{
numberFormatIndex = cellFormat.NumberFormatId;
}
}
cellFormatClone.NumberFormatId = numberFormatIndex;
}
else
{
cellFormatClone.NumberFormatId = 0;
}
}
private static void GetFont(WorkbookPart workbookPartSource, WorkbookPart workbookPartDestination, Dictionary<uint, uint> cacheFont, CellFormat cellFormat, CellFormat cellFormatClone)
{
uint fontIndex;
if (cellFormat.FontId.Value != 0)
{
if (cacheFont.Keys.Contains(cellFormat.FontId.Value))
{
fontIndex = cacheFont[cellFormat.FontId.Value];
}
else
{
Font font = workbookPartSource.WorkbookStylesPart.Stylesheet.Fonts.Descendants<Font>().ToList()[int.Parse(cellFormat.FontId)];
if (workbookPartDestination.WorkbookStylesPart.Stylesheet.Fonts.Descendants<Font>().ToList().Count > int.Parse(cellFormat.FontId) &&
workbookPartDestination.WorkbookStylesPart.Stylesheet.Fonts.Descendants<Font>().ToList()[int.Parse(cellFormat.FontId)].OuterXml == font.OuterXml)
{
cellFormatClone.FontId = (uint)int.Parse(cellFormat.FontId);
return;
}
Font fontClone = new Font();
if (font.Bold != null)
fontClone.Bold = (Bold)font.Bold.Clone();
if (font.Color != null)
fontClone.Color = (Color)font.Color.Clone();
if (font.Condense != null)
fontClone.Condense = (Condense)font.Condense.Clone();
if (font.Extend != null)
fontClone.Extend = (Extend)font.Extend.Clone();
if (font.FontCharSet != null)
fontClone.FontCharSet = (FontCharSet)font.FontCharSet.Clone();
if (font.FontName != null)
fontClone.FontName = (FontName)font.FontName.Clone();
if (font.FontScheme != null)
fontClone.FontScheme = (FontScheme)font.FontScheme.Clone();
if (font.FontSize != null)
fontClone.FontSize = (FontSize)font.FontSize.Clone();
if (font.Italic != null)
fontClone.Italic = (Italic)font.Italic.Clone();
if (font.Outline != null)
fontClone.Outline = (Outline)font.Outline.Clone();
if (font.Shadow != null)
fontClone.Shadow = (Shadow)font.Shadow.Clone();
if (font.Strike != null)
fontClone.Strike = (Strike)font.Strike.Clone();
if (font.Underline != null)
fontClone.Underline = (Underline)font.Underline.Clone();
if (font.VerticalTextAlignment != null)
fontClone.VerticalTextAlignment = (VerticalTextAlignment)font.VerticalTextAlignment.Clone();
if (font.FontFamilyNumbering != null)
fontClone.FontFamilyNumbering = (FontFamilyNumbering)font.FontFamilyNumbering.Clone();
workbookPartDestination.WorkbookStylesPart.Stylesheet.Fonts.Append(fontClone);
fontIndex = (uint)workbookPartDestination.WorkbookStylesPart.Stylesheet.Fonts.Descendants<Font>().ToList().IndexOf(fontClone);
cacheFont.Add(cellFormat.FontId.Value, fontIndex);
}
cellFormatClone.FontId = fontIndex;
}
else
{
cellFormatClone.FontId = 0;
}
}
private static void GetFill(WorkbookPart workbookPartSource, WorkbookPart workbookPartDestination, Dictionary<uint, uint> cacheFill, CellFormat cellFormat, CellFormat cellFormatClone)
{
uint fillIndex;
if (cellFormat.FillId.Value != 0)
{
if (cacheFill.Keys.Contains(cellFormat.FillId.Value))
{
fillIndex = cacheFill[cellFormat.FillId.Value];
}
else
{
Fill fill = workbookPartSource.WorkbookStylesPart.Stylesheet.Fills.Descendants<Fill>().ToList()[int.Parse(cellFormat.FillId)];
if (workbookPartDestination.WorkbookStylesPart.Stylesheet.Fills.Descendants<Fill>().ToList().Count > int.Parse(cellFormat.FillId) &&
workbookPartDestination.WorkbookStylesPart.Stylesheet.Fills.Descendants<Fill>().ToList()[int.Parse(cellFormat.FillId)].OuterXml == fill.OuterXml)
{
cellFormatClone.FillId = (uint)int.Parse(cellFormat.FillId);
return;
}
Fill fillclone = new Fill();
if (fill.GradientFill != null)
fillclone.GradientFill = (GradientFill)fill.GradientFill.Clone();
if (fill.PatternFill != null)
fillclone.PatternFill = (PatternFill)fill.PatternFill.Clone();
workbookPartDestination.WorkbookStylesPart.Stylesheet.Fills.Append(fillclone);
fillIndex = (uint)workbookPartDestination.WorkbookStylesPart.Stylesheet.Fills.Descendants<Fill>().ToList().IndexOf(fillclone);
cacheFill.Add(cellFormat.FillId.Value, fillIndex);
}
cellFormatClone.FillId = fillIndex;
}
else
{
cellFormatClone.FillId = 0;
}
}
private static void GetBorder(WorkbookPart workbookPartSource, WorkbookPart workbookPartDestination, Dictionary<uint, uint> cacheBorder, CellFormat cellFormat, CellFormat cellFormatClone)
{
uint borderIndex;
if (cellFormat.BorderId.Value != 0)
{
if (cacheBorder.Keys.Contains(cellFormat.BorderId.Value))
{
borderIndex = cacheBorder[cellFormat.BorderId.Value];
}
else
{
Border border = workbookPartSource.WorkbookStylesPart.Stylesheet.Borders.Descendants<Border>().ToList()[int.Parse(cellFormat.BorderId)];
if (workbookPartDestination.WorkbookStylesPart.Stylesheet.Borders.Descendants<Border>().ToList().Count > int.Parse(cellFormat.BorderId) &&
workbookPartDestination.WorkbookStylesPart.Stylesheet.Borders.Descendants<Border>().ToList()[int.Parse(cellFormat.BorderId)].OuterXml == border.OuterXml)
{
cellFormatClone.BorderId = (uint)int.Parse(cellFormat.BorderId);
return;
}
Border borderclone = new Border();
if (border.StartBorder != null)
borderclone.StartBorder = (StartBorder)border.StartBorder.Clone();
if (border.EndBorder != null)
borderclone.EndBorder = (EndBorder)border.EndBorder.Clone();
if (border.LeftBorder != null)
borderclone.LeftBorder = (LeftBorder)border.LeftBorder.Clone();
if (border.RightBorder != null)
borderclone.RightBorder = (RightBorder)border.RightBorder.Clone();
if (border.TopBorder != null)
borderclone.TopBorder = (TopBorder)border.TopBorder.Clone();
if (border.BottomBorder != null)
borderclone.BottomBorder = (BottomBorder)border.BottomBorder.Clone();
if (border.DiagonalBorder != null)
borderclone.DiagonalBorder = (DiagonalBorder)border.DiagonalBorder.Clone();
if (border.VerticalBorder != null)
borderclone.VerticalBorder = (VerticalBorder)border.VerticalBorder.Clone();
if (border.HorizontalBorder != null)
borderclone.HorizontalBorder = (HorizontalBorder)border.HorizontalBorder.Clone();
workbookPartDestination.WorkbookStylesPart.Stylesheet.Borders.Append(borderclone);
borderIndex = (uint)workbookPartDestination.WorkbookStylesPart.Stylesheet.Borders.Descendants<Border>().ToList().IndexOf(borderclone);
cacheBorder.Add(cellFormat.BorderId.Value, borderIndex);
}
cellFormatClone.BorderId = borderIndex;
}
else
{
cellFormatClone.BorderId = 0;
}
}
private static int InsertSharedStringItem_(string text, SharedStringTablePart shareStringPart)
{
// If the part does not contain a SharedStringTable, create one.
if (shareStringPart.SharedStringTable == null)
{
shareStringPart.SharedStringTable = new SharedStringTable();
}
int i = 0;
// Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>())
{
if (item.InnerText == text)
{
return i;
}
i++;
}
// The text does not exist in the part. Create the SharedStringItem and return its index.
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
shareStringPart.SharedStringTable.Save();
return i;
}
private static void DeleteWorkSheet(WorkbookPart wbPart, string sheetToDelete)
{
string Sheetid = "";
// Get the pivot Table Parts
IEnumerable<PivotTableCacheDefinitionPart> pvtTableCacheParts = wbPart.PivotTableCacheDefinitionParts;
Dictionary<PivotTableCacheDefinitionPart, string> pvtTableCacheDefinationPart = new Dictionary<PivotTableCacheDefinitionPart, string>();
foreach (PivotTableCacheDefinitionPart Item in pvtTableCacheParts)
{
PivotCacheDefinition pvtCacheDef = Item.PivotCacheDefinition;
//Check if this CacheSource is linked to SheetToDelete
var pvtCahce = pvtCacheDef.Descendants<CacheSource>().Where(s => s.WorksheetSource.Sheet == sheetToDelete);
if (pvtCahce.Count() > 0)
{
pvtTableCacheDefinationPart.Add(Item, Item.ToString());
}
}
foreach (var Item in pvtTableCacheDefinationPart)
{
wbPart.DeletePart(Item.Key);
}
//Get the SheetToDelete from workbook.xml
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetToDelete).FirstOrDefault();
if (theSheet == null)
{
// The specified sheet doesn't exist.
}
//Store the SheetID for the reference
Sheetid = theSheet.SheetId;
// Remove the sheet reference from the workbook.
WorksheetPart worksheetPart = (WorksheetPart)(wbPart.GetPartById(theSheet.Id));
theSheet.Remove();
// Delete the worksheet part.
wbPart.DeletePart(worksheetPart);
//Get the DefinedNames
var definedNames = wbPart.Workbook.Descendants<DefinedNames>().FirstOrDefault();
if (definedNames != null)
{
foreach (DefinedName Item in definedNames)
{
// This condition checks to delete only those names which are part of Sheet in question
if (Item.Text.Contains(sheetToDelete + "!"))
Item.Remove();
}
}
// Get the CalculationChainPart
//Note: An instance of this part type contains an ordered set of references to all cells in all worksheets in the
//workbook whose value is calculated from any formula
CalculationChainPart calChainPart;
calChainPart = wbPart.CalculationChainPart;
if (calChainPart != null)
{
var calChainEntries = calChainPart.CalculationChain.Descendants<CalculationCell>().Where(c => c.SheetId == Sheetid);
foreach (CalculationCell Item in calChainEntries)
{
Item.Remove();
}
if (calChainPart.CalculationChain.Count() == 0)
{
wbPart.DeletePart(calChainPart);
}
}
// Save the workbook.
wbPart.Workbook.Save();
}
After spending many hours on the problem of copying the entire sheet, I finally found a solution. The CloneSheet method copies the entire sheet (content + style) to a new sheet with a new name.
static void CloneSheet(SpreadsheetDocument spreadsheetDocument, string sheetName, string clonedSheetName)
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart sourceSheetPart = GetWorkSheetPart(workbookPart, sheetName);
Sheets sheets = workbookPart.Workbook.GetFirstChild<Sheets>();
SpreadsheetDocument tempSheet = SpreadsheetDocument.Create(new MemoryStream(), spreadsheetDocument.DocumentType);
WorkbookPart tempWorkbookPart = tempSheet.AddWorkbookPart();
WorksheetPart tempWorksheetPart = tempWorkbookPart.AddPart(sourceSheetPart);
WorksheetPart clonedSheet = workbookPart.AddPart(tempWorksheetPart);
Sheet copiedSheet = new Sheet();
copiedSheet.Name = clonedSheetName;
copiedSheet.Id = workbookPart.GetIdOfPart(clonedSheet);
copiedSheet.SheetId = (uint)sheets.ChildElements.Count + 1;
sheets.Append(copiedSheet);
}
the fact of assigning :
copiedSheet.SheetId = (uint)sheets.ChildElements.Count + 1;
is not correct because this SheetId could be taken.
instead you can write :
copiedSheet.SheetId = newSheetId (workbookPart);
where newsheetId is defined so :
private UInt32Value NewSheetId(WorkbookPart workbookPart)
{
UInt32Value resultat = 0;
foreach (Sheet sheet in workbookPart.Workbook.Descendants<Sheet>())
{
if (sheet.SheetId > resultat)
resultat = sheet.SheetId;
}
return resultat + 1;
}

Read excel values to key value pair using open xml

I have an array of excel cell addresses, I just need to read these cell values to a dictionary, ie, I need to use open xml to do this. Any help?
When I'm reading I'm getting only numeric values and some numbers are coming for string type cells. Or any specific way to read multiple cells from excel using openxml?
public static Dictionary<string, string> GetCellValue(string filePath, string sheetName)
{
string[] adderssNames = { "H29", "H30", "H31", "H32", "H33", "H36", "H37", "H38", "H40", "H41", "H42", "H43", "H47",
"H48", "H49", "H50", "H51", "H52", "H57", "H58", "H61", "H62", "H65", "H66", "H69", "H70",
"I29", "I30", "I31", "I32", "I33", "I36", "I37", "I38", "I40", "I41", "I42", "I43", "I47",
"I48", "I49", "I50", "I51", "I52", "I57", "I58", "I61", "I62", "I65", "I66", "I69", "I70",
"J29", "J30", "J31", "J32", "J33", "J36", "J37", "J38", "J40", "J41", "J42", "J43", "J47",
"J48", "J49", "J50", "J51", "J52", "J57", "J58", "J61", "J62", "J65", "J66", "J69", "J70",
"K29", "K30", "K31", "K32", "K33", "K36", "K37", "K38", "K40", "K41", "K42", "K43", "K47",
"K48", "K49", "K50", "K51", "K52", "K57", "K58", "K61", "K62", "K65", "K66", "K69", "K70",
"L29", "L30", "L31", "L32", "L33", "L36", "L37", "L38", "L40", "L41", "L42", "L43", "L47",
"L48", "L49", "L50", "L51", "L52", "L57", "L58", "L61", "L62", "L65", "L66", "L69", "L70",
};
Dictionary<string, string> cellValues = new Dictionary<string, string>();
string value = null;
using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, false))
{
WorkbookPart wbPart = document.WorkbookPart;
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
Where(s => s.Name == sheetName).FirstOrDefault();
if (theSheet == null)
{
throw new ArgumentException("Invalid sheet name");
}
WorksheetPart wsPart =
(WorksheetPart)(wbPart.GetPartById(theSheet.Id));
for (int i = 0; i < adderssNames.Length; i++)
{
Cell theCell = wsPart.Worksheet.Descendants<Cell>().
Where(c => c.CellReference == adderssNames[i]).FirstOrDefault();
if (theCell != null)
{
value = theCell.CellValue == null ? "" : theCell.CellValue.Text;
cellValues.Add(adderssNames[i], value);
if (theCell.DataType != null)
{
switch (theCell.DataType.Value)
{
case CellValues.SharedString:
var stringTable =
wbPart.GetPartsOfType<SharedStringTablePart>()
.FirstOrDefault();
if (stringTable != null)
{
value =
stringTable.SharedStringTable
.ElementAt(int.Parse(value)).InnerText;
}
break;
case CellValues.Boolean:
switch (value)
{
case "0":
cellValues[adderssNames[i]] = "FALSE";
break;
default:
cellValues[adderssNames[i]] = "TRUE";
break;
}
break;
}
}
}
}
}
return cellValues;
}
Thanks
Ragesh

Categories

Resources